mirror of
https://github.com/Pathduck/gallery3.git
synced 2026-04-27 07:59:14 -04:00
Update to Kohana r4684 which is now Kohana 2.4 and has substantial
changes.
This commit is contained in:
@@ -1,21 +1,15 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* Kohana process control file, loaded by the front controller.
|
||||
*
|
||||
* $Id: Bootstrap.php 4135 2009-03-28 17:51:04Z zombor $
|
||||
*
|
||||
* $Id: Bootstrap.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
|
||||
define('KOHANA_VERSION', '2.3.3');
|
||||
define('KOHANA_CODENAME', 'aegolius');
|
||||
|
||||
// Test of Kohana is running in Windows
|
||||
define('KOHANA_IS_WIN', DIRECTORY_SEPARATOR === '\\');
|
||||
|
||||
// Kohana benchmarks are prefixed to prevent collisions
|
||||
define('SYSTEM_BENCHMARK', 'system_benchmark');
|
||||
|
||||
@@ -29,9 +23,19 @@ Benchmark::start(SYSTEM_BENCHMARK.'_total_execution');
|
||||
Benchmark::start(SYSTEM_BENCHMARK.'_kohana_loading');
|
||||
|
||||
// Load core files
|
||||
require SYSPATH.'core/utf8'.EXT;
|
||||
require SYSPATH.'core/Event'.EXT;
|
||||
final class Event extends Event_Core {}
|
||||
|
||||
require SYSPATH.'core/Kohana'.EXT;
|
||||
final class Kohana extends Kohana_Core {}
|
||||
|
||||
require SYSPATH.'core/Kohana_Exception'.EXT;
|
||||
class Kohana_Exception extends Kohana_Exception_Core {}
|
||||
|
||||
require SYSPATH.'core/Kohana_Config'.EXT;
|
||||
require SYSPATH.'libraries/drivers/Config'.EXT;
|
||||
require SYSPATH.'libraries/drivers/Config/Array'.EXT;
|
||||
final class Kohana_Config extends Kohana_Config_Core {}
|
||||
|
||||
// Prepare the environment
|
||||
Kohana::setup();
|
||||
@@ -52,7 +56,4 @@ Event::run('system.routing');
|
||||
Benchmark::stop(SYSTEM_BENCHMARK.'_system_initialization');
|
||||
|
||||
// Make the magic happen!
|
||||
Event::run('system.execute');
|
||||
|
||||
// Clean up and exit
|
||||
Event::run('system.shutdown');
|
||||
Event::run('system.execute');
|
||||
@@ -129,6 +129,12 @@ $config["render_stats"] = TRUE;
|
||||
*/
|
||||
$config["extension_prefix"] = "MY_";
|
||||
|
||||
/**
|
||||
* An optional list of Config Drivers to use, they "fallback" to the one below them if they
|
||||
* dont work so the first driver is tried then so on until it hits the built in "array" driver and fails
|
||||
*/
|
||||
$config['config_drivers'] = array();
|
||||
|
||||
/**
|
||||
* Additional resource paths, or "modules". Each path can either be absolute
|
||||
* or relative to the docroot. Modules can include any resource that can exist
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
<p>This license is a legal agreement between you and the Kohana Software Foundation for the use of Kohana Framework (the "Software"). By obtaining the Software you agree to comply with the terms and conditions of this license.</p>
|
||||
|
||||
<p>Copyright (c) 2007-2008 Kohana Team<br/>All rights reserved.</p>
|
||||
<p>Copyright (c) 2007-2009 Kohana Team<br/>All rights reserved.</p>
|
||||
|
||||
<p>Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:</p>
|
||||
|
||||
|
||||
@@ -19,14 +19,10 @@
|
||||
* thirty minutes. Specific lifetime can also be set when creating a new cache.
|
||||
* Setting this to 0 will never automatically delete caches.
|
||||
*
|
||||
* requests - Average number of cache requests that will processed before all expired
|
||||
* caches are deleted. This is commonly referred to as "garbage collection".
|
||||
* Setting this to 0 or a negative number will disable automatic garbage collection.
|
||||
*/
|
||||
$config['default'] = array
|
||||
(
|
||||
'driver' => 'file',
|
||||
'params' => APPPATH.'cache',
|
||||
'params' => array('directory' => APPPATH.'cache', 'gc_probability' => 1000),
|
||||
'lifetime' => 1800,
|
||||
'requests' => 1000
|
||||
);
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* @package Cache:Memcache
|
||||
*
|
||||
* memcache server configuration.
|
||||
*/
|
||||
$config['servers'] = array
|
||||
(
|
||||
array
|
||||
(
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 11211,
|
||||
'persistent' => FALSE,
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* Enable cache data compression.
|
||||
*/
|
||||
$config['compression'] = FALSE;
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* @package Cache:SQLite
|
||||
*/
|
||||
$config['schema'] =
|
||||
'CREATE TABLE caches(
|
||||
id VARCHAR(127) PRIMARY KEY,
|
||||
tags VARCHAR(255),
|
||||
expiration INTEGER,
|
||||
cache TEXT);';
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* @package Cache:Xcache
|
||||
*
|
||||
* Xcache administrator username.
|
||||
*/
|
||||
$config['PHP_AUTH_USER'] = 'kohana';
|
||||
|
||||
/**
|
||||
* Xcache administrator password.
|
||||
*/
|
||||
$config['PHP_AUTH_PW'] = 'kohana';
|
||||
@@ -26,7 +26,13 @@ $config['expire'] = 0;
|
||||
$config['secure'] = FALSE;
|
||||
|
||||
/**
|
||||
* Enable this option to disable the cookie from being accessed when using a
|
||||
* secure protocol. This option is only available in PHP 5.2 and above.
|
||||
* Enable this option to make the cookie accessible only through the
|
||||
* HTTP protocol (e.g. no javascript access). This is not supported by all browsers.
|
||||
*/
|
||||
$config['httponly'] = FALSE;
|
||||
$config['httponly'] = FALSE;
|
||||
|
||||
/**
|
||||
* Cookie salt for signed cookies.
|
||||
* Make sure you change this to a unique value.
|
||||
*/
|
||||
$config['salt'] = 'K0hAN4 15 Th3 B357';
|
||||
@@ -25,7 +25,7 @@
|
||||
*/
|
||||
$config['default'] = array
|
||||
(
|
||||
'benchmark' => TRUE,
|
||||
'benchmark' => FALSE,
|
||||
'persistent' => FALSE,
|
||||
'connection' => array
|
||||
(
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* SwiftMailer driver, used with the email helper.
|
||||
*
|
||||
* @see http://www.swiftmailer.org/wikidocs/v3/connections/nativemail
|
||||
* @see http://www.swiftmailer.org/wikidocs/v3/connections/sendmail
|
||||
* @see http://www.swiftmailer.org/wikidocs/v3/connections/smtp
|
||||
*
|
||||
* Valid drivers are: native, sendmail, smtp
|
||||
*/
|
||||
$config['driver'] = 'native';
|
||||
|
||||
/**
|
||||
* To use secure connections with SMTP, set "port" to 465 instead of 25.
|
||||
* To enable TLS, set "encryption" to "tls".
|
||||
*
|
||||
* Driver options:
|
||||
* @param null native: no options
|
||||
* @param string sendmail: executable path, with -bs or equivalent attached
|
||||
* @param array smtp: hostname, (username), (password), (port), (auth), (encryption)
|
||||
*/
|
||||
$config['options'] = NULL;
|
||||
@@ -7,6 +7,7 @@ $config['uncountable'] = array
|
||||
'art',
|
||||
'baggage',
|
||||
'dances',
|
||||
'data',
|
||||
'equipment',
|
||||
'fish',
|
||||
'fuel',
|
||||
@@ -19,6 +20,7 @@ $config['uncountable'] = array
|
||||
'information',
|
||||
'knowledge',
|
||||
'luggage',
|
||||
'metadata',
|
||||
'money',
|
||||
'music',
|
||||
'news',
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
$config['language'] = array('en_US', 'English_United States');
|
||||
|
||||
/**
|
||||
* Locale timezone. Defaults to use the server timezone.
|
||||
* Locale timezone. Defaults to the timezone you have set in your php config
|
||||
* This cannot be left empty, a valid timezone is required!
|
||||
* @see http://php.net/timezones
|
||||
*/
|
||||
$config['timezone'] = '';
|
||||
$config['timezone'] = ini_get('date.timezone');
|
||||
19
system/config/log.php
Normal file
19
system/config/log.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
|
||||
|
||||
// Different log levels
|
||||
$config['log_levels'] = array
|
||||
(
|
||||
'error' => 1,
|
||||
'alert' => 2,
|
||||
'info' => 3,
|
||||
'debug' => 4,
|
||||
);
|
||||
|
||||
// See different log levels above
|
||||
$config['log_threshold'] = 1;
|
||||
|
||||
$config['date_format'] = 'Y-m-d H:i:s P';
|
||||
|
||||
// We can define multiple logging backends at the same time.
|
||||
$config['drivers'] = array('file');
|
||||
@@ -6,7 +6,7 @@
|
||||
* the operating system MIME list.
|
||||
*
|
||||
* If there are any missing options, please create a ticket on our issue tracker,
|
||||
* http://kohanaphp.com/trac/newticket. Be sure to give the filename and
|
||||
* http://dev.kohanaphp.com/projects/kohana2. Be sure to give the filename and
|
||||
* expected MIME type, as well as any additional information you can provide.
|
||||
*/
|
||||
$config = array
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* @package Pagination
|
||||
*
|
||||
* Pagination configuration is defined in groups which allows you to easily switch
|
||||
* between different pagination settings for different website sections.
|
||||
* Note: all groups inherit and overwrite the default group.
|
||||
*
|
||||
* Group Options:
|
||||
* directory - Views folder in which your pagination style templates reside
|
||||
* style - Pagination style template (matches view filename)
|
||||
* uri_segment - URI segment (int or 'label') in which the current page number can be found
|
||||
* query_string - Alternative to uri_segment: query string key that contains the page number
|
||||
* items_per_page - Number of items to display per page
|
||||
* auto_hide - Automatically hides pagination for single pages
|
||||
*/
|
||||
$config['default'] = array
|
||||
(
|
||||
'directory' => 'pagination',
|
||||
'style' => 'classic',
|
||||
'uri_segment' => 3,
|
||||
'query_string' => '',
|
||||
'items_per_page' => 20,
|
||||
'auto_hide' => FALSE,
|
||||
);
|
||||
@@ -6,3 +6,7 @@
|
||||
* Built in sections are benchmarks, database, session, post and cookies, custom sections can be used too.
|
||||
*/
|
||||
$config['show'] = TRUE;
|
||||
|
||||
$config['time_decimals'] = 3;
|
||||
|
||||
$config['memory_decimals'] = 2;
|
||||
@@ -25,7 +25,6 @@ $config['validate'] = array('user_agent');
|
||||
/**
|
||||
* Enable or disable session encryption.
|
||||
* Note: this has no effect on the native session driver.
|
||||
* Note: the cookie driver always encrypts session data. Set to TRUE for stronger encryption.
|
||||
*/
|
||||
$config['encryption'] = FALSE;
|
||||
|
||||
@@ -38,8 +37,10 @@ $config['expiration'] = 7200;
|
||||
/**
|
||||
* Number of page loads before the session id is regenerated.
|
||||
* A value of 0 will disable automatic session id regeneration.
|
||||
* NOTE: Enabling automatic session regeneration can cause a race condition see the
|
||||
* docs for details: http://docs.kohanaphp.com/libraries/session#regenerate
|
||||
*/
|
||||
$config['regenerate'] = 3;
|
||||
$config['regenerate'] = 0;
|
||||
|
||||
/**
|
||||
* Percentage probability that the gc (garbage collection) routine is started.
|
||||
|
||||
@@ -4,55 +4,90 @@
|
||||
*
|
||||
* SQL data types. If there are missing values, please report them:
|
||||
*
|
||||
* @link http://trac.kohanaphp.com/newticket
|
||||
* @link http://dev.kohanaphp.com/projects/kohana2
|
||||
*/
|
||||
$config = array
|
||||
(
|
||||
'tinyint' => array('type' => 'int', 'max' => 127),
|
||||
'smallint' => array('type' => 'int', 'max' => 32767),
|
||||
'mediumint' => array('type' => 'int', 'max' => 8388607),
|
||||
'int' => array('type' => 'int', 'max' => 2147483647),
|
||||
'integer' => array('type' => 'int', 'max' => 2147483647),
|
||||
'bigint' => array('type' => 'int', 'max' => 9223372036854775807),
|
||||
'float' => array('type' => 'float'),
|
||||
'float unsigned' => array('type' => 'float', 'min' => 0),
|
||||
'boolean' => array('type' => 'boolean'),
|
||||
'time' => array('type' => 'string', 'format' => '00:00:00'),
|
||||
'time with time zone' => array('type' => 'string'),
|
||||
'date' => array('type' => 'string', 'format' => '0000-00-00'),
|
||||
'year' => array('type' => 'string', 'format' => '0000'),
|
||||
'datetime' => array('type' => 'string', 'format' => '0000-00-00 00:00:00'),
|
||||
// SQL-92
|
||||
'bit' => array('type' => 'string', 'exact' => TRUE),
|
||||
'bit varying' => array('type' => 'string'),
|
||||
'character' => array('type' => 'string', 'exact' => TRUE),
|
||||
'character varying' => array('type' => 'string'),
|
||||
'date' => array('type' => 'string'),
|
||||
'decimal' => array('type' => 'float', 'exact' => TRUE),
|
||||
'double precision' => array('type' => 'float'),
|
||||
'float' => array('type' => 'float'),
|
||||
'integer' => array('type' => 'int', 'min' => -2147483648, 'max' => 2147483647),
|
||||
'interval' => array('type' => 'string'),
|
||||
'national character' => array('type' => 'string', 'exact' => TRUE),
|
||||
'national character varying' => array('type' => 'string'),
|
||||
'numeric' => array('type' => 'float', 'exact' => TRUE),
|
||||
'real' => array('type' => 'float'),
|
||||
'smallint' => array('type' => 'int', 'min' => -32768, 'max' => 32767),
|
||||
'time' => array('type' => 'string'),
|
||||
'time with time zone' => array('type' => 'string'),
|
||||
'timestamp' => array('type' => 'string'),
|
||||
'timestamp with time zone' => array('type' => 'string'),
|
||||
'char' => array('type' => 'string', 'exact' => TRUE),
|
||||
'binary' => array('type' => 'string', 'binary' => TRUE, 'exact' => TRUE),
|
||||
'varchar' => array('type' => 'string'),
|
||||
'varbinary' => array('type' => 'string', 'binary' => TRUE),
|
||||
'blob' => array('type' => 'string', 'binary' => TRUE),
|
||||
'text' => array('type' => 'string')
|
||||
|
||||
// SQL:1999
|
||||
//'array','ref','row'
|
||||
'binary large object' => array('type' => 'string', 'binary' => TRUE),
|
||||
'boolean' => array('type' => 'boolean'),
|
||||
'character large object' => array('type' => 'string'),
|
||||
'national character large object' => array('type' => 'string'),
|
||||
|
||||
// SQL:2003
|
||||
'bigint' => array('type' => 'int', 'min' => -9223372036854775808, 'max' => 9223372036854775807),
|
||||
|
||||
// SQL:2008
|
||||
'binary' => array('type' => 'string', 'binary' => TRUE, 'exact' => TRUE),
|
||||
'binary varying' => array('type' => 'string', 'binary' => TRUE),
|
||||
|
||||
// MySQL
|
||||
'bigint unsigned' => array('type' => 'int', 'min' => 0, 'max' => 18446744073709551615),
|
||||
'decimal unsigned' => array('type' => 'float', 'exact' => TRUE, 'min' => 0.0),
|
||||
'double unsigned' => array('type' => 'float', 'min' => 0.0),
|
||||
'float unsigned' => array('type' => 'float', 'min' => 0.0),
|
||||
'integer unsigned' => array('type' => 'int', 'min' => 0, 'max' => 4294967295),
|
||||
'mediumint' => array('type' => 'int', 'min' => -8388608, 'max' => 8388607),
|
||||
'mediumint unsigned' => array('type' => 'int', 'min' => 0, 'max' => 16777215),
|
||||
'real unsigned' => array('type' => 'float', 'min' => 0.0),
|
||||
'smallint unsigned' => array('type' => 'int', 'min' => 0, 'max' => 65535),
|
||||
'text' => array('type' => 'string'),
|
||||
'tinyint' => array('type' => 'int', 'min' => -128, 'max' => 127),
|
||||
'tinyint unsigned' => array('type' => 'int', 'min' => 0, 'max' => 255),
|
||||
'year' => array('type' => 'string'),
|
||||
);
|
||||
|
||||
// DOUBLE
|
||||
$config['double'] = $config['double precision'] = $config['decimal'] = $config['real'] = $config['numeric'] = $config['float'];
|
||||
$config['double unsigned'] = $config['float unsigned'];
|
||||
// SQL-92
|
||||
$config['char'] = $config['character'];
|
||||
$config['char varying'] = $config['character varying'];
|
||||
$config['dec'] = $config['decimal'];
|
||||
$config['int'] = $config['integer'];
|
||||
$config['nchar'] = $config['national char'] = $config['national character'];
|
||||
$config['nchar varying'] = $config['national char varying'] = $config['national character varying'];
|
||||
$config['varchar'] = $config['character varying'];
|
||||
|
||||
// BIT
|
||||
$config['bit'] = $config['boolean'];
|
||||
|
||||
// TIMESTAMP
|
||||
$config['timestamp'] = $config['timestamp without time zone'] = $config['datetime'];
|
||||
|
||||
// ENUM
|
||||
$config['enum'] = $config['set'] = $config['varchar'];
|
||||
|
||||
// TEXT
|
||||
$config['tinytext'] = $config['mediumtext'] = $config['longtext'] = $config['text'];
|
||||
|
||||
// BLOB
|
||||
$config['tsvector'] = $config['tinyblob'] = $config['mediumblob'] = $config['longblob'] = $config['clob'] = $config['bytea'] = $config['blob'];
|
||||
|
||||
// CHARACTER
|
||||
$config['character'] = $config['char'];
|
||||
$config['character varying'] = $config['varchar'];
|
||||
|
||||
// TIME
|
||||
// SQL:1999
|
||||
$config['blob'] = $config['binary large object'];
|
||||
$config['clob'] = $config['char large object'] = $config['character large object'];
|
||||
$config['nclob'] = $config['nchar large object'] = $config['national character large object'];
|
||||
$config['time without time zone'] = $config['time'];
|
||||
$config['timestamp without time zone'] = $config['timestamp'];
|
||||
|
||||
// SQL:2008
|
||||
$config['varbinary'] = $config['binary varying'];
|
||||
|
||||
// MySQL
|
||||
$config['bool'] = $config['boolean'];
|
||||
$config['datetime'] = $config['timestamp'];
|
||||
$config['double'] = $config['double precision'];
|
||||
$config['double precision unsigned'] = $config['double unsigned'];
|
||||
$config['enum'] = $config['set'] = $config['character varying'];
|
||||
$config['fixed'] = $config['decimal'];
|
||||
$config['fixed unsigned'] = $config['decimal unsigned'];
|
||||
$config['int unsigned'] = $config['integer unsigned'];
|
||||
$config['longblob'] = $config['mediumblob'] = $config['tinyblob'] = $config['binary large object'];
|
||||
$config['longtext'] = $config['mediumtext'] = $config['tinytext'] = $config['text'];
|
||||
$config['numeric unsigned'] = $config['decimal unsigned'];
|
||||
$config['nvarchar'] = $config['national varchar'] = $config['national character varying'];
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @package Core
|
||||
*
|
||||
* Allowed non-php view types. Most file extensions are supported.
|
||||
* Do not forget to add a valid MIME type in mimes.php
|
||||
*/
|
||||
$config['allowed_filetypes'] = array
|
||||
(
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
* To use it, declare your controller to extend this class:
|
||||
* `class Your_Controller extends Template_Controller`
|
||||
*
|
||||
* $Id: template.php 3769 2008-12-15 00:48:56Z zombor $
|
||||
* $Id: template.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
abstract class Template_Controller extends Controller {
|
||||
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
/**
|
||||
* Simple benchmarking.
|
||||
*
|
||||
* $Id: Benchmark.php 4149 2009-04-01 13:32:50Z Shadowhand $
|
||||
* $Id: Benchmark.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
final class Benchmark {
|
||||
|
||||
@@ -22,6 +22,9 @@ final class Benchmark {
|
||||
*/
|
||||
public static function start($name)
|
||||
{
|
||||
if (isset(self::$marks[$name]) AND self::$marks[$name][0]['stop'] === FALSE)
|
||||
throw new Kohana_Exception('A benchmark named :name is already running.', array(':name' => $name));
|
||||
|
||||
if ( ! isset(self::$marks[$name]))
|
||||
{
|
||||
self::$marks[$name] = array();
|
||||
|
||||
@@ -4,21 +4,21 @@
|
||||
* to be added to 'events'. Events can be run multiple times, and can also
|
||||
* process event-specific data. By default, Kohana has several system events.
|
||||
*
|
||||
* $Id: Event.php 4390 2009-06-04 03:05:36Z zombor $
|
||||
* $Id: Event.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
* @link http://docs.kohanaphp.com/general/events
|
||||
*/
|
||||
final class Event {
|
||||
abstract class Event_Core {
|
||||
|
||||
// Event callbacks
|
||||
private static $events = array();
|
||||
protected static $events = array();
|
||||
|
||||
// Cache of events that have been run
|
||||
private static $has_run = array();
|
||||
protected static $has_run = array();
|
||||
|
||||
// Data that can be processed during events
|
||||
public static $data;
|
||||
@@ -26,25 +26,26 @@ final class Event {
|
||||
/**
|
||||
* Add a callback to an event queue.
|
||||
*
|
||||
* @param string event name
|
||||
* @param array http://php.net/callback
|
||||
* @param string event name
|
||||
* @param array http://php.net/callback
|
||||
* @param boolean prevent duplicates
|
||||
* @return boolean
|
||||
*/
|
||||
public static function add($name, $callback)
|
||||
public static function add($name, $callback, $unique = FALSE)
|
||||
{
|
||||
if ( ! isset(self::$events[$name]))
|
||||
if ( ! isset(Event::$events[$name]))
|
||||
{
|
||||
// Create an empty event if it is not yet defined
|
||||
self::$events[$name] = array();
|
||||
Event::$events[$name] = array();
|
||||
}
|
||||
elseif (in_array($callback, self::$events[$name], TRUE))
|
||||
elseif ($unique AND in_array($callback, Event::$events[$name], TRUE))
|
||||
{
|
||||
// The event already exists
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Add the event
|
||||
self::$events[$name][] = $callback;
|
||||
Event::$events[$name][] = $callback;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -59,15 +60,15 @@ final class Event {
|
||||
*/
|
||||
public static function add_before($name, $existing, $callback)
|
||||
{
|
||||
if (empty(self::$events[$name]) OR ($key = array_search($existing, self::$events[$name])) === FALSE)
|
||||
if (empty(Event::$events[$name]) OR ($key = array_search($existing, Event::$events[$name])) === FALSE)
|
||||
{
|
||||
// Just add the event if there are no events
|
||||
return self::add($name, $callback);
|
||||
return Event::add($name, $callback);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Insert the event immediately before the existing event
|
||||
return self::insert_event($name, $key, $callback);
|
||||
return Event::insert_event($name, $key, $callback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,15 +82,15 @@ final class Event {
|
||||
*/
|
||||
public static function add_after($name, $existing, $callback)
|
||||
{
|
||||
if (empty(self::$events[$name]) OR ($key = array_search($existing, self::$events[$name])) === FALSE)
|
||||
if (empty(Event::$events[$name]) OR ($key = array_search($existing, Event::$events[$name])) === FALSE)
|
||||
{
|
||||
// Just add the event if there are no events
|
||||
return self::add($name, $callback);
|
||||
return Event::add($name, $callback);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Insert the event immediately after the existing event
|
||||
return self::insert_event($name, $key + 1, $callback);
|
||||
return Event::insert_event($name, $key + 1, $callback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,18 +104,18 @@ final class Event {
|
||||
*/
|
||||
private static function insert_event($name, $key, $callback)
|
||||
{
|
||||
if (in_array($callback, self::$events[$name], TRUE))
|
||||
if (in_array($callback, Event::$events[$name], TRUE))
|
||||
return FALSE;
|
||||
|
||||
// Add the new event at the given key location
|
||||
self::$events[$name] = array_merge
|
||||
Event::$events[$name] = array_merge
|
||||
(
|
||||
// Events before the key
|
||||
array_slice(self::$events[$name], 0, $key),
|
||||
array_slice(Event::$events[$name], 0, $key),
|
||||
// New event callback
|
||||
array($callback),
|
||||
// Events after the key
|
||||
array_slice(self::$events[$name], $key)
|
||||
array_slice(Event::$events[$name], $key)
|
||||
);
|
||||
|
||||
return TRUE;
|
||||
@@ -130,21 +131,21 @@ final class Event {
|
||||
*/
|
||||
public static function replace($name, $existing, $callback)
|
||||
{
|
||||
if (empty(self::$events[$name]) OR ($key = array_search($existing, self::$events[$name], TRUE)) === FALSE)
|
||||
if (empty(Event::$events[$name]) OR ($key = array_search($existing, Event::$events[$name], TRUE)) === FALSE)
|
||||
return FALSE;
|
||||
|
||||
if ( ! in_array($callback, self::$events[$name], TRUE))
|
||||
if ( ! in_array($callback, Event::$events[$name], TRUE))
|
||||
{
|
||||
// Replace the exisiting event with the new event
|
||||
self::$events[$name][$key] = $callback;
|
||||
Event::$events[$name][$key] = $callback;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove the existing event from the queue
|
||||
unset(self::$events[$name][$key]);
|
||||
unset(Event::$events[$name][$key]);
|
||||
|
||||
// Reset the array so the keys are ordered properly
|
||||
self::$events[$name] = array_values(self::$events[$name]);
|
||||
Event::$events[$name] = array_values(Event::$events[$name]);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@@ -158,7 +159,7 @@ final class Event {
|
||||
*/
|
||||
public static function get($name)
|
||||
{
|
||||
return empty(self::$events[$name]) ? array() : self::$events[$name];
|
||||
return empty(Event::$events[$name]) ? array() : Event::$events[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,18 +173,18 @@ final class Event {
|
||||
{
|
||||
if ($callback === FALSE)
|
||||
{
|
||||
self::$events[$name] = array();
|
||||
Event::$events[$name] = array();
|
||||
}
|
||||
elseif (isset(self::$events[$name]))
|
||||
elseif (isset(Event::$events[$name]))
|
||||
{
|
||||
// Loop through each of the event callbacks and compare it to the
|
||||
// callback requested for removal. The callback is removed if it
|
||||
// matches.
|
||||
foreach (self::$events[$name] as $i => $event_callback)
|
||||
foreach (Event::$events[$name] as $i => $event_callback)
|
||||
{
|
||||
if ($callback === $event_callback)
|
||||
{
|
||||
unset(self::$events[$name][$i]);
|
||||
unset(Event::$events[$name][$i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -198,24 +199,24 @@ final class Event {
|
||||
*/
|
||||
public static function run($name, & $data = NULL)
|
||||
{
|
||||
if ( ! empty(self::$events[$name]))
|
||||
if ( ! empty(Event::$events[$name]))
|
||||
{
|
||||
// So callbacks can access Event::$data
|
||||
self::$data =& $data;
|
||||
$callbacks = self::get($name);
|
||||
Event::$data =& $data;
|
||||
$callbacks = Event::get($name);
|
||||
|
||||
foreach ($callbacks as $callback)
|
||||
{
|
||||
call_user_func($callback);
|
||||
call_user_func_array($callback, array(&$data));
|
||||
}
|
||||
|
||||
// Do this to prevent data from getting 'stuck'
|
||||
$clear_data = '';
|
||||
self::$data =& $clear_data;
|
||||
Event::$data =& $clear_data;
|
||||
}
|
||||
|
||||
// The event has been run!
|
||||
self::$has_run[$name] = $name;
|
||||
Event::$has_run[$name] = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -226,7 +227,7 @@ final class Event {
|
||||
*/
|
||||
public static function has_run($name)
|
||||
{
|
||||
return isset(self::$has_run[$name]);
|
||||
return isset(Event::$has_run[$name]);
|
||||
}
|
||||
|
||||
} // End Event
|
||||
File diff suppressed because it is too large
Load Diff
331
system/core/Kohana_Config.php
Normal file
331
system/core/Kohana_Config.php
Normal file
@@ -0,0 +1,331 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Provides a driver-based interface for setting and getting
|
||||
* configuration options for the Kohana environment
|
||||
*
|
||||
* $Id: Kohana_Config.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package KohanaConfig
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Kohana_Config_Core implements ArrayAccess {
|
||||
|
||||
/**
|
||||
* The default Kohana_Config driver
|
||||
* to use for system setup
|
||||
*
|
||||
* @var string
|
||||
* @static
|
||||
*/
|
||||
public static $default_driver = 'array';
|
||||
|
||||
/**
|
||||
* Kohana_Config instance
|
||||
*
|
||||
* @var array
|
||||
* @static
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
/**
|
||||
* Returns a new instance of the Kohana_Config library
|
||||
* based on the singleton pattern
|
||||
*
|
||||
* @param string driver
|
||||
* @return Kohana_Config
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
public static function & instance()
|
||||
{
|
||||
// If the driver has not been initialised, intialise it
|
||||
if ( empty(Kohana_Config::$instance))
|
||||
{
|
||||
//call a 1 time non singleton of Kohana_Config to get a list of drivers
|
||||
$config = new Kohana_Config(array(
|
||||
'config_drivers'=>array(
|
||||
), 'internal_cache'=>FALSE
|
||||
));
|
||||
$core_config = $config->get('core');
|
||||
Kohana_Config::$instance = new Kohana_Config($core_config);
|
||||
}
|
||||
|
||||
// Return the Kohana_Config driver requested
|
||||
return Kohana_Config::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* The drivers for this object
|
||||
*
|
||||
* @var Kohana_Config_Driver
|
||||
*/
|
||||
protected $drivers;
|
||||
|
||||
/**
|
||||
* Kohana_Config constructor to load the supplied driver.
|
||||
* Enforces the singleton pattern.
|
||||
*
|
||||
* @param string driver
|
||||
* @access protected
|
||||
*/
|
||||
protected function __construct(array $core_config)
|
||||
{
|
||||
$drivers = $core_config['config_drivers'];
|
||||
|
||||
//remove array if it's found in config
|
||||
if (in_array('array', $drivers))
|
||||
unset($drivers[array_search('array', $drivers)]);
|
||||
|
||||
//add array at the very end
|
||||
$this->drivers = $drivers = array_merge($drivers, array(
|
||||
'array'
|
||||
));
|
||||
|
||||
foreach ($this->drivers as & $driver)
|
||||
{
|
||||
// Create the driver name
|
||||
$driver = 'Config_'.ucfirst($driver).'_Driver';
|
||||
|
||||
// Ensure the driver loads correctly
|
||||
if (!Kohana::auto_load($driver))
|
||||
throw new Kohana_Exception('The :driver: driver for the :library: library could not be found.', array(
|
||||
':driver:' => $driver, ':library:' => get_class($this)
|
||||
));
|
||||
|
||||
// Load the new driver
|
||||
$driver = new $driver($core_config);
|
||||
|
||||
// Ensure the new driver is valid
|
||||
if (!$driver instanceof Config_Driver)
|
||||
throw new Kohana_Exception('The :driver: driver for the :library: library must implement the :interface: interface', array(
|
||||
':driver:' => $driver, ':library:' => get_class($this), ':interface:' => 'Config_Driver'
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a value from the configuration driver
|
||||
*
|
||||
* @param string key
|
||||
* @param bool slash
|
||||
* @param bool required
|
||||
* @return mixed
|
||||
* @access public
|
||||
*/
|
||||
public function get($key, $slash = FALSE, $required = FALSE)
|
||||
{
|
||||
foreach ($this->drivers as $driver)
|
||||
{
|
||||
try
|
||||
{
|
||||
return $driver->get($key, $slash, $required);
|
||||
}
|
||||
catch (Kohana_Config_Exception $e)
|
||||
{
|
||||
//if it's the last driver in the list and it threw an exception, re throw it
|
||||
if ($driver === $this->drivers[(count($this->drivers) - 1)])
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a value to the configuration drivers
|
||||
*
|
||||
* @param string key
|
||||
* @param mixed value
|
||||
* @return bool
|
||||
* @access public
|
||||
*/
|
||||
public function set($key, $value)
|
||||
{
|
||||
foreach ($this->drivers as $driver)
|
||||
{
|
||||
try
|
||||
{
|
||||
$driver->set($key, $value);
|
||||
}
|
||||
catch (Kohana_Config_Exception $e)
|
||||
{
|
||||
//if it's the last driver in the list and it threw an exception, re throw it
|
||||
if ($driver === $this->drivers[(count($this->drivers) - 1)])
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears a group from configuration
|
||||
*
|
||||
* @param string group
|
||||
* @return bool
|
||||
* @access public
|
||||
*/
|
||||
public function clear($group)
|
||||
{
|
||||
foreach ($this->drivers as $driver)
|
||||
{
|
||||
try
|
||||
{
|
||||
$driver->clear($group);
|
||||
}
|
||||
catch (Kohana_Config_Exception $e)
|
||||
{
|
||||
//if it's the last driver in the list and it threw an exception, re throw it
|
||||
if ($driver === $this->drivers[(count($this->drivers) - 1)])
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a configuration group
|
||||
*
|
||||
* @param string group
|
||||
* @param bool required
|
||||
* @return array
|
||||
* @access public
|
||||
*/
|
||||
public function load($group, $required = FALSE)
|
||||
{
|
||||
foreach ($this->drivers as $driver)
|
||||
{
|
||||
try
|
||||
{
|
||||
return $driver->load($group, $required);
|
||||
}
|
||||
catch (Kohana_Config_Exception $e)
|
||||
{
|
||||
//if it's the last driver in the list and it threw an exception, re throw it
|
||||
if ($driver === $this->drivers[(count($this->drivers) - 1)])
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true or false if any config has been loaded(either manually or from cache)
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function loaded()
|
||||
{
|
||||
return $this->drivers[(count($this->drivers) - 1)]->loaded;
|
||||
}
|
||||
|
||||
/**
|
||||
* The following allows access using
|
||||
* array syntax.
|
||||
*
|
||||
* @example $config['core.site_domain']
|
||||
*/
|
||||
|
||||
/**
|
||||
* Allows access to configuration settings
|
||||
* using the ArrayAccess interface
|
||||
*
|
||||
* @param string key
|
||||
* @return mixed
|
||||
* @access public
|
||||
*/
|
||||
public function offsetGet($key)
|
||||
{
|
||||
foreach ($this->drivers as $driver)
|
||||
{
|
||||
try
|
||||
{
|
||||
return $driver->get($key);
|
||||
}
|
||||
catch (Kohana_Config_Exception $e)
|
||||
{
|
||||
//if it's the last driver in the list and it threw an exception, re throw it
|
||||
if ($driver === $this->drivers[(count($this->drivers) - 1)])
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows access to configuration settings
|
||||
* using the ArrayAccess interface
|
||||
*
|
||||
* @param string key
|
||||
* @param mixed value
|
||||
* @return bool
|
||||
* @access public
|
||||
*/
|
||||
public function offsetSet($key, $value)
|
||||
{
|
||||
foreach ($this->drivers as $driver)
|
||||
{
|
||||
try
|
||||
{
|
||||
$driver->set($key, $value);
|
||||
}
|
||||
catch (Kohana_Config_Exception $e)
|
||||
{
|
||||
//if it's the last driver in the list and it threw an exception, re throw it
|
||||
if ($driver === $this->drivers[(count($this->drivers) - 1)])
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows access to configuration settings
|
||||
* using the ArrayAccess interface
|
||||
*
|
||||
* @param string key
|
||||
* @return bool
|
||||
* @access public
|
||||
*/
|
||||
public function offsetExists($key)
|
||||
{
|
||||
foreach ($this->drivers as $driver)
|
||||
{
|
||||
try
|
||||
{
|
||||
return $driver->setting_exists($key);
|
||||
}
|
||||
catch (Kohana_Config_Exception $e)
|
||||
{
|
||||
//if it's the last driver in the list and it threw an exception, re throw it
|
||||
if ($driver === $this->drivers[(count($this->drivers) - 1)])
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows access to configuration settings
|
||||
* using the ArrayAccess interface
|
||||
*
|
||||
* @param string key
|
||||
* @return bool
|
||||
* @access public
|
||||
*/
|
||||
public function offsetUnset($key)
|
||||
{
|
||||
foreach ($this->drivers as $driver)
|
||||
{
|
||||
try
|
||||
{
|
||||
return $driver->set($key, NULL);
|
||||
}
|
||||
catch (Kohana_Config_Exception $e)
|
||||
{
|
||||
//if it's the last driver in the list and it threw an exception, re throw it
|
||||
if ($driver === $this->drivers[(count($this->drivers) - 1)])
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
} // End KohanaConfig
|
||||
|
||||
class Kohana_Config_Exception extends Kohana_Exception {}
|
||||
619
system/core/Kohana_Exception.php
Normal file
619
system/core/Kohana_Exception.php
Normal file
@@ -0,0 +1,619 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* Kohana Exceptions
|
||||
*
|
||||
* $Id: Kohana_Exception.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
|
||||
class Kohana_Exception_Core extends Exception {
|
||||
|
||||
public static $enabled = FALSE;
|
||||
|
||||
// Template file
|
||||
public static $template = 'kohana/error';
|
||||
|
||||
// Show stack traces in errors
|
||||
public static $trace_output = TRUE;
|
||||
|
||||
// Show source code in errors
|
||||
public static $source_output = TRUE;
|
||||
|
||||
// To hold unique identifier to distinguish error output
|
||||
protected $instance_identifier;
|
||||
|
||||
// Error code
|
||||
protected $code = E_KOHANA;
|
||||
|
||||
/**
|
||||
* Creates a new translated exception.
|
||||
*
|
||||
* @param string error message
|
||||
* @param array translation variables
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($message, array $variables = NULL, $code = 0)
|
||||
{
|
||||
$this->instance_identifier = uniqid();
|
||||
|
||||
// Translate the error message
|
||||
$message = __($message, $variables);
|
||||
|
||||
// Sets $this->message the proper way
|
||||
parent::__construct($message, $code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable Kohana exception handling.
|
||||
*
|
||||
* @uses Kohana_Exception::$template
|
||||
* @return void
|
||||
*/
|
||||
public static function enable()
|
||||
{
|
||||
if ( ! Kohana_Exception::$enabled)
|
||||
{
|
||||
set_exception_handler(array('Kohana_Exception', 'handle'));
|
||||
|
||||
Kohana_Exception::$enabled = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable Kohana exception handling.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function disable()
|
||||
{
|
||||
if (Kohana_Exception::$enabled)
|
||||
{
|
||||
restore_exception_handler();
|
||||
|
||||
Kohana_Exception::$enabled = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a single line of text representing the exception:
|
||||
*
|
||||
* Error [ Code ]: Message ~ File [ Line ]
|
||||
*
|
||||
* @param object Exception
|
||||
* @return string
|
||||
*/
|
||||
public static function text($e)
|
||||
{
|
||||
return sprintf('%s [ %s ]: %s ~ %s [ %d ]',
|
||||
get_class($e), $e->getCode(), strip_tags($e->getMessage()), Kohana_Exception::debug_path($e->getFile()), $e->getLine());
|
||||
}
|
||||
|
||||
/**
|
||||
* exception handler, displays the error message, source of the
|
||||
* exception, and the stack trace of the error.
|
||||
*
|
||||
* @uses Kohana::message()
|
||||
* @uses Kohana_Exception::text()
|
||||
* @param object exception object
|
||||
* @return void
|
||||
*/
|
||||
public static function handle(Exception $e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get the exception information
|
||||
$type = get_class($e);
|
||||
$code = $e->getCode();
|
||||
$message = $e->getMessage();
|
||||
|
||||
// Create a text version of the exception
|
||||
$error = Kohana_Exception::text($e);
|
||||
|
||||
// Add this exception to the log
|
||||
Kohana_Log::add('error', $error);
|
||||
|
||||
// Manually save logs after exceptions
|
||||
Kohana_Log::save();
|
||||
|
||||
if (Kohana::config('core.display_errors') === FALSE)
|
||||
{
|
||||
// Do not show the details
|
||||
$file = $line = NULL;
|
||||
$trace = array();
|
||||
|
||||
$template = '_disabled';
|
||||
}
|
||||
else
|
||||
{
|
||||
$file = $e->getFile();
|
||||
$line = $e->getLine();
|
||||
$trace = $e->getTrace();
|
||||
|
||||
$template = '';
|
||||
}
|
||||
|
||||
if ($e instanceof Kohana_Exception)
|
||||
{
|
||||
$template = $e->getTemplate().$template;
|
||||
|
||||
if ( ! headers_sent())
|
||||
{
|
||||
$e->sendHeaders();
|
||||
}
|
||||
|
||||
// Use the human-readable error name
|
||||
$code = Kohana::message('core.errors.'.$code);
|
||||
}
|
||||
else
|
||||
{
|
||||
$template = Kohana_Exception::$template.$template;
|
||||
|
||||
if ( ! headers_sent())
|
||||
{
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
|
||||
if ($e instanceof ErrorException)
|
||||
{
|
||||
// Use the human-readable error name
|
||||
$code = Kohana::message('core.errors.'.$e->getSeverity());
|
||||
|
||||
if (version_compare(PHP_VERSION, '5.3', '<'))
|
||||
{
|
||||
// Workaround for a bug in ErrorException::getTrace() that exists in
|
||||
// all PHP 5.2 versions. @see http://bugs.php.net/45895
|
||||
for ($i = count($trace) - 1; $i > 0; --$i)
|
||||
{
|
||||
if (isset($trace[$i - 1]['args']))
|
||||
{
|
||||
// Re-position the arguments
|
||||
$trace[$i]['args'] = $trace[$i - 1]['args'];
|
||||
|
||||
unset($trace[$i - 1]['args']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clean the output buffer if one exists
|
||||
ob_get_level() and ob_clean();
|
||||
|
||||
if ($template = Kohana::find_file('views', $template))
|
||||
{
|
||||
include $template;
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
// Clean the output buffer if one exists
|
||||
ob_get_level() and ob_clean();
|
||||
|
||||
// Display the exception text
|
||||
echo Kohana_Exception::text($e), "\n";
|
||||
}
|
||||
|
||||
if (PHP_SAPI === 'cli')
|
||||
{
|
||||
// Exit with an error status
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the template for this exception.
|
||||
*
|
||||
* @uses Kohana_Exception::$template
|
||||
* @return string
|
||||
*/
|
||||
public function getTemplate()
|
||||
{
|
||||
return Kohana_Exception::$template;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an Internal Server Error header.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function sendHeaders()
|
||||
{
|
||||
// Send the 500 header
|
||||
header('HTTP/1.1 500 Internal Server Error');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an HTML string of information about a single variable.
|
||||
*
|
||||
* Borrows heavily on concepts from the Debug class of {@link http://nettephp.com/ Nette}.
|
||||
*
|
||||
* @param mixed variable to dump
|
||||
* @param integer maximum length of strings
|
||||
* @return string
|
||||
*/
|
||||
public static function dump($value, $length = 128)
|
||||
{
|
||||
return Kohana_Exception::_dump($value, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for Kohana_Exception::dump(), handles recursion in arrays and objects.
|
||||
*
|
||||
* @param mixed variable to dump
|
||||
* @param integer maximum length of strings
|
||||
* @param integer recursion level (internal)
|
||||
* @return string
|
||||
*/
|
||||
private static function _dump( & $var, $length = 128, $level = 0)
|
||||
{
|
||||
if ($var === NULL)
|
||||
{
|
||||
return '<small>NULL</small>';
|
||||
}
|
||||
elseif (is_bool($var))
|
||||
{
|
||||
return '<small>bool</small> '.($var ? 'TRUE' : 'FALSE');
|
||||
}
|
||||
elseif (is_float($var))
|
||||
{
|
||||
return '<small>float</small> '.$var;
|
||||
}
|
||||
elseif (is_resource($var))
|
||||
{
|
||||
if (($type = get_resource_type($var)) === 'stream' AND $meta = stream_get_meta_data($var))
|
||||
{
|
||||
$meta = stream_get_meta_data($var);
|
||||
|
||||
if (isset($meta['uri']))
|
||||
{
|
||||
$file = $meta['uri'];
|
||||
|
||||
if (function_exists('stream_is_local'))
|
||||
{
|
||||
// Only exists on PHP >= 5.2.4
|
||||
if (stream_is_local($file))
|
||||
{
|
||||
$file = Kohana_Exception::debug_path($file);
|
||||
}
|
||||
}
|
||||
|
||||
return '<small>resource</small><span>('.$type.')</span> '.htmlspecialchars($file, ENT_NOQUOTES, Kohana::CHARSET);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return '<small>resource</small><span>('.$type.')</span>';
|
||||
}
|
||||
}
|
||||
elseif (is_string($var))
|
||||
{
|
||||
if (strlen($var) > $length)
|
||||
{
|
||||
// Encode the truncated string
|
||||
$str = htmlspecialchars(substr($var, 0, $length), ENT_NOQUOTES, Kohana::CHARSET).' …';
|
||||
}
|
||||
else
|
||||
{
|
||||
// Encode the string
|
||||
$str = htmlspecialchars($var, ENT_NOQUOTES, Kohana::CHARSET);
|
||||
}
|
||||
|
||||
return '<small>string</small><span>('.strlen($var).')</span> "'.$str.'"';
|
||||
}
|
||||
elseif (is_array($var))
|
||||
{
|
||||
$output = array();
|
||||
|
||||
// Indentation for this variable
|
||||
$space = str_repeat($s = ' ', $level);
|
||||
|
||||
static $marker;
|
||||
|
||||
if ($marker === NULL)
|
||||
{
|
||||
// Make a unique marker
|
||||
$marker = uniqid("\x00");
|
||||
}
|
||||
|
||||
if (empty($var))
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
elseif (isset($var[$marker]))
|
||||
{
|
||||
$output[] = "(\n$space$s*RECURSION*\n$space)";
|
||||
}
|
||||
elseif ($level < 5)
|
||||
{
|
||||
$output[] = "<span>(";
|
||||
|
||||
$var[$marker] = TRUE;
|
||||
foreach ($var as $key => & $val)
|
||||
{
|
||||
if ($key === $marker) continue;
|
||||
if ( ! is_int($key))
|
||||
{
|
||||
$key = '"'.$key.'"';
|
||||
}
|
||||
|
||||
$output[] = "$space$s$key => ".Kohana_Exception::_dump($val, $length, $level + 1);
|
||||
}
|
||||
unset($var[$marker]);
|
||||
|
||||
$output[] = "$space)</span>";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Depth too great
|
||||
$output[] = "(\n$space$s...\n$space)";
|
||||
}
|
||||
|
||||
return '<small>array</small><span>('.count($var).')</span> '.implode("\n", $output);
|
||||
}
|
||||
elseif (is_object($var))
|
||||
{
|
||||
// Copy the object as an array
|
||||
$array = (array) $var;
|
||||
|
||||
$output = array();
|
||||
|
||||
// Indentation for this variable
|
||||
$space = str_repeat($s = ' ', $level);
|
||||
|
||||
$hash = spl_object_hash($var);
|
||||
|
||||
// Objects that are being dumped
|
||||
static $objects = array();
|
||||
|
||||
if (empty($var))
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
elseif (isset($objects[$hash]))
|
||||
{
|
||||
$output[] = "{\n$space$s*RECURSION*\n$space}";
|
||||
}
|
||||
elseif ($level < 5)
|
||||
{
|
||||
$output[] = "<code>{";
|
||||
|
||||
$objects[$hash] = TRUE;
|
||||
foreach ($array as $key => & $val)
|
||||
{
|
||||
if ($key[0] === "\x00")
|
||||
{
|
||||
// Determine if the access is private or protected
|
||||
$access = '<small>'.($key[1] === '*' ? 'protected' : 'private').'</small>';
|
||||
|
||||
// Remove the access level from the variable name
|
||||
$key = substr($key, strrpos($key, "\x00") + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
$access = '<small>public</small>';
|
||||
}
|
||||
|
||||
$output[] = "$space$s$access $key => ".Kohana_Exception::_dump($val, $length, $level + 1);
|
||||
}
|
||||
unset($objects[$hash]);
|
||||
|
||||
$output[] = "$space}</code>";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Depth too great
|
||||
$output[] = "{\n$space$s...\n$space}";
|
||||
}
|
||||
|
||||
return '<small>object</small> <span>'.get_class($var).'('.count($array).')</span> '.implode("\n", $output);
|
||||
}
|
||||
else
|
||||
{
|
||||
return '<small>'.gettype($var).'</small> '.htmlspecialchars(print_r($var, TRUE), ENT_NOQUOTES, Kohana::CHARSET);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes APPPATH, SYSPATH, MODPATH, and DOCROOT from filenames, replacing
|
||||
* them with the plain text equivalents.
|
||||
*
|
||||
* @param string path to sanitize
|
||||
* @return string
|
||||
*/
|
||||
public static function debug_path($file)
|
||||
{
|
||||
if (strpos($file, APPPATH) === 0)
|
||||
{
|
||||
$file = 'APPPATH/'.substr($file, strlen(APPPATH));
|
||||
}
|
||||
elseif (strpos($file, SYSPATH) === 0)
|
||||
{
|
||||
$file = 'SYSPATH/'.substr($file, strlen(SYSPATH));
|
||||
}
|
||||
elseif (strpos($file, MODPATH) === 0)
|
||||
{
|
||||
$file = 'MODPATH/'.substr($file, strlen(MODPATH));
|
||||
}
|
||||
elseif (strpos($file, DOCROOT) === 0)
|
||||
{
|
||||
$file = 'DOCROOT/'.substr($file, strlen(DOCROOT));
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of lines from a file.
|
||||
*
|
||||
* // Returns the current line of the current file
|
||||
* echo Kohana_Exception::debug_source(__FILE__, __LINE__);
|
||||
*
|
||||
* @param string file to open
|
||||
* @param integer line number to find
|
||||
* @param integer number of padding lines
|
||||
* @return array
|
||||
*/
|
||||
public static function debug_source($file, $line_number, $padding = 5)
|
||||
{
|
||||
// Make sure we can read the source file
|
||||
if ( ! is_readable($file))
|
||||
return array();
|
||||
|
||||
// Open the file and set the line position
|
||||
$file = fopen($file, 'r');
|
||||
$line = 0;
|
||||
|
||||
// Set the reading range
|
||||
$range = array('start' => $line_number - $padding, 'end' => $line_number + $padding);
|
||||
|
||||
// Set the zero-padding amount for line numbers
|
||||
$format = '% '.strlen($range['end']).'d';
|
||||
|
||||
$source = array();
|
||||
while (($row = fgets($file)) !== FALSE)
|
||||
{
|
||||
// Increment the line number
|
||||
if (++$line > $range['end'])
|
||||
break;
|
||||
|
||||
if ($line >= $range['start'])
|
||||
{
|
||||
$source[sprintf($format, $line)] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
// Close the file
|
||||
fclose($file);
|
||||
|
||||
return $source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of strings that represent each step in the backtrace.
|
||||
*
|
||||
* @param array trace to analyze
|
||||
* @return array
|
||||
*/
|
||||
public static function trace($trace = NULL)
|
||||
{
|
||||
if ($trace === NULL)
|
||||
{
|
||||
// Start a new trace
|
||||
$trace = debug_backtrace();
|
||||
}
|
||||
|
||||
// Non-standard function calls
|
||||
$statements = array('include', 'include_once', 'require', 'require_once');
|
||||
|
||||
$output = array();
|
||||
foreach ($trace as $step)
|
||||
{
|
||||
if ( ! isset($step['function']))
|
||||
{
|
||||
// Invalid trace step
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($step['file']) AND isset($step['line']))
|
||||
{
|
||||
// Include the source of this step
|
||||
$source = Kohana_Exception::debug_source($step['file'], $step['line']);
|
||||
}
|
||||
|
||||
if (isset($step['file']))
|
||||
{
|
||||
$file = $step['file'];
|
||||
|
||||
if (isset($step['line']))
|
||||
{
|
||||
$line = $step['line'];
|
||||
}
|
||||
}
|
||||
|
||||
// function()
|
||||
$function = $step['function'];
|
||||
|
||||
if (in_array($step['function'], $statements))
|
||||
{
|
||||
if (empty($step['args']))
|
||||
{
|
||||
// No arguments
|
||||
$args = array();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Sanitize the file path
|
||||
$args = array($step['args'][0]);
|
||||
}
|
||||
}
|
||||
elseif (isset($step['args']))
|
||||
{
|
||||
if ($step['function'] === '{closure}')
|
||||
{
|
||||
// Introspection on closures in a stack trace is impossible
|
||||
$params = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isset($step['class']))
|
||||
{
|
||||
if (method_exists($step['class'], $step['function']))
|
||||
{
|
||||
$reflection = new ReflectionMethod($step['class'], $step['function']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$reflection = new ReflectionMethod($step['class'], '__call');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$reflection = new ReflectionFunction($step['function']);
|
||||
}
|
||||
|
||||
// Get the function parameters
|
||||
$params = $reflection->getParameters();
|
||||
}
|
||||
|
||||
$args = array();
|
||||
|
||||
foreach ($step['args'] as $i => $arg)
|
||||
{
|
||||
if (isset($params[$i]))
|
||||
{
|
||||
// Assign the argument by the parameter name
|
||||
$args[$params[$i]->name] = $arg;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assign the argument by number
|
||||
$args[$i] = $arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($step['class']))
|
||||
{
|
||||
// Class->method() or Class::method()
|
||||
$function = $step['class'].$step['type'].$step['function'];
|
||||
}
|
||||
|
||||
$output[] = array(
|
||||
'function' => $function,
|
||||
'args' => isset($args) ? $args : NULL,
|
||||
'file' => isset($file) ? $file : NULL,
|
||||
'line' => isset($line) ? $line : NULL,
|
||||
'source' => isset($source) ? $source : NULL,
|
||||
);
|
||||
|
||||
unset($function, $args, $file, $line, $source);
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
} // End Kohana Exception
|
||||
@@ -1,743 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* A port of phputf8 to a unified file/class. Checks PHP status to ensure that
|
||||
* UTF-8 support is available and normalize global variables to UTF-8. It also
|
||||
* provides multi-byte aware replacement string functions.
|
||||
*
|
||||
* This file is licensed differently from the rest of Kohana. As a port of
|
||||
* phputf8, which is LGPL software, this file is released under the LGPL.
|
||||
*
|
||||
* PCRE needs to be compiled with UTF-8 support (--enable-utf8).
|
||||
* Support for Unicode properties is highly recommended (--enable-unicode-properties).
|
||||
* @see http://php.net/manual/reference.pcre.pattern.modifiers.php
|
||||
*
|
||||
* UTF-8 conversion will be much more reliable if the iconv extension is loaded.
|
||||
* @see http://php.net/iconv
|
||||
*
|
||||
* The mbstring extension is highly recommended, but must not be overloading
|
||||
* string functions.
|
||||
* @see http://php.net/mbstring
|
||||
*
|
||||
* $Id: utf8.php 3769 2008-12-15 00:48:56Z zombor $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
|
||||
if ( ! preg_match('/^.$/u', 'ñ'))
|
||||
{
|
||||
trigger_error
|
||||
(
|
||||
'<a href="http://php.net/pcre">PCRE</a> has not been compiled with UTF-8 support. '.
|
||||
'See <a href="http://php.net/manual/reference.pcre.pattern.modifiers.php">PCRE Pattern Modifiers</a> '.
|
||||
'for more information. This application cannot be run without UTF-8 support.',
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! extension_loaded('iconv'))
|
||||
{
|
||||
trigger_error
|
||||
(
|
||||
'The <a href="http://php.net/iconv">iconv</a> extension is not loaded. '.
|
||||
'Without iconv, strings cannot be properly translated to UTF-8 from user input. '.
|
||||
'This application cannot be run without UTF-8 support.',
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
if (extension_loaded('mbstring') AND (ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING))
|
||||
{
|
||||
trigger_error
|
||||
(
|
||||
'The <a href="http://php.net/mbstring">mbstring</a> extension is overloading PHP\'s native string functions. '.
|
||||
'Disable this by setting mbstring.func_overload to 0, 1, 4 or 5 in php.ini or a .htaccess file.'.
|
||||
'This application cannot be run without UTF-8 support.',
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
// Check PCRE support for Unicode properties such as \p and \X.
|
||||
$ER = error_reporting(0);
|
||||
define('PCRE_UNICODE_PROPERTIES', (bool) preg_match('/^\pL$/u', 'ñ'));
|
||||
error_reporting($ER);
|
||||
|
||||
// SERVER_UTF8 ? use mb_* functions : use non-native functions
|
||||
if (extension_loaded('mbstring'))
|
||||
{
|
||||
mb_internal_encoding('UTF-8');
|
||||
define('SERVER_UTF8', TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
define('SERVER_UTF8', FALSE);
|
||||
}
|
||||
|
||||
// Convert all global variables to UTF-8.
|
||||
$_GET = utf8::clean($_GET);
|
||||
$_POST = utf8::clean($_POST);
|
||||
$_COOKIE = utf8::clean($_COOKIE);
|
||||
$_SERVER = utf8::clean($_SERVER);
|
||||
|
||||
if (PHP_SAPI == 'cli')
|
||||
{
|
||||
// Convert command line arguments
|
||||
$_SERVER['argv'] = utf8::clean($_SERVER['argv']);
|
||||
}
|
||||
|
||||
final class utf8 {
|
||||
|
||||
// Called methods
|
||||
static $called = array();
|
||||
|
||||
/**
|
||||
* Recursively cleans arrays, objects, and strings. Removes ASCII control
|
||||
* codes and converts to UTF-8 while silently discarding incompatible
|
||||
* UTF-8 characters.
|
||||
*
|
||||
* @param string string to clean
|
||||
* @return string
|
||||
*/
|
||||
public static function clean($str)
|
||||
{
|
||||
if (is_array($str) OR is_object($str))
|
||||
{
|
||||
foreach ($str as $key => $val)
|
||||
{
|
||||
// Recursion!
|
||||
$str[self::clean($key)] = self::clean($val);
|
||||
}
|
||||
}
|
||||
elseif (is_string($str) AND $str !== '')
|
||||
{
|
||||
// Remove control characters
|
||||
$str = self::strip_ascii_ctrl($str);
|
||||
|
||||
if ( ! self::is_ascii($str))
|
||||
{
|
||||
// Disable notices
|
||||
$ER = error_reporting(~E_NOTICE);
|
||||
|
||||
// iconv is expensive, so it is only used when needed
|
||||
$str = iconv('UTF-8', 'UTF-8//IGNORE', $str);
|
||||
|
||||
// Turn notices back on
|
||||
error_reporting($ER);
|
||||
}
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether a string contains only 7bit ASCII bytes. This is used to
|
||||
* determine when to use native functions or UTF-8 functions.
|
||||
*
|
||||
* @param string string to check
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_ascii($str)
|
||||
{
|
||||
return ! preg_match('/[^\x00-\x7F]/S', $str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips out device control codes in the ASCII range.
|
||||
*
|
||||
* @param string string to clean
|
||||
* @return string
|
||||
*/
|
||||
public static function strip_ascii_ctrl($str)
|
||||
{
|
||||
return preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S', '', $str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips out all non-7bit ASCII bytes.
|
||||
*
|
||||
* @param string string to clean
|
||||
* @return string
|
||||
*/
|
||||
public static function strip_non_ascii($str)
|
||||
{
|
||||
return preg_replace('/[^\x00-\x7F]+/S', '', $str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces special/accented UTF-8 characters by ASCII-7 'equivalents'.
|
||||
*
|
||||
* @author Andreas Gohr <andi@splitbrain.org>
|
||||
*
|
||||
* @param string string to transliterate
|
||||
* @param integer -1 lowercase only, +1 uppercase only, 0 both cases
|
||||
* @return string
|
||||
*/
|
||||
public static function transliterate_to_ascii($str, $case = 0)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _transliterate_to_ascii($str, $case);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of the given string.
|
||||
* @see http://php.net/strlen
|
||||
*
|
||||
* @param string string being measured for length
|
||||
* @return integer
|
||||
*/
|
||||
public static function strlen($str)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _strlen($str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds position of first occurrence of a UTF-8 string.
|
||||
* @see http://php.net/strlen
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string haystack
|
||||
* @param string needle
|
||||
* @param integer offset from which character in haystack to start searching
|
||||
* @return integer position of needle
|
||||
* @return boolean FALSE if the needle is not found
|
||||
*/
|
||||
public static function strpos($str, $search, $offset = 0)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _strpos($str, $search, $offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds position of last occurrence of a char in a UTF-8 string.
|
||||
* @see http://php.net/strrpos
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string haystack
|
||||
* @param string needle
|
||||
* @param integer offset from which character in haystack to start searching
|
||||
* @return integer position of needle
|
||||
* @return boolean FALSE if the needle is not found
|
||||
*/
|
||||
public static function strrpos($str, $search, $offset = 0)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _strrpos($str, $search, $offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns part of a UTF-8 string.
|
||||
* @see http://php.net/substr
|
||||
*
|
||||
* @author Chris Smith <chris@jalakai.co.uk>
|
||||
*
|
||||
* @param string input string
|
||||
* @param integer offset
|
||||
* @param integer length limit
|
||||
* @return string
|
||||
*/
|
||||
public static function substr($str, $offset, $length = NULL)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _substr($str, $offset, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces text within a portion of a UTF-8 string.
|
||||
* @see http://php.net/substr_replace
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string input string
|
||||
* @param string replacement string
|
||||
* @param integer offset
|
||||
* @return string
|
||||
*/
|
||||
public static function substr_replace($str, $replacement, $offset, $length = NULL)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _substr_replace($str, $replacement, $offset, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a UTF-8 string lowercase.
|
||||
* @see http://php.net/strtolower
|
||||
*
|
||||
* @author Andreas Gohr <andi@splitbrain.org>
|
||||
*
|
||||
* @param string mixed case string
|
||||
* @return string
|
||||
*/
|
||||
public static function strtolower($str)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _strtolower($str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a UTF-8 string uppercase.
|
||||
* @see http://php.net/strtoupper
|
||||
*
|
||||
* @author Andreas Gohr <andi@splitbrain.org>
|
||||
*
|
||||
* @param string mixed case string
|
||||
* @return string
|
||||
*/
|
||||
public static function strtoupper($str)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _strtoupper($str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a UTF-8 string's first character uppercase.
|
||||
* @see http://php.net/ucfirst
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string mixed case string
|
||||
* @return string
|
||||
*/
|
||||
public static function ucfirst($str)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _ucfirst($str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the first character of every word in a UTF-8 string uppercase.
|
||||
* @see http://php.net/ucwords
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string mixed case string
|
||||
* @return string
|
||||
*/
|
||||
public static function ucwords($str)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _ucwords($str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Case-insensitive UTF-8 string comparison.
|
||||
* @see http://php.net/strcasecmp
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string string to compare
|
||||
* @param string string to compare
|
||||
* @return integer less than 0 if str1 is less than str2
|
||||
* @return integer greater than 0 if str1 is greater than str2
|
||||
* @return integer 0 if they are equal
|
||||
*/
|
||||
public static function strcasecmp($str1, $str2)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _strcasecmp($str1, $str2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string or an array with all occurrences of search in subject (ignoring case).
|
||||
* replaced with the given replace value.
|
||||
* @see http://php.net/str_ireplace
|
||||
*
|
||||
* @note It's not fast and gets slower if $search and/or $replace are arrays.
|
||||
* @author Harry Fuecks <hfuecks@gmail.com
|
||||
*
|
||||
* @param string|array text to replace
|
||||
* @param string|array replacement text
|
||||
* @param string|array subject text
|
||||
* @param integer number of matched and replaced needles will be returned via this parameter which is passed by reference
|
||||
* @return string if the input was a string
|
||||
* @return array if the input was an array
|
||||
*/
|
||||
public static function str_ireplace($search, $replace, $str, & $count = NULL)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _str_ireplace($search, $replace, $str, $count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Case-insenstive UTF-8 version of strstr. Returns all of input string
|
||||
* from the first occurrence of needle to the end.
|
||||
* @see http://php.net/stristr
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string input string
|
||||
* @param string needle
|
||||
* @return string matched substring if found
|
||||
* @return boolean FALSE if the substring was not found
|
||||
*/
|
||||
public static function stristr($str, $search)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _stristr($str, $search);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the length of the initial segment matching mask.
|
||||
* @see http://php.net/strspn
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string input string
|
||||
* @param string mask for search
|
||||
* @param integer start position of the string to examine
|
||||
* @param integer length of the string to examine
|
||||
* @return integer length of the initial segment that contains characters in the mask
|
||||
*/
|
||||
public static function strspn($str, $mask, $offset = NULL, $length = NULL)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _strspn($str, $mask, $offset, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the length of the initial segment not matching mask.
|
||||
* @see http://php.net/strcspn
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string input string
|
||||
* @param string mask for search
|
||||
* @param integer start position of the string to examine
|
||||
* @param integer length of the string to examine
|
||||
* @return integer length of the initial segment that contains characters not in the mask
|
||||
*/
|
||||
public static function strcspn($str, $mask, $offset = NULL, $length = NULL)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _strcspn($str, $mask, $offset, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pads a UTF-8 string to a certain length with another string.
|
||||
* @see http://php.net/str_pad
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string input string
|
||||
* @param integer desired string length after padding
|
||||
* @param string string to use as padding
|
||||
* @param string padding type: STR_PAD_RIGHT, STR_PAD_LEFT, or STR_PAD_BOTH
|
||||
* @return string
|
||||
*/
|
||||
public static function str_pad($str, $final_str_length, $pad_str = ' ', $pad_type = STR_PAD_RIGHT)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _str_pad($str, $final_str_length, $pad_str, $pad_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a UTF-8 string to an array.
|
||||
* @see http://php.net/str_split
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string input string
|
||||
* @param integer maximum length of each chunk
|
||||
* @return array
|
||||
*/
|
||||
public static function str_split($str, $split_length = 1)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _str_split($str, $split_length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverses a UTF-8 string.
|
||||
* @see http://php.net/strrev
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string string to be reversed
|
||||
* @return string
|
||||
*/
|
||||
public static function strrev($str)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _strrev($str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips whitespace (or other UTF-8 characters) from the beginning and
|
||||
* end of a string.
|
||||
* @see http://php.net/trim
|
||||
*
|
||||
* @author Andreas Gohr <andi@splitbrain.org>
|
||||
*
|
||||
* @param string input string
|
||||
* @param string string of characters to remove
|
||||
* @return string
|
||||
*/
|
||||
public static function trim($str, $charlist = NULL)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _trim($str, $charlist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips whitespace (or other UTF-8 characters) from the beginning of a string.
|
||||
* @see http://php.net/ltrim
|
||||
*
|
||||
* @author Andreas Gohr <andi@splitbrain.org>
|
||||
*
|
||||
* @param string input string
|
||||
* @param string string of characters to remove
|
||||
* @return string
|
||||
*/
|
||||
public static function ltrim($str, $charlist = NULL)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _ltrim($str, $charlist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips whitespace (or other UTF-8 characters) from the end of a string.
|
||||
* @see http://php.net/rtrim
|
||||
*
|
||||
* @author Andreas Gohr <andi@splitbrain.org>
|
||||
*
|
||||
* @param string input string
|
||||
* @param string string of characters to remove
|
||||
* @return string
|
||||
*/
|
||||
public static function rtrim($str, $charlist = NULL)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _rtrim($str, $charlist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unicode ordinal for a character.
|
||||
* @see http://php.net/ord
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string UTF-8 encoded character
|
||||
* @return integer
|
||||
*/
|
||||
public static function ord($chr)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _ord($chr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an UTF-8 string and returns an array of ints representing the Unicode characters.
|
||||
* Astral planes are supported i.e. the ints in the output can be > 0xFFFF.
|
||||
* Occurrances of the BOM are ignored. Surrogates are not allowed.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
* The Initial Developer of the Original Code is Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998 the Initial Developer.
|
||||
* Ported to PHP by Henri Sivonen <hsivonen@iki.fi>, see http://hsivonen.iki.fi/php-utf8/.
|
||||
* Slight modifications to fit with phputf8 library by Harry Fuecks <hfuecks@gmail.com>.
|
||||
*
|
||||
* @param string UTF-8 encoded string
|
||||
* @return array unicode code points
|
||||
* @return boolean FALSE if the string is invalid
|
||||
*/
|
||||
public static function to_unicode($str)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _to_unicode($str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an array of ints representing the Unicode characters and returns a UTF-8 string.
|
||||
* Astral planes are supported i.e. the ints in the input can be > 0xFFFF.
|
||||
* Occurrances of the BOM are ignored. Surrogates are not allowed.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
* The Initial Developer of the Original Code is Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998 the Initial Developer.
|
||||
* Ported to PHP by Henri Sivonen <hsivonen@iki.fi>, see http://hsivonen.iki.fi/php-utf8/.
|
||||
* Slight modifications to fit with phputf8 library by Harry Fuecks <hfuecks@gmail.com>.
|
||||
*
|
||||
* @param array unicode code points representing a string
|
||||
* @return string utf8 string of characters
|
||||
* @return boolean FALSE if a code point cannot be found
|
||||
*/
|
||||
public static function from_unicode($arr)
|
||||
{
|
||||
if ( ! isset(self::$called[__FUNCTION__]))
|
||||
{
|
||||
require SYSPATH.'core/utf8/'.__FUNCTION__.EXT;
|
||||
|
||||
// Function has been called
|
||||
self::$called[__FUNCTION__] = TRUE;
|
||||
}
|
||||
|
||||
return _from_unicode($arr);
|
||||
}
|
||||
|
||||
} // End utf8
|
||||
@@ -1,68 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::from_unicode
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _from_unicode($arr)
|
||||
{
|
||||
ob_start();
|
||||
|
||||
$keys = array_keys($arr);
|
||||
|
||||
foreach ($keys as $k)
|
||||
{
|
||||
// ASCII range (including control chars)
|
||||
if (($arr[$k] >= 0) AND ($arr[$k] <= 0x007f))
|
||||
{
|
||||
echo chr($arr[$k]);
|
||||
}
|
||||
// 2 byte sequence
|
||||
elseif ($arr[$k] <= 0x07ff)
|
||||
{
|
||||
echo chr(0xc0 | ($arr[$k] >> 6));
|
||||
echo chr(0x80 | ($arr[$k] & 0x003f));
|
||||
}
|
||||
// Byte order mark (skip)
|
||||
elseif ($arr[$k] == 0xFEFF)
|
||||
{
|
||||
// nop -- zap the BOM
|
||||
}
|
||||
// Test for illegal surrogates
|
||||
elseif ($arr[$k] >= 0xD800 AND $arr[$k] <= 0xDFFF)
|
||||
{
|
||||
// Found a surrogate
|
||||
trigger_error('utf8::from_unicode: Illegal surrogate at index: '.$k.', value: '.$arr[$k], E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
// 3 byte sequence
|
||||
elseif ($arr[$k] <= 0xffff)
|
||||
{
|
||||
echo chr(0xe0 | ($arr[$k] >> 12));
|
||||
echo chr(0x80 | (($arr[$k] >> 6) & 0x003f));
|
||||
echo chr(0x80 | ($arr[$k] & 0x003f));
|
||||
}
|
||||
// 4 byte sequence
|
||||
elseif ($arr[$k] <= 0x10ffff)
|
||||
{
|
||||
echo chr(0xf0 | ($arr[$k] >> 18));
|
||||
echo chr(0x80 | (($arr[$k] >> 12) & 0x3f));
|
||||
echo chr(0x80 | (($arr[$k] >> 6) & 0x3f));
|
||||
echo chr(0x80 | ($arr[$k] & 0x3f));
|
||||
}
|
||||
// Out of range
|
||||
else
|
||||
{
|
||||
trigger_error('utf8::from_unicode: Codepoint out of Unicode range at index: '.$k.', value: '.$arr[$k], E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
$result = ob_get_contents();
|
||||
ob_end_clean();
|
||||
return $result;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::ltrim
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _ltrim($str, $charlist = NULL)
|
||||
{
|
||||
if ($charlist === NULL)
|
||||
return ltrim($str);
|
||||
|
||||
if (utf8::is_ascii($charlist))
|
||||
return ltrim($str, $charlist);
|
||||
|
||||
$charlist = preg_replace('#[-\[\]:\\\\^/]#', '\\\\$0', $charlist);
|
||||
|
||||
return preg_replace('/^['.$charlist.']+/u', '', $str);
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::ord
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _ord($chr)
|
||||
{
|
||||
$ord0 = ord($chr);
|
||||
|
||||
if ($ord0 >= 0 AND $ord0 <= 127)
|
||||
{
|
||||
return $ord0;
|
||||
}
|
||||
|
||||
if ( ! isset($chr[1]))
|
||||
{
|
||||
trigger_error('Short sequence - at least 2 bytes expected, only 1 seen', E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$ord1 = ord($chr[1]);
|
||||
|
||||
if ($ord0 >= 192 AND $ord0 <= 223)
|
||||
{
|
||||
return ($ord0 - 192) * 64 + ($ord1 - 128);
|
||||
}
|
||||
|
||||
if ( ! isset($chr[2]))
|
||||
{
|
||||
trigger_error('Short sequence - at least 3 bytes expected, only 2 seen', E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$ord2 = ord($chr[2]);
|
||||
|
||||
if ($ord0 >= 224 AND $ord0 <= 239)
|
||||
{
|
||||
return ($ord0 - 224) * 4096 + ($ord1 - 128) * 64 + ($ord2 - 128);
|
||||
}
|
||||
|
||||
if ( ! isset($chr[3]))
|
||||
{
|
||||
trigger_error('Short sequence - at least 4 bytes expected, only 3 seen', E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$ord3 = ord($chr[3]);
|
||||
|
||||
if ($ord0 >= 240 AND $ord0 <= 247)
|
||||
{
|
||||
return ($ord0 - 240) * 262144 + ($ord1 - 128) * 4096 + ($ord2-128) * 64 + ($ord3 - 128);
|
||||
}
|
||||
|
||||
if ( ! isset($chr[4]))
|
||||
{
|
||||
trigger_error('Short sequence - at least 5 bytes expected, only 4 seen', E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$ord4 = ord($chr[4]);
|
||||
|
||||
if ($ord0 >= 248 AND $ord0 <= 251)
|
||||
{
|
||||
return ($ord0 - 248) * 16777216 + ($ord1-128) * 262144 + ($ord2 - 128) * 4096 + ($ord3 - 128) * 64 + ($ord4 - 128);
|
||||
}
|
||||
|
||||
if ( ! isset($chr[5]))
|
||||
{
|
||||
trigger_error('Short sequence - at least 6 bytes expected, only 5 seen', E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ($ord0 >= 252 AND $ord0 <= 253)
|
||||
{
|
||||
return ($ord0 - 252) * 1073741824 + ($ord1 - 128) * 16777216 + ($ord2 - 128) * 262144 + ($ord3 - 128) * 4096 + ($ord4 - 128) * 64 + (ord($chr[5]) - 128);
|
||||
}
|
||||
|
||||
if ($ord0 >= 254 AND $ord0 <= 255)
|
||||
{
|
||||
trigger_error('Invalid UTF-8 with surrogate ordinal '.$ord0, E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::rtrim
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _rtrim($str, $charlist = NULL)
|
||||
{
|
||||
if ($charlist === NULL)
|
||||
return rtrim($str);
|
||||
|
||||
if (utf8::is_ascii($charlist))
|
||||
return rtrim($str, $charlist);
|
||||
|
||||
$charlist = preg_replace('#[-\[\]:\\\\^/]#', '\\\\$0', $charlist);
|
||||
|
||||
return preg_replace('/['.$charlist.']++$/uD', '', $str);
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::str_ireplace
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _str_ireplace($search, $replace, $str, & $count = NULL)
|
||||
{
|
||||
if (utf8::is_ascii($search) AND utf8::is_ascii($replace) AND utf8::is_ascii($str))
|
||||
return str_ireplace($search, $replace, $str, $count);
|
||||
|
||||
if (is_array($str))
|
||||
{
|
||||
foreach ($str as $key => $val)
|
||||
{
|
||||
$str[$key] = utf8::str_ireplace($search, $replace, $val, $count);
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
if (is_array($search))
|
||||
{
|
||||
$keys = array_keys($search);
|
||||
|
||||
foreach ($keys as $k)
|
||||
{
|
||||
if (is_array($replace))
|
||||
{
|
||||
if (array_key_exists($k, $replace))
|
||||
{
|
||||
$str = utf8::str_ireplace($search[$k], $replace[$k], $str, $count);
|
||||
}
|
||||
else
|
||||
{
|
||||
$str = utf8::str_ireplace($search[$k], '', $str, $count);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$str = utf8::str_ireplace($search[$k], $replace, $str, $count);
|
||||
}
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
$search = utf8::strtolower($search);
|
||||
$str_lower = utf8::strtolower($str);
|
||||
|
||||
$total_matched_strlen = 0;
|
||||
$i = 0;
|
||||
|
||||
while (preg_match('/(.*?)'.preg_quote($search, '/').'/s', $str_lower, $matches))
|
||||
{
|
||||
$matched_strlen = strlen($matches[0]);
|
||||
$str_lower = substr($str_lower, $matched_strlen);
|
||||
|
||||
$offset = $total_matched_strlen + strlen($matches[1]) + ($i * (strlen($replace) - 1));
|
||||
$str = substr_replace($str, $replace, $offset, strlen($search));
|
||||
|
||||
$total_matched_strlen += $matched_strlen;
|
||||
$i++;
|
||||
}
|
||||
|
||||
$count += $i;
|
||||
return $str;
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::str_pad
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _str_pad($str, $final_str_length, $pad_str = ' ', $pad_type = STR_PAD_RIGHT)
|
||||
{
|
||||
if (utf8::is_ascii($str) AND utf8::is_ascii($pad_str))
|
||||
{
|
||||
return str_pad($str, $final_str_length, $pad_str, $pad_type);
|
||||
}
|
||||
|
||||
$str_length = utf8::strlen($str);
|
||||
|
||||
if ($final_str_length <= 0 OR $final_str_length <= $str_length)
|
||||
{
|
||||
return $str;
|
||||
}
|
||||
|
||||
$pad_str_length = utf8::strlen($pad_str);
|
||||
$pad_length = $final_str_length - $str_length;
|
||||
|
||||
if ($pad_type == STR_PAD_RIGHT)
|
||||
{
|
||||
$repeat = ceil($pad_length / $pad_str_length);
|
||||
return utf8::substr($str.str_repeat($pad_str, $repeat), 0, $final_str_length);
|
||||
}
|
||||
|
||||
if ($pad_type == STR_PAD_LEFT)
|
||||
{
|
||||
$repeat = ceil($pad_length / $pad_str_length);
|
||||
return utf8::substr(str_repeat($pad_str, $repeat), 0, floor($pad_length)).$str;
|
||||
}
|
||||
|
||||
if ($pad_type == STR_PAD_BOTH)
|
||||
{
|
||||
$pad_length /= 2;
|
||||
$pad_length_left = floor($pad_length);
|
||||
$pad_length_right = ceil($pad_length);
|
||||
$repeat_left = ceil($pad_length_left / $pad_str_length);
|
||||
$repeat_right = ceil($pad_length_right / $pad_str_length);
|
||||
|
||||
$pad_left = utf8::substr(str_repeat($pad_str, $repeat_left), 0, $pad_length_left);
|
||||
$pad_right = utf8::substr(str_repeat($pad_str, $repeat_right), 0, $pad_length_left);
|
||||
return $pad_left.$str.$pad_right;
|
||||
}
|
||||
|
||||
trigger_error('utf8::str_pad: Unknown padding type (' . $pad_type . ')', E_USER_ERROR);
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::str_split
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _str_split($str, $split_length = 1)
|
||||
{
|
||||
$split_length = (int) $split_length;
|
||||
|
||||
if (utf8::is_ascii($str))
|
||||
{
|
||||
return str_split($str, $split_length);
|
||||
}
|
||||
|
||||
if ($split_length < 1)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (utf8::strlen($str) <= $split_length)
|
||||
{
|
||||
return array($str);
|
||||
}
|
||||
|
||||
preg_match_all('/.{'.$split_length.'}|[^\x00]{1,'.$split_length.'}$/us', $str, $matches);
|
||||
|
||||
return $matches[0];
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::strcasecmp
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _strcasecmp($str1, $str2)
|
||||
{
|
||||
if (utf8::is_ascii($str1) AND utf8::is_ascii($str2))
|
||||
return strcasecmp($str1, $str2);
|
||||
|
||||
$str1 = utf8::strtolower($str1);
|
||||
$str2 = utf8::strtolower($str2);
|
||||
return strcmp($str1, $str2);
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::strcspn
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _strcspn($str, $mask, $offset = NULL, $length = NULL)
|
||||
{
|
||||
if ($str == '' OR $mask == '')
|
||||
return 0;
|
||||
|
||||
if (utf8::is_ascii($str) AND utf8::is_ascii($mask))
|
||||
return ($offset === NULL) ? strcspn($str, $mask) : (($length === NULL) ? strcspn($str, $mask, $offset) : strcspn($str, $mask, $offset, $length));
|
||||
|
||||
if ($str !== NULL OR $length !== NULL)
|
||||
{
|
||||
$str = utf8::substr($str, $offset, $length);
|
||||
}
|
||||
|
||||
// Escape these characters: - [ ] . : \ ^ /
|
||||
// The . and : are escaped to prevent possible warnings about POSIX regex elements
|
||||
$mask = preg_replace('#[-[\].:\\\\^/]#', '\\\\$0', $mask);
|
||||
preg_match('/^[^'.$mask.']+/u', $str, $matches);
|
||||
|
||||
return isset($matches[0]) ? utf8::strlen($matches[0]) : 0;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::stristr
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _stristr($str, $search)
|
||||
{
|
||||
if (utf8::is_ascii($str) AND utf8::is_ascii($search))
|
||||
return stristr($str, $search);
|
||||
|
||||
if ($search == '')
|
||||
return $str;
|
||||
|
||||
$str_lower = utf8::strtolower($str);
|
||||
$search_lower = utf8::strtolower($search);
|
||||
|
||||
preg_match('/^(.*?)'.preg_quote($search, '/').'/s', $str_lower, $matches);
|
||||
|
||||
if (isset($matches[1]))
|
||||
return substr($str, strlen($matches[1]));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::strlen
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _strlen($str)
|
||||
{
|
||||
// Try mb_strlen() first because it's faster than combination of is_ascii() and strlen()
|
||||
if (SERVER_UTF8)
|
||||
return mb_strlen($str);
|
||||
|
||||
if (utf8::is_ascii($str))
|
||||
return strlen($str);
|
||||
|
||||
return strlen(utf8_decode($str));
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::strpos
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _strpos($str, $search, $offset = 0)
|
||||
{
|
||||
$offset = (int) $offset;
|
||||
|
||||
if (SERVER_UTF8)
|
||||
return mb_strpos($str, $search, $offset);
|
||||
|
||||
if (utf8::is_ascii($str) AND utf8::is_ascii($search))
|
||||
return strpos($str, $search, $offset);
|
||||
|
||||
if ($offset == 0)
|
||||
{
|
||||
$array = explode($search, $str, 2);
|
||||
return isset($array[1]) ? utf8::strlen($array[0]) : FALSE;
|
||||
}
|
||||
|
||||
$str = utf8::substr($str, $offset);
|
||||
$pos = utf8::strpos($str, $search);
|
||||
return ($pos === FALSE) ? FALSE : $pos + $offset;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::strrev
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _strrev($str)
|
||||
{
|
||||
if (utf8::is_ascii($str))
|
||||
return strrev($str);
|
||||
|
||||
preg_match_all('/./us', $str, $matches);
|
||||
return implode('', array_reverse($matches[0]));
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::strrpos
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _strrpos($str, $search, $offset = 0)
|
||||
{
|
||||
$offset = (int) $offset;
|
||||
|
||||
if (SERVER_UTF8)
|
||||
return mb_strrpos($str, $search, $offset);
|
||||
|
||||
if (utf8::is_ascii($str) AND utf8::is_ascii($search))
|
||||
return strrpos($str, $search, $offset);
|
||||
|
||||
if ($offset == 0)
|
||||
{
|
||||
$array = explode($search, $str, -1);
|
||||
return isset($array[0]) ? utf8::strlen(implode($search, $array)) : FALSE;
|
||||
}
|
||||
|
||||
$str = utf8::substr($str, $offset);
|
||||
$pos = utf8::strrpos($str, $search);
|
||||
return ($pos === FALSE) ? FALSE : $pos + $offset;
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::strspn
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _strspn($str, $mask, $offset = NULL, $length = NULL)
|
||||
{
|
||||
if ($str == '' OR $mask == '')
|
||||
return 0;
|
||||
|
||||
if (utf8::is_ascii($str) AND utf8::is_ascii($mask))
|
||||
return ($offset === NULL) ? strspn($str, $mask) : (($length === NULL) ? strspn($str, $mask, $offset) : strspn($str, $mask, $offset, $length));
|
||||
|
||||
if ($offset !== NULL OR $length !== NULL)
|
||||
{
|
||||
$str = utf8::substr($str, $offset, $length);
|
||||
}
|
||||
|
||||
// Escape these characters: - [ ] . : \ ^ /
|
||||
// The . and : are escaped to prevent possible warnings about POSIX regex elements
|
||||
$mask = preg_replace('#[-[\].:\\\\^/]#', '\\\\$0', $mask);
|
||||
preg_match('/^[^'.$mask.']+/u', $str, $matches);
|
||||
|
||||
return isset($matches[0]) ? utf8::strlen($matches[0]) : 0;
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::strtolower
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _strtolower($str)
|
||||
{
|
||||
if (SERVER_UTF8)
|
||||
return mb_strtolower($str);
|
||||
|
||||
if (utf8::is_ascii($str))
|
||||
return strtolower($str);
|
||||
|
||||
static $UTF8_UPPER_TO_LOWER = NULL;
|
||||
|
||||
if ($UTF8_UPPER_TO_LOWER === NULL)
|
||||
{
|
||||
$UTF8_UPPER_TO_LOWER = array(
|
||||
0x0041=>0x0061, 0x03A6=>0x03C6, 0x0162=>0x0163, 0x00C5=>0x00E5, 0x0042=>0x0062,
|
||||
0x0139=>0x013A, 0x00C1=>0x00E1, 0x0141=>0x0142, 0x038E=>0x03CD, 0x0100=>0x0101,
|
||||
0x0490=>0x0491, 0x0394=>0x03B4, 0x015A=>0x015B, 0x0044=>0x0064, 0x0393=>0x03B3,
|
||||
0x00D4=>0x00F4, 0x042A=>0x044A, 0x0419=>0x0439, 0x0112=>0x0113, 0x041C=>0x043C,
|
||||
0x015E=>0x015F, 0x0143=>0x0144, 0x00CE=>0x00EE, 0x040E=>0x045E, 0x042F=>0x044F,
|
||||
0x039A=>0x03BA, 0x0154=>0x0155, 0x0049=>0x0069, 0x0053=>0x0073, 0x1E1E=>0x1E1F,
|
||||
0x0134=>0x0135, 0x0427=>0x0447, 0x03A0=>0x03C0, 0x0418=>0x0438, 0x00D3=>0x00F3,
|
||||
0x0420=>0x0440, 0x0404=>0x0454, 0x0415=>0x0435, 0x0429=>0x0449, 0x014A=>0x014B,
|
||||
0x0411=>0x0431, 0x0409=>0x0459, 0x1E02=>0x1E03, 0x00D6=>0x00F6, 0x00D9=>0x00F9,
|
||||
0x004E=>0x006E, 0x0401=>0x0451, 0x03A4=>0x03C4, 0x0423=>0x0443, 0x015C=>0x015D,
|
||||
0x0403=>0x0453, 0x03A8=>0x03C8, 0x0158=>0x0159, 0x0047=>0x0067, 0x00C4=>0x00E4,
|
||||
0x0386=>0x03AC, 0x0389=>0x03AE, 0x0166=>0x0167, 0x039E=>0x03BE, 0x0164=>0x0165,
|
||||
0x0116=>0x0117, 0x0108=>0x0109, 0x0056=>0x0076, 0x00DE=>0x00FE, 0x0156=>0x0157,
|
||||
0x00DA=>0x00FA, 0x1E60=>0x1E61, 0x1E82=>0x1E83, 0x00C2=>0x00E2, 0x0118=>0x0119,
|
||||
0x0145=>0x0146, 0x0050=>0x0070, 0x0150=>0x0151, 0x042E=>0x044E, 0x0128=>0x0129,
|
||||
0x03A7=>0x03C7, 0x013D=>0x013E, 0x0422=>0x0442, 0x005A=>0x007A, 0x0428=>0x0448,
|
||||
0x03A1=>0x03C1, 0x1E80=>0x1E81, 0x016C=>0x016D, 0x00D5=>0x00F5, 0x0055=>0x0075,
|
||||
0x0176=>0x0177, 0x00DC=>0x00FC, 0x1E56=>0x1E57, 0x03A3=>0x03C3, 0x041A=>0x043A,
|
||||
0x004D=>0x006D, 0x016A=>0x016B, 0x0170=>0x0171, 0x0424=>0x0444, 0x00CC=>0x00EC,
|
||||
0x0168=>0x0169, 0x039F=>0x03BF, 0x004B=>0x006B, 0x00D2=>0x00F2, 0x00C0=>0x00E0,
|
||||
0x0414=>0x0434, 0x03A9=>0x03C9, 0x1E6A=>0x1E6B, 0x00C3=>0x00E3, 0x042D=>0x044D,
|
||||
0x0416=>0x0436, 0x01A0=>0x01A1, 0x010C=>0x010D, 0x011C=>0x011D, 0x00D0=>0x00F0,
|
||||
0x013B=>0x013C, 0x040F=>0x045F, 0x040A=>0x045A, 0x00C8=>0x00E8, 0x03A5=>0x03C5,
|
||||
0x0046=>0x0066, 0x00DD=>0x00FD, 0x0043=>0x0063, 0x021A=>0x021B, 0x00CA=>0x00EA,
|
||||
0x0399=>0x03B9, 0x0179=>0x017A, 0x00CF=>0x00EF, 0x01AF=>0x01B0, 0x0045=>0x0065,
|
||||
0x039B=>0x03BB, 0x0398=>0x03B8, 0x039C=>0x03BC, 0x040C=>0x045C, 0x041F=>0x043F,
|
||||
0x042C=>0x044C, 0x00DE=>0x00FE, 0x00D0=>0x00F0, 0x1EF2=>0x1EF3, 0x0048=>0x0068,
|
||||
0x00CB=>0x00EB, 0x0110=>0x0111, 0x0413=>0x0433, 0x012E=>0x012F, 0x00C6=>0x00E6,
|
||||
0x0058=>0x0078, 0x0160=>0x0161, 0x016E=>0x016F, 0x0391=>0x03B1, 0x0407=>0x0457,
|
||||
0x0172=>0x0173, 0x0178=>0x00FF, 0x004F=>0x006F, 0x041B=>0x043B, 0x0395=>0x03B5,
|
||||
0x0425=>0x0445, 0x0120=>0x0121, 0x017D=>0x017E, 0x017B=>0x017C, 0x0396=>0x03B6,
|
||||
0x0392=>0x03B2, 0x0388=>0x03AD, 0x1E84=>0x1E85, 0x0174=>0x0175, 0x0051=>0x0071,
|
||||
0x0417=>0x0437, 0x1E0A=>0x1E0B, 0x0147=>0x0148, 0x0104=>0x0105, 0x0408=>0x0458,
|
||||
0x014C=>0x014D, 0x00CD=>0x00ED, 0x0059=>0x0079, 0x010A=>0x010B, 0x038F=>0x03CE,
|
||||
0x0052=>0x0072, 0x0410=>0x0430, 0x0405=>0x0455, 0x0402=>0x0452, 0x0126=>0x0127,
|
||||
0x0136=>0x0137, 0x012A=>0x012B, 0x038A=>0x03AF, 0x042B=>0x044B, 0x004C=>0x006C,
|
||||
0x0397=>0x03B7, 0x0124=>0x0125, 0x0218=>0x0219, 0x00DB=>0x00FB, 0x011E=>0x011F,
|
||||
0x041E=>0x043E, 0x1E40=>0x1E41, 0x039D=>0x03BD, 0x0106=>0x0107, 0x03AB=>0x03CB,
|
||||
0x0426=>0x0446, 0x00DE=>0x00FE, 0x00C7=>0x00E7, 0x03AA=>0x03CA, 0x0421=>0x0441,
|
||||
0x0412=>0x0432, 0x010E=>0x010F, 0x00D8=>0x00F8, 0x0057=>0x0077, 0x011A=>0x011B,
|
||||
0x0054=>0x0074, 0x004A=>0x006A, 0x040B=>0x045B, 0x0406=>0x0456, 0x0102=>0x0103,
|
||||
0x039B=>0x03BB, 0x00D1=>0x00F1, 0x041D=>0x043D, 0x038C=>0x03CC, 0x00C9=>0x00E9,
|
||||
0x00D0=>0x00F0, 0x0407=>0x0457, 0x0122=>0x0123,
|
||||
);
|
||||
}
|
||||
|
||||
$uni = utf8::to_unicode($str);
|
||||
|
||||
if ($uni === FALSE)
|
||||
return FALSE;
|
||||
|
||||
for ($i = 0, $c = count($uni); $i < $c; $i++)
|
||||
{
|
||||
if (isset($UTF8_UPPER_TO_LOWER[$uni[$i]]))
|
||||
{
|
||||
$uni[$i] = $UTF8_UPPER_TO_LOWER[$uni[$i]];
|
||||
}
|
||||
}
|
||||
|
||||
return utf8::from_unicode($uni);
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::strtoupper
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _strtoupper($str)
|
||||
{
|
||||
if (SERVER_UTF8)
|
||||
return mb_strtoupper($str);
|
||||
|
||||
if (utf8::is_ascii($str))
|
||||
return strtoupper($str);
|
||||
|
||||
static $UTF8_LOWER_TO_UPPER = NULL;
|
||||
|
||||
if ($UTF8_LOWER_TO_UPPER === NULL)
|
||||
{
|
||||
$UTF8_LOWER_TO_UPPER = array(
|
||||
0x0061=>0x0041, 0x03C6=>0x03A6, 0x0163=>0x0162, 0x00E5=>0x00C5, 0x0062=>0x0042,
|
||||
0x013A=>0x0139, 0x00E1=>0x00C1, 0x0142=>0x0141, 0x03CD=>0x038E, 0x0101=>0x0100,
|
||||
0x0491=>0x0490, 0x03B4=>0x0394, 0x015B=>0x015A, 0x0064=>0x0044, 0x03B3=>0x0393,
|
||||
0x00F4=>0x00D4, 0x044A=>0x042A, 0x0439=>0x0419, 0x0113=>0x0112, 0x043C=>0x041C,
|
||||
0x015F=>0x015E, 0x0144=>0x0143, 0x00EE=>0x00CE, 0x045E=>0x040E, 0x044F=>0x042F,
|
||||
0x03BA=>0x039A, 0x0155=>0x0154, 0x0069=>0x0049, 0x0073=>0x0053, 0x1E1F=>0x1E1E,
|
||||
0x0135=>0x0134, 0x0447=>0x0427, 0x03C0=>0x03A0, 0x0438=>0x0418, 0x00F3=>0x00D3,
|
||||
0x0440=>0x0420, 0x0454=>0x0404, 0x0435=>0x0415, 0x0449=>0x0429, 0x014B=>0x014A,
|
||||
0x0431=>0x0411, 0x0459=>0x0409, 0x1E03=>0x1E02, 0x00F6=>0x00D6, 0x00F9=>0x00D9,
|
||||
0x006E=>0x004E, 0x0451=>0x0401, 0x03C4=>0x03A4, 0x0443=>0x0423, 0x015D=>0x015C,
|
||||
0x0453=>0x0403, 0x03C8=>0x03A8, 0x0159=>0x0158, 0x0067=>0x0047, 0x00E4=>0x00C4,
|
||||
0x03AC=>0x0386, 0x03AE=>0x0389, 0x0167=>0x0166, 0x03BE=>0x039E, 0x0165=>0x0164,
|
||||
0x0117=>0x0116, 0x0109=>0x0108, 0x0076=>0x0056, 0x00FE=>0x00DE, 0x0157=>0x0156,
|
||||
0x00FA=>0x00DA, 0x1E61=>0x1E60, 0x1E83=>0x1E82, 0x00E2=>0x00C2, 0x0119=>0x0118,
|
||||
0x0146=>0x0145, 0x0070=>0x0050, 0x0151=>0x0150, 0x044E=>0x042E, 0x0129=>0x0128,
|
||||
0x03C7=>0x03A7, 0x013E=>0x013D, 0x0442=>0x0422, 0x007A=>0x005A, 0x0448=>0x0428,
|
||||
0x03C1=>0x03A1, 0x1E81=>0x1E80, 0x016D=>0x016C, 0x00F5=>0x00D5, 0x0075=>0x0055,
|
||||
0x0177=>0x0176, 0x00FC=>0x00DC, 0x1E57=>0x1E56, 0x03C3=>0x03A3, 0x043A=>0x041A,
|
||||
0x006D=>0x004D, 0x016B=>0x016A, 0x0171=>0x0170, 0x0444=>0x0424, 0x00EC=>0x00CC,
|
||||
0x0169=>0x0168, 0x03BF=>0x039F, 0x006B=>0x004B, 0x00F2=>0x00D2, 0x00E0=>0x00C0,
|
||||
0x0434=>0x0414, 0x03C9=>0x03A9, 0x1E6B=>0x1E6A, 0x00E3=>0x00C3, 0x044D=>0x042D,
|
||||
0x0436=>0x0416, 0x01A1=>0x01A0, 0x010D=>0x010C, 0x011D=>0x011C, 0x00F0=>0x00D0,
|
||||
0x013C=>0x013B, 0x045F=>0x040F, 0x045A=>0x040A, 0x00E8=>0x00C8, 0x03C5=>0x03A5,
|
||||
0x0066=>0x0046, 0x00FD=>0x00DD, 0x0063=>0x0043, 0x021B=>0x021A, 0x00EA=>0x00CA,
|
||||
0x03B9=>0x0399, 0x017A=>0x0179, 0x00EF=>0x00CF, 0x01B0=>0x01AF, 0x0065=>0x0045,
|
||||
0x03BB=>0x039B, 0x03B8=>0x0398, 0x03BC=>0x039C, 0x045C=>0x040C, 0x043F=>0x041F,
|
||||
0x044C=>0x042C, 0x00FE=>0x00DE, 0x00F0=>0x00D0, 0x1EF3=>0x1EF2, 0x0068=>0x0048,
|
||||
0x00EB=>0x00CB, 0x0111=>0x0110, 0x0433=>0x0413, 0x012F=>0x012E, 0x00E6=>0x00C6,
|
||||
0x0078=>0x0058, 0x0161=>0x0160, 0x016F=>0x016E, 0x03B1=>0x0391, 0x0457=>0x0407,
|
||||
0x0173=>0x0172, 0x00FF=>0x0178, 0x006F=>0x004F, 0x043B=>0x041B, 0x03B5=>0x0395,
|
||||
0x0445=>0x0425, 0x0121=>0x0120, 0x017E=>0x017D, 0x017C=>0x017B, 0x03B6=>0x0396,
|
||||
0x03B2=>0x0392, 0x03AD=>0x0388, 0x1E85=>0x1E84, 0x0175=>0x0174, 0x0071=>0x0051,
|
||||
0x0437=>0x0417, 0x1E0B=>0x1E0A, 0x0148=>0x0147, 0x0105=>0x0104, 0x0458=>0x0408,
|
||||
0x014D=>0x014C, 0x00ED=>0x00CD, 0x0079=>0x0059, 0x010B=>0x010A, 0x03CE=>0x038F,
|
||||
0x0072=>0x0052, 0x0430=>0x0410, 0x0455=>0x0405, 0x0452=>0x0402, 0x0127=>0x0126,
|
||||
0x0137=>0x0136, 0x012B=>0x012A, 0x03AF=>0x038A, 0x044B=>0x042B, 0x006C=>0x004C,
|
||||
0x03B7=>0x0397, 0x0125=>0x0124, 0x0219=>0x0218, 0x00FB=>0x00DB, 0x011F=>0x011E,
|
||||
0x043E=>0x041E, 0x1E41=>0x1E40, 0x03BD=>0x039D, 0x0107=>0x0106, 0x03CB=>0x03AB,
|
||||
0x0446=>0x0426, 0x00FE=>0x00DE, 0x00E7=>0x00C7, 0x03CA=>0x03AA, 0x0441=>0x0421,
|
||||
0x0432=>0x0412, 0x010F=>0x010E, 0x00F8=>0x00D8, 0x0077=>0x0057, 0x011B=>0x011A,
|
||||
0x0074=>0x0054, 0x006A=>0x004A, 0x045B=>0x040B, 0x0456=>0x0406, 0x0103=>0x0102,
|
||||
0x03BB=>0x039B, 0x00F1=>0x00D1, 0x043D=>0x041D, 0x03CC=>0x038C, 0x00E9=>0x00C9,
|
||||
0x00F0=>0x00D0, 0x0457=>0x0407, 0x0123=>0x0122,
|
||||
);
|
||||
}
|
||||
|
||||
$uni = utf8::to_unicode($str);
|
||||
|
||||
if ($uni === FALSE)
|
||||
return FALSE;
|
||||
|
||||
for ($i = 0, $c = count($uni); $i < $c; $i++)
|
||||
{
|
||||
if (isset($UTF8_LOWER_TO_UPPER[$uni[$i]]))
|
||||
{
|
||||
$uni[$i] = $UTF8_LOWER_TO_UPPER[$uni[$i]];
|
||||
}
|
||||
}
|
||||
|
||||
return utf8::from_unicode($uni);
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::substr
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _substr($str, $offset, $length = NULL)
|
||||
{
|
||||
if (SERVER_UTF8)
|
||||
return ($length === NULL) ? mb_substr($str, $offset) : mb_substr($str, $offset, $length);
|
||||
|
||||
if (utf8::is_ascii($str))
|
||||
return ($length === NULL) ? substr($str, $offset) : substr($str, $offset, $length);
|
||||
|
||||
// Normalize params
|
||||
$str = (string) $str;
|
||||
$strlen = utf8::strlen($str);
|
||||
$offset = (int) ($offset < 0) ? max(0, $strlen + $offset) : $offset; // Normalize to positive offset
|
||||
$length = ($length === NULL) ? NULL : (int) $length;
|
||||
|
||||
// Impossible
|
||||
if ($length === 0 OR $offset >= $strlen OR ($length < 0 AND $length <= $offset - $strlen))
|
||||
return '';
|
||||
|
||||
// Whole string
|
||||
if ($offset == 0 AND ($length === NULL OR $length >= $strlen))
|
||||
return $str;
|
||||
|
||||
// Build regex
|
||||
$regex = '^';
|
||||
|
||||
// Create an offset expression
|
||||
if ($offset > 0)
|
||||
{
|
||||
// PCRE repeating quantifiers must be less than 65536, so repeat when necessary
|
||||
$x = (int) ($offset / 65535);
|
||||
$y = (int) ($offset % 65535);
|
||||
$regex .= ($x == 0) ? '' : '(?:.{65535}){'.$x.'}';
|
||||
$regex .= ($y == 0) ? '' : '.{'.$y.'}';
|
||||
}
|
||||
|
||||
// Create a length expression
|
||||
if ($length === NULL)
|
||||
{
|
||||
$regex .= '(.*)'; // No length set, grab it all
|
||||
}
|
||||
// Find length from the left (positive length)
|
||||
elseif ($length > 0)
|
||||
{
|
||||
// Reduce length so that it can't go beyond the end of the string
|
||||
$length = min($strlen - $offset, $length);
|
||||
|
||||
$x = (int) ($length / 65535);
|
||||
$y = (int) ($length % 65535);
|
||||
$regex .= '(';
|
||||
$regex .= ($x == 0) ? '' : '(?:.{65535}){'.$x.'}';
|
||||
$regex .= '.{'.$y.'})';
|
||||
}
|
||||
// Find length from the right (negative length)
|
||||
else
|
||||
{
|
||||
$x = (int) (-$length / 65535);
|
||||
$y = (int) (-$length % 65535);
|
||||
$regex .= '(.*)';
|
||||
$regex .= ($x == 0) ? '' : '(?:.{65535}){'.$x.'}';
|
||||
$regex .= '.{'.$y.'}';
|
||||
}
|
||||
|
||||
preg_match('/'.$regex.'/us', $str, $matches);
|
||||
return $matches[1];
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::substr_replace
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _substr_replace($str, $replacement, $offset, $length = NULL)
|
||||
{
|
||||
if (utf8::is_ascii($str))
|
||||
return ($length === NULL) ? substr_replace($str, $replacement, $offset) : substr_replace($str, $replacement, $offset, $length);
|
||||
|
||||
$length = ($length === NULL) ? utf8::strlen($str) : (int) $length;
|
||||
preg_match_all('/./us', $str, $str_array);
|
||||
preg_match_all('/./us', $replacement, $replacement_array);
|
||||
|
||||
array_splice($str_array[0], $offset, $length, $replacement_array[0]);
|
||||
return implode('', $str_array[0]);
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::to_unicode
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _to_unicode($str)
|
||||
{
|
||||
$mState = 0; // cached expected number of octets after the current octet until the beginning of the next UTF8 character sequence
|
||||
$mUcs4 = 0; // cached Unicode character
|
||||
$mBytes = 1; // cached expected number of octets in the current sequence
|
||||
|
||||
$out = array();
|
||||
|
||||
$len = strlen($str);
|
||||
|
||||
for ($i = 0; $i < $len; $i++)
|
||||
{
|
||||
$in = ord($str[$i]);
|
||||
|
||||
if ($mState == 0)
|
||||
{
|
||||
// When mState is zero we expect either a US-ASCII character or a
|
||||
// multi-octet sequence.
|
||||
if (0 == (0x80 & $in))
|
||||
{
|
||||
// US-ASCII, pass straight through.
|
||||
$out[] = $in;
|
||||
$mBytes = 1;
|
||||
}
|
||||
elseif (0xC0 == (0xE0 & $in))
|
||||
{
|
||||
// First octet of 2 octet sequence
|
||||
$mUcs4 = $in;
|
||||
$mUcs4 = ($mUcs4 & 0x1F) << 6;
|
||||
$mState = 1;
|
||||
$mBytes = 2;
|
||||
}
|
||||
elseif (0xE0 == (0xF0 & $in))
|
||||
{
|
||||
// First octet of 3 octet sequence
|
||||
$mUcs4 = $in;
|
||||
$mUcs4 = ($mUcs4 & 0x0F) << 12;
|
||||
$mState = 2;
|
||||
$mBytes = 3;
|
||||
}
|
||||
elseif (0xF0 == (0xF8 & $in))
|
||||
{
|
||||
// First octet of 4 octet sequence
|
||||
$mUcs4 = $in;
|
||||
$mUcs4 = ($mUcs4 & 0x07) << 18;
|
||||
$mState = 3;
|
||||
$mBytes = 4;
|
||||
}
|
||||
elseif (0xF8 == (0xFC & $in))
|
||||
{
|
||||
// First octet of 5 octet sequence.
|
||||
//
|
||||
// This is illegal because the encoded codepoint must be either
|
||||
// (a) not the shortest form or
|
||||
// (b) outside the Unicode range of 0-0x10FFFF.
|
||||
// Rather than trying to resynchronize, we will carry on until the end
|
||||
// of the sequence and let the later error handling code catch it.
|
||||
$mUcs4 = $in;
|
||||
$mUcs4 = ($mUcs4 & 0x03) << 24;
|
||||
$mState = 4;
|
||||
$mBytes = 5;
|
||||
}
|
||||
elseif (0xFC == (0xFE & $in))
|
||||
{
|
||||
// First octet of 6 octet sequence, see comments for 5 octet sequence.
|
||||
$mUcs4 = $in;
|
||||
$mUcs4 = ($mUcs4 & 1) << 30;
|
||||
$mState = 5;
|
||||
$mBytes = 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Current octet is neither in the US-ASCII range nor a legal first octet of a multi-octet sequence.
|
||||
trigger_error('utf8::to_unicode: Illegal sequence identifier in UTF-8 at byte '.$i, E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// When mState is non-zero, we expect a continuation of the multi-octet sequence
|
||||
if (0x80 == (0xC0 & $in))
|
||||
{
|
||||
// Legal continuation
|
||||
$shift = ($mState - 1) * 6;
|
||||
$tmp = $in;
|
||||
$tmp = ($tmp & 0x0000003F) << $shift;
|
||||
$mUcs4 |= $tmp;
|
||||
|
||||
// End of the multi-octet sequence. mUcs4 now contains the final Unicode codepoint to be output
|
||||
if (0 == --$mState)
|
||||
{
|
||||
// Check for illegal sequences and codepoints
|
||||
|
||||
// From Unicode 3.1, non-shortest form is illegal
|
||||
if (((2 == $mBytes) AND ($mUcs4 < 0x0080)) OR
|
||||
((3 == $mBytes) AND ($mUcs4 < 0x0800)) OR
|
||||
((4 == $mBytes) AND ($mUcs4 < 0x10000)) OR
|
||||
(4 < $mBytes) OR
|
||||
// From Unicode 3.2, surrogate characters are illegal
|
||||
(($mUcs4 & 0xFFFFF800) == 0xD800) OR
|
||||
// Codepoints outside the Unicode range are illegal
|
||||
($mUcs4 > 0x10FFFF))
|
||||
{
|
||||
trigger_error('utf8::to_unicode: Illegal sequence or codepoint in UTF-8 at byte '.$i, E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (0xFEFF != $mUcs4)
|
||||
{
|
||||
// BOM is legal but we don't want to output it
|
||||
$out[] = $mUcs4;
|
||||
}
|
||||
|
||||
// Initialize UTF-8 cache
|
||||
$mState = 0;
|
||||
$mUcs4 = 0;
|
||||
$mBytes = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ((0xC0 & (*in) != 0x80) AND (mState != 0))
|
||||
// Incomplete multi-octet sequence
|
||||
trigger_error('utf8::to_unicode: Incomplete multi-octet sequence in UTF-8 at byte '.$i, E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::transliterate_to_ascii
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _transliterate_to_ascii($str, $case = 0)
|
||||
{
|
||||
static $UTF8_LOWER_ACCENTS = NULL;
|
||||
static $UTF8_UPPER_ACCENTS = NULL;
|
||||
|
||||
if ($case <= 0)
|
||||
{
|
||||
if ($UTF8_LOWER_ACCENTS === NULL)
|
||||
{
|
||||
$UTF8_LOWER_ACCENTS = array(
|
||||
'à' => 'a', 'ô' => 'o', 'ď' => 'd', 'ḟ' => 'f', 'ë' => 'e', 'š' => 's', 'ơ' => 'o',
|
||||
'ß' => 'ss', 'ă' => 'a', 'ř' => 'r', 'ț' => 't', 'ň' => 'n', 'ā' => 'a', 'ķ' => 'k',
|
||||
'ŝ' => 's', 'ỳ' => 'y', 'ņ' => 'n', 'ĺ' => 'l', 'ħ' => 'h', 'ṗ' => 'p', 'ó' => 'o',
|
||||
'ú' => 'u', 'ě' => 'e', 'é' => 'e', 'ç' => 'c', 'ẁ' => 'w', 'ċ' => 'c', 'õ' => 'o',
|
||||
'ṡ' => 's', 'ø' => 'o', 'ģ' => 'g', 'ŧ' => 't', 'ș' => 's', 'ė' => 'e', 'ĉ' => 'c',
|
||||
'ś' => 's', 'î' => 'i', 'ű' => 'u', 'ć' => 'c', 'ę' => 'e', 'ŵ' => 'w', 'ṫ' => 't',
|
||||
'ū' => 'u', 'č' => 'c', 'ö' => 'o', 'è' => 'e', 'ŷ' => 'y', 'ą' => 'a', 'ł' => 'l',
|
||||
'ų' => 'u', 'ů' => 'u', 'ş' => 's', 'ğ' => 'g', 'ļ' => 'l', 'ƒ' => 'f', 'ž' => 'z',
|
||||
'ẃ' => 'w', 'ḃ' => 'b', 'å' => 'a', 'ì' => 'i', 'ï' => 'i', 'ḋ' => 'd', 'ť' => 't',
|
||||
'ŗ' => 'r', 'ä' => 'a', 'í' => 'i', 'ŕ' => 'r', 'ê' => 'e', 'ü' => 'u', 'ò' => 'o',
|
||||
'ē' => 'e', 'ñ' => 'n', 'ń' => 'n', 'ĥ' => 'h', 'ĝ' => 'g', 'đ' => 'd', 'ĵ' => 'j',
|
||||
'ÿ' => 'y', 'ũ' => 'u', 'ŭ' => 'u', 'ư' => 'u', 'ţ' => 't', 'ý' => 'y', 'ő' => 'o',
|
||||
'â' => 'a', 'ľ' => 'l', 'ẅ' => 'w', 'ż' => 'z', 'ī' => 'i', 'ã' => 'a', 'ġ' => 'g',
|
||||
'ṁ' => 'm', 'ō' => 'o', 'ĩ' => 'i', 'ù' => 'u', 'į' => 'i', 'ź' => 'z', 'á' => 'a',
|
||||
'û' => 'u', 'þ' => 'th', 'ð' => 'dh', 'æ' => 'ae', 'µ' => 'u', 'ĕ' => 'e',
|
||||
);
|
||||
}
|
||||
|
||||
$str = str_replace(
|
||||
array_keys($UTF8_LOWER_ACCENTS),
|
||||
array_values($UTF8_LOWER_ACCENTS),
|
||||
$str
|
||||
);
|
||||
}
|
||||
|
||||
if ($case >= 0)
|
||||
{
|
||||
if ($UTF8_UPPER_ACCENTS === NULL)
|
||||
{
|
||||
$UTF8_UPPER_ACCENTS = array(
|
||||
'À' => 'A', 'Ô' => 'O', 'Ď' => 'D', 'Ḟ' => 'F', 'Ë' => 'E', 'Š' => 'S', 'Ơ' => 'O',
|
||||
'Ă' => 'A', 'Ř' => 'R', 'Ț' => 'T', 'Ň' => 'N', 'Ā' => 'A', 'Ķ' => 'K', 'Ĕ' => 'E',
|
||||
'Ŝ' => 'S', 'Ỳ' => 'Y', 'Ņ' => 'N', 'Ĺ' => 'L', 'Ħ' => 'H', 'Ṗ' => 'P', 'Ó' => 'O',
|
||||
'Ú' => 'U', 'Ě' => 'E', 'É' => 'E', 'Ç' => 'C', 'Ẁ' => 'W', 'Ċ' => 'C', 'Õ' => 'O',
|
||||
'Ṡ' => 'S', 'Ø' => 'O', 'Ģ' => 'G', 'Ŧ' => 'T', 'Ș' => 'S', 'Ė' => 'E', 'Ĉ' => 'C',
|
||||
'Ś' => 'S', 'Î' => 'I', 'Ű' => 'U', 'Ć' => 'C', 'Ę' => 'E', 'Ŵ' => 'W', 'Ṫ' => 'T',
|
||||
'Ū' => 'U', 'Č' => 'C', 'Ö' => 'O', 'È' => 'E', 'Ŷ' => 'Y', 'Ą' => 'A', 'Ł' => 'L',
|
||||
'Ų' => 'U', 'Ů' => 'U', 'Ş' => 'S', 'Ğ' => 'G', 'Ļ' => 'L', 'Ƒ' => 'F', 'Ž' => 'Z',
|
||||
'Ẃ' => 'W', 'Ḃ' => 'B', 'Å' => 'A', 'Ì' => 'I', 'Ï' => 'I', 'Ḋ' => 'D', 'Ť' => 'T',
|
||||
'Ŗ' => 'R', 'Ä' => 'A', 'Í' => 'I', 'Ŕ' => 'R', 'Ê' => 'E', 'Ü' => 'U', 'Ò' => 'O',
|
||||
'Ē' => 'E', 'Ñ' => 'N', 'Ń' => 'N', 'Ĥ' => 'H', 'Ĝ' => 'G', 'Đ' => 'D', 'Ĵ' => 'J',
|
||||
'Ÿ' => 'Y', 'Ũ' => 'U', 'Ŭ' => 'U', 'Ư' => 'U', 'Ţ' => 'T', 'Ý' => 'Y', 'Ő' => 'O',
|
||||
'Â' => 'A', 'Ľ' => 'L', 'Ẅ' => 'W', 'Ż' => 'Z', 'Ī' => 'I', 'Ã' => 'A', 'Ġ' => 'G',
|
||||
'Ṁ' => 'M', 'Ō' => 'O', 'Ĩ' => 'I', 'Ù' => 'U', 'Į' => 'I', 'Ź' => 'Z', 'Á' => 'A',
|
||||
'Û' => 'U', 'Þ' => 'Th', 'Ð' => 'Dh', 'Æ' => 'Ae',
|
||||
);
|
||||
}
|
||||
|
||||
$str = str_replace(
|
||||
array_keys($UTF8_UPPER_ACCENTS),
|
||||
array_values($UTF8_UPPER_ACCENTS),
|
||||
$str
|
||||
);
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::trim
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _trim($str, $charlist = NULL)
|
||||
{
|
||||
if ($charlist === NULL)
|
||||
return trim($str);
|
||||
|
||||
return utf8::ltrim(utf8::rtrim($str, $charlist), $charlist);
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::ucfirst
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _ucfirst($str)
|
||||
{
|
||||
if (utf8::is_ascii($str))
|
||||
return ucfirst($str);
|
||||
|
||||
preg_match('/^(.?)(.*)$/us', $str, $matches);
|
||||
return utf8::strtoupper($matches[1]).$matches[2];
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* utf8::ucwords
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
function _ucwords($str)
|
||||
{
|
||||
if (SERVER_UTF8)
|
||||
return mb_convert_case($str, MB_CASE_TITLE);
|
||||
|
||||
if (utf8::is_ascii($str))
|
||||
return ucwords($str);
|
||||
|
||||
// [\x0c\x09\x0b\x0a\x0d\x20] matches form feeds, horizontal tabs, vertical tabs, linefeeds and carriage returns.
|
||||
// This corresponds to the definition of a 'word' defined at http://php.net/ucwords
|
||||
return preg_replace(
|
||||
'/(?<=^|[\x0c\x09\x0b\x0a\x0d\x20])[^\x0c\x09\x0b\x0a\x0d\x20]/ue',
|
||||
'utf8::strtoupper(\'$0\')',
|
||||
$str
|
||||
);
|
||||
}
|
||||
@@ -2,12 +2,12 @@
|
||||
/**
|
||||
* Array helper class.
|
||||
*
|
||||
* $Id: arr.php 4346 2009-05-11 17:08:15Z zombor $
|
||||
* $Id: arr.php 4680 2009-11-10 01:57:00Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class arr_Core {
|
||||
|
||||
@@ -102,19 +102,25 @@ class arr_Core {
|
||||
$found = array();
|
||||
foreach ($keys as $key)
|
||||
{
|
||||
if (isset($search[$key]))
|
||||
{
|
||||
$found[$key] = $search[$key];
|
||||
}
|
||||
else
|
||||
{
|
||||
$found[$key] = NULL;
|
||||
}
|
||||
$found[$key] = isset($search[$key]) ? $search[$key] : NULL;
|
||||
}
|
||||
|
||||
return $found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of array[key]. If it doesn't exist, return default.
|
||||
*
|
||||
* @param array array to search
|
||||
* @param string key name
|
||||
* @param mixed default value
|
||||
* @return mixed
|
||||
*/
|
||||
public static function get(array $array, $key, $default = NULL)
|
||||
{
|
||||
return isset($array[$key]) ? $array[$key] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Because PHP does not have this function.
|
||||
*
|
||||
@@ -151,44 +157,6 @@ class arr_Core {
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $needle the value to search for
|
||||
* @param array $haystack an array of values to search in
|
||||
* @param boolean $sort sort the array now
|
||||
* @return integer|FALSE the index of the match or FALSE when not found
|
||||
*/
|
||||
public static function binary_search($needle, $haystack, $sort = FALSE)
|
||||
{
|
||||
if ($sort)
|
||||
{
|
||||
sort($haystack);
|
||||
}
|
||||
|
||||
$high = count($haystack) - 1;
|
||||
$low = 0;
|
||||
|
||||
while ($low <= $high)
|
||||
{
|
||||
$mid = ($low + $high) >> 1;
|
||||
|
||||
if ($haystack[$mid] < $needle)
|
||||
{
|
||||
$low = $mid + 1;
|
||||
}
|
||||
elseif ($haystack[$mid] > $needle)
|
||||
{
|
||||
$high = $mid - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return $mid;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Emulates array_merge_recursive, but appends numeric keys and replaces
|
||||
* associative keys, instead of appending all keys.
|
||||
@@ -263,27 +231,6 @@ class arr_Core {
|
||||
return $array1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill an array with a range of numbers.
|
||||
*
|
||||
* @param integer stepping
|
||||
* @param integer ending number
|
||||
* @return array
|
||||
*/
|
||||
public static function range($step = 10, $max = 100)
|
||||
{
|
||||
if ($step < 1)
|
||||
return array();
|
||||
|
||||
$array = array();
|
||||
for ($i = $step; $i <= $max; $i += $step)
|
||||
{
|
||||
$array[$i] = $i;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively convert an array to an object.
|
||||
*
|
||||
@@ -309,4 +256,20 @@ class arr_Core {
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns specific key/column from an array of objects.
|
||||
*
|
||||
* @param string|integer $key The key or column number to pluck from each object.
|
||||
* @param array $array The array of objects to pluck from.
|
||||
* @return array
|
||||
*/
|
||||
public static function pluck($key, $array)
|
||||
{
|
||||
$result = array();
|
||||
foreach ($array as $i => $object)
|
||||
{
|
||||
$result[$i] = isset($object[$key]) ? $object[$key] : NULL;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
} // End arr
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
/**
|
||||
* Cookie helper class.
|
||||
*
|
||||
* $Id: cookie.php 3769 2008-12-15 00:48:56Z zombor $
|
||||
* $Id: cookie.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class cookie_Core {
|
||||
|
||||
@@ -42,8 +42,13 @@ class cookie_Core {
|
||||
}
|
||||
}
|
||||
|
||||
// Expiration timestamp
|
||||
$expire = ($expire == 0) ? 0 : time() + (int) $expire;
|
||||
if ($expire !== 0)
|
||||
{
|
||||
// The expiration is expected to be a UNIX timestamp
|
||||
$expire += time();
|
||||
}
|
||||
|
||||
$value = cookie::salt($name, $value).'~'.$value;
|
||||
|
||||
return setcookie($name, $value, $expire, $path, $domain, $secure, $httponly);
|
||||
}
|
||||
@@ -56,9 +61,51 @@ class cookie_Core {
|
||||
* @param boolean use XSS cleaning on the value
|
||||
* @return string
|
||||
*/
|
||||
public static function get($name, $default = NULL, $xss_clean = FALSE)
|
||||
public static function get($name = NULL, $default = NULL, $xss_clean = FALSE)
|
||||
{
|
||||
return Input::instance()->cookie($name, $default, $xss_clean);
|
||||
// Return an array of all the cookies if we don't have a name
|
||||
if ($name === NULL)
|
||||
{
|
||||
$cookies = array();
|
||||
|
||||
foreach($_COOKIE AS $key => $value)
|
||||
{
|
||||
$cookies[$key] = cookie::get($key, $default, $xss_clean);
|
||||
}
|
||||
return $cookies;
|
||||
}
|
||||
|
||||
if ( ! isset($_COOKIE[$name]))
|
||||
{
|
||||
return $default;
|
||||
}
|
||||
|
||||
// Get the cookie value
|
||||
$cookie = $_COOKIE[$name];
|
||||
|
||||
// Find the position of the split between salt and contents
|
||||
$split = strlen(cookie::salt($name, NULL));
|
||||
|
||||
if (isset($cookie[$split]) AND $cookie[$split] === '~')
|
||||
{
|
||||
// Separate the salt and the value
|
||||
list ($hash, $value) = explode('~', $cookie, 2);
|
||||
|
||||
if (cookie::salt($name, $value) === $hash)
|
||||
{
|
||||
if ($xss_clean === TRUE AND Kohana::config('core.global_xss_filtering') === FALSE)
|
||||
{
|
||||
return Input::instance()->xss_clean($value);
|
||||
}
|
||||
// Cookie signature is valid
|
||||
return $value;
|
||||
}
|
||||
|
||||
// The cookie signature is invalid, delete it
|
||||
cookie::delete($name);
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,9 +118,6 @@ class cookie_Core {
|
||||
*/
|
||||
public static function delete($name, $path = NULL, $domain = NULL)
|
||||
{
|
||||
if ( ! isset($_COOKIE[$name]))
|
||||
return FALSE;
|
||||
|
||||
// Delete the cookie from globals
|
||||
unset($_COOKIE[$name]);
|
||||
|
||||
@@ -81,4 +125,27 @@ class cookie_Core {
|
||||
return cookie::set($name, '', -86400, $path, $domain, FALSE, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a salt string for a cookie based on the name and value.
|
||||
*
|
||||
* @param string $name name of cookie
|
||||
* @param string $value value of cookie
|
||||
* @return string sha1 hash
|
||||
*/
|
||||
public static function salt($name, $value)
|
||||
{
|
||||
// Determine the user agent
|
||||
$agent = isset($_SERVER['HTTP_USER_AGENT']) ? strtolower($_SERVER['HTTP_USER_AGENT']) : 'unknown';
|
||||
|
||||
// Cookie salt.
|
||||
$salt = Kohana::config('cookie.salt');
|
||||
|
||||
return sha1($agent.$name.$value.$salt);
|
||||
}
|
||||
|
||||
final private function __construct()
|
||||
{
|
||||
// Static class.
|
||||
}
|
||||
|
||||
} // End cookie
|
||||
@@ -2,12 +2,12 @@
|
||||
/**
|
||||
* Date helper class.
|
||||
*
|
||||
* $Id: date.php 4316 2009-05-04 01:03:54Z kiall $
|
||||
* $Id: date.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class date_Core {
|
||||
|
||||
@@ -57,36 +57,28 @@ class date_Core {
|
||||
* Returns the offset (in seconds) between two time zones.
|
||||
* @see http://php.net/timezones
|
||||
*
|
||||
* @param string timezone that to find the offset of
|
||||
* @param string timezone to find the offset of
|
||||
* @param string|boolean timezone used as the baseline
|
||||
* @param string time at which to calculate
|
||||
* @return integer
|
||||
*/
|
||||
public static function offset($remote, $local = TRUE)
|
||||
public static function offset($remote, $local = TRUE, $when = 'now')
|
||||
{
|
||||
static $offsets;
|
||||
|
||||
// Default values
|
||||
$remote = (string) $remote;
|
||||
$local = ($local === TRUE) ? date_default_timezone_get() : (string) $local;
|
||||
|
||||
// Cache key name
|
||||
$cache = $remote.$local;
|
||||
|
||||
if (empty($offsets[$cache]))
|
||||
if ($local === TRUE)
|
||||
{
|
||||
// Create timezone objects
|
||||
$remote = new DateTimeZone($remote);
|
||||
$local = new DateTimeZone($local);
|
||||
|
||||
// Create date objects from timezones
|
||||
$time_there = new DateTime('now', $remote);
|
||||
$time_here = new DateTime('now', $local);
|
||||
|
||||
// Find the offset
|
||||
$offsets[$cache] = $remote->getOffset($time_there) - $local->getOffset($time_here);
|
||||
$local = date_default_timezone_get();
|
||||
}
|
||||
|
||||
return $offsets[$cache];
|
||||
// Create timezone objects
|
||||
$remote = new DateTimeZone($remote);
|
||||
$local = new DateTimeZone($local);
|
||||
|
||||
// Create date objects from timezones
|
||||
$time_there = new DateTime($when, $remote);
|
||||
$time_here = new DateTime($when, $local);
|
||||
|
||||
// Find the offset
|
||||
return $remote->getOffset($time_there) - $local->getOffset($time_here);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
49
system/helpers/db.php
Normal file
49
system/helpers/db.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Database helper class.
|
||||
*
|
||||
* $Id: $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class db_Core {
|
||||
|
||||
public static function query($sql)
|
||||
{
|
||||
return new Database_Query($sql);
|
||||
}
|
||||
|
||||
public static function build($database = 'default')
|
||||
{
|
||||
return new Database_Builder($database);
|
||||
}
|
||||
|
||||
public static function select($columns = NULL)
|
||||
{
|
||||
return db::build()->select($columns);
|
||||
}
|
||||
|
||||
public static function insert($table = NULL, $set = NULL)
|
||||
{
|
||||
return db::build()->insert($table, $set);
|
||||
}
|
||||
|
||||
public static function update($table = NULL, $set = NULL, $where = NULL)
|
||||
{
|
||||
return db::build()->update($table, $set, $where);
|
||||
}
|
||||
|
||||
public static function delete($table = NULL, $where = NULL)
|
||||
{
|
||||
return db::build()->delete($table, $where);
|
||||
}
|
||||
|
||||
public static function expr($expression)
|
||||
{
|
||||
return new Database_Expression($expression);
|
||||
}
|
||||
|
||||
} // End db
|
||||
@@ -2,18 +2,98 @@
|
||||
/**
|
||||
* Download helper class.
|
||||
*
|
||||
* $Id: download.php 3769 2008-12-15 00:48:56Z zombor $
|
||||
* $Id: download.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class download_Core {
|
||||
|
||||
/**
|
||||
* Force a download of a file to the user's browser. This function is
|
||||
* binary-safe and will work with any MIME type that Kohana is aware of.
|
||||
* Send headers necessary to invoke a "Save As" dialog
|
||||
*
|
||||
* @link http://support.microsoft.com/kb/260519
|
||||
* @link http://greenbytes.de/tech/tc2231/
|
||||
*
|
||||
* @param string file name
|
||||
* @return string file name as it was sent
|
||||
*/
|
||||
public static function dialog($filename)
|
||||
{
|
||||
$filename = basename($filename);
|
||||
|
||||
header('Content-Disposition: attachment; filename="'.$filename.'"');
|
||||
|
||||
return $filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the contents of a file or a data string with the proper MIME type and exit.
|
||||
*
|
||||
* @uses exit()
|
||||
* @uses Kohana::close_buffers()
|
||||
*
|
||||
* @param string a file path or file name
|
||||
* @param string optional data to send
|
||||
* @return void
|
||||
*/
|
||||
public static function send($filename, $data = NULL)
|
||||
{
|
||||
if ($data === NULL)
|
||||
{
|
||||
$filepath = realpath($filename);
|
||||
|
||||
$filename = basename($filepath);
|
||||
$filesize = filesize($filepath);
|
||||
}
|
||||
else
|
||||
{
|
||||
$filename = basename($filename);
|
||||
$filesize = strlen($data);
|
||||
}
|
||||
|
||||
// Retrieve MIME type by extension
|
||||
$mime = Kohana::config('mimes.'.strtolower(substr(strrchr($filename, '.'), 1)));
|
||||
$mime = empty($mime) ? 'application/octet-stream' : $mime[0];
|
||||
|
||||
// Close output buffers
|
||||
Kohana::close_buffers(FALSE);
|
||||
|
||||
// Clear any output
|
||||
Event::add('system.display', create_function('', 'Kohana::$output = "";'));
|
||||
|
||||
// Send headers
|
||||
header("Content-Type: $mime");
|
||||
header('Content-Length: '.sprintf('%d', $filesize));
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
|
||||
// Send data
|
||||
if ($data === NULL)
|
||||
{
|
||||
$handle = fopen($filepath, 'rb');
|
||||
|
||||
fpassthru($handle);
|
||||
fclose($handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
echo $data;
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the download of a file by the user's browser by preventing any
|
||||
* caching. Contains a workaround for Internet Explorer.
|
||||
*
|
||||
* @link http://support.microsoft.com/kb/316431
|
||||
* @link http://support.microsoft.com/kb/812935
|
||||
*
|
||||
* @uses download::dialog()
|
||||
* @uses download::send()
|
||||
*
|
||||
* @param string a file path or file name
|
||||
* @param mixed data to be sent if the filename does not exist
|
||||
@@ -22,84 +102,36 @@ class download_Core {
|
||||
*/
|
||||
public static function force($filename = NULL, $data = NULL, $nicename = NULL)
|
||||
{
|
||||
if (empty($filename))
|
||||
return FALSE;
|
||||
download::dialog(empty($nicename) ? $filename : $nicename);
|
||||
|
||||
// Prevent caching
|
||||
header('Expires: Thu, 01 Jan 1970 00:00:00 GMT');
|
||||
|
||||
if (request::user_agent('browser') === 'Internet Explorer' AND request::user_agent('version') <= '6.0')
|
||||
{
|
||||
// HTTP 1.0
|
||||
header('Pragma:');
|
||||
|
||||
// HTTP 1.1 with IE extensions
|
||||
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
|
||||
}
|
||||
else
|
||||
{
|
||||
// HTTP 1.0
|
||||
header('Pragma: no-cache');
|
||||
|
||||
// HTTP 1.1
|
||||
header('Cache-Control: no-cache, max-age=0');
|
||||
}
|
||||
|
||||
if (is_file($filename))
|
||||
{
|
||||
// Get the real path
|
||||
$filepath = str_replace('\\', '/', realpath($filename));
|
||||
|
||||
// Set filesize
|
||||
$filesize = filesize($filepath);
|
||||
|
||||
// Get filename
|
||||
$filename = substr(strrchr('/'.$filepath, '/'), 1);
|
||||
|
||||
// Get extension
|
||||
$extension = strtolower(substr(strrchr($filepath, '.'), 1));
|
||||
download::send($filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get filesize
|
||||
$filesize = strlen($data);
|
||||
|
||||
// Make sure the filename does not have directory info
|
||||
$filename = substr(strrchr('/'.$filename, '/'), 1);
|
||||
|
||||
// Get extension
|
||||
$extension = strtolower(substr(strrchr($filename, '.'), 1));
|
||||
}
|
||||
|
||||
// Get the mime type of the file
|
||||
$mime = Kohana::config('mimes.'.$extension);
|
||||
|
||||
if (empty($mime))
|
||||
{
|
||||
// Set a default mime if none was found
|
||||
$mime = array('application/octet-stream');
|
||||
}
|
||||
|
||||
// Generate the server headers
|
||||
header('Content-Type: '.$mime[0]);
|
||||
header('Content-Disposition: attachment; filename="'.(empty($nicename) ? $filename : $nicename).'"');
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
header('Content-Length: '.sprintf('%d', $filesize));
|
||||
|
||||
// More caching prevention
|
||||
header('Expires: 0');
|
||||
|
||||
if (Kohana::user_agent('browser') === 'Internet Explorer')
|
||||
{
|
||||
// Send IE headers
|
||||
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
|
||||
header('Pragma: public');
|
||||
}
|
||||
else
|
||||
{
|
||||
// Send normal headers
|
||||
header('Pragma: no-cache');
|
||||
}
|
||||
|
||||
// Clear the output buffer
|
||||
Kohana::close_buffers(FALSE);
|
||||
|
||||
if (isset($filepath))
|
||||
{
|
||||
// Open the file
|
||||
$handle = fopen($filepath, 'rb');
|
||||
|
||||
// Send the file data
|
||||
fpassthru($handle);
|
||||
|
||||
// Close the file
|
||||
fclose($handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Send the file data
|
||||
echo $data;
|
||||
download::send($filename, $data);
|
||||
}
|
||||
}
|
||||
|
||||
} // End download
|
||||
} // End download
|
||||
|
||||
@@ -1,181 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* Email helper class.
|
||||
*
|
||||
* $Id: email.php 3769 2008-12-15 00:48:56Z zombor $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
*/
|
||||
class email_Core {
|
||||
|
||||
// SwiftMailer instance
|
||||
protected static $mail;
|
||||
|
||||
/**
|
||||
* Creates a SwiftMailer instance.
|
||||
*
|
||||
* @param string DSN connection string
|
||||
* @return object Swift object
|
||||
*/
|
||||
public static function connect($config = NULL)
|
||||
{
|
||||
if ( ! class_exists('Swift', FALSE))
|
||||
{
|
||||
// Load SwiftMailer
|
||||
require Kohana::find_file('vendor', 'swift/Swift');
|
||||
|
||||
// Register the Swift ClassLoader as an autoload
|
||||
spl_autoload_register(array('Swift_ClassLoader', 'load'));
|
||||
}
|
||||
|
||||
// Load default configuration
|
||||
($config === NULL) and $config = Kohana::config('email');
|
||||
|
||||
switch ($config['driver'])
|
||||
{
|
||||
case 'smtp':
|
||||
// Set port
|
||||
$port = empty($config['options']['port']) ? NULL : (int) $config['options']['port'];
|
||||
|
||||
if (empty($config['options']['encryption']))
|
||||
{
|
||||
// No encryption
|
||||
$encryption = Swift_Connection_SMTP::ENC_OFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set encryption
|
||||
switch (strtolower($config['options']['encryption']))
|
||||
{
|
||||
case 'tls': $encryption = Swift_Connection_SMTP::ENC_TLS; break;
|
||||
case 'ssl': $encryption = Swift_Connection_SMTP::ENC_SSL; break;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a SMTP connection
|
||||
$connection = new Swift_Connection_SMTP($config['options']['hostname'], $port, $encryption);
|
||||
|
||||
// Do authentication, if part of the DSN
|
||||
empty($config['options']['username']) or $connection->setUsername($config['options']['username']);
|
||||
empty($config['options']['password']) or $connection->setPassword($config['options']['password']);
|
||||
|
||||
if ( ! empty($config['options']['auth']))
|
||||
{
|
||||
// Get the class name and params
|
||||
list ($class, $params) = arr::callback_string($config['options']['auth']);
|
||||
|
||||
if ($class === 'PopB4Smtp')
|
||||
{
|
||||
// Load the PopB4Smtp class manually, due to its odd filename
|
||||
require Kohana::find_file('vendor', 'swift/Swift/Authenticator/$PopB4Smtp$');
|
||||
}
|
||||
|
||||
// Prepare the class name for auto-loading
|
||||
$class = 'Swift_Authenticator_'.$class;
|
||||
|
||||
// Attach the authenticator
|
||||
$connection->attachAuthenticator(($params === NULL) ? new $class : new $class($params[0]));
|
||||
}
|
||||
|
||||
// Set the timeout to 5 seconds
|
||||
$connection->setTimeout(empty($config['options']['timeout']) ? 5 : (int) $config['options']['timeout']);
|
||||
break;
|
||||
case 'sendmail':
|
||||
// Create a sendmail connection
|
||||
$connection = new Swift_Connection_Sendmail
|
||||
(
|
||||
empty($config['options']) ? Swift_Connection_Sendmail::AUTO_DETECT : $config['options']
|
||||
);
|
||||
|
||||
// Set the timeout to 5 seconds
|
||||
$connection->setTimeout(5);
|
||||
break;
|
||||
default:
|
||||
// Use the native connection
|
||||
$connection = new Swift_Connection_NativeMail($config['options']);
|
||||
break;
|
||||
}
|
||||
|
||||
// Create the SwiftMailer instance
|
||||
return email::$mail = new Swift($connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an email message.
|
||||
*
|
||||
* @param string|array recipient email (and name), or an array of To, Cc, Bcc names
|
||||
* @param string|array sender email (and name)
|
||||
* @param string message subject
|
||||
* @param string message body
|
||||
* @param boolean send email as HTML
|
||||
* @return integer number of emails sent
|
||||
*/
|
||||
public static function send($to, $from, $subject, $message, $html = FALSE)
|
||||
{
|
||||
// Connect to SwiftMailer
|
||||
(email::$mail === NULL) and email::connect();
|
||||
|
||||
// Determine the message type
|
||||
$html = ($html === TRUE) ? 'text/html' : 'text/plain';
|
||||
|
||||
// Create the message
|
||||
$message = new Swift_Message($subject, $message, $html, '8bit', 'utf-8');
|
||||
|
||||
if (is_string($to))
|
||||
{
|
||||
// Single recipient
|
||||
$recipients = new Swift_Address($to);
|
||||
}
|
||||
elseif (is_array($to))
|
||||
{
|
||||
if (isset($to[0]) AND isset($to[1]))
|
||||
{
|
||||
// Create To: address set
|
||||
$to = array('to' => $to);
|
||||
}
|
||||
|
||||
// Create a list of recipients
|
||||
$recipients = new Swift_RecipientList;
|
||||
|
||||
foreach ($to as $method => $set)
|
||||
{
|
||||
if ( ! in_array($method, array('to', 'cc', 'bcc')))
|
||||
{
|
||||
// Use To: by default
|
||||
$method = 'to';
|
||||
}
|
||||
|
||||
// Create method name
|
||||
$method = 'add'.ucfirst($method);
|
||||
|
||||
if (is_array($set))
|
||||
{
|
||||
// Add a recipient with name
|
||||
$recipients->$method($set[0], $set[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add a recipient without name
|
||||
$recipients->$method($set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_string($from))
|
||||
{
|
||||
// From without a name
|
||||
$from = new Swift_Address($from);
|
||||
}
|
||||
elseif (is_array($from))
|
||||
{
|
||||
// From with a name
|
||||
$from = new Swift_Address($from[0], $from[1]);
|
||||
}
|
||||
|
||||
return email::$mail->send($message, $recipients, $from);
|
||||
}
|
||||
|
||||
} // End email
|
||||
@@ -2,54 +2,49 @@
|
||||
/**
|
||||
* Controls headers that effect client caching of pages
|
||||
*
|
||||
* $Id: expires.php 4272 2009-04-25 21:47:26Z zombor $
|
||||
* $Id: expires.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class expires_Core {
|
||||
|
||||
/**
|
||||
* Sets the amount of time before a page expires
|
||||
* Sets the amount of time before content expires
|
||||
*
|
||||
* @param integer Seconds before the page expires
|
||||
* @return boolean
|
||||
* @param integer Seconds before the content expires
|
||||
* @return integer Timestamp when the content expires
|
||||
*/
|
||||
public static function set($seconds = 60)
|
||||
{
|
||||
if (expires::check_headers())
|
||||
{
|
||||
$now = $expires = time();
|
||||
$now = time();
|
||||
$expires = $now + $seconds;
|
||||
|
||||
// Set the expiration timestamp
|
||||
$expires += $seconds;
|
||||
header('Last-Modified: '.gmdate('D, d M Y H:i:s T', $now));
|
||||
|
||||
// Send headers
|
||||
header('Last-Modified: '.gmdate('D, d M Y H:i:s T', $now));
|
||||
header('Expires: '.gmdate('D, d M Y H:i:s T', $expires));
|
||||
header('Cache-Control: max-age='.$seconds);
|
||||
// HTTP 1.0
|
||||
header('Expires: '.gmdate('D, d M Y H:i:s T', $expires));
|
||||
|
||||
return $expires;
|
||||
}
|
||||
// HTTP 1.1
|
||||
header('Cache-Control: max-age='.$seconds);
|
||||
|
||||
return FALSE;
|
||||
return $expires;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a page should be updated or send Not Modified status
|
||||
* Parses the If-Modified-Since header
|
||||
*
|
||||
* @param integer Seconds added to the modified time received to calculate what should be sent
|
||||
* @return bool FALSE when the request needs to be updated
|
||||
* @return integer|boolean Timestamp or FALSE when header is lacking or malformed
|
||||
*/
|
||||
public static function check($seconds = 60)
|
||||
public static function get()
|
||||
{
|
||||
if ( ! empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) AND expires::check_headers())
|
||||
if ( ! empty($_SERVER['HTTP_IF_MODIFIED_SINCE']))
|
||||
{
|
||||
// Some versions of IE6 append "; length=####"
|
||||
if (($strpos = strpos($_SERVER['HTTP_IF_MODIFIED_SINCE'], ';')) !== FALSE)
|
||||
{
|
||||
// IE6 and perhaps other IE versions send length too, compensate here
|
||||
$mod_time = substr($_SERVER['HTTP_IF_MODIFIED_SINCE'], 0, $strpos);
|
||||
}
|
||||
else
|
||||
@@ -57,55 +52,69 @@ class expires_Core {
|
||||
$mod_time = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
|
||||
}
|
||||
|
||||
$mod_time = strtotime($mod_time);
|
||||
$mod_time_diff = $mod_time + $seconds - time();
|
||||
|
||||
if ($mod_time_diff > 0)
|
||||
{
|
||||
// Re-send headers
|
||||
header('Last-Modified: '.gmdate('D, d M Y H:i:s T', $mod_time));
|
||||
header('Expires: '.gmdate('D, d M Y H:i:s T', time() + $mod_time_diff));
|
||||
header('Cache-Control: max-age='.$mod_time_diff);
|
||||
header('Status: 304 Not Modified', TRUE, 304);
|
||||
|
||||
// Prevent any output
|
||||
Event::add('system.display', array('expires', 'prevent_output'));
|
||||
|
||||
// Exit to prevent other output
|
||||
exit;
|
||||
}
|
||||
return strtotime($mod_time);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check headers already created to not step on download or Img_lib's feet
|
||||
* Checks to see if content should be updated otherwise sends Not Modified status
|
||||
* and exits.
|
||||
*
|
||||
* @return boolean
|
||||
* @uses exit()
|
||||
* @uses expires::get()
|
||||
*
|
||||
* @param integer Maximum age of the content in seconds
|
||||
* @return integer|boolean Timestamp of the If-Modified-Since header or FALSE when header is lacking or malformed
|
||||
*/
|
||||
public static function check_headers()
|
||||
public static function check($seconds = 60)
|
||||
{
|
||||
foreach (headers_list() as $header)
|
||||
if ($last_modified = expires::get())
|
||||
{
|
||||
if ((session_cache_limiter() == '' AND stripos($header, 'Last-Modified:') === 0)
|
||||
OR stripos($header, 'Expires:') === 0)
|
||||
$expires = $last_modified + $seconds;
|
||||
$max_age = $expires - time();
|
||||
|
||||
if ($max_age > 0)
|
||||
{
|
||||
return FALSE;
|
||||
// Content has not expired
|
||||
header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified');
|
||||
header('Last-Modified: '.gmdate('D, d M Y H:i:s T', $last_modified));
|
||||
|
||||
// HTTP 1.0
|
||||
header('Expires: '.gmdate('D, d M Y H:i:s T', $expires));
|
||||
|
||||
// HTTP 1.1
|
||||
header('Cache-Control: max-age='.$max_age);
|
||||
|
||||
// Clear any output
|
||||
Event::add('system.display', create_function('', 'Kohana::$output = "";'));
|
||||
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return $last_modified;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent any output from being displayed. Executed during system.display.
|
||||
* Check if expiration headers are already set
|
||||
*
|
||||
* @return void
|
||||
* @return boolean
|
||||
*/
|
||||
public static function prevent_output()
|
||||
public static function headers_set()
|
||||
{
|
||||
Kohana::$output = '';
|
||||
foreach (headers_list() as $header)
|
||||
{
|
||||
if (strncasecmp($header, 'Expires:', 8) === 0
|
||||
OR strncasecmp($header, 'Cache-Control:', 14) === 0
|
||||
OR strncasecmp($header, 'Last-Modified:', 14) === 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
} // End expires
|
||||
} // End expires
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
/**
|
||||
* Feed helper class.
|
||||
*
|
||||
* $Id: feed.php 4152 2009-04-03 23:26:23Z ixmatus $
|
||||
* $Id: feed.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class feed_Core {
|
||||
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
/**
|
||||
* File helper class.
|
||||
*
|
||||
* $Id: file.php 3769 2008-12-15 00:48:56Z zombor $
|
||||
* $Id: file.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class file_Core {
|
||||
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
/**
|
||||
* Form helper class.
|
||||
*
|
||||
* $Id: form.php 4291 2009-04-29 22:51:58Z kiall $
|
||||
* $Id: form.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class form_Core {
|
||||
|
||||
@@ -17,9 +17,10 @@ class form_Core {
|
||||
* @param string form action attribute
|
||||
* @param array extra attributes
|
||||
* @param array hidden fields to be created immediately after the form tag
|
||||
* @param string non-default protocol, eg: https
|
||||
* @return string
|
||||
*/
|
||||
public static function open($action = NULL, $attr = array(), $hidden = NULL)
|
||||
public static function open($action = NULL, $attr = array(), $hidden = NULL, $protocol = NULL)
|
||||
{
|
||||
// Make sure that the method is always set
|
||||
empty($attr['method']) and $attr['method'] = 'post';
|
||||
@@ -33,12 +34,12 @@ class form_Core {
|
||||
if ($action === NULL)
|
||||
{
|
||||
// Use the current URL as the default action
|
||||
$action = url::site(Router::$complete_uri);
|
||||
$action = url::site(Router::$complete_uri, $protocol);
|
||||
}
|
||||
elseif (strpos($action, '://') === FALSE)
|
||||
{
|
||||
// Make the action URI into a URL
|
||||
$action = url::site($action);
|
||||
$action = url::site($action, $protocol);
|
||||
}
|
||||
|
||||
// Set action
|
||||
@@ -70,72 +71,23 @@ class form_Core {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a fieldset opening tag.
|
||||
* Creates a HTML form hidden input tag.
|
||||
*
|
||||
* @param array html attributes
|
||||
* @param string a string to be attached to the end of the attributes
|
||||
* @param string|array input name or an array of HTML attributes
|
||||
* @param string input value, when using a name
|
||||
* @param string a string to be attached to the end of the attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function open_fieldset($data = NULL, $extra = '')
|
||||
{
|
||||
return '<fieldset'.html::attributes((array) $data).' '.$extra.'>'."\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a fieldset closing tag.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function close_fieldset()
|
||||
{
|
||||
return '</fieldset>'."\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a legend tag for use with a fieldset.
|
||||
*
|
||||
* @param string legend text
|
||||
* @param array HTML attributes
|
||||
* @param string a string to be attached to the end of the attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function legend($text = '', $data = NULL, $extra = '')
|
||||
{
|
||||
return '<legend'.form::attributes((array) $data).' '.$extra.'>'.$text.'</legend>'."\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates hidden form fields.
|
||||
* You can pass a simple key/value string or an associative array with multiple values.
|
||||
*
|
||||
* @param string|array input name (string) or key/value pairs (array)
|
||||
* @param string input value, if using an input name
|
||||
* @return string
|
||||
*/
|
||||
public static function hidden($data, $value = '')
|
||||
public static function hidden($data, $value = '', $extra = '')
|
||||
{
|
||||
if ( ! is_array($data))
|
||||
{
|
||||
$data = array
|
||||
(
|
||||
$data => $value
|
||||
);
|
||||
$data = array('name' => $data);
|
||||
}
|
||||
|
||||
$input = '';
|
||||
foreach ($data as $name => $value)
|
||||
{
|
||||
$attr = array
|
||||
(
|
||||
'type' => 'hidden',
|
||||
'name' => $name,
|
||||
'value' => $value
|
||||
);
|
||||
$data['type'] = 'hidden';
|
||||
|
||||
$input .= form::input($attr)."\n";
|
||||
}
|
||||
|
||||
return $input;
|
||||
return form::input($data, $value, $extra);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -219,13 +171,23 @@ class form_Core {
|
||||
$data = array('name' => $data);
|
||||
}
|
||||
|
||||
if ( ! isset($data['rows']))
|
||||
{
|
||||
$data['rows'] = '';
|
||||
}
|
||||
|
||||
if ( ! isset($data['cols']))
|
||||
{
|
||||
$data['cols'] = '';
|
||||
}
|
||||
|
||||
// Use the value from $data if possible, or use $value
|
||||
$value = isset($data['value']) ? $data['value'] : $value;
|
||||
|
||||
// Value is not part of the attributes
|
||||
unset($data['value']);
|
||||
|
||||
return '<textarea'.form::attributes($data, 'textarea').' '.$extra.'>'.html::specialchars($value, $double_encode).'</textarea>';
|
||||
return '<textarea'.form::attributes($data, 'textarea').' '.$extra.'>'.htmlspecialchars($value, ENT_QUOTES, Kohana::CHARSET, $double_encode).'</textarea>';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -283,21 +245,15 @@ class form_Core {
|
||||
// Inner key should always be a string
|
||||
$inner_key = (string) $inner_key;
|
||||
|
||||
$attr = array('value' => $inner_key);
|
||||
if (in_array($inner_key, $selected)) {
|
||||
$attr['selected'] = 'selected';
|
||||
}
|
||||
$input .= '<option '.html::attributes($attr).'>'.html::purify($inner_val).'</option>'."\n";
|
||||
$sel = in_array($inner_key, $selected) ? ' selected="selected"' : '';
|
||||
$input .= '<option value="'.$inner_key.'"'.$sel.'>'.htmlspecialchars($inner_val, ENT_QUOTES, Kohana::CHARSET).'</option>'."\n";
|
||||
}
|
||||
$input .= '</optgroup>'."\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$attr = array('value' => $key);
|
||||
if (in_array($key, $selected)) {
|
||||
$attr['selected'] = 'selected';
|
||||
}
|
||||
$input .= '<option '.html::attributes($attr).'>'.html::purify($val).'</option>'."\n";
|
||||
$sel = in_array($key, $selected) ? ' selected="selected"' : '';
|
||||
$input .= '<option value="'.$key.'"'.$sel.'>'.htmlspecialchars($val, ENT_QUOTES, Kohana::CHARSET).'</option>'."\n";
|
||||
}
|
||||
}
|
||||
$input .= '</select>';
|
||||
@@ -416,20 +372,8 @@ class form_Core {
|
||||
{
|
||||
$value = arr::remove('value', $data);
|
||||
}
|
||||
// $value must be ::purify
|
||||
|
||||
return '<button'.form::attributes($data, 'button').' '.$extra.'>'.html::purify($value).'</button>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes an open form tag.
|
||||
*
|
||||
* @param string string to be attached after the closing tag
|
||||
* @return string
|
||||
*/
|
||||
public static function close($extra = '')
|
||||
{
|
||||
return '</form>'."\n".$extra;
|
||||
return '<button'.form::attributes($data, 'button').' '.$extra.'>'.$value.'</button>';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -462,7 +406,7 @@ class form_Core {
|
||||
$text = ucwords(inflector::humanize($data['for']));
|
||||
}
|
||||
|
||||
return '<label'.form::attributes($data).' '.$extra.'>'.html::purify($text).'</label>';
|
||||
return '<label'.form::attributes($data).' '.$extra.'>'.$text.'</label>';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -496,6 +440,7 @@ class form_Core {
|
||||
case 'image':
|
||||
case 'button':
|
||||
case 'submit':
|
||||
case 'hidden':
|
||||
// Only specific types of inputs use name to id matching
|
||||
$attr['id'] = $attr['name'];
|
||||
break;
|
||||
@@ -546,4 +491,4 @@ class form_Core {
|
||||
return html::attributes(array_merge($sorted, $attr));
|
||||
}
|
||||
|
||||
} // End form
|
||||
} // End form
|
||||
|
||||
@@ -2,15 +2,32 @@
|
||||
/**
|
||||
* Format helper class.
|
||||
*
|
||||
* $Id: format.php 4070 2009-03-11 20:37:38Z Geert $
|
||||
* $Id: format.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class format_Core {
|
||||
|
||||
/**
|
||||
* Formats a number according to the current locale.
|
||||
*
|
||||
* @param float
|
||||
* @param int|boolean number of fractional digits or TRUE to use the locale default
|
||||
* @return string
|
||||
*/
|
||||
public static function number($number, $decimals = 0)
|
||||
{
|
||||
$locale = localeconv();
|
||||
|
||||
if ($decimals === TRUE)
|
||||
return number_format($number, $locale['frac_digits'], $locale['decimal_point'], $locale['thousands_sep']);
|
||||
|
||||
return number_format($number, $decimals, $locale['decimal_point'], $locale['thousands_sep']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a phone number according to the specified format.
|
||||
*
|
||||
@@ -63,4 +80,35 @@ class format_Core {
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes a hexadecimal HTML color value. All values will be converted
|
||||
* to lowercase, have a "#" prepended and contain six characters.
|
||||
*
|
||||
* @param string hexadecimal HTML color value
|
||||
* @return string
|
||||
*/
|
||||
public static function color($str = '')
|
||||
{
|
||||
// Reject invalid values
|
||||
if ( ! valid::color($str))
|
||||
return '';
|
||||
|
||||
// Convert to lowercase
|
||||
$str = strtolower($str);
|
||||
|
||||
// Prepend "#"
|
||||
if ($str[0] !== '#')
|
||||
{
|
||||
$str = '#'.$str;
|
||||
}
|
||||
|
||||
// Expand short notation
|
||||
if (strlen($str) === 4)
|
||||
{
|
||||
$str = '#'.$str[1].$str[1].$str[2].$str[2].$str[3].$str[3];
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
} // End format
|
||||
@@ -2,12 +2,12 @@
|
||||
/**
|
||||
* HTML helper class.
|
||||
*
|
||||
* $Id: html.php 4376 2009-06-01 11:40:39Z samsoir $
|
||||
* $Id: html.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class html_Core {
|
||||
|
||||
@@ -21,46 +21,12 @@ class html_Core {
|
||||
* @param boolean encode existing entities
|
||||
* @return string
|
||||
*/
|
||||
public static function specialchars($str, $double_encode = TRUE)
|
||||
public static function chars($str, $double_encode = TRUE)
|
||||
{
|
||||
// Force the string to be a string
|
||||
$str = (string) $str;
|
||||
|
||||
// Do encode existing HTML entities (default)
|
||||
if ($double_encode === TRUE)
|
||||
{
|
||||
$str = htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do not encode existing HTML entities
|
||||
// From PHP 5.2.3 this functionality is built-in, otherwise use a regex
|
||||
if (version_compare(PHP_VERSION, '5.2.3', '>='))
|
||||
{
|
||||
$str = htmlspecialchars($str, ENT_QUOTES, 'UTF-8', FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
$str = preg_replace('/&(?!(?:#\d++|[a-z]++);)/ui', '&', $str);
|
||||
$str = str_replace(array('<', '>', '\'', '"'), array('<', '>', ''', '"'), $str);
|
||||
}
|
||||
}
|
||||
|
||||
return $str;
|
||||
// Return HTML entities using the Kohana charset
|
||||
return htmlspecialchars($str, ENT_QUOTES, Kohana::CHARSET, $double_encode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a html::specialchars() with additional URL specific encoding.
|
||||
*
|
||||
* @param string string to convert
|
||||
* @param boolean encode existing entities
|
||||
* @return string
|
||||
*/
|
||||
public static function specialurlencode($str, $double_encode = TRUE)
|
||||
{
|
||||
return str_replace(' ', '%20', html::specialchars($str, $double_encode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create HTML link anchors.
|
||||
*
|
||||
@@ -98,11 +64,11 @@ class html_Core {
|
||||
|
||||
return
|
||||
// Parsed URL
|
||||
'<a href="'.html::specialurlencode($site_url, FALSE).'"'
|
||||
'<a href="'.htmlspecialchars($site_url, ENT_QUOTES, Kohana::CHARSET, FALSE).'"'
|
||||
// Attributes empty? Use an empty string
|
||||
.(is_array($attributes) ? html::attributes($attributes) : '').'>'
|
||||
// Title empty? Use the parsed URL
|
||||
.($escape_title ? html::specialchars((($title === NULL) ? $site_url : $title), FALSE) : (($title === NULL) ? $site_url : $title)).'</a>';
|
||||
.($escape_title ? htmlspecialchars((($title === NULL) ? $site_url : $title), ENT_QUOTES, Kohana::CHARSET, FALSE) : (($title === NULL) ? $site_url : $title)).'</a>';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,44 +84,13 @@ class html_Core {
|
||||
{
|
||||
return
|
||||
// Base URL + URI = full URL
|
||||
'<a href="'.html::specialurlencode(url::base(FALSE, $protocol).$file, FALSE).'"'
|
||||
'<a href="'.htmlspecialchars(url::base(FALSE, $protocol).$file, ENT_QUOTES, Kohana::CHARSET, FALSE).'"'
|
||||
// Attributes empty? Use an empty string
|
||||
.(is_array($attributes) ? html::attributes($attributes) : '').'>'
|
||||
// Title empty? Use the filename part of the URI
|
||||
.(($title === NULL) ? end(explode('/', $file)) : $title) .'</a>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to anchor, but with the protocol parameter first.
|
||||
*
|
||||
* @param string link protocol
|
||||
* @param string URI or URL to link to
|
||||
* @param string link text
|
||||
* @param array HTML anchor attributes
|
||||
* @return string
|
||||
*/
|
||||
public static function panchor($protocol, $uri, $title = NULL, $attributes = FALSE)
|
||||
{
|
||||
return html::anchor($uri, $title, $attributes, $protocol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an array of anchors from an array of link/title pairs.
|
||||
*
|
||||
* @param array link/title pairs
|
||||
* @return array
|
||||
*/
|
||||
public static function anchor_array(array $array)
|
||||
{
|
||||
$anchors = array();
|
||||
foreach ($array as $link => $title)
|
||||
{
|
||||
// Create list of anchors
|
||||
$anchors[] = html::anchor($link, $title);
|
||||
}
|
||||
return $anchors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an obfuscated version of an email address.
|
||||
*
|
||||
@@ -286,7 +221,7 @@ class html_Core {
|
||||
*/
|
||||
public static function stylesheet($style, $media = FALSE, $index = FALSE)
|
||||
{
|
||||
return html::link($style, 'stylesheet', 'text/css', '.css', $media, $index);
|
||||
return html::link($style, 'stylesheet', 'text/css', $media, $index);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -295,12 +230,11 @@ class html_Core {
|
||||
* @param string|array filename
|
||||
* @param string|array relationship
|
||||
* @param string|array mimetype
|
||||
* @param string specifies suffix of the file
|
||||
* @param string|array specifies on what device the document will be displayed
|
||||
* @param boolean include the index_page in the link
|
||||
* @return string
|
||||
*/
|
||||
public static function link($href, $rel, $type, $suffix = FALSE, $media = FALSE, $index = FALSE)
|
||||
public static function link($href, $rel, $type, $media = FALSE, $index = FALSE)
|
||||
{
|
||||
$compiled = '';
|
||||
|
||||
@@ -312,7 +246,7 @@ class html_Core {
|
||||
$_type = is_array($type) ? array_shift($type) : $type;
|
||||
$_media = is_array($media) ? array_shift($media) : $media;
|
||||
|
||||
$compiled .= html::link($_href, $_rel, $_type, $suffix, $_media, $index);
|
||||
$compiled .= html::link($_href, $_rel, $_type, $_media, $index);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -323,14 +257,6 @@ class html_Core {
|
||||
$href = url::base($index).$href;
|
||||
}
|
||||
|
||||
$length = strlen($suffix);
|
||||
|
||||
if ( $length > 0 AND substr_compare($href, $suffix, -$length, $length, FALSE) !== 0)
|
||||
{
|
||||
// Add the defined suffix
|
||||
$href .= $suffix;
|
||||
}
|
||||
|
||||
$attr = array
|
||||
(
|
||||
'rel' => $rel,
|
||||
@@ -376,12 +302,6 @@ class html_Core {
|
||||
$script = url::base((bool) $index).$script;
|
||||
}
|
||||
|
||||
if (substr_compare($script, '.js', -3, 3, FALSE) !== 0)
|
||||
{
|
||||
// Add the javascript suffix
|
||||
$script .= '.js';
|
||||
}
|
||||
|
||||
$compiled = '<script type="text/javascript" src="'.$script.'"></script>';
|
||||
}
|
||||
|
||||
@@ -437,7 +357,7 @@ class html_Core {
|
||||
$compiled = '';
|
||||
foreach ($attrs as $key => $val)
|
||||
{
|
||||
$compiled .= ' '.$key.'="'.html::specialchars($val).'"';
|
||||
$compiled .= ' '.$key.'="'.htmlspecialchars($val, ENT_QUOTES, Kohana::CHARSET).'"';
|
||||
}
|
||||
|
||||
return $compiled;
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
/**
|
||||
* Inflector helper class.
|
||||
*
|
||||
* $Id: inflector.php 4072 2009-03-13 17:20:38Z jheathco $
|
||||
* $Id: inflector.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class inflector_Core {
|
||||
|
||||
@@ -45,7 +45,27 @@ class inflector_Core {
|
||||
* @param integer number of things
|
||||
* @return string
|
||||
*/
|
||||
public static function singular($str, $count = NULL)
|
||||
public static function singular($str, $count = NULL) {
|
||||
$parts = explode('_', $str);
|
||||
|
||||
$last = inflector::_singular(array_pop($parts), $count);
|
||||
|
||||
$pre = implode('_', $parts);
|
||||
if (strlen($pre))
|
||||
$pre .= '_';
|
||||
|
||||
return $pre.$last;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Makes a plural word singular.
|
||||
*
|
||||
* @param string word to singularize
|
||||
* @param integer number of things
|
||||
* @return string
|
||||
*/
|
||||
public static function _singular($str, $count = NULL)
|
||||
{
|
||||
// Remove garbage
|
||||
$str = strtolower(trim($str));
|
||||
@@ -103,6 +123,29 @@ class inflector_Core {
|
||||
* @return string
|
||||
*/
|
||||
public static function plural($str, $count = NULL)
|
||||
{
|
||||
if ( ! $str)
|
||||
return $str;
|
||||
|
||||
$parts = explode('_', $str);
|
||||
|
||||
$last = inflector::_plural(array_pop($parts), $count);
|
||||
|
||||
$pre = implode('_', $parts);
|
||||
if (strlen($pre))
|
||||
$pre .= '_';
|
||||
|
||||
return $pre.$last;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Makes a singular word plural.
|
||||
*
|
||||
* @param string word to pluralize
|
||||
* @return string
|
||||
*/
|
||||
public static function _plural($str, $count = NULL)
|
||||
{
|
||||
// Remove garbage
|
||||
$str = strtolower(trim($str));
|
||||
@@ -154,6 +197,24 @@ class inflector_Core {
|
||||
return inflector::$cache[$key] = $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a word possessive.
|
||||
*
|
||||
* @param string word to to make possessive
|
||||
* @return string
|
||||
*/
|
||||
public static function possessive($string)
|
||||
{
|
||||
$length = strlen($string);
|
||||
|
||||
if (substr($string, $length - 1, $length) == 's')
|
||||
{
|
||||
return $string.'\'';
|
||||
}
|
||||
|
||||
return $string.'\'s';
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a phrase camel case.
|
||||
*
|
||||
@@ -176,7 +237,7 @@ class inflector_Core {
|
||||
*/
|
||||
public static function underscore($str)
|
||||
{
|
||||
return preg_replace('/\s+/', '_', trim($str));
|
||||
return trim(preg_replace('/[\s_]+/', '_', $str), '_');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -187,7 +248,7 @@ class inflector_Core {
|
||||
*/
|
||||
public static function humanize($str)
|
||||
{
|
||||
return preg_replace('/[_-]+/', ' ', trim($str));
|
||||
return trim(preg_replace('/[_-\s]+/', ' ', $str));
|
||||
}
|
||||
|
||||
} // End inflector
|
||||
@@ -2,12 +2,12 @@
|
||||
/**
|
||||
* Number helper class.
|
||||
*
|
||||
* $Id: num.php 3769 2008-12-15 00:48:56Z zombor $
|
||||
* $Id: num.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class num_Core {
|
||||
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
/**
|
||||
* Remote url/file helper.
|
||||
*
|
||||
* $Id: remote.php 3769 2008-12-15 00:48:56Z zombor $
|
||||
* $Id: remote.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class remote_Core {
|
||||
|
||||
@@ -35,7 +35,7 @@ class remote_Core {
|
||||
$CRLF = "\r\n";
|
||||
|
||||
// Send request
|
||||
fwrite($remote, 'HEAD '.$url['path'].' HTTP/1.0'.$CRLF);
|
||||
fwrite($remote, 'HEAD '.$url['path'].(isset($url['query']) ? '?'.$url['query'] : '').' HTTP/1.0'.$CRLF);
|
||||
fwrite($remote, 'Host: '.$url['host'].$CRLF);
|
||||
fwrite($remote, 'Connection: close'.$CRLF);
|
||||
fwrite($remote, 'User-Agent: Kohana Framework (+http://kohanaphp.com/)'.$CRLF);
|
||||
@@ -63,4 +63,4 @@ class remote_Core {
|
||||
return isset($response) ? $response : FALSE;
|
||||
}
|
||||
|
||||
} // End remote
|
||||
} // End remote
|
||||
|
||||
@@ -2,35 +2,48 @@
|
||||
/**
|
||||
* Request helper class.
|
||||
*
|
||||
* $Id: request.php 4355 2009-05-15 17:18:28Z kiall $
|
||||
* $Id: request.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class request_Core {
|
||||
|
||||
// Possible HTTP methods
|
||||
protected static $http_methods = array('get', 'head', 'options', 'post', 'put', 'delete');
|
||||
|
||||
// Content types from client's HTTP Accept request header (array)
|
||||
// Character sets from client's HTTP Accept-Charset request header
|
||||
protected static $accept_charsets;
|
||||
|
||||
// Content codings from client's HTTP Accept-Encoding request header
|
||||
protected static $accept_encodings;
|
||||
|
||||
// Language tags from client's HTTP Accept-Language request header
|
||||
protected static $accept_languages;
|
||||
|
||||
// Content types from client's HTTP Accept request header
|
||||
protected static $accept_types;
|
||||
|
||||
// The current user agent and its parsed attributes
|
||||
protected static $user_agent;
|
||||
|
||||
/**
|
||||
* Returns the HTTP referrer, or the default if the referrer is not set.
|
||||
*
|
||||
* @param mixed default to return
|
||||
* @param bool Remove base URL
|
||||
* @return string
|
||||
*/
|
||||
public static function referrer($default = FALSE)
|
||||
public static function referrer($default = FALSE, $remove_base = FALSE)
|
||||
{
|
||||
if ( ! empty($_SERVER['HTTP_REFERER']))
|
||||
{
|
||||
// Set referrer
|
||||
$ref = $_SERVER['HTTP_REFERER'];
|
||||
|
||||
if (strpos($ref, url::base(FALSE)) === 0)
|
||||
if ($remove_base === TRUE AND (strpos($ref, url::base(FALSE)) === 0))
|
||||
{
|
||||
// Remove the base URL from the referrer
|
||||
$ref = substr($ref, strlen(url::base(FALSE)));
|
||||
@@ -84,10 +97,59 @@ class request_Core {
|
||||
$method = strtolower($_SERVER['REQUEST_METHOD']);
|
||||
|
||||
if ( ! in_array($method, request::$http_methods))
|
||||
throw new Kohana_Exception('request.unknown_method', $method);
|
||||
throw new Kohana_Exception('Invalid request method :method:', array(':method:' => $method));
|
||||
|
||||
return $method;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves current user agent information
|
||||
* keys: browser, version, platform, mobile, robot
|
||||
*
|
||||
* @param string key
|
||||
* @return mixed NULL or the parsed value
|
||||
*/
|
||||
public static function user_agent($key = 'agent')
|
||||
{
|
||||
// Retrieve raw user agent without parsing
|
||||
if ($key === 'agent')
|
||||
{
|
||||
if (request::$user_agent === NULL)
|
||||
return request::$user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? trim($_SERVER['HTTP_USER_AGENT']) : '';
|
||||
|
||||
if (is_array(request::$user_agent))
|
||||
return request::$user_agent['agent'];
|
||||
|
||||
return request::$user_agent;
|
||||
}
|
||||
|
||||
if ( ! is_array(request::$user_agent))
|
||||
{
|
||||
request::$user_agent['agent'] = isset($_SERVER['HTTP_USER_AGENT']) ? trim($_SERVER['HTTP_USER_AGENT']) : '';
|
||||
|
||||
// Parse the user agent and extract basic information
|
||||
foreach (Kohana::config('user_agents') as $type => $data)
|
||||
{
|
||||
foreach ($data as $fragment => $name)
|
||||
{
|
||||
if (stripos(request::$user_agent['agent'], $fragment) !== FALSE)
|
||||
{
|
||||
if ($type === 'browser' AND preg_match('|'.preg_quote($fragment).'[^0-9.]*+([0-9.][0-9.a-z]*)|i', request::$user_agent['agent'], $match))
|
||||
{
|
||||
// Set the browser version
|
||||
request::$user_agent['version'] = $match[1];
|
||||
}
|
||||
|
||||
// Set the agent name
|
||||
request::$user_agent[$type] = $name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return isset(request::$user_agent[$key]) ? request::$user_agent[$key] : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns boolean of whether client accepts content type.
|
||||
@@ -98,7 +160,7 @@ class request_Core {
|
||||
*/
|
||||
public static function accepts($type = NULL, $explicit_check = FALSE)
|
||||
{
|
||||
request::parse_accept_header();
|
||||
request::parse_accept_content_header();
|
||||
|
||||
if ($type === NULL)
|
||||
return request::$accept_types;
|
||||
@@ -106,6 +168,56 @@ class request_Core {
|
||||
return (request::accepts_at_quality($type, $explicit_check) > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns boolean indicating if the client accepts a charset
|
||||
*
|
||||
* @param string
|
||||
* @return boolean
|
||||
*/
|
||||
public static function accepts_charset($charset = NULL)
|
||||
{
|
||||
request::parse_accept_charset_header();
|
||||
|
||||
if ($charset === NULL)
|
||||
return request::$accept_charsets;
|
||||
|
||||
return (request::accepts_charset_at_quality($charset) > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns boolean indicating if the client accepts an encoding
|
||||
*
|
||||
* @param string
|
||||
* @param boolean set to TRUE to disable wildcard checking
|
||||
* @return boolean
|
||||
*/
|
||||
public static function accepts_encoding($encoding = NULL, $explicit_check = FALSE)
|
||||
{
|
||||
request::parse_accept_encoding_header();
|
||||
|
||||
if ($encoding === NULL)
|
||||
return request::$accept_encodings;
|
||||
|
||||
return (request::accepts_encoding_at_quality($encoding, $explicit_check) > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns boolean indicating if the client accepts a language tag
|
||||
*
|
||||
* @param string language tag
|
||||
* @param boolean set to TRUE to disable prefix and wildcard checking
|
||||
* @return boolean
|
||||
*/
|
||||
public static function accepts_language($tag = NULL, $explicit_check = FALSE)
|
||||
{
|
||||
request::parse_accept_language_header();
|
||||
|
||||
if ($tag === NULL)
|
||||
return request::$accept_languages;
|
||||
|
||||
return (request::accepts_language_at_quality($tag, $explicit_check) > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the q values for given array of content types and return the one with the highest value.
|
||||
* If items are found to have the same q value, the first one encountered in the given array wins.
|
||||
@@ -117,20 +229,13 @@ class request_Core {
|
||||
*/
|
||||
public static function preferred_accept($types, $explicit_check = FALSE)
|
||||
{
|
||||
// Initialize
|
||||
$mime_types = array();
|
||||
$max_q = 0;
|
||||
$preferred = FALSE;
|
||||
|
||||
// Load q values for all given content types
|
||||
foreach (array_unique($types) as $type)
|
||||
foreach ($types as $type)
|
||||
{
|
||||
$mime_types[$type] = request::accepts_at_quality($type, $explicit_check);
|
||||
}
|
||||
$q = request::accepts_at_quality($type, $explicit_check);
|
||||
|
||||
// Look for the highest q value
|
||||
foreach ($mime_types as $type => $q)
|
||||
{
|
||||
if ($q > $max_q)
|
||||
{
|
||||
$max_q = $q;
|
||||
@@ -142,18 +247,104 @@ class request_Core {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns quality factor at which the client accepts content type.
|
||||
* Compare the q values for a given array of character sets and return the
|
||||
* one with the highest value. If items are found to have the same q value,
|
||||
* the first one encountered takes precedence. If all items in the given
|
||||
* array have a q value of 0, FALSE is returned.
|
||||
*
|
||||
* @param array character sets
|
||||
* @return mixed
|
||||
*/
|
||||
public static function preferred_charset($charsets)
|
||||
{
|
||||
$max_q = 0;
|
||||
$preferred = FALSE;
|
||||
|
||||
foreach ($charsets as $charset)
|
||||
{
|
||||
$q = request::accepts_charset_at_quality($charset);
|
||||
|
||||
if ($q > $max_q)
|
||||
{
|
||||
$max_q = $q;
|
||||
$preferred = $charset;
|
||||
}
|
||||
}
|
||||
|
||||
return $preferred;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the q values for a given array of encodings and return the one with
|
||||
* the highest value. If items are found to have the same q value, the first
|
||||
* one encountered takes precedence. If all items in the given array have
|
||||
* a q value of 0, FALSE is returned.
|
||||
*
|
||||
* @param array encodings
|
||||
* @param boolean set to TRUE to disable wildcard checking
|
||||
* @return mixed
|
||||
*/
|
||||
public static function preferred_encoding($encodings, $explicit_check = FALSE)
|
||||
{
|
||||
$max_q = 0;
|
||||
$preferred = FALSE;
|
||||
|
||||
foreach ($encodings as $encoding)
|
||||
{
|
||||
$q = request::accepts_encoding_at_quality($encoding, $explicit_check);
|
||||
|
||||
if ($q > $max_q)
|
||||
{
|
||||
$max_q = $q;
|
||||
$preferred = $encoding;
|
||||
}
|
||||
}
|
||||
|
||||
return $preferred;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the q values for a given array of language tags and return the
|
||||
* one with the highest value. If items are found to have the same q value,
|
||||
* the first one encountered takes precedence. If all items in the given
|
||||
* array have a q value of 0, FALSE is returned.
|
||||
*
|
||||
* @param array language tags
|
||||
* @param boolean set to TRUE to disable prefix and wildcard checking
|
||||
* @return mixed
|
||||
*/
|
||||
public static function preferred_language($tags, $explicit_check = FALSE)
|
||||
{
|
||||
$max_q = 0;
|
||||
$preferred = FALSE;
|
||||
|
||||
foreach ($tags as $tag)
|
||||
{
|
||||
$q = request::accepts_language_at_quality($tag, $explicit_check);
|
||||
|
||||
if ($q > $max_q)
|
||||
{
|
||||
$max_q = $q;
|
||||
$preferred = $tag;
|
||||
}
|
||||
}
|
||||
|
||||
return $preferred;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns quality factor at which the client accepts content type
|
||||
*
|
||||
* @param string content type (e.g. "image/jpg", "jpg")
|
||||
* @param boolean set to TRUE to disable wildcard checking
|
||||
* @return integer|float
|
||||
*/
|
||||
public static function accepts_at_quality($type = NULL, $explicit_check = FALSE)
|
||||
public static function accepts_at_quality($type, $explicit_check = FALSE)
|
||||
{
|
||||
request::parse_accept_header();
|
||||
request::parse_accept_content_header();
|
||||
|
||||
// Normalize type
|
||||
$type = strtolower((string) $type);
|
||||
$type = strtolower($type);
|
||||
|
||||
// General content type (e.g. "jpg")
|
||||
if (strpos($type, '/') === FALSE)
|
||||
@@ -178,62 +369,251 @@ class request_Core {
|
||||
if (isset(request::$accept_types[$type[0]][$type[1]]))
|
||||
return request::$accept_types[$type[0]][$type[1]];
|
||||
|
||||
// Wildcard match (if not checking explicitly)
|
||||
if ($explicit_check === FALSE AND isset(request::$accept_types[$type[0]]['*']))
|
||||
return request::$accept_types[$type[0]]['*'];
|
||||
if ($explicit_check === FALSE)
|
||||
{
|
||||
// Wildcard match
|
||||
if (isset(request::$accept_types[$type[0]]['*']))
|
||||
return request::$accept_types[$type[0]]['*'];
|
||||
|
||||
// Catch-all wildcard match (if not checking explicitly)
|
||||
if ($explicit_check === FALSE AND isset(request::$accept_types['*']['*']))
|
||||
return request::$accept_types['*']['*'];
|
||||
// Catch-all wildcard match
|
||||
if (isset(request::$accept_types['*']['*']))
|
||||
return request::$accept_types['*']['*'];
|
||||
}
|
||||
|
||||
// Content type not accepted
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses client's HTTP Accept request header, and builds array structure representing it.
|
||||
* Returns quality factor at which the client accepts a charset
|
||||
*
|
||||
* @return void
|
||||
* @param string charset (e.g., "ISO-8859-1", "utf-8")
|
||||
* @return integer|float
|
||||
*/
|
||||
protected static function parse_accept_header()
|
||||
public static function accepts_charset_at_quality($charset)
|
||||
{
|
||||
request::parse_accept_charset_header();
|
||||
|
||||
// Normalize charset
|
||||
$charset = strtolower($charset);
|
||||
|
||||
// Exact match
|
||||
if (isset(request::$accept_charsets[$charset]))
|
||||
return request::$accept_charsets[$charset];
|
||||
|
||||
if (isset(request::$accept_charsets['*']))
|
||||
return request::$accept_charsets['*'];
|
||||
|
||||
if ($charset === 'iso-8859-1')
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns quality factor at which the client accepts an encoding
|
||||
*
|
||||
* @param string encoding (e.g., "gzip", "deflate")
|
||||
* @param boolean set to TRUE to disable wildcard checking
|
||||
* @return integer|float
|
||||
*/
|
||||
public static function accepts_encoding_at_quality($encoding, $explicit_check = FALSE)
|
||||
{
|
||||
request::parse_accept_encoding_header();
|
||||
|
||||
// Normalize encoding
|
||||
$encoding = strtolower($encoding);
|
||||
|
||||
// Exact match
|
||||
if (isset(request::$accept_encodings[$encoding]))
|
||||
return request::$accept_encodings[$encoding];
|
||||
|
||||
if ($explicit_check === FALSE)
|
||||
{
|
||||
if (isset(request::$accept_encodings['*']))
|
||||
return request::$accept_encodings['*'];
|
||||
|
||||
if ($encoding === 'identity')
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns quality factor at which the client accepts a language
|
||||
*
|
||||
* @param string tag (e.g., "en", "en-us", "fr-ca")
|
||||
* @param boolean set to TRUE to disable prefix and wildcard checking
|
||||
* @return integer|float
|
||||
*/
|
||||
public static function accepts_language_at_quality($tag, $explicit_check = FALSE)
|
||||
{
|
||||
request::parse_accept_language_header();
|
||||
|
||||
$tag = explode('-', strtolower($tag), 2);
|
||||
|
||||
if (isset(request::$accept_languages[$tag[0]]))
|
||||
{
|
||||
if (isset($tag[1]))
|
||||
{
|
||||
// Exact match
|
||||
if (isset(request::$accept_languages[$tag[0]][$tag[1]]))
|
||||
return request::$accept_languages[$tag[0]][$tag[1]];
|
||||
|
||||
// A prefix matches
|
||||
if ($explicit_check === FALSE AND isset(request::$accept_languages[$tag[0]]['*']))
|
||||
return request::$accept_languages[$tag[0]]['*'];
|
||||
}
|
||||
else
|
||||
{
|
||||
// No subtags
|
||||
if (isset(request::$accept_languages[$tag[0]]['*']))
|
||||
return request::$accept_languages[$tag[0]]['*'];
|
||||
}
|
||||
}
|
||||
|
||||
if ($explicit_check === FALSE AND isset(request::$accept_languages['*']))
|
||||
return request::$accept_languages['*'];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a HTTP Accept or Accept-* header for q values
|
||||
*
|
||||
* @param string header data
|
||||
* @return array
|
||||
*/
|
||||
protected static function parse_accept_header($header)
|
||||
{
|
||||
$result = array();
|
||||
|
||||
// Remove linebreaks and parse the HTTP Accept header
|
||||
foreach (explode(',', str_replace(array("\r", "\n"), '', strtolower($header))) as $entry)
|
||||
{
|
||||
// Explode each entry in content type and possible quality factor
|
||||
$entry = explode(';', trim($entry), 2);
|
||||
|
||||
$q = (isset($entry[1]) AND preg_match('~\bq\s*+=\s*+([.0-9]+)~', $entry[1], $match)) ? (float) $match[1] : 1;
|
||||
|
||||
// Overwrite entries with a smaller q value
|
||||
if ( ! isset($result[$entry[0]]) OR $q > $result[$entry[0]])
|
||||
{
|
||||
$result[$entry[0]] = $q;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a client's HTTP Accept-Charset header
|
||||
*/
|
||||
protected static function parse_accept_charset_header()
|
||||
{
|
||||
// Run this function just once
|
||||
if (request::$accept_charsets !== NULL)
|
||||
return;
|
||||
|
||||
// No HTTP Accept-Charset header found
|
||||
if (empty($_SERVER['HTTP_ACCEPT_CHARSET']))
|
||||
{
|
||||
// Accept everything
|
||||
request::$accept_charsets['*'] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
request::$accept_charsets = request::parse_accept_header($_SERVER['HTTP_ACCEPT_CHARSET']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a client's HTTP Accept header
|
||||
*/
|
||||
protected static function parse_accept_content_header()
|
||||
{
|
||||
// Run this function just once
|
||||
if (request::$accept_types !== NULL)
|
||||
return;
|
||||
|
||||
// Initialize accept_types array
|
||||
request::$accept_types = array();
|
||||
|
||||
// No HTTP Accept header found
|
||||
if (empty($_SERVER['HTTP_ACCEPT']))
|
||||
{
|
||||
// Accept everything
|
||||
request::$accept_types['*']['*'] = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove linebreaks and parse the HTTP Accept header
|
||||
foreach (explode(',', str_replace(array("\r", "\n"), '', $_SERVER['HTTP_ACCEPT'])) as $accept_entry)
|
||||
else
|
||||
{
|
||||
// Explode each entry in content type and possible quality factor
|
||||
$accept_entry = explode(';', trim($accept_entry), 2);
|
||||
request::$accept_types = array();
|
||||
|
||||
// Explode each content type (e.g. "text/html")
|
||||
$type = explode('/', $accept_entry[0], 2);
|
||||
|
||||
// Skip invalid content types
|
||||
if ( ! isset($type[1]))
|
||||
continue;
|
||||
|
||||
// Assume a default quality factor of 1 if no custom q value found
|
||||
$q = (isset($accept_entry[1]) AND preg_match('~\bq\s*+=\s*+([.0-9]+)~', $accept_entry[1], $match)) ? (float) $match[1] : 1;
|
||||
|
||||
// Populate accept_types array
|
||||
if ( ! isset(request::$accept_types[$type[0]][$type[1]]) OR $q > request::$accept_types[$type[0]][$type[1]])
|
||||
foreach (request::parse_accept_header($_SERVER['HTTP_ACCEPT']) as $type => $q)
|
||||
{
|
||||
// Explode each content type (e.g. "text/html")
|
||||
$type = explode('/', $type, 2);
|
||||
|
||||
// Skip invalid content types
|
||||
if ( ! isset($type[1]))
|
||||
continue;
|
||||
|
||||
request::$accept_types[$type[0]][$type[1]] = $q;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End request
|
||||
/**
|
||||
* Parses a client's HTTP Accept-Encoding header
|
||||
*/
|
||||
protected static function parse_accept_encoding_header()
|
||||
{
|
||||
// Run this function just once
|
||||
if (request::$accept_encodings !== NULL)
|
||||
return;
|
||||
|
||||
// No HTTP Accept-Encoding header found
|
||||
if ( ! isset($_SERVER['HTTP_ACCEPT_ENCODING']))
|
||||
{
|
||||
// Accept everything
|
||||
request::$accept_encodings['*'] = 1;
|
||||
}
|
||||
elseif ($_SERVER['HTTP_ACCEPT_ENCODING'] === '')
|
||||
{
|
||||
// Accept only identity
|
||||
request::$accept_encodings['identity'] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
request::$accept_encodings = request::parse_accept_header($_SERVER['HTTP_ACCEPT_ENCODING']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a client's HTTP Accept-Language header
|
||||
*/
|
||||
protected static function parse_accept_language_header()
|
||||
{
|
||||
// Run this function just once
|
||||
if (request::$accept_languages !== NULL)
|
||||
return;
|
||||
|
||||
// No HTTP Accept-Language header found
|
||||
if (empty($_SERVER['HTTP_ACCEPT_LANGUAGE']))
|
||||
{
|
||||
// Accept everything
|
||||
request::$accept_languages['*'] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
request::$accept_languages = array();
|
||||
|
||||
foreach (request::parse_accept_header($_SERVER['HTTP_ACCEPT_LANGUAGE']) as $tag => $q)
|
||||
{
|
||||
// Explode each language (e.g. "en-us")
|
||||
$tag = explode('-', $tag, 2);
|
||||
|
||||
request::$accept_languages[$tag[0]][isset($tag[1]) ? $tag[1] : '*'] = $q;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End request
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
/**
|
||||
* Security helper class.
|
||||
*
|
||||
* $Id: security.php 3769 2008-12-15 00:48:56Z zombor $
|
||||
* $Id: security.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class security_Core {
|
||||
|
||||
@@ -15,11 +15,12 @@ class security_Core {
|
||||
* Sanitize a string with the xss_clean method.
|
||||
*
|
||||
* @param string string to sanitize
|
||||
* @param string xss_clean method to use ('htmlpurifier' or defaults to built-in method)
|
||||
* @return string
|
||||
*/
|
||||
public static function xss_clean($str)
|
||||
public static function xss_clean($str, $tool = NULL)
|
||||
{
|
||||
return Input::instance()->xss_clean($str);
|
||||
return Input::instance()->xss_clean($str, $tool);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
/**
|
||||
* Text helper class.
|
||||
*
|
||||
* $Id: text.php 3769 2008-12-15 00:48:56Z zombor $
|
||||
* $Id: text.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class text_Core {
|
||||
|
||||
@@ -52,7 +52,7 @@ class text_Core {
|
||||
|
||||
$limit = (int) $limit;
|
||||
|
||||
if (trim($str) === '' OR utf8::strlen($str) <= $limit)
|
||||
if (trim($str) === '' OR mb_strlen($str) <= $limit)
|
||||
return $str;
|
||||
|
||||
if ($limit <= 0)
|
||||
@@ -60,7 +60,7 @@ class text_Core {
|
||||
|
||||
if ($preserve_words == FALSE)
|
||||
{
|
||||
return rtrim(utf8::substr($str, 0, $limit)).$end_char;
|
||||
return rtrim(mb_substr($str, 0, $limit)).$end_char;
|
||||
}
|
||||
|
||||
preg_match('/^.{'.($limit - 1).'}\S*/us', $str, $matches);
|
||||
@@ -128,7 +128,7 @@ class text_Core {
|
||||
break;
|
||||
default:
|
||||
$pool = (string) $type;
|
||||
$utf8 = ! utf8::is_ascii($pool);
|
||||
$utf8 = ! text::is_ascii($pool);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ class text_Core {
|
||||
* @param boolean replace words across word boundries (space, period, etc)
|
||||
* @return string
|
||||
*/
|
||||
public static function censor($str, $badwords, $replacement = '#', $replace_partial_words = FALSE)
|
||||
public static function censor($str, $badwords, $replacement = '#', $replace_partial_words = TRUE)
|
||||
{
|
||||
foreach ((array) $badwords as $key => $badword)
|
||||
{
|
||||
@@ -192,7 +192,7 @@ class text_Core {
|
||||
|
||||
$regex = '('.implode('|', $badwords).')';
|
||||
|
||||
if ($replace_partial_words == TRUE)
|
||||
if ($replace_partial_words === FALSE)
|
||||
{
|
||||
// Just using \b isn't sufficient when we need to replace a badword that already contains word boundaries itself
|
||||
$regex = '(?<=\b|\s|^)'.$regex.'(?=\b|\s|$)';
|
||||
@@ -200,10 +200,10 @@ class text_Core {
|
||||
|
||||
$regex = '!'.$regex.'!ui';
|
||||
|
||||
if (utf8::strlen($replacement) == 1)
|
||||
if (mb_strlen($replacement) == 1)
|
||||
{
|
||||
$regex .= 'e';
|
||||
return preg_replace($regex, 'str_repeat($replacement, utf8::strlen(\'$1\'))', $str);
|
||||
return preg_replace($regex, 'str_repeat($replacement, mb_strlen(\'$1\'))', $str);
|
||||
}
|
||||
|
||||
return preg_replace($regex, $replacement, $str);
|
||||
@@ -235,15 +235,59 @@ class text_Core {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts text email addresses and anchors into links.
|
||||
* An alternative to the php levenshtein() function that work out the
|
||||
* distance between 2 words using the Damerau–Levenshtein algorithm.
|
||||
* Credit: http://forums.devnetwork.net/viewtopic.php?f=50&t=89094
|
||||
*
|
||||
* @param string text to auto link
|
||||
* @return string
|
||||
* @see http://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance
|
||||
* @param string first word
|
||||
* @param string second word
|
||||
* @return int distance between words
|
||||
*/
|
||||
public static function auto_link($text)
|
||||
public static function distance($string1, $string2)
|
||||
{
|
||||
// Auto link emails first to prevent problems with "www.domain.com@example.com"
|
||||
return text::auto_link_urls(text::auto_link_emails($text));
|
||||
$string1_length = strlen($string1);
|
||||
$string2_length = strlen($string2);
|
||||
|
||||
// Here we start building the table of values
|
||||
$matrix = array();
|
||||
|
||||
// String1 length + 1 = rows.
|
||||
for ($i = 0; $i <= $string1_length; ++$i)
|
||||
{
|
||||
$matrix[$i][0] = $i;
|
||||
}
|
||||
|
||||
// String2 length + 1 columns.
|
||||
for ($j = 0; $j <= $string2_length; ++$j)
|
||||
{
|
||||
$matrix[0][$j] = $j;
|
||||
}
|
||||
|
||||
for ($i = 1; $i <= $string1_length; ++$i)
|
||||
{
|
||||
for ($j = 1; $j <= $string2_length; ++$j)
|
||||
{
|
||||
$cost = substr($string1, $i - 1, 1) == substr($string2, $j - 1, 1) ? 0 : 1;
|
||||
|
||||
$matrix[$i][$j] = min(
|
||||
$matrix[$i - 1][$j] + 1, // deletion
|
||||
$matrix[$i][$j - 1] + 1, // insertion
|
||||
$matrix[$i - 1][$j - 1] + $cost // substitution
|
||||
);
|
||||
|
||||
if ($i > 1 && $j > 1 && (substr($string1, $i - 1, 1) == substr($string2, $j - 2, 1))
|
||||
&& (substr($string1, $i - 2, 1) == substr($string2, $j - 1, 1)))
|
||||
{
|
||||
$matrix[$i][$j] = min(
|
||||
$matrix[$i][$j],
|
||||
$matrix[$i - 2][$j - 2] + $cost // transposition
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $matrix[$string1_length][$string2_length];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -304,9 +348,10 @@ class text_Core {
|
||||
* Automatically applies <p> and <br /> markup to text. Basically nl2br() on steroids.
|
||||
*
|
||||
* @param string subject
|
||||
* @param boolean convert single linebreaks to <br />
|
||||
* @return string
|
||||
*/
|
||||
public static function auto_p($str)
|
||||
public static function auto_p($str, $br = TRUE)
|
||||
{
|
||||
// Trim whitespace
|
||||
if (($str = trim($str)) === '')
|
||||
@@ -343,7 +388,10 @@ class text_Core {
|
||||
}
|
||||
|
||||
// Convert single linebreaks to <br />
|
||||
$str = preg_replace('~(?<!\n)\n(?!\n)~', "<br />\n", $str);
|
||||
if ($br === TRUE)
|
||||
{
|
||||
$str = preg_replace('~(?<!\n)\n(?!\n)~', "<br />\n", $str);
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
@@ -368,13 +416,13 @@ class text_Core {
|
||||
// IEC prefixes (binary)
|
||||
if ($si == FALSE OR strpos($force_unit, 'i') !== FALSE)
|
||||
{
|
||||
$units = array('B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB');
|
||||
$units = array(__('B'), __('KiB'), __('MiB'), __('GiB'), __('TiB'), __('PiB'));
|
||||
$mod = 1024;
|
||||
}
|
||||
// SI prefixes (decimal)
|
||||
else
|
||||
{
|
||||
$units = array('B', 'kB', 'MB', 'GB', 'TB', 'PB');
|
||||
$units = array(__('B'), __('kB'), __('MB'), __('GB'), __('TB'), __('PB'));
|
||||
$mod = 1000;
|
||||
}
|
||||
|
||||
@@ -407,4 +455,134 @@ class text_Core {
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether a string contains only 7bit ASCII bytes. This is used to
|
||||
* determine when to use native functions or UTF-8 functions.
|
||||
*
|
||||
* @see http://sourceforge.net/projects/phputf8/
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*
|
||||
* @param string string to check
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_ascii($str)
|
||||
{
|
||||
return is_string($str) AND ! preg_match('/[^\x00-\x7F]/S', $str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips out device control codes in the ASCII range.
|
||||
*
|
||||
* @see http://sourceforge.net/projects/phputf8/
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*
|
||||
* @param string string to clean
|
||||
* @return string
|
||||
*/
|
||||
public static function strip_ascii_ctrl($str)
|
||||
{
|
||||
return preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S', '', $str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips out all non-7bit ASCII bytes.
|
||||
*
|
||||
* @see http://sourceforge.net/projects/phputf8/
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*
|
||||
* @param string string to clean
|
||||
* @return string
|
||||
*/
|
||||
public static function strip_non_ascii($str)
|
||||
{
|
||||
return preg_replace('/[^\x00-\x7F]+/S', '', $str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces special/accented UTF-8 characters by ASCII-7 'equivalents'.
|
||||
*
|
||||
* @author Andreas Gohr <andi@splitbrain.org>
|
||||
* @see http://sourceforge.net/projects/phputf8/
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*
|
||||
* @param string string to transliterate
|
||||
* @param integer -1 lowercase only, +1 uppercase only, 0 both cases
|
||||
* @return string
|
||||
*/
|
||||
public static function transliterate_to_ascii($str, $case = 0)
|
||||
{
|
||||
static $UTF8_LOWER_ACCENTS = NULL;
|
||||
static $UTF8_UPPER_ACCENTS = NULL;
|
||||
|
||||
if ($case <= 0)
|
||||
{
|
||||
if ($UTF8_LOWER_ACCENTS === NULL)
|
||||
{
|
||||
$UTF8_LOWER_ACCENTS = array(
|
||||
'à' => 'a', 'ô' => 'o', 'ď' => 'd', 'ḟ' => 'f', 'ë' => 'e', 'š' => 's', 'ơ' => 'o',
|
||||
'ß' => 'ss', 'ă' => 'a', 'ř' => 'r', 'ț' => 't', 'ň' => 'n', 'ā' => 'a', 'ķ' => 'k',
|
||||
'ŝ' => 's', 'ỳ' => 'y', 'ņ' => 'n', 'ĺ' => 'l', 'ħ' => 'h', 'ṗ' => 'p', 'ó' => 'o',
|
||||
'ú' => 'u', 'ě' => 'e', 'é' => 'e', 'ç' => 'c', 'ẁ' => 'w', 'ċ' => 'c', 'õ' => 'o',
|
||||
'ṡ' => 's', 'ø' => 'o', 'ģ' => 'g', 'ŧ' => 't', 'ș' => 's', 'ė' => 'e', 'ĉ' => 'c',
|
||||
'ś' => 's', 'î' => 'i', 'ű' => 'u', 'ć' => 'c', 'ę' => 'e', 'ŵ' => 'w', 'ṫ' => 't',
|
||||
'ū' => 'u', 'č' => 'c', 'ö' => 'o', 'è' => 'e', 'ŷ' => 'y', 'ą' => 'a', 'ł' => 'l',
|
||||
'ų' => 'u', 'ů' => 'u', 'ş' => 's', 'ğ' => 'g', 'ļ' => 'l', 'ƒ' => 'f', 'ž' => 'z',
|
||||
'ẃ' => 'w', 'ḃ' => 'b', 'å' => 'a', 'ì' => 'i', 'ï' => 'i', 'ḋ' => 'd', 'ť' => 't',
|
||||
'ŗ' => 'r', 'ä' => 'a', 'í' => 'i', 'ŕ' => 'r', 'ê' => 'e', 'ü' => 'u', 'ò' => 'o',
|
||||
'ē' => 'e', 'ñ' => 'n', 'ń' => 'n', 'ĥ' => 'h', 'ĝ' => 'g', 'đ' => 'd', 'ĵ' => 'j',
|
||||
'ÿ' => 'y', 'ũ' => 'u', 'ŭ' => 'u', 'ư' => 'u', 'ţ' => 't', 'ý' => 'y', 'ő' => 'o',
|
||||
'â' => 'a', 'ľ' => 'l', 'ẅ' => 'w', 'ż' => 'z', 'ī' => 'i', 'ã' => 'a', 'ġ' => 'g',
|
||||
'ṁ' => 'm', 'ō' => 'o', 'ĩ' => 'i', 'ù' => 'u', 'į' => 'i', 'ź' => 'z', 'á' => 'a',
|
||||
'û' => 'u', 'þ' => 'th', 'ð' => 'dh', 'æ' => 'ae', 'µ' => 'u', 'ĕ' => 'e', 'ı' => 'i',
|
||||
);
|
||||
}
|
||||
|
||||
$str = str_replace(
|
||||
array_keys($UTF8_LOWER_ACCENTS),
|
||||
array_values($UTF8_LOWER_ACCENTS),
|
||||
$str
|
||||
);
|
||||
}
|
||||
|
||||
if ($case >= 0)
|
||||
{
|
||||
if ($UTF8_UPPER_ACCENTS === NULL)
|
||||
{
|
||||
$UTF8_UPPER_ACCENTS = array(
|
||||
'À' => 'A', 'Ô' => 'O', 'Ď' => 'D', 'Ḟ' => 'F', 'Ë' => 'E', 'Š' => 'S', 'Ơ' => 'O',
|
||||
'Ă' => 'A', 'Ř' => 'R', 'Ț' => 'T', 'Ň' => 'N', 'Ā' => 'A', 'Ķ' => 'K', 'Ĕ' => 'E',
|
||||
'Ŝ' => 'S', 'Ỳ' => 'Y', 'Ņ' => 'N', 'Ĺ' => 'L', 'Ħ' => 'H', 'Ṗ' => 'P', 'Ó' => 'O',
|
||||
'Ú' => 'U', 'Ě' => 'E', 'É' => 'E', 'Ç' => 'C', 'Ẁ' => 'W', 'Ċ' => 'C', 'Õ' => 'O',
|
||||
'Ṡ' => 'S', 'Ø' => 'O', 'Ģ' => 'G', 'Ŧ' => 'T', 'Ș' => 'S', 'Ė' => 'E', 'Ĉ' => 'C',
|
||||
'Ś' => 'S', 'Î' => 'I', 'Ű' => 'U', 'Ć' => 'C', 'Ę' => 'E', 'Ŵ' => 'W', 'Ṫ' => 'T',
|
||||
'Ū' => 'U', 'Č' => 'C', 'Ö' => 'O', 'È' => 'E', 'Ŷ' => 'Y', 'Ą' => 'A', 'Ł' => 'L',
|
||||
'Ų' => 'U', 'Ů' => 'U', 'Ş' => 'S', 'Ğ' => 'G', 'Ļ' => 'L', 'Ƒ' => 'F', 'Ž' => 'Z',
|
||||
'Ẃ' => 'W', 'Ḃ' => 'B', 'Å' => 'A', 'Ì' => 'I', 'Ï' => 'I', 'Ḋ' => 'D', 'Ť' => 'T',
|
||||
'Ŗ' => 'R', 'Ä' => 'A', 'Í' => 'I', 'Ŕ' => 'R', 'Ê' => 'E', 'Ü' => 'U', 'Ò' => 'O',
|
||||
'Ē' => 'E', 'Ñ' => 'N', 'Ń' => 'N', 'Ĥ' => 'H', 'Ĝ' => 'G', 'Đ' => 'D', 'Ĵ' => 'J',
|
||||
'Ÿ' => 'Y', 'Ũ' => 'U', 'Ŭ' => 'U', 'Ư' => 'U', 'Ţ' => 'T', 'Ý' => 'Y', 'Ő' => 'O',
|
||||
'Â' => 'A', 'Ľ' => 'L', 'Ẅ' => 'W', 'Ż' => 'Z', 'Ī' => 'I', 'Ã' => 'A', 'Ġ' => 'G',
|
||||
'Ṁ' => 'M', 'Ō' => 'O', 'Ĩ' => 'I', 'Ù' => 'U', 'Į' => 'I', 'Ź' => 'Z', 'Á' => 'A',
|
||||
'Û' => 'U', 'Þ' => 'Th', 'Ð' => 'Dh', 'Æ' => 'Ae', 'İ' => 'I',
|
||||
);
|
||||
}
|
||||
|
||||
$str = str_replace(
|
||||
array_keys($UTF8_UPPER_ACCENTS),
|
||||
array_values($UTF8_UPPER_ACCENTS),
|
||||
$str
|
||||
);
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
} // End text
|
||||
@@ -3,12 +3,12 @@
|
||||
* Upload helper class for working with the global $_FILES
|
||||
* array and Validation library.
|
||||
*
|
||||
* $Id: upload.php 3769 2008-12-15 00:48:56Z zombor $
|
||||
* $Id: upload.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class upload_Core {
|
||||
|
||||
@@ -54,7 +54,7 @@ class upload_Core {
|
||||
}
|
||||
|
||||
if ( ! is_writable($directory))
|
||||
throw new Kohana_Exception('upload.not_writable', $directory);
|
||||
throw new Kohana_Exception('The upload destination folder, :dir:, does not appear to be writable.', array(':dir:' => $directory));
|
||||
|
||||
if (is_uploaded_file($file['tmp_name']) AND move_uploaded_file($file['tmp_name'], $filename = $directory.$filename))
|
||||
{
|
||||
@@ -118,11 +118,8 @@ class upload_Core {
|
||||
// Get the default extension of the file
|
||||
$extension = strtolower(substr(strrchr($file['name'], '.'), 1));
|
||||
|
||||
// Get the mime types for the extension
|
||||
$mime_types = Kohana::config('mimes.'.$extension);
|
||||
|
||||
// Make sure there is an extension, that the extension is allowed, and that mime types exist
|
||||
return ( ! empty($extension) AND in_array($extension, $allowed_types) AND is_array($mime_types));
|
||||
// Make sure there is an extension and that the extension is allowed
|
||||
return ( ! empty($extension) AND in_array($extension, $allowed_types));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
/**
|
||||
* URL helper class.
|
||||
*
|
||||
* $Id: url.php 4479 2009-07-23 04:51:22Z ixmatus $
|
||||
* $Id: url.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class url_Core {
|
||||
|
||||
@@ -15,7 +15,7 @@ class url_Core {
|
||||
* Fetches the current URI.
|
||||
*
|
||||
* @param boolean include the query string
|
||||
* @param boolean include the suffix
|
||||
* @param boolean include the suffix
|
||||
* @return string
|
||||
*/
|
||||
public static function current($qs = FALSE, $suffix = FALSE)
|
||||
@@ -167,7 +167,7 @@ class url_Core {
|
||||
$separator = ($separator === '-') ? '-' : '_';
|
||||
|
||||
// Replace accented characters by their unaccented equivalents
|
||||
$title = utf8::transliterate_to_ascii($title);
|
||||
$title = text::transliterate_to_ascii($title);
|
||||
|
||||
// Remove all characters that are not the separator, a-z, 0-9, or whitespace
|
||||
$title = preg_replace('/[^'.$separator.'a-z0-9\s]+/', '', strtolower($title));
|
||||
|
||||
746
system/helpers/utf8.php
Normal file
746
system/helpers/utf8.php
Normal file
@@ -0,0 +1,746 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* A port of phputf8 to a unified file/class.
|
||||
*
|
||||
* This file is licensed differently from the rest of Kohana. As a port of
|
||||
* phputf8, which is LGPL software, this file is released under the LGPL.
|
||||
*
|
||||
* PCRE needs to be compiled with UTF-8 support (--enable-utf8).
|
||||
* Support for Unicode properties is highly recommended (--enable-unicode-properties).
|
||||
* @see http://php.net/manual/reference.pcre.pattern.modifiers.php
|
||||
*
|
||||
* string functions.
|
||||
* @see http://php.net/mbstring
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @copyright (c) 2005 Harry Fuecks
|
||||
* @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
|
||||
*/
|
||||
|
||||
class utf8 {
|
||||
|
||||
/**
|
||||
* Replaces text within a portion of a UTF-8 string.
|
||||
* @see http://php.net/substr_replace
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string input string
|
||||
* @param string replacement string
|
||||
* @param integer offset
|
||||
* @return string
|
||||
*/
|
||||
public static function substr_replace($str, $replacement, $offset, $length = NULL)
|
||||
{
|
||||
if (text::is_ascii($str))
|
||||
return ($length === NULL) ? substr_replace($str, $replacement, $offset) : substr_replace($str, $replacement, $offset, $length);
|
||||
|
||||
$length = ($length === NULL) ? mb_strlen($str) : (int) $length;
|
||||
preg_match_all('/./us', $str, $str_array);
|
||||
preg_match_all('/./us', $replacement, $replacement_array);
|
||||
|
||||
array_splice($str_array[0], $offset, $length, $replacement_array[0]);
|
||||
return implode('', $str_array[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a UTF-8 string's first character uppercase.
|
||||
* @see http://php.net/ucfirst
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string mixed case string
|
||||
* @return string
|
||||
*/
|
||||
public static function ucfirst($str)
|
||||
{
|
||||
if (text::is_ascii($str))
|
||||
return ucfirst($str);
|
||||
|
||||
preg_match('/^(.?)(.*)$/us', $str, $matches);
|
||||
return mb_strtoupper($matches[1]).$matches[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Case-insensitive UTF-8 string comparison.
|
||||
* @see http://php.net/strcasecmp
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string string to compare
|
||||
* @param string string to compare
|
||||
* @return integer less than 0 if str1 is less than str2
|
||||
* @return integer greater than 0 if str1 is greater than str2
|
||||
* @return integer 0 if they are equal
|
||||
*/
|
||||
public static function strcasecmp($str1, $str2)
|
||||
{
|
||||
if (text::is_ascii($str1) AND text::is_ascii($str2))
|
||||
return strcasecmp($str1, $str2);
|
||||
|
||||
$str1 = mb_strtolower($str1);
|
||||
$str2 = mb_strtolower($str2);
|
||||
return strcmp($str1, $str2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string or an array with all occurrences of search in subject (ignoring case).
|
||||
* replaced with the given replace value.
|
||||
* @see http://php.net/str_ireplace
|
||||
*
|
||||
* @note It's not fast and gets slower if $search and/or $replace are arrays.
|
||||
* @author Harry Fuecks <hfuecks@gmail.com
|
||||
*
|
||||
* @param string|array text to replace
|
||||
* @param string|array replacement text
|
||||
* @param string|array subject text
|
||||
* @param integer number of matched and replaced needles will be returned via this parameter which is passed by reference
|
||||
* @return string if the input was a string
|
||||
* @return array if the input was an array
|
||||
*/
|
||||
public static function str_ireplace($search, $replace, $str, & $count = NULL)
|
||||
{
|
||||
if (text::is_ascii($search) AND text::is_ascii($replace) AND text::is_ascii($str))
|
||||
return str_ireplace($search, $replace, $str, $count);
|
||||
|
||||
if (is_array($str))
|
||||
{
|
||||
foreach ($str as $key => $val)
|
||||
{
|
||||
$str[$key] = utf8::str_ireplace($search, $replace, $val, $count);
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
if (is_array($search))
|
||||
{
|
||||
$keys = array_keys($search);
|
||||
|
||||
foreach ($keys as $k)
|
||||
{
|
||||
if (is_array($replace))
|
||||
{
|
||||
if (array_key_exists($k, $replace))
|
||||
{
|
||||
$str = utf8::str_ireplace($search[$k], $replace[$k], $str, $count);
|
||||
}
|
||||
else
|
||||
{
|
||||
$str = utf8::str_ireplace($search[$k], '', $str, $count);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$str = utf8::str_ireplace($search[$k], $replace, $str, $count);
|
||||
}
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
$search = mb_strtolower($search);
|
||||
$str_lower = mb_strtolower($str);
|
||||
|
||||
$total_matched_strlen = 0;
|
||||
$i = 0;
|
||||
|
||||
while (preg_match('/(.*?)'.preg_quote($search, '/').'/s', $str_lower, $matches))
|
||||
{
|
||||
$matched_strlen = strlen($matches[0]);
|
||||
$str_lower = substr($str_lower, $matched_strlen);
|
||||
|
||||
$offset = $total_matched_strlen + strlen($matches[1]) + ($i * (strlen($replace) - 1));
|
||||
$str = substr_replace($str, $replace, $offset, strlen($search));
|
||||
|
||||
$total_matched_strlen += $matched_strlen;
|
||||
$i++;
|
||||
}
|
||||
|
||||
$count += $i;
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Case-insenstive UTF-8 version of strstr. Returns all of input string
|
||||
* from the first occurrence of needle to the end.
|
||||
* @see http://php.net/stristr
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string input string
|
||||
* @param string needle
|
||||
* @return string matched substring if found
|
||||
* @return boolean FALSE if the substring was not found
|
||||
*/
|
||||
public static function stristr($str, $search)
|
||||
{
|
||||
if (text::is_ascii($str) AND text::is_ascii($search))
|
||||
return stristr($str, $search);
|
||||
|
||||
if ($search == '')
|
||||
return $str;
|
||||
|
||||
$str_lower = mb_strtolower($str);
|
||||
$search_lower = mb_strtolower($search);
|
||||
|
||||
preg_match('/^(.*?)'.preg_quote($search, '/').'/s', $str_lower, $matches);
|
||||
|
||||
if (isset($matches[1]))
|
||||
return substr($str, strlen($matches[1]));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the length of the initial segment matching mask.
|
||||
* @see http://php.net/strspn
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string input string
|
||||
* @param string mask for search
|
||||
* @param integer start position of the string to examine
|
||||
* @param integer length of the string to examine
|
||||
* @return integer length of the initial segment that contains characters in the mask
|
||||
*/
|
||||
public static function strspn($str, $mask, $offset = NULL, $length = NULL)
|
||||
{
|
||||
if ($str == '' OR $mask == '')
|
||||
return 0;
|
||||
|
||||
if (text::is_ascii($str) AND text::is_ascii($mask))
|
||||
return ($offset === NULL) ? strspn($str, $mask) : (($length === NULL) ? strspn($str, $mask, $offset) : strspn($str, $mask, $offset, $length));
|
||||
|
||||
if ($offset !== NULL OR $length !== NULL)
|
||||
{
|
||||
$str = mb_substr($str, $offset, $length);
|
||||
}
|
||||
|
||||
// Escape these characters: - [ ] . : \ ^ /
|
||||
// The . and : are escaped to prevent possible warnings about POSIX regex elements
|
||||
$mask = preg_replace('#[-[\].:\\\\^/]#', '\\\\$0', $mask);
|
||||
preg_match('/^[^'.$mask.']+/u', $str, $matches);
|
||||
|
||||
return isset($matches[0]) ? mb_strlen($matches[0]) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the length of the initial segment not matching mask.
|
||||
* @see http://php.net/strcspn
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string input string
|
||||
* @param string mask for search
|
||||
* @param integer start position of the string to examine
|
||||
* @param integer length of the string to examine
|
||||
* @return integer length of the initial segment that contains characters not in the mask
|
||||
*/
|
||||
public static function strcspn($str, $mask, $offset = NULL, $length = NULL)
|
||||
{
|
||||
if ($str == '' OR $mask == '')
|
||||
return 0;
|
||||
|
||||
if (text::is_ascii($str) AND text::is_ascii($mask))
|
||||
return ($offset === NULL) ? strcspn($str, $mask) : (($length === NULL) ? strcspn($str, $mask, $offset) : strcspn($str, $mask, $offset, $length));
|
||||
|
||||
if ($str !== NULL OR $length !== NULL)
|
||||
{
|
||||
$str = mb_substr($str, $offset, $length);
|
||||
}
|
||||
|
||||
// Escape these characters: - [ ] . : \ ^ /
|
||||
// The . and : are escaped to prevent possible warnings about POSIX regex elements
|
||||
$mask = preg_replace('#[-[\].:\\\\^/]#', '\\\\$0', $mask);
|
||||
preg_match('/^[^'.$mask.']+/u', $str, $matches);
|
||||
|
||||
return isset($matches[0]) ? mb_strlen($matches[0]) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pads a UTF-8 string to a certain length with another string.
|
||||
* @see http://php.net/str_pad
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string input string
|
||||
* @param integer desired string length after padding
|
||||
* @param string string to use as padding
|
||||
* @param string padding type: STR_PAD_RIGHT, STR_PAD_LEFT, or STR_PAD_BOTH
|
||||
* @return string
|
||||
*/
|
||||
public static function str_pad($str, $final_str_length, $pad_str = ' ', $pad_type = STR_PAD_RIGHT)
|
||||
{
|
||||
if (text::is_ascii($str) AND text::is_ascii($pad_str))
|
||||
{
|
||||
return str_pad($str, $final_str_length, $pad_str, $pad_type);
|
||||
}
|
||||
|
||||
$str_length = mb_strlen($str);
|
||||
|
||||
if ($final_str_length <= 0 OR $final_str_length <= $str_length)
|
||||
{
|
||||
return $str;
|
||||
}
|
||||
|
||||
$pad_str_length = mb_strlen($pad_str);
|
||||
$pad_length = $final_str_length - $str_length;
|
||||
|
||||
if ($pad_type == STR_PAD_RIGHT)
|
||||
{
|
||||
$repeat = ceil($pad_length / $pad_str_length);
|
||||
return mb_substr($str.str_repeat($pad_str, $repeat), 0, $final_str_length);
|
||||
}
|
||||
|
||||
if ($pad_type == STR_PAD_LEFT)
|
||||
{
|
||||
$repeat = ceil($pad_length / $pad_str_length);
|
||||
return mb_substr(str_repeat($pad_str, $repeat), 0, floor($pad_length)).$str;
|
||||
}
|
||||
|
||||
if ($pad_type == STR_PAD_BOTH)
|
||||
{
|
||||
$pad_length /= 2;
|
||||
$pad_length_left = floor($pad_length);
|
||||
$pad_length_right = ceil($pad_length);
|
||||
$repeat_left = ceil($pad_length_left / $pad_str_length);
|
||||
$repeat_right = ceil($pad_length_right / $pad_str_length);
|
||||
|
||||
$pad_left = mb_substr(str_repeat($pad_str, $repeat_left), 0, $pad_length_left);
|
||||
$pad_right = mb_substr(str_repeat($pad_str, $repeat_right), 0, $pad_length_left);
|
||||
return $pad_left.$str.$pad_right;
|
||||
}
|
||||
|
||||
trigger_error('utf8::str_pad: Unknown padding type (' . $pad_type . ')', E_USER_ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a UTF-8 string to an array.
|
||||
* @see http://php.net/str_split
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string input string
|
||||
* @param integer maximum length of each chunk
|
||||
* @return array
|
||||
*/
|
||||
public static function str_split($str, $split_length = 1)
|
||||
{
|
||||
$split_length = (int) $split_length;
|
||||
|
||||
if (text::is_ascii($str))
|
||||
{
|
||||
return str_split($str, $split_length);
|
||||
}
|
||||
|
||||
if ($split_length < 1)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (mb_strlen($str) <= $split_length)
|
||||
{
|
||||
return array($str);
|
||||
}
|
||||
|
||||
preg_match_all('/.{'.$split_length.'}|[^\x00]{1,'.$split_length.'}$/us', $str, $matches);
|
||||
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverses a UTF-8 string.
|
||||
* @see http://php.net/strrev
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string string to be reversed
|
||||
* @return string
|
||||
*/
|
||||
public static function strrev($str)
|
||||
{
|
||||
if (text::is_ascii($str))
|
||||
return strrev($str);
|
||||
|
||||
preg_match_all('/./us', $str, $matches);
|
||||
return implode('', array_reverse($matches[0]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips whitespace (or other UTF-8 characters) from the beginning and
|
||||
* end of a string.
|
||||
* @see http://php.net/trim
|
||||
*
|
||||
* @author Andreas Gohr <andi@splitbrain.org>
|
||||
*
|
||||
* @param string input string
|
||||
* @param string string of characters to remove
|
||||
* @return string
|
||||
*/
|
||||
public static function trim($str, $charlist = NULL)
|
||||
{
|
||||
if ($charlist === NULL)
|
||||
return trim($str);
|
||||
|
||||
return utf8::ltrim(utf8::rtrim($str, $charlist), $charlist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips whitespace (or other UTF-8 characters) from the beginning of a string.
|
||||
* @see http://php.net/ltrim
|
||||
*
|
||||
* @author Andreas Gohr <andi@splitbrain.org>
|
||||
*
|
||||
* @param string input string
|
||||
* @param string string of characters to remove
|
||||
* @return string
|
||||
*/
|
||||
public static function ltrim($str, $charlist = NULL)
|
||||
{
|
||||
if ($charlist === NULL)
|
||||
return ltrim($str);
|
||||
|
||||
if (text::is_ascii($charlist))
|
||||
return ltrim($str, $charlist);
|
||||
|
||||
$charlist = preg_replace('#[-\[\]:\\\\^/]#', '\\\\$0', $charlist);
|
||||
|
||||
return preg_replace('/^['.$charlist.']+/u', '', $str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips whitespace (or other UTF-8 characters) from the end of a string.
|
||||
* @see http://php.net/rtrim
|
||||
*
|
||||
* @author Andreas Gohr <andi@splitbrain.org>
|
||||
*
|
||||
* @param string input string
|
||||
* @param string string of characters to remove
|
||||
* @return string
|
||||
*/
|
||||
public static function rtrim($str, $charlist = NULL)
|
||||
{
|
||||
if ($charlist === NULL)
|
||||
return rtrim($str);
|
||||
|
||||
if (text::is_ascii($charlist))
|
||||
return rtrim($str, $charlist);
|
||||
|
||||
$charlist = preg_replace('#[-\[\]:\\\\^/]#', '\\\\$0', $charlist);
|
||||
|
||||
return preg_replace('/['.$charlist.']++$/uD', '', $str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unicode ordinal for a character.
|
||||
* @see http://php.net/ord
|
||||
*
|
||||
* @author Harry Fuecks <hfuecks@gmail.com>
|
||||
*
|
||||
* @param string UTF-8 encoded character
|
||||
* @return integer
|
||||
*/
|
||||
public static function ord($chr)
|
||||
{
|
||||
$ord0 = ord($chr);
|
||||
|
||||
if ($ord0 >= 0 AND $ord0 <= 127)
|
||||
{
|
||||
return $ord0;
|
||||
}
|
||||
|
||||
if ( ! isset($chr[1]))
|
||||
{
|
||||
trigger_error('Short sequence - at least 2 bytes expected, only 1 seen', E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$ord1 = ord($chr[1]);
|
||||
|
||||
if ($ord0 >= 192 AND $ord0 <= 223)
|
||||
{
|
||||
return ($ord0 - 192) * 64 + ($ord1 - 128);
|
||||
}
|
||||
|
||||
if ( ! isset($chr[2]))
|
||||
{
|
||||
trigger_error('Short sequence - at least 3 bytes expected, only 2 seen', E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$ord2 = ord($chr[2]);
|
||||
|
||||
if ($ord0 >= 224 AND $ord0 <= 239)
|
||||
{
|
||||
return ($ord0 - 224) * 4096 + ($ord1 - 128) * 64 + ($ord2 - 128);
|
||||
}
|
||||
|
||||
if ( ! isset($chr[3]))
|
||||
{
|
||||
trigger_error('Short sequence - at least 4 bytes expected, only 3 seen', E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$ord3 = ord($chr[3]);
|
||||
|
||||
if ($ord0 >= 240 AND $ord0 <= 247)
|
||||
{
|
||||
return ($ord0 - 240) * 262144 + ($ord1 - 128) * 4096 + ($ord2-128) * 64 + ($ord3 - 128);
|
||||
}
|
||||
|
||||
if ( ! isset($chr[4]))
|
||||
{
|
||||
trigger_error('Short sequence - at least 5 bytes expected, only 4 seen', E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$ord4 = ord($chr[4]);
|
||||
|
||||
if ($ord0 >= 248 AND $ord0 <= 251)
|
||||
{
|
||||
return ($ord0 - 248) * 16777216 + ($ord1-128) * 262144 + ($ord2 - 128) * 4096 + ($ord3 - 128) * 64 + ($ord4 - 128);
|
||||
}
|
||||
|
||||
if ( ! isset($chr[5]))
|
||||
{
|
||||
trigger_error('Short sequence - at least 6 bytes expected, only 5 seen', E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ($ord0 >= 252 AND $ord0 <= 253)
|
||||
{
|
||||
return ($ord0 - 252) * 1073741824 + ($ord1 - 128) * 16777216 + ($ord2 - 128) * 262144 + ($ord3 - 128) * 4096 + ($ord4 - 128) * 64 + (ord($chr[5]) - 128);
|
||||
}
|
||||
|
||||
if ($ord0 >= 254 AND $ord0 <= 255)
|
||||
{
|
||||
trigger_error('Invalid UTF-8 with surrogate ordinal '.$ord0, E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an UTF-8 string and returns an array of ints representing the Unicode characters.
|
||||
* Astral planes are supported i.e. the ints in the output can be > 0xFFFF.
|
||||
* Occurrances of the BOM are ignored. Surrogates are not allowed.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
* The Initial Developer of the Original Code is Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998 the Initial Developer.
|
||||
* Ported to PHP by Henri Sivonen <hsivonen@iki.fi>, see http://hsivonen.iki.fi/php-utf8/.
|
||||
* Slight modifications to fit with phputf8 library by Harry Fuecks <hfuecks@gmail.com>.
|
||||
*
|
||||
* @param string UTF-8 encoded string
|
||||
* @return array unicode code points
|
||||
* @return boolean FALSE if the string is invalid
|
||||
*/
|
||||
public static function to_unicode($str)
|
||||
{
|
||||
$mState = 0; // cached expected number of octets after the current octet until the beginning of the next UTF8 character sequence
|
||||
$mUcs4 = 0; // cached Unicode character
|
||||
$mBytes = 1; // cached expected number of octets in the current sequence
|
||||
|
||||
$out = array();
|
||||
|
||||
$len = strlen($str);
|
||||
|
||||
for ($i = 0; $i < $len; $i++)
|
||||
{
|
||||
$in = ord($str[$i]);
|
||||
|
||||
if ($mState == 0)
|
||||
{
|
||||
// When mState is zero we expect either a US-ASCII character or a
|
||||
// multi-octet sequence.
|
||||
if (0 == (0x80 & $in))
|
||||
{
|
||||
// US-ASCII, pass straight through.
|
||||
$out[] = $in;
|
||||
$mBytes = 1;
|
||||
}
|
||||
elseif (0xC0 == (0xE0 & $in))
|
||||
{
|
||||
// First octet of 2 octet sequence
|
||||
$mUcs4 = $in;
|
||||
$mUcs4 = ($mUcs4 & 0x1F) << 6;
|
||||
$mState = 1;
|
||||
$mBytes = 2;
|
||||
}
|
||||
elseif (0xE0 == (0xF0 & $in))
|
||||
{
|
||||
// First octet of 3 octet sequence
|
||||
$mUcs4 = $in;
|
||||
$mUcs4 = ($mUcs4 & 0x0F) << 12;
|
||||
$mState = 2;
|
||||
$mBytes = 3;
|
||||
}
|
||||
elseif (0xF0 == (0xF8 & $in))
|
||||
{
|
||||
// First octet of 4 octet sequence
|
||||
$mUcs4 = $in;
|
||||
$mUcs4 = ($mUcs4 & 0x07) << 18;
|
||||
$mState = 3;
|
||||
$mBytes = 4;
|
||||
}
|
||||
elseif (0xF8 == (0xFC & $in))
|
||||
{
|
||||
// First octet of 5 octet sequence.
|
||||
//
|
||||
// This is illegal because the encoded codepoint must be either
|
||||
// (a) not the shortest form or
|
||||
// (b) outside the Unicode range of 0-0x10FFFF.
|
||||
// Rather than trying to resynchronize, we will carry on until the end
|
||||
// of the sequence and let the later error handling code catch it.
|
||||
$mUcs4 = $in;
|
||||
$mUcs4 = ($mUcs4 & 0x03) << 24;
|
||||
$mState = 4;
|
||||
$mBytes = 5;
|
||||
}
|
||||
elseif (0xFC == (0xFE & $in))
|
||||
{
|
||||
// First octet of 6 octet sequence, see comments for 5 octet sequence.
|
||||
$mUcs4 = $in;
|
||||
$mUcs4 = ($mUcs4 & 1) << 30;
|
||||
$mState = 5;
|
||||
$mBytes = 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Current octet is neither in the US-ASCII range nor a legal first octet of a multi-octet sequence.
|
||||
trigger_error('utf8::to_unicode: Illegal sequence identifier in UTF-8 at byte '.$i, E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// When mState is non-zero, we expect a continuation of the multi-octet sequence
|
||||
if (0x80 == (0xC0 & $in))
|
||||
{
|
||||
// Legal continuation
|
||||
$shift = ($mState - 1) * 6;
|
||||
$tmp = $in;
|
||||
$tmp = ($tmp & 0x0000003F) << $shift;
|
||||
$mUcs4 |= $tmp;
|
||||
|
||||
// End of the multi-octet sequence. mUcs4 now contains the final Unicode codepoint to be output
|
||||
if (0 == --$mState)
|
||||
{
|
||||
// Check for illegal sequences and codepoints
|
||||
|
||||
// From Unicode 3.1, non-shortest form is illegal
|
||||
if (((2 == $mBytes) AND ($mUcs4 < 0x0080)) OR
|
||||
((3 == $mBytes) AND ($mUcs4 < 0x0800)) OR
|
||||
((4 == $mBytes) AND ($mUcs4 < 0x10000)) OR
|
||||
(4 < $mBytes) OR
|
||||
// From Unicode 3.2, surrogate characters are illegal
|
||||
(($mUcs4 & 0xFFFFF800) == 0xD800) OR
|
||||
// Codepoints outside the Unicode range are illegal
|
||||
($mUcs4 > 0x10FFFF))
|
||||
{
|
||||
trigger_error('utf8::to_unicode: Illegal sequence or codepoint in UTF-8 at byte '.$i, E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (0xFEFF != $mUcs4)
|
||||
{
|
||||
// BOM is legal but we don't want to output it
|
||||
$out[] = $mUcs4;
|
||||
}
|
||||
|
||||
// Initialize UTF-8 cache
|
||||
$mState = 0;
|
||||
$mUcs4 = 0;
|
||||
$mBytes = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ((0xC0 & (*in) != 0x80) AND (mState != 0))
|
||||
// Incomplete multi-octet sequence
|
||||
trigger_error('utf8::to_unicode: Incomplete multi-octet sequence in UTF-8 at byte '.$i, E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an array of ints representing the Unicode characters and returns a UTF-8 string.
|
||||
* Astral planes are supported i.e. the ints in the input can be > 0xFFFF.
|
||||
* Occurrances of the BOM are ignored. Surrogates are not allowed.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
* The Initial Developer of the Original Code is Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998 the Initial Developer.
|
||||
* Ported to PHP by Henri Sivonen <hsivonen@iki.fi>, see http://hsivonen.iki.fi/php-utf8/.
|
||||
* Slight modifications to fit with phputf8 library by Harry Fuecks <hfuecks@gmail.com>.
|
||||
*
|
||||
* @param array unicode code points representing a string
|
||||
* @return string utf8 string of characters
|
||||
* @return boolean FALSE if a code point cannot be found
|
||||
*/
|
||||
public static function from_unicode($arr)
|
||||
{
|
||||
ob_start();
|
||||
|
||||
$keys = array_keys($arr);
|
||||
|
||||
foreach ($keys as $k)
|
||||
{
|
||||
// ASCII range (including control chars)
|
||||
if (($arr[$k] >= 0) AND ($arr[$k] <= 0x007f))
|
||||
{
|
||||
echo chr($arr[$k]);
|
||||
}
|
||||
// 2 byte sequence
|
||||
elseif ($arr[$k] <= 0x07ff)
|
||||
{
|
||||
echo chr(0xc0 | ($arr[$k] >> 6));
|
||||
echo chr(0x80 | ($arr[$k] & 0x003f));
|
||||
}
|
||||
// Byte order mark (skip)
|
||||
elseif ($arr[$k] == 0xFEFF)
|
||||
{
|
||||
// nop -- zap the BOM
|
||||
}
|
||||
// Test for illegal surrogates
|
||||
elseif ($arr[$k] >= 0xD800 AND $arr[$k] <= 0xDFFF)
|
||||
{
|
||||
// Found a surrogate
|
||||
trigger_error('utf8::from_unicode: Illegal surrogate at index: '.$k.', value: '.$arr[$k], E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
// 3 byte sequence
|
||||
elseif ($arr[$k] <= 0xffff)
|
||||
{
|
||||
echo chr(0xe0 | ($arr[$k] >> 12));
|
||||
echo chr(0x80 | (($arr[$k] >> 6) & 0x003f));
|
||||
echo chr(0x80 | ($arr[$k] & 0x003f));
|
||||
}
|
||||
// 4 byte sequence
|
||||
elseif ($arr[$k] <= 0x10ffff)
|
||||
{
|
||||
echo chr(0xf0 | ($arr[$k] >> 18));
|
||||
echo chr(0x80 | (($arr[$k] >> 12) & 0x3f));
|
||||
echo chr(0x80 | (($arr[$k] >> 6) & 0x3f));
|
||||
echo chr(0x80 | ($arr[$k] & 0x3f));
|
||||
}
|
||||
// Out of range
|
||||
else
|
||||
{
|
||||
trigger_error('utf8::from_unicode: Codepoint out of Unicode range at index: '.$k.', value: '.$arr[$k], E_USER_WARNING);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
$result = ob_get_contents();
|
||||
ob_end_clean();
|
||||
return $result;
|
||||
}
|
||||
|
||||
} // End utf8
|
||||
@@ -2,12 +2,12 @@
|
||||
/**
|
||||
* Validation helper class.
|
||||
*
|
||||
* $Id: valid.php 4367 2009-05-27 21:23:57Z samsoir $
|
||||
* $Id: valid.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class valid_Core {
|
||||
|
||||
@@ -161,13 +161,13 @@ class valid_Core {
|
||||
for ($i = $length - 1; $i >= 0; $i -= 2)
|
||||
{
|
||||
// Add up every 2nd digit, starting from the right
|
||||
$checksum += $number[$i];
|
||||
$checksum += substr($number, $i, 1);
|
||||
}
|
||||
|
||||
for ($i = $length - 2; $i >= 0; $i -= 2)
|
||||
{
|
||||
// Add up every 2nd digit doubled, starting from the right
|
||||
$double = $number[$i] * 2;
|
||||
$double = substr($number, $i, 1) * 2;
|
||||
|
||||
// Subtract 9 from the double where value is greater than 10
|
||||
$checksum += ($double >= 10) ? $double - 9 : $double;
|
||||
@@ -199,7 +199,7 @@ class valid_Core {
|
||||
|
||||
/**
|
||||
* Tests if a string is a valid date string.
|
||||
*
|
||||
*
|
||||
* @param string date to check
|
||||
* @return boolean
|
||||
*/
|
||||
@@ -269,7 +269,7 @@ class valid_Core {
|
||||
*
|
||||
* @see Uses locale conversion to allow decimal point to be locale specific.
|
||||
* @see http://www.php.net/manual/en/function.localeconv.php
|
||||
*
|
||||
*
|
||||
* @param string input string
|
||||
* @return boolean
|
||||
*/
|
||||
@@ -281,21 +281,35 @@ class valid_Core {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a string is a valid text. Letters, numbers, whitespace,
|
||||
* dashes, periods, and underscores are allowed.
|
||||
* Tests if an integer is within a range.
|
||||
*
|
||||
* @param string text to check
|
||||
* @param integer number to check
|
||||
* @param array valid range of input
|
||||
* @return boolean
|
||||
*/
|
||||
public static function standard_text($str)
|
||||
public static function range($number, array $range)
|
||||
{
|
||||
// pL matches letters
|
||||
// pN matches numbers
|
||||
// pZ matches whitespace
|
||||
// pPc matches underscores
|
||||
// pPd matches dashes
|
||||
// pPo matches normal puncuation
|
||||
return (bool) preg_match('/^[\pL\pN\pZ\p{Pc}\p{Pd}\p{Po}]++$/uD', (string) $str);
|
||||
// Invalid by default
|
||||
$status = FALSE;
|
||||
|
||||
if (is_int($number) OR ctype_digit($number))
|
||||
{
|
||||
if (count($range) > 1)
|
||||
{
|
||||
if ($number >= $range[0] AND $number <= $range[1])
|
||||
{
|
||||
// Number is within the required range
|
||||
$status = TRUE;
|
||||
}
|
||||
}
|
||||
elseif ($number >= $range[0])
|
||||
{
|
||||
// Number is greater than the minimum
|
||||
$status = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -335,4 +349,18 @@ class valid_Core {
|
||||
return (bool) preg_match($pattern, (string) $str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a string is a proper hexadecimal HTML color value. The validation
|
||||
* is quite flexible as it does not require an initial "#" and also allows for
|
||||
* the short notation using only three instead of six hexadecimal characters.
|
||||
* You may want to normalize these values with format::color().
|
||||
*
|
||||
* @param string input string
|
||||
* @return boolean
|
||||
*/
|
||||
public static function color($str)
|
||||
{
|
||||
return (bool) preg_match('/^#?+[0-9a-f]{3}(?:[0-9a-f]{3})?$/iD', $str);
|
||||
}
|
||||
|
||||
} // End valid
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
|
||||
$lang = array
|
||||
(
|
||||
'undefined_group' => 'The %s group is not defined in your configuration.',
|
||||
'extension_not_loaded' => 'The %s PHP extension must be loaded to use this driver.',
|
||||
'unwritable' => 'The configured storage location, %s, is not writable.',
|
||||
'resources' => 'Caching of resources is impossible, because resources cannot be serialized.',
|
||||
'driver_error' => '%s',
|
||||
);
|
||||
@@ -1,59 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
|
||||
$lang = array
|
||||
(
|
||||
// Two letter days
|
||||
'su' => 'Su',
|
||||
'mo' => 'Mo',
|
||||
'tu' => 'Tu',
|
||||
'we' => 'We',
|
||||
'th' => 'Th',
|
||||
'fr' => 'Fr',
|
||||
'sa' => 'Sa',
|
||||
|
||||
// Short day names
|
||||
'sun' => 'Sun',
|
||||
'mon' => 'Mon',
|
||||
'tue' => 'Tue',
|
||||
'wed' => 'Wed',
|
||||
'thu' => 'Thu',
|
||||
'fri' => 'Fri',
|
||||
'sat' => 'Sat',
|
||||
|
||||
// Long day names
|
||||
'sunday' => 'Sunday',
|
||||
'monday' => 'Monday',
|
||||
'tuesday' => 'Tuesday',
|
||||
'wednesday' => 'Wednesday',
|
||||
'thursday' => 'Thursday',
|
||||
'friday' => 'Friday',
|
||||
'saturday' => 'Saturday',
|
||||
|
||||
// Short month names
|
||||
'jan' => 'Jan',
|
||||
'feb' => 'Feb',
|
||||
'mar' => 'Mar',
|
||||
'apr' => 'Apr',
|
||||
'may' => 'May',
|
||||
'jun' => 'Jun',
|
||||
'jul' => 'Jul',
|
||||
'aug' => 'Aug',
|
||||
'sep' => 'Sep',
|
||||
'oct' => 'Oct',
|
||||
'nov' => 'Nov',
|
||||
'dec' => 'Dec',
|
||||
|
||||
// Long month names
|
||||
'january' => 'January',
|
||||
'february' => 'February',
|
||||
'march' => 'March',
|
||||
'april' => 'April',
|
||||
'mayl' => 'May',
|
||||
'june' => 'June',
|
||||
'july' => 'July',
|
||||
'august' => 'August',
|
||||
'september' => 'September',
|
||||
'october' => 'October',
|
||||
'november' => 'November',
|
||||
'december' => 'December'
|
||||
);
|
||||
@@ -1,34 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
|
||||
$lang = array
|
||||
(
|
||||
'there_can_be_only_one' => 'There can be only one instance of Kohana per page request',
|
||||
'uncaught_exception' => 'Uncaught %s: %s in file %s on line %s',
|
||||
'invalid_method' => 'Invalid method %s called in %s',
|
||||
'invalid_property' => 'The %s property does not exist in the %s class.',
|
||||
'log_dir_unwritable' => 'The log directory is not writable: %s',
|
||||
'resource_not_found' => 'The requested %s, %s, could not be found',
|
||||
'invalid_filetype' => 'The requested filetype, .%s, is not allowed in your view configuration file',
|
||||
'view_set_filename' => 'You must set the the view filename before calling render',
|
||||
'no_default_route' => 'Please set a default route in config/routes.php',
|
||||
'no_controller' => 'Kohana was not able to determine a controller to process this request: %s',
|
||||
'page_not_found' => 'The page you requested, %s, could not be found.',
|
||||
'stats_footer' => 'Loaded in {execution_time} seconds, using {memory_usage} of memory. Generated by Kohana v{kohana_version}.',
|
||||
'error_file_line' => '<tt>%s <strong>[%s]:</strong></tt>',
|
||||
'stack_trace' => 'Stack Trace',
|
||||
'generic_error' => 'Unable to Complete Request',
|
||||
'errors_disabled' => 'You can go to the <a href="%s">home page</a> or <a href="%s">try again</a>.',
|
||||
|
||||
// Drivers
|
||||
'driver_implements' => 'The %s driver for the %s library must implement the %s interface',
|
||||
'driver_not_found' => 'The %s driver for the %s library could not be found',
|
||||
|
||||
// Resource names
|
||||
'config' => 'config file',
|
||||
'controller' => 'controller',
|
||||
'helper' => 'helper',
|
||||
'library' => 'library',
|
||||
'driver' => 'driver',
|
||||
'model' => 'model',
|
||||
'view' => 'view',
|
||||
);
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
|
||||
$lang = array
|
||||
(
|
||||
'undefined_group' => 'The %s group is not defined in your configuration.',
|
||||
'error' => 'There was an SQL error: %s',
|
||||
'connection' => 'There was an error connecting to the database: %s',
|
||||
'invalid_dsn' => 'The DSN you supplied is not valid: %s',
|
||||
'must_use_set' => 'You must set a SET clause for your query.',
|
||||
'must_use_where' => 'You must set a WHERE clause for your query.',
|
||||
'must_use_table' => 'You must set a database table for your query.',
|
||||
'table_not_found' => 'Table %s does not exist in your database.',
|
||||
'not_implemented' => 'The method you called, %s, is not supported by this driver.',
|
||||
'result_read_only' => 'Query results are read only.'
|
||||
);
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
|
||||
$lang = array
|
||||
(
|
||||
'undefined_group' => 'The %s group is not defined in your configuration.',
|
||||
'requires_mcrypt' => 'To use the Encrypt library, mcrypt must be enabled in your PHP installation',
|
||||
'no_encryption_key' => 'To use the Encrypt library, you must set an encryption key in your config file'
|
||||
);
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
|
||||
$lang = array
|
||||
(
|
||||
E_KOHANA => array( 1, 'Framework Error', 'Please check the Kohana documentation for information about the following error.'),
|
||||
E_PAGE_NOT_FOUND => array( 1, 'Page Not Found', 'The requested page was not found. It may have moved, been deleted, or archived.'),
|
||||
E_DATABASE_ERROR => array( 1, 'Database Error', 'A database error occurred while performing the requested procedure. Please review the database error below for more information.'),
|
||||
E_RECOVERABLE_ERROR => array( 1, 'Recoverable Error', 'An error was detected which prevented the loading of this page. If this problem persists, please contact the website administrator.'),
|
||||
E_ERROR => array( 1, 'Fatal Error', ''),
|
||||
E_USER_ERROR => array( 1, 'Fatal Error', ''),
|
||||
E_PARSE => array( 1, 'Syntax Error', ''),
|
||||
E_WARNING => array( 1, 'Warning Message', ''),
|
||||
E_USER_WARNING => array( 1, 'Warning Message', ''),
|
||||
E_STRICT => array( 2, 'Strict Mode Error', ''),
|
||||
E_NOTICE => array( 2, 'Runtime Message', ''),
|
||||
);
|
||||
@@ -1,7 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
|
||||
$lang = array
|
||||
(
|
||||
'invalid_subject' => 'Attempt to attach invalid subject %s to %s failed: Subjects must extend the Event_Subject class',
|
||||
'invalid_observer' => 'Attempt to attach invalid observer %s to %s failed: Observers must extend the Event_Observer class',
|
||||
);
|
||||
@@ -1,33 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
|
||||
$lang = array
|
||||
(
|
||||
'getimagesize_missing' => 'The Image library requires the getimagesize() PHP function, which is not available in your installation.',
|
||||
'unsupported_method' => 'Your configured driver does not support the %s image transformation.',
|
||||
'file_not_found' => 'The specified image, %s, was not found. Please verify that images exist by using file_exists() before manipulating them.',
|
||||
'type_not_allowed' => 'The specified image, %s, is not an allowed image type.',
|
||||
'invalid_width' => 'The width you specified, %s, is not valid.',
|
||||
'invalid_height' => 'The height you specified, %s, is not valid.',
|
||||
'invalid_dimensions' => 'The dimensions specified for %s are not valid.',
|
||||
'invalid_master' => 'The master dimension specified is not valid.',
|
||||
'invalid_flip' => 'The flip direction specified is not valid.',
|
||||
'directory_unwritable' => 'The specified directory, %s, is not writable.',
|
||||
|
||||
// ImageMagick specific messages
|
||||
'imagemagick' => array
|
||||
(
|
||||
'not_found' => 'The ImageMagick directory specified does not contain a required program, %s.',
|
||||
),
|
||||
|
||||
// GraphicsMagick specific messages
|
||||
'graphicsmagick' => array
|
||||
(
|
||||
'not_found' => 'The GraphicsMagick directory specified does not contain a required program, %s.',
|
||||
),
|
||||
|
||||
// GD specific messages
|
||||
'gd' => array
|
||||
(
|
||||
'requires_v2' => 'The Image library requires GD2. Please see http://php.net/gd_info for more information.',
|
||||
),
|
||||
);
|
||||
@@ -1,3 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
|
||||
$lang['query_methods_not_allowed'] = 'Query methods cannot be used through ORM';
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
|
||||
$lang = array
|
||||
(
|
||||
'benchmarks' => 'Benchmarks',
|
||||
'post_data' => 'Post Data',
|
||||
'no_post' => 'No post data',
|
||||
'session_data' => 'Session Data',
|
||||
'no_session' => 'No session data',
|
||||
'queries' => 'Database Queries',
|
||||
'no_queries' => 'No queries',
|
||||
'no_database' => 'Database not loaded',
|
||||
'cookie_data' => 'Cookie Data',
|
||||
'no_cookie' => 'No cookie data',
|
||||
);
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
|
||||
$lang = array
|
||||
(
|
||||
'invalid_session_name' => 'The session_name, %s, is invalid. It must contain only alphanumeric characters and underscores. Also at least one letter must be present.',
|
||||
);
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
|
||||
$lang = array
|
||||
(
|
||||
'not_writable' => 'The upload destination folder, %s, does not appear to be writable.',
|
||||
);
|
||||
@@ -1,41 +0,0 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
|
||||
$lang = array
|
||||
(
|
||||
// Class errors
|
||||
'invalid_rule' => 'Invalid validation rule used: %s',
|
||||
'i18n_array' => 'The %s i18n key must be an array to be used with the in_lang rule',
|
||||
'not_callable' => 'Callback %s used for Validation is not callable',
|
||||
|
||||
// General errors
|
||||
'unknown_error' => 'Unknown validation error while validating the %s field.',
|
||||
'required' => 'The %s field is required.',
|
||||
'min_length' => 'The %s field must be at least %d characters long.',
|
||||
'max_length' => 'The %s field must be %d characters or fewer.',
|
||||
'exact_length' => 'The %s field must be exactly %d characters.',
|
||||
'in_array' => 'The %s field must be selected from the options listed.',
|
||||
'matches' => 'The %s field must match the %s field.',
|
||||
'valid_url' => 'The %s field must contain a valid URL.',
|
||||
'valid_email' => 'The %s field must contain a valid email address.',
|
||||
'valid_ip' => 'The %s field must contain a valid IP address.',
|
||||
'valid_type' => 'The %s field must only contain %s characters.',
|
||||
'range' => 'The %s field must be between specified ranges.',
|
||||
'regex' => 'The %s field does not match accepted input.',
|
||||
'depends_on' => 'The %s field depends on the %s field.',
|
||||
|
||||
// Upload errors
|
||||
'user_aborted' => 'The %s file was aborted during upload.',
|
||||
'invalid_type' => 'The %s file is not an allowed file type.',
|
||||
'max_size' => 'The %s file you uploaded was too large. The maximum size allowed is %s.',
|
||||
'max_width' => 'The %s file you uploaded was too big. The maximum allowed width is %spx.',
|
||||
'max_height' => 'The %s file you uploaded was too big. The maximum allowed height is %spx.',
|
||||
'min_width' => 'The %s file you uploaded was too small. The minimum allowed width is %spx.',
|
||||
'min_height' => 'The %s file you uploaded was too small. The minimum allowed height is %spx.',
|
||||
|
||||
// Field types
|
||||
'alpha' => 'alphabetical',
|
||||
'alpha_numeric' => 'alphabetical and numeric',
|
||||
'alpha_dash' => 'alphabetical, dash, and underscore',
|
||||
'digit' => 'digit',
|
||||
'numeric' => 'numeric',
|
||||
);
|
||||
@@ -4,20 +4,17 @@
|
||||
* resources. Caches are identified by a unique string. Tagging of caches is
|
||||
* also supported, and caches can be found and deleted by id or tag.
|
||||
*
|
||||
* $Id: Cache.php 4321 2009-05-04 01:39:44Z kiall $
|
||||
* $Id: Cache.php 4605 2009-09-14 17:22:21Z kiall $
|
||||
*
|
||||
* @package Cache
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Cache_Core {
|
||||
|
||||
protected static $instances = array();
|
||||
|
||||
// For garbage collection
|
||||
protected static $loaded;
|
||||
|
||||
// Configuration
|
||||
protected $config;
|
||||
|
||||
@@ -55,7 +52,7 @@ class Cache_Core {
|
||||
|
||||
// Test the config group name
|
||||
if (($config = Kohana::config('cache.'.$config)) === NULL)
|
||||
throw new Kohana_Exception('cache.undefined_group', $name);
|
||||
throw new Kohana_Exception('The :group: group is not defined in your configuration.', array(':group:' => $name));
|
||||
}
|
||||
|
||||
if (is_array($config))
|
||||
@@ -77,132 +74,98 @@ class Cache_Core {
|
||||
|
||||
// Load the driver
|
||||
if ( ! Kohana::auto_load($driver))
|
||||
throw new Kohana_Exception('core.driver_not_found', $this->config['driver'], get_class($this));
|
||||
throw new Kohana_Exception('The :driver: driver for the :class: library could not be found',
|
||||
array(':driver:' => $this->config['driver'], ':class:' => get_class($this)));
|
||||
|
||||
// Initialize the driver
|
||||
$this->driver = new $driver($this->config['params']);
|
||||
|
||||
// Validate the driver
|
||||
if ( ! ($this->driver instanceof Cache_Driver))
|
||||
throw new Kohana_Exception('core.driver_implements', $this->config['driver'], get_class($this), 'Cache_Driver');
|
||||
throw new Kohana_Exception('The :driver: driver for the :library: library must implement the :interface: interface',
|
||||
array(':driver:' => $this->config['driver'], ':library:' => get_class($this), ':interface:' => 'Cache_Driver'));
|
||||
|
||||
Kohana::log('debug', 'Cache Library initialized');
|
||||
|
||||
if (Cache::$loaded !== TRUE)
|
||||
{
|
||||
$this->config['requests'] = (int) $this->config['requests'];
|
||||
|
||||
if ($this->config['requests'] > 0 AND mt_rand(1, $this->config['requests']) === 1)
|
||||
{
|
||||
// Do garbage collection
|
||||
$this->driver->delete_expired();
|
||||
|
||||
Kohana::log('debug', 'Cache: Expired caches deleted.');
|
||||
}
|
||||
|
||||
// Cache has been loaded once
|
||||
Cache::$loaded = TRUE;
|
||||
}
|
||||
Kohana_Log::add('debug', 'Cache Library initialized');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a cache by id. NULL is returned when a cache item is not found.
|
||||
*
|
||||
* @param string cache id
|
||||
* @return mixed cached data or NULL
|
||||
* Set cache items
|
||||
*/
|
||||
public function get($id)
|
||||
public function set($key, $value = NULL, $tags = NULL, $lifetime = NULL)
|
||||
{
|
||||
// Sanitize the ID
|
||||
$id = $this->sanitize_id($id);
|
||||
|
||||
return $this->driver->get($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches all of the caches for a given tag. An empty array will be
|
||||
* returned when no matching caches are found.
|
||||
*
|
||||
* @param string cache tag
|
||||
* @return array all cache items matching the tag
|
||||
*/
|
||||
public function find($tag)
|
||||
{
|
||||
return $this->driver->find($tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a cache item by id. Tags may also be added and a custom lifetime
|
||||
* can be set. Non-string data is automatically serialized.
|
||||
*
|
||||
* @param string unique cache id
|
||||
* @param mixed data to cache
|
||||
* @param array|string tags for this item
|
||||
* @param integer number of seconds until the cache expires
|
||||
* @return boolean
|
||||
*/
|
||||
function set($id, $data, $tags = NULL, $lifetime = NULL)
|
||||
{
|
||||
if (is_resource($data))
|
||||
throw new Kohana_Exception('cache.resources');
|
||||
|
||||
// Sanitize the ID
|
||||
$id = $this->sanitize_id($id);
|
||||
|
||||
if ($lifetime === NULL)
|
||||
{
|
||||
// Get the default lifetime
|
||||
$lifetime = $this->config['lifetime'];
|
||||
}
|
||||
|
||||
return $this->driver->set($id, $data, (array) $tags, $lifetime);
|
||||
if ( ! is_array($key))
|
||||
{
|
||||
$key = array($key => $value);
|
||||
}
|
||||
|
||||
return $this->driver->set($key, $tags, $lifetime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a cache item by id.
|
||||
*
|
||||
* @param string cache id
|
||||
* @return boolean
|
||||
* Get a cache items by key
|
||||
*/
|
||||
public function delete($id)
|
||||
public function get($keys)
|
||||
{
|
||||
// Sanitize the ID
|
||||
$id = $this->sanitize_id($id);
|
||||
$single = FALSE;
|
||||
|
||||
return $this->driver->delete($id);
|
||||
if ( ! is_array($keys))
|
||||
{
|
||||
$keys = array($keys);
|
||||
$single = TRUE;
|
||||
}
|
||||
|
||||
return $this->driver->get($keys, $single);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all cache items with a given tag.
|
||||
*
|
||||
* @param string cache tag name
|
||||
* @return boolean
|
||||
* Get cache items by tags
|
||||
*/
|
||||
public function delete_tag($tag)
|
||||
public function get_tag($tags)
|
||||
{
|
||||
return $this->driver->delete($tag, TRUE);
|
||||
if ( ! is_array($tags))
|
||||
{
|
||||
$tags = array($tags);
|
||||
}
|
||||
|
||||
return $this->driver->get_tag($tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete ALL cache items items.
|
||||
*
|
||||
* @return boolean
|
||||
* Delete cache item by key
|
||||
*/
|
||||
public function delete($keys)
|
||||
{
|
||||
if ( ! is_array($keys))
|
||||
{
|
||||
$keys = array($keys);
|
||||
}
|
||||
|
||||
return $this->driver->delete($keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete cache items by tag
|
||||
*/
|
||||
public function delete_tag($tags)
|
||||
{
|
||||
if ( ! is_array($tags))
|
||||
{
|
||||
$tags = array($tags);
|
||||
}
|
||||
|
||||
return $this->driver->delete_tag($tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty the cache
|
||||
*/
|
||||
public function delete_all()
|
||||
{
|
||||
return $this->driver->delete(TRUE);
|
||||
return $this->driver->delete_all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces troublesome characters with underscores.
|
||||
*
|
||||
* @param string cache id
|
||||
* @return string
|
||||
*/
|
||||
protected function sanitize_id($id)
|
||||
{
|
||||
// Change slashes and spaces to underscores
|
||||
return str_replace(array('/', '\\', ' '), '_', $id);
|
||||
}
|
||||
|
||||
} // End Cache
|
||||
} // End Cache Library
|
||||
12
system/libraries/Cache_Exception.php
Normal file
12
system/libraries/Cache_Exception.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
/**
|
||||
* $Id: Kohana_User_Exception.php 4543 2009-09-04 16:58:56Z nodren $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
|
||||
class Cache_Exception_Core extends Kohana_Exception {}
|
||||
// End Kohana User Exception
|
||||
@@ -3,12 +3,12 @@
|
||||
* Kohana Controller class. The controller class must be extended to work
|
||||
* properly, so this class is defined as abstract.
|
||||
*
|
||||
* $Id: Controller.php 4365 2009-05-27 21:09:27Z samsoir $
|
||||
* $Id: Controller.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
abstract class Controller_Core {
|
||||
|
||||
@@ -48,39 +48,4 @@ abstract class Controller_Core {
|
||||
Event::run('system.404');
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes a View within the controller scope.
|
||||
*
|
||||
* @param string view filename
|
||||
* @param array array of view variables
|
||||
* @return string
|
||||
*/
|
||||
public function _kohana_load_view($kohana_view_filename, $kohana_input_data)
|
||||
{
|
||||
if ($kohana_view_filename == '')
|
||||
return;
|
||||
|
||||
// Buffering on
|
||||
ob_start();
|
||||
|
||||
// Import the view variables to local namespace
|
||||
extract($kohana_input_data, EXTR_SKIP);
|
||||
|
||||
// Views are straight HTML pages with embedded PHP, so importing them
|
||||
// this way insures that $this can be accessed as if the user was in
|
||||
// the controller, which gives the easiest access to libraries in views
|
||||
try
|
||||
{
|
||||
include $kohana_view_filename;
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
ob_end_clean();
|
||||
throw $e;
|
||||
}
|
||||
|
||||
// Fetch the output and close the buffer
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
} // End Controller Class
|
||||
File diff suppressed because it is too large
Load Diff
938
system/libraries/Database_Builder.php
Normal file
938
system/libraries/Database_Builder.php
Normal file
@@ -0,0 +1,938 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Database builder
|
||||
*
|
||||
* @package Kohana
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Database_Builder_Core {
|
||||
|
||||
// Valid ORDER BY directions
|
||||
protected $order_directions = array('ASC', 'DESC', 'RAND()');
|
||||
|
||||
// Database object
|
||||
protected $db;
|
||||
|
||||
// Builder members
|
||||
protected $select = array();
|
||||
protected $from = array();
|
||||
protected $join = array();
|
||||
protected $where = array();
|
||||
protected $group_by = array();
|
||||
protected $having = array();
|
||||
protected $order_by = array();
|
||||
protected $limit = NULL;
|
||||
protected $offset = NULL;
|
||||
protected $set = array();
|
||||
protected $columns = array();
|
||||
protected $values = array();
|
||||
protected $type;
|
||||
|
||||
// TTL for caching (using Cache library)
|
||||
protected $ttl = FALSE;
|
||||
|
||||
public function __construct($db = 'default')
|
||||
{
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all query components
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
$this->select = array();
|
||||
$this->from = array();
|
||||
$this->join = array();
|
||||
$this->where = array();
|
||||
$this->group_by = array();
|
||||
$this->having = array();
|
||||
$this->order_by = array();
|
||||
$this->limit = NULL;
|
||||
$this->offset = NULL;
|
||||
$this->set = array();
|
||||
$this->values = array();
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->compile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the builder object into a SQL query
|
||||
*
|
||||
* @return string Compiled query
|
||||
*/
|
||||
protected function compile()
|
||||
{
|
||||
if ( ! is_object($this->db))
|
||||
{
|
||||
// Use default database for compiling to string if none is given
|
||||
$this->db = Database::instance($this->db);
|
||||
}
|
||||
|
||||
if ($this->type === Database::SELECT)
|
||||
{
|
||||
// SELECT columns FROM table
|
||||
$sql = 'SELECT '.$this->compile_select();
|
||||
|
||||
if ( ! empty($this->from))
|
||||
{
|
||||
$sql .= "\nFROM ".$this->compile_from();
|
||||
}
|
||||
}
|
||||
elseif ($this->type === Database::UPDATE)
|
||||
{
|
||||
$sql = 'UPDATE '.$this->compile_from()."\n".'SET '.$this->compile_set();
|
||||
}
|
||||
elseif ($this->type === Database::INSERT)
|
||||
{
|
||||
$sql = 'INSERT INTO '.$this->compile_from()."\n".$this->compile_columns()."\nVALUES ".$this->compile_values();
|
||||
}
|
||||
elseif ($this->type === Database::DELETE)
|
||||
{
|
||||
$sql = 'DELETE FROM '.$this->compile_from();
|
||||
}
|
||||
|
||||
if ( ! empty($this->join))
|
||||
{
|
||||
$sql .= $this->compile_join();
|
||||
}
|
||||
|
||||
if ( ! empty($this->where))
|
||||
{
|
||||
$sql .= "\n".'WHERE '.$this->compile_conditions($this->where);
|
||||
}
|
||||
|
||||
if ( ! empty($this->having))
|
||||
{
|
||||
$sql .= "\n".'HAVING '.$this->compile_conditions($this->having);
|
||||
}
|
||||
|
||||
if ( ! empty($this->group_by))
|
||||
{
|
||||
$sql .= "\n".'GROUP BY '.$this->compile_group_by();
|
||||
}
|
||||
|
||||
if ( ! empty($this->order_by))
|
||||
{
|
||||
$sql .= "\nORDER BY ".$this->compile_order_by();
|
||||
}
|
||||
|
||||
if (is_int($this->limit))
|
||||
{
|
||||
$sql .= "\nLIMIT ".$this->limit;
|
||||
}
|
||||
|
||||
if (is_int($this->offset))
|
||||
{
|
||||
$sql .= "\nOFFSET ".$this->offset;
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the SELECT portion of the query
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function compile_select()
|
||||
{
|
||||
$vals = array();
|
||||
|
||||
foreach ($this->select as $alias => $name)
|
||||
{
|
||||
if (is_string($alias))
|
||||
{
|
||||
$vals[] = $this->db->quote_column($name, $alias);
|
||||
}
|
||||
else
|
||||
{
|
||||
$vals[] = $this->db->quote_column($name);
|
||||
}
|
||||
}
|
||||
|
||||
return implode(', ', $vals);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the FROM portion of the query
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function compile_from()
|
||||
{
|
||||
$vals = array();
|
||||
|
||||
foreach ($this->from as $alias => $name)
|
||||
{
|
||||
if (is_string($alias))
|
||||
{
|
||||
// Using AS format so escape both
|
||||
$vals[] = $this->db->quote_table($name, $alias);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Just using the table name itself
|
||||
$vals[] = $this->db->quote_table($name);
|
||||
}
|
||||
}
|
||||
|
||||
return implode(', ', $vals);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the JOIN portion of the query
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function compile_join()
|
||||
{
|
||||
$sql = '';
|
||||
foreach ($this->join as $join)
|
||||
{
|
||||
list($table, $keys, $type) = $join;
|
||||
|
||||
if ($type !== NULL)
|
||||
{
|
||||
// Join type
|
||||
$sql .= ' '.$type;
|
||||
}
|
||||
|
||||
$sql .= ' JOIN '.$this->db->quote_table($table);
|
||||
|
||||
$condition = '';
|
||||
if ($keys instanceof Database_Expression)
|
||||
{
|
||||
$condition = (string) $keys;
|
||||
}
|
||||
elseif (is_array($keys))
|
||||
{
|
||||
// ON condition is an array of matches
|
||||
foreach ($keys as $key => $value)
|
||||
{
|
||||
if ( ! empty($condition))
|
||||
{
|
||||
$condition .= ' AND ';
|
||||
}
|
||||
|
||||
$condition .= $this->db->quote_column($key).' = '.$this->db->quote_column($value);
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty($condition))
|
||||
{
|
||||
// Add ON condition
|
||||
$sql .= ' ON ('.$condition.')';
|
||||
}
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the GROUP BY portion of the query
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function compile_group_by()
|
||||
{
|
||||
$vals = array();
|
||||
|
||||
foreach ($this->group_by as $column)
|
||||
{
|
||||
// Escape the column
|
||||
$vals[] = $this->db->quote_column($column);
|
||||
}
|
||||
|
||||
return implode(', ', $vals);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the ORDER BY portion of the query
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function compile_order_by()
|
||||
{
|
||||
$ordering = array();
|
||||
|
||||
foreach ($this->order_by as $column => $order_by)
|
||||
{
|
||||
list($column, $direction) = each($order_by);
|
||||
|
||||
$column = $this->db->quote_column($column);
|
||||
|
||||
if ($direction !== NULL)
|
||||
{
|
||||
$direction = ' '.$direction;
|
||||
}
|
||||
|
||||
$ordering[] = $column.$direction;
|
||||
}
|
||||
|
||||
return implode(', ', $ordering);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the SET portion of the query for UPDATE
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function compile_set()
|
||||
{
|
||||
$vals = array();
|
||||
|
||||
foreach ($this->set as $key => $value)
|
||||
{
|
||||
// Using an UPDATE so Key = Val
|
||||
$vals[] = $this->db->quote_column($key).' = '.$this->db->quote($value);
|
||||
}
|
||||
|
||||
return implode(', ', $vals);
|
||||
}
|
||||
|
||||
/**
|
||||
* Join tables to the builder
|
||||
*
|
||||
* @param mixed Table name
|
||||
* @param mixed Key, or an array of key => value pair, for join condition (can be a Database_Expression)
|
||||
* @param mixed Value if $keys is not an array or Database_Expression
|
||||
* @param string Join type (LEFT, RIGHT, INNER, etc.)
|
||||
* @return Database_Builder
|
||||
*/
|
||||
public function join($table, $keys, $value = NULL, $type = NULL)
|
||||
{
|
||||
if (is_string($keys))
|
||||
{
|
||||
$keys = array($keys => $value);
|
||||
}
|
||||
|
||||
if ($type !== NULL)
|
||||
{
|
||||
$type = strtoupper($type);
|
||||
}
|
||||
|
||||
$this->join[] = array($table, $keys, $type);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add tables to the FROM portion of the builder
|
||||
*
|
||||
* @param string|array table name or array(alias => table)
|
||||
* @return Database_Builder
|
||||
*/
|
||||
public function from($tables)
|
||||
{
|
||||
if ( ! is_array($tables))
|
||||
{
|
||||
$tables = func_get_args();
|
||||
}
|
||||
|
||||
$this->from = array_merge($this->from, $tables);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add fields to the GROUP BY portion
|
||||
*
|
||||
* @param mixed Field names or an array of fields
|
||||
* @return Database_Builder
|
||||
*/
|
||||
public function group_by($columns)
|
||||
{
|
||||
if ( ! is_array($columns))
|
||||
{
|
||||
$columns = func_get_args();
|
||||
}
|
||||
|
||||
$this->group_by = array_merge($this->group_by, $columns);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add conditions to the HAVING clause (AND)
|
||||
*
|
||||
* @param mixed Column name or array of columns => vals
|
||||
* @param string Operation to perform
|
||||
* @param mixed Value
|
||||
* @return Database_Builder
|
||||
*/
|
||||
public function having($columns, $op = '=', $value = NULL)
|
||||
{
|
||||
return $this->and_having($columns, $op, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add conditions to the HAVING clause (AND)
|
||||
*
|
||||
* @param mixed Column name or array of columns => vals
|
||||
* @param string Operation to perform
|
||||
* @param mixed Value
|
||||
* @return Database_Builder
|
||||
*/
|
||||
public function and_having($columns, $op = '=', $value = NULL)
|
||||
{
|
||||
$this->having[] = array('AND' => array($columns, $op, $value));
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add conditions to the HAVING clause (OR)
|
||||
*
|
||||
* @param mixed Column name or array of columns => vals
|
||||
* @param string Operation to perform
|
||||
* @param mixed Value
|
||||
* @return Database_Builder
|
||||
*/
|
||||
public function or_having($columns, $op = '=', $value = NULL)
|
||||
{
|
||||
$this->having[] = array('OR' => array($columns, $op, $value));
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add fields to the ORDER BY portion
|
||||
*
|
||||
* @param mixed Field names or an array of fields (field => direction)
|
||||
* @param string Direction or NULL for ascending
|
||||
* @return Database_Builder
|
||||
*/
|
||||
public function order_by($columns, $direction = NULL)
|
||||
{
|
||||
if (is_string($columns))
|
||||
{
|
||||
$columns = array($columns => $direction);
|
||||
}
|
||||
|
||||
$this->order_by[] = $columns;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit rows returned
|
||||
*
|
||||
* @param int Number of rows
|
||||
* @return Database_Builder
|
||||
*/
|
||||
public function limit($number)
|
||||
{
|
||||
$this->limit = (int) $number;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Offset into result set
|
||||
*
|
||||
* @param int Offset
|
||||
* @return Database_Builder
|
||||
*/
|
||||
public function offset($number)
|
||||
{
|
||||
$this->offset = (int) $number;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function left_join($table, $keys, $value = NULL)
|
||||
{
|
||||
return $this->join($table, $keys, $value, 'LEFT');
|
||||
}
|
||||
|
||||
public function right_join($table, $keys, $value = NULL)
|
||||
{
|
||||
return $this->join($table, $keys, $value, 'RIGHT');
|
||||
}
|
||||
|
||||
public function inner_join($table, $keys, $value = NULL)
|
||||
{
|
||||
return $this->join($table, $keys, $value, 'INNER');
|
||||
}
|
||||
|
||||
public function outer_join($table, $keys, $value = NULL)
|
||||
{
|
||||
return $this->join($table, $keys, $value, 'OUTER');
|
||||
}
|
||||
|
||||
public function full_join($table, $keys, $value = NULL)
|
||||
{
|
||||
return $this->join($table, $keys, $value, 'FULL');
|
||||
}
|
||||
|
||||
public function left_inner_join($table, $keys, $value = NULL)
|
||||
{
|
||||
return $this->join($table, $keys, $value, 'LEFT INNER');
|
||||
}
|
||||
|
||||
public function right_inner_join($table, $keys, $value = NULL)
|
||||
{
|
||||
return $this->join($table, $keys, $value, 'RIGHT INNER');
|
||||
}
|
||||
|
||||
public function open($clause = 'WHERE')
|
||||
{
|
||||
return $this->and_open($clause);
|
||||
}
|
||||
|
||||
public function and_open($clause = 'WHERE')
|
||||
{
|
||||
if ($clause === 'WHERE')
|
||||
{
|
||||
$this->where[] = array('AND' => '(');
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->having[] = array('AND' => '(');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function or_open($clause = 'WHERE')
|
||||
{
|
||||
if ($clause === 'WHERE')
|
||||
{
|
||||
$this->where[] = array('OR' => '(');
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->having[] = array('OR' => '(');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function close($clause = 'WHERE')
|
||||
{
|
||||
if ($clause === 'WHERE')
|
||||
{
|
||||
$this->where[] = array(')');
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->having[] = array(')');
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add conditions to the WHERE clause (AND)
|
||||
*
|
||||
* @param mixed Column name or array of columns => vals
|
||||
* @param string Operation to perform
|
||||
* @param mixed Value
|
||||
* @return Database_Builder
|
||||
*/
|
||||
public function where($columns, $op = '=', $value = NULL)
|
||||
{
|
||||
return $this->and_where($columns, $op, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add conditions to the WHERE clause (AND)
|
||||
*
|
||||
* @param mixed Column name or array of columns => vals
|
||||
* @param string Operation to perform
|
||||
* @param mixed Value
|
||||
* @return Database_Builder
|
||||
*/
|
||||
public function and_where($columns, $op = '=', $value = NULL)
|
||||
{
|
||||
$this->where[] = array('AND' => array($columns, $op, $value));
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add conditions to the WHERE clause (OR)
|
||||
*
|
||||
* @param mixed Column name or array of columns => vals
|
||||
* @param string Operation to perform
|
||||
* @param mixed Value
|
||||
* @return Database_Builder
|
||||
*/
|
||||
public function or_where($columns, $op = '=', $value = NULL)
|
||||
{
|
||||
$this->where[] = array('OR' => array($columns, $op, $value));
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the given clause's conditions
|
||||
*
|
||||
* @param array Clause conditions
|
||||
* @return string
|
||||
*/
|
||||
protected function compile_conditions($groups)
|
||||
{
|
||||
$last_condition = NULL;
|
||||
|
||||
$sql = '';
|
||||
foreach ($groups as $group)
|
||||
{
|
||||
// Process groups of conditions
|
||||
foreach ($group as $logic => $condition)
|
||||
{
|
||||
if ($condition === '(')
|
||||
{
|
||||
if ( ! empty($sql) AND $last_condition !== '(')
|
||||
{
|
||||
// Include logic operator
|
||||
$sql .= ' '.$logic.' ';
|
||||
}
|
||||
|
||||
$sql .= '(';
|
||||
}
|
||||
elseif ($condition === ')')
|
||||
{
|
||||
$sql .= ')';
|
||||
}
|
||||
else
|
||||
{
|
||||
list($columns, $op, $value) = $condition;
|
||||
|
||||
// Stores each individual condition
|
||||
$vals = array();
|
||||
|
||||
if ($columns instanceof Database_Expression)
|
||||
{
|
||||
// Add directly to condition list
|
||||
$vals[] = (string) $columns;
|
||||
}
|
||||
else
|
||||
{
|
||||
$op = strtoupper($op);
|
||||
|
||||
if ( ! is_array($columns))
|
||||
{
|
||||
$columns = array($columns => $value);
|
||||
}
|
||||
|
||||
foreach ($columns as $column => $value)
|
||||
{
|
||||
if ($value instanceof Database_Builder)
|
||||
{
|
||||
// Using a subquery
|
||||
$value->db = $this->db;
|
||||
$value = '('.(string) $value.')';
|
||||
}
|
||||
elseif (is_array($value))
|
||||
{
|
||||
if ($op === 'BETWEEN' OR $op === 'NOT BETWEEN')
|
||||
{
|
||||
// Falls between two values
|
||||
$value = $this->db->quote($value[0]).' AND '.$this->db->quote($value[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Return as list
|
||||
$value = array_map(array($this->db, 'quote'), $value);
|
||||
$value = '('.implode(', ', $value).')';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$value = $this->db->quote($value);
|
||||
}
|
||||
|
||||
if ( ! empty($column))
|
||||
{
|
||||
// Ignore blank columns
|
||||
$column = $this->db->quote_column($column);
|
||||
}
|
||||
|
||||
// Add to condition list
|
||||
$vals[] = $column.' '.$op.' '.$value;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty($sql) AND $last_condition !== '(')
|
||||
{
|
||||
// Add the logic operator
|
||||
$sql .= ' '.$logic.' ';
|
||||
}
|
||||
|
||||
// Join the condition list items together by the given logic operator
|
||||
$sql .= implode(' '.$logic.' ', $vals);
|
||||
}
|
||||
|
||||
$last_condition = $condition;
|
||||
}
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set values for UPDATE
|
||||
*
|
||||
* @param mixed Column name or array of columns => vals
|
||||
* @param mixed Value (can be a Database_Expression)
|
||||
* @return Database_Builder
|
||||
*/
|
||||
public function set($keys, $value = NULL)
|
||||
{
|
||||
if (is_string($keys))
|
||||
{
|
||||
$keys = array($keys => $value);
|
||||
}
|
||||
|
||||
$this->set = array_merge($keys, $this->set);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Columns used for INSERT queries
|
||||
*
|
||||
* @param array Columns
|
||||
* @return Database_Builder
|
||||
*/
|
||||
public function columns($columns)
|
||||
{
|
||||
if ( ! is_array($columns))
|
||||
{
|
||||
$columns = func_get_args();
|
||||
}
|
||||
|
||||
$this->columns = $columns;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the columns portion of the query for INSERT
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function compile_columns()
|
||||
{
|
||||
return '('.implode(', ', array_map(array($this->db, 'quote_column'), $this->columns)).')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Values used for INSERT queries
|
||||
*
|
||||
* @param array Values
|
||||
* @return Database_Builder
|
||||
*/
|
||||
public function values($values)
|
||||
{
|
||||
if ( ! is_array($values))
|
||||
{
|
||||
$values = func_get_args();
|
||||
}
|
||||
|
||||
$this->values[] = $values;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the VALUES portion of the query for INSERT
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function compile_values()
|
||||
{
|
||||
$values = array();
|
||||
foreach ($this->values as $group)
|
||||
{
|
||||
// Each set of values to be inserted
|
||||
$values[] = '('.implode(', ', array_map(array($this->db, 'quote'), $group)).')';
|
||||
}
|
||||
|
||||
return implode(', ', $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a SELECT query and specify selected columns
|
||||
*
|
||||
* @param string|array column name or array(alias => column)
|
||||
* @return Database_Builder
|
||||
*/
|
||||
public function select($columns = NULL)
|
||||
{
|
||||
$this->type = Database::SELECT;
|
||||
|
||||
if ($columns === NULL)
|
||||
{
|
||||
$columns = array('*');
|
||||
}
|
||||
elseif ( ! is_array($columns))
|
||||
{
|
||||
$columns = func_get_args();
|
||||
}
|
||||
|
||||
$this->select = array_merge($this->select, $columns);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an UPDATE query
|
||||
*
|
||||
* @param string Table name
|
||||
* @param array Array of Keys => Values
|
||||
* @param array WHERE conditions
|
||||
* @return Database_Builder
|
||||
*/
|
||||
public function update($table = NULL, $set = NULL, $where = NULL)
|
||||
{
|
||||
$this->type = Database::UPDATE;
|
||||
|
||||
if (is_array($set))
|
||||
{
|
||||
$this->set($set);
|
||||
}
|
||||
|
||||
if ($where !== NULL)
|
||||
{
|
||||
$this->where($where);
|
||||
}
|
||||
|
||||
if ($table !== NULL)
|
||||
{
|
||||
$this->from($table);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an INSERT query. Use 'columns' and 'values' methods for multi-row inserts
|
||||
*
|
||||
* @param string Table name
|
||||
* @param array Array of Keys => Values
|
||||
* @return Database_Builder
|
||||
*/
|
||||
public function insert($table = NULL, $set = NULL)
|
||||
{
|
||||
$this->type = Database::INSERT;
|
||||
|
||||
if (is_array($set))
|
||||
{
|
||||
$this->columns(array_keys($set));
|
||||
$this->values(array_values($set));
|
||||
}
|
||||
|
||||
if ($table !== NULL)
|
||||
{
|
||||
$this->from($table);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a DELETE query
|
||||
*
|
||||
* @param string Table name
|
||||
* @param array WHERE conditions
|
||||
* @return Database_Builder
|
||||
*/
|
||||
public function delete($table, $where = NULL)
|
||||
{
|
||||
$this->type = Database::DELETE;
|
||||
|
||||
if ($where !== NULL)
|
||||
{
|
||||
$this->where($where);
|
||||
}
|
||||
|
||||
if ($table !== NULL)
|
||||
{
|
||||
$this->from($table);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count records for a given table
|
||||
*
|
||||
* @param string Table name
|
||||
* @param array WHERE conditions
|
||||
* @return int
|
||||
*/
|
||||
public function count_records($table = FALSE, $where = NULL)
|
||||
{
|
||||
if (count($this->from) < 1)
|
||||
{
|
||||
if ($table === FALSE)
|
||||
throw new Database_Exception('Database count_records requires a table');
|
||||
|
||||
$this->from($table);
|
||||
}
|
||||
|
||||
if ($where !== NULL)
|
||||
{
|
||||
$this->where($where);
|
||||
}
|
||||
|
||||
// Grab the count AS records_found
|
||||
$result = $this->select(array('records_found' => 'COUNT("*")'))->execute();
|
||||
|
||||
return $result->get('records_found');
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the built query
|
||||
*
|
||||
* @param mixed Database name or object
|
||||
* @return Database_Result
|
||||
*/
|
||||
public function execute($db = NULL)
|
||||
{
|
||||
if ($db !== NULL)
|
||||
{
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
if ( ! is_object($this->db))
|
||||
{
|
||||
// Get the database instance
|
||||
$this->db = Database::instance($this->db);
|
||||
}
|
||||
|
||||
$query = $this->compile();
|
||||
|
||||
// Reset the query after executing
|
||||
$this->reset();
|
||||
|
||||
if ($this->ttl !== FALSE AND $this->type === Database::SELECT)
|
||||
{
|
||||
// Return result from cache (only allowed with SELECT)
|
||||
return $this->db->query_cache($query, $this->ttl);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load the result (no caching)
|
||||
return $this->db->query($query);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set caching for the query
|
||||
*
|
||||
* @param mixed Time-to-live (FALSE to disable, NULL for Cache default, seconds otherwise)
|
||||
* @return Database_Builder
|
||||
*/
|
||||
public function cache($ttl = NULL)
|
||||
{
|
||||
$this->ttl = $ttl;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
} // End Database_Builder
|
||||
83
system/libraries/Database_Cache_Result.php
Normal file
83
system/libraries/Database_Cache_Result.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Cached database result.
|
||||
*
|
||||
* $Id: Database_Cache_Result.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Kohana
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Database_Cache_Result_Core extends Database_Result {
|
||||
|
||||
/**
|
||||
* Result data (array of rows)
|
||||
* @var array
|
||||
*/
|
||||
protected $data;
|
||||
|
||||
public function __construct($data, $sql, $return_objects)
|
||||
{
|
||||
$this->data = $data;
|
||||
$this->sql = $sql;
|
||||
$this->total_rows = count($data);
|
||||
$this->return_objects = $return_objects;
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
// Not used
|
||||
}
|
||||
|
||||
public function as_array($return = FALSE)
|
||||
{
|
||||
// Return arrays rather than objects
|
||||
$this->return_objects = FALSE;
|
||||
|
||||
if ( ! $return )
|
||||
{
|
||||
// Return this result object
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Return the entire array of rows
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function as_object($class = NULL, $return = FALSE)
|
||||
{
|
||||
if ($class !== NULL)
|
||||
throw new Database_Exception('Database cache results do not support object casting');
|
||||
|
||||
// Return objects of type $class (or stdClass if none given)
|
||||
$this->return_objects = TRUE;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function seek($offset)
|
||||
{
|
||||
if ( ! $this->offsetExists($offset))
|
||||
return FALSE;
|
||||
|
||||
$this->current_row = $offset;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
public function current()
|
||||
{
|
||||
if ($this->return_objects)
|
||||
{
|
||||
// Return a new object with the current row of data
|
||||
return (object) $this->data[$this->current_row];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Return an array of the row
|
||||
return $this->data[$this->current_row];
|
||||
}
|
||||
}
|
||||
|
||||
} // End Database_Cache_Result
|
||||
17
system/libraries/Database_Exception.php
Normal file
17
system/libraries/Database_Exception.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Database exceptions.
|
||||
*
|
||||
* $Id: Database_Exception.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Kohana
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Database_Exception_Core extends Kohana_Exception {
|
||||
|
||||
// Database error code
|
||||
protected $code = E_DATABASE_ERROR;
|
||||
|
||||
} // End Database_Exception
|
||||
@@ -1,13 +1,13 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access allowed.');
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Database expression class to allow for explicit joins and where expressions.
|
||||
*
|
||||
* $Id: Database_Expression.php 4037 2009-03-04 23:35:53Z jheathco $
|
||||
*
|
||||
* @package Core
|
||||
* Database expression.
|
||||
*
|
||||
* $Id: Database_Expression.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Kohana
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Database_Expression_Core {
|
||||
|
||||
@@ -20,7 +20,6 @@ class Database_Expression_Core {
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return (string) $this->expression;
|
||||
return $this->expression;
|
||||
}
|
||||
|
||||
} // End Database Expr Class
|
||||
}
|
||||
|
||||
229
system/libraries/Database_Mysql.php
Normal file
229
system/libraries/Database_Mysql.php
Normal file
@@ -0,0 +1,229 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* MySQL database connection.
|
||||
*
|
||||
* $Id: Database_Mysql.php 4684 2009-11-18 14:26:48Z isaiah $
|
||||
*
|
||||
* @package Kohana
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Database_Mysql_Core extends Database {
|
||||
|
||||
// Quote character to use for identifiers (tables/columns/aliases)
|
||||
protected $quote = '`';
|
||||
|
||||
// Use SET NAMES to set the character set
|
||||
protected static $set_names;
|
||||
|
||||
public function connect()
|
||||
{
|
||||
if ($this->connection)
|
||||
return;
|
||||
|
||||
if (Database_Mysql::$set_names === NULL)
|
||||
{
|
||||
// Determine if we can use mysql_set_charset(), which is only
|
||||
// available on PHP 5.2.3+ when compiled against MySQL 5.0+
|
||||
Database_Mysql::$set_names = ! function_exists('mysql_set_charset');
|
||||
}
|
||||
|
||||
extract($this->config['connection']);
|
||||
|
||||
// Set the connection type
|
||||
$connect = ($this->config['persistent'] === TRUE) ? 'mysql_pconnect' : 'mysql_connect';
|
||||
|
||||
$host = isset($host) ? $host : $socket;
|
||||
$port = isset($port) ? ':'.$port : '';
|
||||
|
||||
try
|
||||
{
|
||||
// Connect to the database
|
||||
$this->connection = $connect($host.$port, $user, $pass, TRUE);
|
||||
}
|
||||
catch (Kohana_PHP_Exception $e)
|
||||
{
|
||||
// No connection exists
|
||||
$this->connection = NULL;
|
||||
|
||||
// Unable to connect to the database
|
||||
throw new Database_Exception('#:errno: :error',
|
||||
array(':error' => mysql_error(),
|
||||
':errno' => mysql_errno()));
|
||||
}
|
||||
|
||||
if ( ! mysql_select_db($database, $this->connection))
|
||||
{
|
||||
// Unable to select database
|
||||
throw new Database_Exception('#:errno: :error',
|
||||
array(':error' => mysql_error($this->connection),
|
||||
':errno' => mysql_errno($this->connection)));
|
||||
}
|
||||
|
||||
if (isset($this->config['character_set']))
|
||||
{
|
||||
// Set the character set
|
||||
$this->set_charset($this->config['character_set']);
|
||||
}
|
||||
}
|
||||
|
||||
public function disconnect()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Database is assumed disconnected
|
||||
$status = TRUE;
|
||||
|
||||
if (is_resource($this->connection))
|
||||
{
|
||||
$status = mysql_close($this->connection);
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
// Database is probably not disconnected
|
||||
$status = is_resource($this->connection);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
public function set_charset($charset)
|
||||
{
|
||||
// Make sure the database is connected
|
||||
$this->connection or $this->connect();
|
||||
|
||||
if (Database_Mysql::$set_names === TRUE)
|
||||
{
|
||||
// PHP is compiled against MySQL 4.x
|
||||
$status = (bool) mysql_query('SET NAMES '.$this->quote($charset), $this->connection);
|
||||
}
|
||||
else
|
||||
{
|
||||
// PHP is compiled against MySQL 5.x
|
||||
$status = mysql_set_charset($charset, $this->connection);
|
||||
}
|
||||
|
||||
if ($status === FALSE)
|
||||
{
|
||||
// Unable to set charset
|
||||
throw new Database_Exception('#:errno: :error',
|
||||
array(':error' => mysql_error($this->connection),
|
||||
':errno' => mysql_errno($this->connection)));
|
||||
}
|
||||
}
|
||||
|
||||
public function query_execute($sql)
|
||||
{
|
||||
// Make sure the database is connected
|
||||
$this->connection or $this->connect();
|
||||
|
||||
$result = mysql_query($sql, $this->connection);
|
||||
|
||||
// Set the last query
|
||||
$this->last_query = $sql;
|
||||
|
||||
return new Database_Mysql_Result($result, $sql, $this->connection, $this->config['object']);
|
||||
}
|
||||
|
||||
public function escape($value)
|
||||
{
|
||||
// Make sure the database is connected
|
||||
$this->connection or $this->connect();
|
||||
|
||||
if (($value = mysql_real_escape_string($value, $this->connection)) === FALSE)
|
||||
{
|
||||
throw new Database_Exception('#:errno: :error',
|
||||
array(':error' => mysql_error($this->connection),
|
||||
':errno' => mysql_errno($this->connection)));
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function list_constraints($table)
|
||||
{
|
||||
$prefix = strlen($this->table_prefix());
|
||||
$result = array();
|
||||
|
||||
$constraints = $this->query('
|
||||
SELECT c.constraint_name, c.constraint_type, k.column_name, k.referenced_table_name, k.referenced_column_name
|
||||
FROM information_schema.table_constraints c
|
||||
JOIN information_schema.key_column_usage k ON (k.table_schema = c.table_schema AND k.table_name = c.table_name AND k.constraint_name = c.constraint_name)
|
||||
WHERE c.table_schema = '.$this->quote($this->config['connection']['database']).'
|
||||
AND c.table_name = '.$this->quote($this->table_prefix().$table).'
|
||||
AND (k.referenced_table_schema IS NULL OR k.referenced_table_schema ='.$this->quote($this->config['connection']['database']).')
|
||||
ORDER BY k.ordinal_position
|
||||
');
|
||||
|
||||
foreach ($constraints->as_array() as $row)
|
||||
{
|
||||
switch ($row['constraint_type'])
|
||||
{
|
||||
case 'FOREIGN KEY':
|
||||
if (isset($result[$row['constraint_name']]))
|
||||
{
|
||||
$result[$row['constraint_name']][1][] = $row['column_name'];
|
||||
$result[$row['constraint_name']][3][] = $row['referenced_column_name'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$result[$row['constraint_name']] = array($row['constraint_type'], array($row['column_name']), substr($row['referenced_table_name'], $prefix), array($row['referenced_column_name']));
|
||||
}
|
||||
break;
|
||||
case 'PRIMARY KEY':
|
||||
case 'UNIQUE':
|
||||
if (isset($result[$row['constraint_name']]))
|
||||
{
|
||||
$result[$row['constraint_name']][1][] = $row['column_name'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$result[$row['constraint_name']] = array($row['constraint_type'], array($row['column_name']));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function list_fields($table)
|
||||
{
|
||||
$result = array();
|
||||
|
||||
foreach ($this->query('SHOW COLUMNS FROM '.$this->quote_table($table))->as_array() as $row)
|
||||
{
|
||||
$column = $this->sql_type($row['Type']);
|
||||
|
||||
$column['default'] = $row['Default'];
|
||||
$column['nullable'] = $row['Null'] === 'YES';
|
||||
$column['sequenced'] = $row['Extra'] === 'auto_increment';
|
||||
|
||||
if (isset($column['length']) AND $column['type'] === 'float')
|
||||
{
|
||||
list($column['precision'], $column['scale']) = explode(',', $column['length']);
|
||||
}
|
||||
|
||||
$result[$row['Field']] = $column;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function list_tables()
|
||||
{
|
||||
$prefix = strlen($this->table_prefix());
|
||||
$tables = array();
|
||||
|
||||
foreach ($this->query('SHOW TABLES FROM '.$this->escape($this->config['connection']['database']).' LIKE '.$this->quote($this->table_prefix().'%'))->as_array() as $row)
|
||||
{
|
||||
// The value is the table name
|
||||
$tables[] = substr(current($row), $prefix);
|
||||
}
|
||||
|
||||
return $tables;
|
||||
}
|
||||
|
||||
} // End Database_MySQL
|
||||
176
system/libraries/Database_Mysql_Result.php
Normal file
176
system/libraries/Database_Mysql_Result.php
Normal file
@@ -0,0 +1,176 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* MySQL database result.
|
||||
*
|
||||
* $Id: Database_Mysql_Result.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Kohana
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Database_Mysql_Result_Core extends Database_Result {
|
||||
|
||||
protected $internal_row = 0;
|
||||
|
||||
public function __construct($result, $sql, $link, $return_objects)
|
||||
{
|
||||
if (is_resource($result))
|
||||
{
|
||||
// True to return objects, false for arrays
|
||||
$this->return_objects = $return_objects;
|
||||
|
||||
$this->total_rows = mysql_num_rows($result);
|
||||
}
|
||||
elseif (is_bool($result))
|
||||
{
|
||||
if ($result == FALSE)
|
||||
{
|
||||
throw new Database_Exception('#:errno: :error [ :query ]',
|
||||
array(':error' => mysql_error($link),
|
||||
':query' => $sql,
|
||||
':errno' => mysql_errno($link)));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's a DELETE, INSERT, REPLACE, or UPDATE query
|
||||
$this->insert_id = mysql_insert_id($link);
|
||||
$this->total_rows = mysql_affected_rows($link);
|
||||
}
|
||||
}
|
||||
|
||||
// Store the result locally
|
||||
$this->result = $result;
|
||||
|
||||
$this->sql = $sql;
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if (is_resource($this->result))
|
||||
{
|
||||
mysql_free_result($this->result);
|
||||
}
|
||||
}
|
||||
|
||||
public function as_array($return = FALSE)
|
||||
{
|
||||
// Return arrays rather than objects
|
||||
$this->return_objects = FALSE;
|
||||
|
||||
if ( ! $return )
|
||||
{
|
||||
// Return this result object
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Return a nested array of all results
|
||||
$array = array();
|
||||
|
||||
if ($this->total_rows > 0)
|
||||
{
|
||||
// Seek to the beginning of the result
|
||||
mysql_data_seek($this->result, 0);
|
||||
|
||||
while ($row = mysql_fetch_assoc($this->result))
|
||||
{
|
||||
// Add each row to the array
|
||||
$array[] = $row;
|
||||
}
|
||||
|
||||
$this->internal_row = $this->total_rows;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
public function as_object($class = NULL, $return = FALSE)
|
||||
{
|
||||
// Return objects of type $class (or stdClass if none given)
|
||||
$this->return_objects = ($class !== NULL) ? $class : TRUE;
|
||||
|
||||
if ( ! $return )
|
||||
{
|
||||
// Return this result object
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Return a nested array of all results
|
||||
$array = array();
|
||||
|
||||
if ($this->total_rows > 0)
|
||||
{
|
||||
// Seek to the beginning of the result
|
||||
mysql_data_seek($this->result, 0);
|
||||
|
||||
if (is_string($this->return_objects))
|
||||
{
|
||||
while ($row = mysql_fetch_object($this->result, $this->return_objects))
|
||||
{
|
||||
// Add each row to the array
|
||||
$array[] = $row;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while ($row = mysql_fetch_object($this->result))
|
||||
{
|
||||
// Add each row to the array
|
||||
$array[] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
$this->internal_row = $this->total_rows;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* SeekableIterator: seek
|
||||
*/
|
||||
public function seek($offset)
|
||||
{
|
||||
if ($this->offsetExists($offset) AND mysql_data_seek($this->result, $offset))
|
||||
{
|
||||
// Set the current row to the offset
|
||||
$this->current_row = $this->internal_row = $offset;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator: current
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
if ($this->current_row !== $this->internal_row AND ! $this->seek($this->current_row))
|
||||
return NULL;
|
||||
|
||||
++$this->internal_row;
|
||||
|
||||
if ($this->return_objects)
|
||||
{
|
||||
if (is_string($this->return_objects))
|
||||
{
|
||||
return mysql_fetch_object($this->result, $this->return_objects);
|
||||
}
|
||||
else
|
||||
{
|
||||
return mysql_fetch_object($this->result);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Return an array of the row
|
||||
return mysql_fetch_assoc($this->result);
|
||||
}
|
||||
}
|
||||
|
||||
} // End Database_MySQL_Result
|
||||
92
system/libraries/Database_Mysqli.php
Normal file
92
system/libraries/Database_Mysqli.php
Normal file
@@ -0,0 +1,92 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* MySQL database connection.
|
||||
*
|
||||
* $Id: Database_Mysqli.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Kohana
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
|
||||
define('RUNS_MYSQLND', function_exists('mysqli_fetch_all'));
|
||||
|
||||
class Database_Mysqli_Core extends Database_Mysql {
|
||||
|
||||
public function connect()
|
||||
{
|
||||
if (is_object($this->connection))
|
||||
return;
|
||||
|
||||
extract($this->config['connection']);
|
||||
|
||||
// Persistent connections are supported as of PHP 5.3
|
||||
if (RUNS_MYSQLND AND $this->config['persistent'] === TRUE)
|
||||
{
|
||||
$host = 'p:'.$host;
|
||||
}
|
||||
|
||||
$host = isset($host) ? $host : $socket;
|
||||
|
||||
if($this->connection = new mysqli($host, $user, $pass, $database, $port)) {
|
||||
|
||||
if (isset($this->config['character_set']))
|
||||
{
|
||||
// Set the character set
|
||||
$this->set_charset($this->config['character_set']);
|
||||
}
|
||||
|
||||
// Clear password after successful connect
|
||||
$this->db_config['connection']['pass'] = NULL;
|
||||
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
// Unable to connect to the database
|
||||
throw new Database_Exception('#:errno: :error',
|
||||
array(':error' => $this->connection->connect_error,
|
||||
':errno' => $this->connection->connect_errno));
|
||||
}
|
||||
|
||||
public function disconnect()
|
||||
{
|
||||
return is_object($this->connection) and $this->connection->close();
|
||||
}
|
||||
|
||||
public function set_charset($charset)
|
||||
{
|
||||
// Make sure the database is connected
|
||||
is_object($this->connection) or $this->connect();
|
||||
|
||||
if ( ! $this->connection->set_charset($charset))
|
||||
{
|
||||
// Unable to set charset
|
||||
throw new Database_Exception('#:errno: :error',
|
||||
array(':error' => $this->connection->connect_error,
|
||||
':errno' => $this->connection->connect_errno));
|
||||
}
|
||||
}
|
||||
|
||||
public function query_execute($sql)
|
||||
{
|
||||
// Make sure the database is connected
|
||||
is_object($this->connection) or $this->connect();
|
||||
|
||||
$result = $this->connection->query($sql);
|
||||
|
||||
// Set the last query
|
||||
$this->last_query = $sql;
|
||||
|
||||
return new Database_Mysqli_Result($result, $sql, $this->connection, $this->config['object']);
|
||||
}
|
||||
|
||||
public function escape($value)
|
||||
{
|
||||
// Make sure the database is connected
|
||||
is_object($this->connection) or $this->connect();
|
||||
|
||||
return $this->connection->real_escape_string($value);
|
||||
}
|
||||
|
||||
} // End Database_MySQLi
|
||||
177
system/libraries/Database_Mysqli_Result.php
Normal file
177
system/libraries/Database_Mysqli_Result.php
Normal file
@@ -0,0 +1,177 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* MySQL database result.
|
||||
*
|
||||
* $Id: Database_Mysqli_Result.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Kohana
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Database_Mysqli_Result_Core extends Database_Result {
|
||||
|
||||
protected $internal_row = 0;
|
||||
|
||||
public function __construct($result, $sql, $link, $return_objects)
|
||||
{
|
||||
if (is_object($result))
|
||||
{
|
||||
// True to return objects, false for arrays
|
||||
$this->return_objects = $return_objects;
|
||||
|
||||
$this->total_rows = $result->num_rows;
|
||||
}
|
||||
elseif (is_bool($result))
|
||||
{
|
||||
if ($result == FALSE)
|
||||
{
|
||||
throw new Database_Exception('#:errno: :error [ :query ]',
|
||||
array(':error' => $link->error,
|
||||
':query' => $sql,
|
||||
':errno' => $link->errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's a DELETE, INSERT, REPLACE, or UPDATE query
|
||||
$this->insert_id = $link->insert_id;
|
||||
$this->total_rows = $link->affected_rows;
|
||||
}
|
||||
}
|
||||
|
||||
// Store the result locally
|
||||
$this->result = $result;
|
||||
|
||||
$this->sql = $sql;
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if (is_object($this->result))
|
||||
{
|
||||
$this->result->free();
|
||||
}
|
||||
}
|
||||
|
||||
public function as_array($return = FALSE)
|
||||
{
|
||||
// Return arrays rather than objects
|
||||
$this->return_objects = FALSE;
|
||||
|
||||
if ( ! $return )
|
||||
{
|
||||
// Return this result object
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Return a nested array of all results
|
||||
if (RUNS_MYSQLND)
|
||||
return $this->result->fetch_all(MYSQLI_ASSOC);
|
||||
|
||||
$array = array();
|
||||
|
||||
if ($this->total_rows > 0)
|
||||
{
|
||||
// Seek to the beginning of the result
|
||||
$this->result->data_seek(0);
|
||||
|
||||
while ($row = $this->result->fetch_assoc())
|
||||
{
|
||||
// Add each row to the array
|
||||
$array[] = $row;
|
||||
}
|
||||
$this->internal_row = $this->total_rows;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
public function as_object($class = NULL, $return = FALSE)
|
||||
{
|
||||
// Return objects of type $class (or stdClass if none given)
|
||||
$this->return_objects = ($class !== NULL) ? $class : TRUE;
|
||||
|
||||
if ( ! $return )
|
||||
{
|
||||
// Return this result object
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Return a nested array of all results
|
||||
$array = array();
|
||||
|
||||
if ($this->total_rows > 0)
|
||||
{
|
||||
// Seek to the beginning of the result
|
||||
$this->result->data_seek(0);
|
||||
|
||||
if (is_string($this->return_objects))
|
||||
{
|
||||
while ($row = $this->result->fetch_object($this->return_objects))
|
||||
{
|
||||
// Add each row to the array
|
||||
$array[] = $row;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while ($row = $this->result->fetch_object())
|
||||
{
|
||||
// Add each row to the array
|
||||
$array[] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
$this->internal_row = $this->total_rows;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* SeekableIterator: seek
|
||||
*/
|
||||
public function seek($offset)
|
||||
{
|
||||
if ($this->offsetExists($offset) AND $this->result->data_seek($offset))
|
||||
{
|
||||
// Set the current row to the offset
|
||||
$this->current_row = $offset;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator: current
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
if ($this->current_row !== $this->internal_row AND ! $this->seek($this->current_row))
|
||||
return NULL;
|
||||
|
||||
++$this->internal_row;
|
||||
|
||||
if ($this->return_objects)
|
||||
{
|
||||
if (is_string($this->return_objects))
|
||||
{
|
||||
return $this->result->fetch_object($this->return_objects);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->result->fetch_object();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Return an array of the row
|
||||
return $this->result->fetch_assoc();
|
||||
}
|
||||
}
|
||||
|
||||
} // End Database_MySQLi_Result
|
||||
95
system/libraries/Database_Query.php
Normal file
95
system/libraries/Database_Query.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Database query wrapper.
|
||||
*
|
||||
* $Id: Database_Query.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Kohana
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Database_Query_Core {
|
||||
|
||||
protected $sql;
|
||||
protected $params;
|
||||
protected $ttl = FALSE;
|
||||
|
||||
public function __construct($sql = NULL)
|
||||
{
|
||||
$this->sql = $sql;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
// Return the SQL of this query
|
||||
return $this->sql;
|
||||
}
|
||||
|
||||
public function sql($sql)
|
||||
{
|
||||
$this->sql = $sql;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function value($key, $value)
|
||||
{
|
||||
$this->params[$key] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function bind($key, & $value)
|
||||
{
|
||||
$this->params[$key] =& $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function execute($db = 'default')
|
||||
{
|
||||
if ( ! is_object($db))
|
||||
{
|
||||
// Get the database instance
|
||||
$db = Database::instance($db);
|
||||
}
|
||||
|
||||
// Import the SQL locally
|
||||
$sql = $this->sql;
|
||||
|
||||
if ( ! empty($this->params))
|
||||
{
|
||||
// Quote all of the values
|
||||
$params = array_map(array($db, 'quote'), $this->params);
|
||||
|
||||
// Replace the values in the SQL
|
||||
$sql = strtr($sql, $params);
|
||||
}
|
||||
|
||||
if ($this->ttl !== FALSE)
|
||||
{
|
||||
// Load the result from the cache
|
||||
return $db->query_cache($sql, $this->ttl);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load the result (no caching)
|
||||
return $db->query($sql);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set caching for the query
|
||||
*
|
||||
* @param mixed Time-to-live (FALSE to disable, NULL for Cache default, seconds otherwise)
|
||||
* @return Database_Query
|
||||
*/
|
||||
public function cache($ttl = NULL)
|
||||
{
|
||||
$this->ttl = $ttl;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
} // End Database_Query
|
||||
170
system/libraries/Database_Result.php
Normal file
170
system/libraries/Database_Result.php
Normal file
@@ -0,0 +1,170 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
/**
|
||||
* Database result wrapper.
|
||||
*
|
||||
* $Id: Database_Result.php 4679 2009-11-10 01:45:52Z isaiah $
|
||||
*
|
||||
* @package Kohana
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2008-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
abstract class Database_Result_Core implements Countable, Iterator, SeekableIterator, ArrayAccess {
|
||||
|
||||
protected $result;
|
||||
|
||||
protected $total_rows = 0;
|
||||
protected $current_row = 0;
|
||||
protected $insert_id;
|
||||
|
||||
// Return objects or arrays for each row
|
||||
protected $return_objects;
|
||||
|
||||
/**
|
||||
* Sets the total number of rows and stores the result locally.
|
||||
*
|
||||
* @param mixed $result query result
|
||||
* @param boolean $return_objects True for results as objects, false for arrays
|
||||
* @return void
|
||||
*/
|
||||
abstract public function __construct($result, $sql, $link, $return_objects);
|
||||
|
||||
/**
|
||||
* Result destruction cleans up all open result sets.
|
||||
*/
|
||||
abstract public function __destruct();
|
||||
|
||||
/**
|
||||
* Return arrays for reach result, or the entire set of results
|
||||
*
|
||||
* @param boolean $return True to return entire result array
|
||||
* @return Database_Result|array
|
||||
*/
|
||||
abstract public function as_array($return = FALSE);
|
||||
|
||||
/**
|
||||
* Returns objects for each result
|
||||
*
|
||||
* @param string $class Class name to return objects as or NULL for stdClass
|
||||
* @return Database_Result
|
||||
*/
|
||||
abstract public function as_object($class = NULL, $return = FALSE);
|
||||
|
||||
/**
|
||||
* Returns the insert id
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function insert_id()
|
||||
{
|
||||
return $this->insert_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the named column from the current row.
|
||||
*
|
||||
* @param string Column name
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($name)
|
||||
{
|
||||
// Get the current row
|
||||
$row = $this->current();
|
||||
|
||||
if ( ! $this->return_objects)
|
||||
return $row[$name];
|
||||
|
||||
return $row->$name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Countable: count
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return $this->total_rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* ArrayAccess: offsetExists
|
||||
*/
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return ($offset >= 0 AND $offset < $this->total_rows);
|
||||
}
|
||||
|
||||
/**
|
||||
* ArrayAccess: offsetGet
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
if ( ! $this->seek($offset))
|
||||
return NULL;
|
||||
|
||||
return $this->current();
|
||||
}
|
||||
|
||||
/**
|
||||
* ArrayAccess: offsetSet
|
||||
*
|
||||
* @throws Kohana_Database_Exception
|
||||
*/
|
||||
final public function offsetSet($offset, $value)
|
||||
{
|
||||
throw new Kohana_Exception('Database results are read-only');
|
||||
}
|
||||
|
||||
/**
|
||||
* ArrayAccess: offsetUnset
|
||||
*
|
||||
* @throws Kohana_Database_Exception
|
||||
*/
|
||||
final public function offsetUnset($offset)
|
||||
{
|
||||
throw new Kohana_Exception('Database results are read-only');
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator: key
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
return $this->current_row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator: next
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
++$this->current_row;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator: prev
|
||||
*/
|
||||
public function prev()
|
||||
{
|
||||
--$this->current_row;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator: rewind
|
||||
*/
|
||||
public function rewind()
|
||||
{
|
||||
$this->current_row = 0;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator: valid
|
||||
*/
|
||||
public function valid()
|
||||
{
|
||||
return $this->offsetExists($this->current_row);
|
||||
}
|
||||
|
||||
} // End Database_Result
|
||||
@@ -4,12 +4,12 @@
|
||||
* using the MCrypt extension.
|
||||
* @see http://php.net/mcrypt
|
||||
*
|
||||
* $Id: Encrypt.php 4072 2009-03-13 17:20:38Z jheathco $
|
||||
* $Id: Encrypt.php 4683 2009-11-14 17:10:53Z isaiah $
|
||||
*
|
||||
* @package Core
|
||||
* @author Kohana Team
|
||||
* @copyright (c) 2007-2008 Kohana Team
|
||||
* @license http://kohanaphp.com/license.html
|
||||
* @copyright (c) 2007-2009 Kohana Team
|
||||
* @license http://kohanaphp.com/license
|
||||
*/
|
||||
class Encrypt_Core {
|
||||
|
||||
@@ -44,7 +44,7 @@ class Encrypt_Core {
|
||||
public function __construct($config = FALSE)
|
||||
{
|
||||
if ( ! defined('MCRYPT_ENCRYPT'))
|
||||
throw new Kohana_Exception('encrypt.requires_mcrypt');
|
||||
throw new Kohana_Exception('To use the Encrypt library, mcrypt must be enabled in your PHP installation');
|
||||
|
||||
if (is_string($config))
|
||||
{
|
||||
@@ -52,7 +52,7 @@ class Encrypt_Core {
|
||||
|
||||
// Test the config group name
|
||||
if (($config = Kohana::config('encryption.'.$config)) === NULL)
|
||||
throw new Kohana_Exception('encrypt.undefined_group', $name);
|
||||
throw new Kohana_Exception('The :name: group is not defined in your configuration.', array(':name:' => $name));
|
||||
}
|
||||
|
||||
if (is_array($config))
|
||||
@@ -67,7 +67,7 @@ class Encrypt_Core {
|
||||
}
|
||||
|
||||
if (empty($config['key']))
|
||||
throw new Kohana_Exception('encrypt.no_encryption_key');
|
||||
throw new Kohana_Exception('To use the Encrypt library, you must set an encryption key in your config file');
|
||||
|
||||
// Find the max length of the key, based on cipher and mode
|
||||
$size = mcrypt_get_key_size($config['cipher'], $config['mode']);
|
||||
@@ -84,7 +84,7 @@ class Encrypt_Core {
|
||||
// Cache the config in the object
|
||||
$this->config = $config;
|
||||
|
||||
Kohana::log('debug', 'Encrypt Library initialized');
|
||||
Kohana_Log::add('debug', 'Encrypt Library initialized');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,16 +144,28 @@ class Encrypt_Core {
|
||||
* Decrypts an encoded string back to its original value.
|
||||
*
|
||||
* @param string encoded string to be decrypted
|
||||
* @return string decrypted data
|
||||
* @return string decrypted data or FALSE if decryption fails
|
||||
*/
|
||||
public function decode($data)
|
||||
{
|
||||
// Convert the data back to binary
|
||||
$data = base64_decode($data);
|
||||
$data = base64_decode($data, TRUE);
|
||||
|
||||
if ( ! $data)
|
||||
{
|
||||
// Invalid base64 data
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Extract the initialization vector from the data
|
||||
$iv = substr($data, 0, $this->config['iv_size']);
|
||||
|
||||
if ($this->config['iv_size'] !== strlen($iv))
|
||||
{
|
||||
// The iv is not the correct size
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Remove the iv from the data
|
||||
$data = substr($data, $this->config['iv_size']);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user