Update to Kohana r4684 which is now Kohana 2.4 and has substantial

changes.
This commit is contained in:
Bharat Mediratta
2009-11-24 19:20:36 -08:00
parent 82ee5f9d33
commit 9b6663f87a
168 changed files with 11575 additions and 11184 deletions

View File

@@ -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');

View File

@@ -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

View File

@@ -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>

View File

@@ -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
);

View File

@@ -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;

View File

@@ -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);';

View File

@@ -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';

View File

@@ -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';

View File

@@ -25,7 +25,7 @@
*/
$config['default'] = array
(
'benchmark' => TRUE,
'benchmark' => FALSE,
'persistent' => FALSE,
'connection' => array
(

View File

@@ -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;

View File

@@ -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',

View File

@@ -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
View 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');

View 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

View File

@@ -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,
);

View File

@@ -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;

View File

@@ -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.

View File

@@ -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'];

View File

@@ -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
(

View File

@@ -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 {

View File

@@ -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();

View File

@@ -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

View 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 {}

View 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).'&nbsp;&hellip;';
}
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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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];
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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));
}

View File

@@ -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;
}

View File

@@ -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]));
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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];
}

View File

@@ -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]);
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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];
}

View File

@@ -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
);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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

View File

@@ -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

View File

@@ -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', '&amp;', $str);
$str = str_replace(array('<', '>', '\'', '"'), array('&lt;', '&gt;', '&#39;', '&quot;'), $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;

View File

@@ -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

View File

@@ -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 {

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}
/**

View File

@@ -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 DamerauLevenshtein 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

View File

@@ -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));
}
/**

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -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',
);

View File

@@ -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'
);

View File

@@ -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',
);

View File

@@ -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.'
);

View File

@@ -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'
);

View 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', ''),
);

View File

@@ -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',
);

View File

@@ -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.',
),
);

View File

@@ -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';

View File

@@ -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',
);

View File

@@ -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.',
);

View File

@@ -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.',
);

View File

@@ -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',
);

View File

@@ -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

View 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

View File

@@ -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

View 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

View 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

View 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

View File

@@ -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
}

View 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

View 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

View 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

View 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

View 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

View 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

View File

@@ -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