New upstream version 0.6.27

This commit is contained in:
geos_one
2025-08-06 18:11:51 +02:00
parent a6b4158f1f
commit 56a986c0ba
563 changed files with 45811 additions and 35282 deletions

View File

@@ -1,4 +1,12 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* Cache driver interface.
*
@@ -9,32 +17,32 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
interface Cache_Driver {
interface Cache_Driver
{
/**
* Set a cache item.
*/
public function set($id, $data, array $tags = null, $lifetime);
/**
* Set a cache item.
*/
public function set($id, $data, array $tags = NULL, $lifetime);
/**
* Find all of the cache ids for a given tag.
*/
public function find($tag);
/**
* Find all of the cache ids for a given tag.
*/
public function find($tag);
/**
* Get a cache item.
* Return NULL if the cache item is not found.
*/
public function get($id);
/**
* Get a cache item.
* Return NULL if the cache item is not found.
*/
public function get($id);
/**
* Delete cache items by id or tag.
*/
public function delete($id, $tag = false);
/**
* Delete cache items by id or tag.
*/
public function delete($id, $tag = FALSE);
/**
* Deletes all expired cache items.
*/
public function delete_expired();
} // End Cache Driver
/**
* Deletes all expired cache items.
*/
public function delete_expired();
}
// End Cache Driver

View File

@@ -1,4 +1,12 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* APC-based Cache driver.
*
@@ -9,56 +17,51 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Cache_Apc_Driver implements Cache_Driver {
class Cache_Apc_Driver implements Cache_Driver
{
public function __construct()
{
if (! extension_loaded('apc')) {
throw new Kohana_Exception('cache.extension_not_loaded', 'apc');
}
}
public function __construct()
{
if ( ! extension_loaded('apc'))
throw new Kohana_Exception('cache.extension_not_loaded', 'apc');
}
public function get($id)
{
return (($return = apc_fetch($id)) === false) ? null : $return;
}
public function get($id)
{
return (($return = apc_fetch($id)) === FALSE) ? NULL : $return;
}
public function set($id, $data, array $tags = null, $lifetime)
{
if (! empty($tags)) {
Kohana::log('error', 'Cache: tags are unsupported by the APC driver');
}
public function set($id, $data, array $tags = NULL, $lifetime)
{
if ( ! empty($tags))
{
Kohana::log('error', 'Cache: tags are unsupported by the APC driver');
}
return apc_store($id, $data, $lifetime);
}
return apc_store($id, $data, $lifetime);
}
public function find($tag)
{
Kohana::log('error', 'Cache: tags are unsupported by the APC driver');
public function find($tag)
{
Kohana::log('error', 'Cache: tags are unsupported by the APC driver');
return array();
}
return array();
}
public function delete($id, $tag = false)
{
if ($tag === true) {
Kohana::log('error', 'Cache: tags are unsupported by the APC driver');
return false;
} elseif ($id === true) {
return apc_clear_cache('user');
} else {
return apc_delete($id);
}
}
public function delete($id, $tag = FALSE)
{
if ($tag === TRUE)
{
Kohana::log('error', 'Cache: tags are unsupported by the APC driver');
return FALSE;
}
elseif ($id === TRUE)
{
return apc_clear_cache('user');
}
else
{
return apc_delete($id);
}
}
public function delete_expired()
{
return TRUE;
}
} // End Cache APC Driver
public function delete_expired()
{
return true;
}
}
// End Cache APC Driver

View File

@@ -1,4 +1,12 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* Eaccelerator-based Cache driver.
*
@@ -9,58 +17,53 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Cache_Eaccelerator_Driver implements Cache_Driver {
class Cache_Eaccelerator_Driver implements Cache_Driver
{
public function __construct()
{
if (! extension_loaded('eaccelerator')) {
throw new Kohana_Exception('cache.extension_not_loaded', 'eaccelerator');
}
}
public function __construct()
{
if ( ! extension_loaded('eaccelerator'))
throw new Kohana_Exception('cache.extension_not_loaded', 'eaccelerator');
}
public function get($id)
{
return eaccelerator_get($id);
}
public function get($id)
{
return eaccelerator_get($id);
}
public function find($tag)
{
Kohana::log('error', 'tags are unsupported by the eAccelerator driver');
public function find($tag)
{
Kohana::log('error', 'tags are unsupported by the eAccelerator driver');
return array();
}
return array();
}
public function set($id, $data, array $tags = null, $lifetime)
{
if (! empty($tags)) {
Kohana::log('error', 'tags are unsupported by the eAccelerator driver');
}
public function set($id, $data, array $tags = NULL, $lifetime)
{
if ( ! empty($tags))
{
Kohana::log('error', 'tags are unsupported by the eAccelerator driver');
}
return eaccelerator_put($id, $data, $lifetime);
}
return eaccelerator_put($id, $data, $lifetime);
}
public function delete($id, $tag = false)
{
if ($tag === true) {
Kohana::log('error', 'tags are unsupported by the eAccelerator driver');
return false;
} elseif ($id === true) {
return eaccelerator_clean();
} else {
return eaccelerator_rm($id);
}
}
public function delete($id, $tag = FALSE)
{
if ($tag === TRUE)
{
Kohana::log('error', 'tags are unsupported by the eAccelerator driver');
return FALSE;
}
elseif ($id === TRUE)
{
return eaccelerator_clean();
}
else
{
return eaccelerator_rm($id);
}
}
public function delete_expired()
{
eaccelerator_gc();
public function delete_expired()
{
eaccelerator_gc();
return TRUE;
}
} // End Cache eAccelerator Driver
return true;
}
}
// End Cache eAccelerator Driver

View File

@@ -1,4 +1,12 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* File-based Cache driver.
*
@@ -9,253 +17,235 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Cache_File_Driver implements Cache_Driver {
class Cache_File_Driver implements Cache_Driver
{
protected $directory = '';
protected $directory = '';
/**
* Tests that the storage location is a directory and is writable.
*/
public function __construct($directory)
{
// Find the real path to the directory
$directory = str_replace('\\', '/', realpath($directory)) . '/';
/**
* Tests that the storage location is a directory and is writable.
*/
public function __construct($directory)
{
// Find the real path to the directory
$directory = str_replace('\\', '/', realpath($directory)).'/';
// Make sure the cache directory is writable
if (! is_dir($directory) or ! is_writable($directory)) {
throw new Kohana_Exception('cache.unwritable', $directory);
}
// Make sure the cache directory is writable
if ( ! is_dir($directory) OR ! is_writable($directory))
throw new Kohana_Exception('cache.unwritable', $directory);
// Directory is valid
$this->directory = $directory;
}
// Directory is valid
$this->directory = $directory;
}
/**
* Finds an array of files matching the given id or tag.
*
* @param string cache id or tag
* @param bool search for tags
* @return array of filenames matching the id or tag
*/
public function exists($id, $tag = false)
{
if ($id === true) {
// Find all the files
return glob($this->directory . '*~*~*');
} elseif ($tag === true) {
// Find all the files that have the tag name
$paths = glob($this->directory . '*~*' . $id . '*~*');
/**
* Finds an array of files matching the given id or tag.
*
* @param string cache id or tag
* @param bool search for tags
* @return array of filenames matching the id or tag
*/
public function exists($id, $tag = FALSE)
{
if ($id === TRUE)
{
// Find all the files
return glob($this->directory.'*~*~*');
}
elseif ($tag === TRUE)
{
// Find all the files that have the tag name
$paths = glob($this->directory.'*~*'.$id.'*~*');
// Find all tags matching the given tag
$files = array();
foreach ($paths as $path) {
// Split the files
$tags = explode('~', basename($path));
// Find all tags matching the given tag
$files = array();
foreach ($paths as $path)
{
// Split the files
$tags = explode('~', basename($path));
// Find valid tags
if (count($tags) !== 3 or empty($tags[1])) {
continue;
}
// Find valid tags
if (count($tags) !== 3 OR empty($tags[1]))
continue;
// Split the tags by plus signs, used to separate tags
$tags = explode('+', $tags[1]);
// Split the tags by plus signs, used to separate tags
$tags = explode('+', $tags[1]);
if (in_array($tag, $tags)) {
// Add the file to the array, it has the requested tag
$files[] = $path;
}
}
if (in_array($tag, $tags))
{
// Add the file to the array, it has the requested tag
$files[] = $path;
}
}
return $files;
} else {
// Find the file matching the given id
return glob($this->directory . $id . '~*');
}
}
return $files;
}
else
{
// Find the file matching the given id
return glob($this->directory.$id.'~*');
}
}
/**
* Sets a cache item to the given data, tags, and lifetime.
*
* @param string cache id to set
* @param string data in the cache
* @param array cache tags
* @param integer lifetime
* @return bool
*/
public function set($id, $data, array $tags = null, $lifetime)
{
// Remove old cache files
$this->delete($id);
/**
* Sets a cache item to the given data, tags, and lifetime.
*
* @param string cache id to set
* @param string data in the cache
* @param array cache tags
* @param integer lifetime
* @return bool
*/
public function set($id, $data, array $tags = NULL, $lifetime)
{
// Remove old cache files
$this->delete($id);
// Cache File driver expects unix timestamp
if ($lifetime !== 0) {
$lifetime += time();
}
// Cache File driver expects unix timestamp
if ($lifetime !== 0)
{
$lifetime += time();
}
if (! empty($tags)) {
// Convert the tags into a string list
$tags = implode('+', $tags);
}
if ( ! empty($tags))
{
// Convert the tags into a string list
$tags = implode('+', $tags);
}
// Write out a serialized cache
return (bool) file_put_contents($this->directory . $id . '~' . $tags . '~' . $lifetime, serialize($data));
}
// Write out a serialized cache
return (bool) file_put_contents($this->directory.$id.'~'.$tags.'~'.$lifetime, serialize($data));
}
/**
* Finds an array of ids for a given tag.
*
* @param string tag name
* @return array of ids that match the tag
*/
public function find($tag)
{
// An array will always be returned
$result = array();
/**
* Finds an array of ids for a given tag.
*
* @param string tag name
* @return array of ids that match the tag
*/
public function find($tag)
{
// An array will always be returned
$result = array();
if ($paths = $this->exists($tag, true)) {
// Length of directory name
$offset = strlen($this->directory);
if ($paths = $this->exists($tag, TRUE))
{
// Length of directory name
$offset = strlen($this->directory);
// Find all the files with the given tag
foreach ($paths as $path) {
// Get the id from the filename
list($id, $junk) = explode('~', basename($path), 2);
// Find all the files with the given tag
foreach ($paths as $path)
{
// Get the id from the filename
list($id, $junk) = explode('~', basename($path), 2);
if (($data = $this->get($id)) !== false) {
// Add the result to the array
$result[$id] = $data;
}
}
}
if (($data = $this->get($id)) !== FALSE)
{
// Add the result to the array
$result[$id] = $data;
}
}
}
return $result;
}
return $result;
}
/**
* Fetches a cache item. This will delete the item if it is expired or if
* the hash does not match the stored hash.
*
* @param string cache id
* @return mixed|NULL
*/
public function get($id)
{
if ($file = $this->exists($id)) {
// Use the first file
$file = current($file);
/**
* Fetches a cache item. This will delete the item if it is expired or if
* the hash does not match the stored hash.
*
* @param string cache id
* @return mixed|NULL
*/
public function get($id)
{
if ($file = $this->exists($id))
{
// Use the first file
$file = current($file);
// Validate that the cache has not expired
if ($this->expired($file)) {
// Remove this cache, it has expired
$this->delete($id);
} else {
// Turn off errors while reading the file
$ER = error_reporting(0);
// Validate that the cache has not expired
if ($this->expired($file))
{
// Remove this cache, it has expired
$this->delete($id);
}
else
{
// Turn off errors while reading the file
$ER = error_reporting(0);
if (($data = file_get_contents($file)) !== false) {
// Unserialize the data
$data = unserialize($data);
} else {
// Delete the data
unset($data);
}
if (($data = file_get_contents($file)) !== FALSE)
{
// Unserialize the data
$data = unserialize($data);
}
else
{
// Delete the data
unset($data);
}
// Turn errors back on
error_reporting($ER);
}
}
// Turn errors back on
error_reporting($ER);
}
}
// Return NULL if there is no data
return isset($data) ? $data : null;
}
// Return NULL if there is no data
return isset($data) ? $data : NULL;
}
/**
* Deletes a cache item by id or tag
*
* @param string cache id or tag, or TRUE for "all items"
* @param boolean use tags
* @return boolean
*/
public function delete($id, $tag = false)
{
$files = $this->exists($id, $tag);
/**
* Deletes a cache item by id or tag
*
* @param string cache id or tag, or TRUE for "all items"
* @param boolean use tags
* @return boolean
*/
public function delete($id, $tag = FALSE)
{
$files = $this->exists($id, $tag);
if (empty($files)) {
return false;
}
if (empty($files))
return FALSE;
// Disable all error reporting while deleting
$ER = error_reporting(0);
// Disable all error reporting while deleting
$ER = error_reporting(0);
foreach ($files as $file) {
// Remove the cache file
if (! unlink($file)) {
Kohana::log('error', 'Cache: Unable to delete cache file: ' . $file);
}
}
foreach ($files as $file)
{
// Remove the cache file
if ( ! unlink($file))
Kohana::log('error', 'Cache: Unable to delete cache file: '.$file);
}
// Turn on error reporting again
error_reporting($ER);
// Turn on error reporting again
error_reporting($ER);
return true;
}
return TRUE;
}
/**
* Deletes all cache files that are older than the current time.
*
* @return void
*/
public function delete_expired()
{
if ($files = $this->exists(true)) {
// Disable all error reporting while deleting
$ER = error_reporting(0);
/**
* Deletes all cache files that are older than the current time.
*
* @return void
*/
public function delete_expired()
{
if ($files = $this->exists(TRUE))
{
// Disable all error reporting while deleting
$ER = error_reporting(0);
foreach ($files as $file) {
if ($this->expired($file)) {
// The cache file has already expired, delete it
if (! unlink($file)) {
Kohana::log('error', 'Cache: Unable to delete cache file: ' . $file);
}
}
}
foreach ($files as $file)
{
if ($this->expired($file))
{
// The cache file has already expired, delete it
if ( ! unlink($file))
Kohana::log('error', 'Cache: Unable to delete cache file: '.$file);
}
}
// Turn on error reporting again
error_reporting($ER);
}
}
// Turn on error reporting again
error_reporting($ER);
}
}
/**
* Check if a cache file has expired by filename.
*
* @param string filename
* @return bool
*/
protected function expired($file)
{
// Get the expiration time
$expires = (int) substr($file, strrpos($file, '~') + 1);
/**
* Check if a cache file has expired by filename.
*
* @param string filename
* @return bool
*/
protected function expired($file)
{
// Get the expiration time
$expires = (int) substr($file, strrpos($file, '~') + 1);
// Expirations of 0 are "never expire"
return ($expires !== 0 AND $expires <= time());
}
} // End Cache File Driver
// Expirations of 0 are "never expire"
return ($expires !== 0 and $expires <= time());
}
}
// End Cache File Driver

View File

@@ -1,4 +1,12 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* Memcache-based Cache driver.
*
@@ -9,183 +17,161 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Cache_Memcache_Driver implements Cache_Driver {
class Cache_Memcache_Driver implements Cache_Driver
{
const TAGS_KEY = 'memcache_tags_array';
const TAGS_KEY = 'memcache_tags_array';
// Cache backend object and flags
protected $backend;
protected $flags;
// Cache backend object and flags
protected $backend;
protected $flags;
// Tags array
protected static $tags;
// Tags array
protected static $tags;
// Have the tags been changed?
protected static $tags_changed = false;
// Have the tags been changed?
protected static $tags_changed = FALSE;
public function __construct()
{
if (! extension_loaded('memcache')) {
throw new Kohana_Exception('cache.extension_not_loaded', 'memcache');
}
public function __construct()
{
if ( ! extension_loaded('memcache'))
throw new Kohana_Exception('cache.extension_not_loaded', 'memcache');
$this->backend = new Memcache();
$this->flags = Kohana::config('cache_memcache.compression') ? MEMCACHE_COMPRESSED : false;
$this->backend = new Memcache;
$this->flags = Kohana::config('cache_memcache.compression') ? MEMCACHE_COMPRESSED : FALSE;
$servers = Kohana::config('cache_memcache.servers');
$servers = Kohana::config('cache_memcache.servers');
foreach ($servers as $server) {
// Make sure all required keys are set
$server += array('host' => '127.0.0.1', 'port' => 11211, 'persistent' => false);
foreach ($servers as $server)
{
// Make sure all required keys are set
$server += array('host' => '127.0.0.1', 'port' => 11211, 'persistent' => FALSE);
// Add the server to the pool
$this->backend->addServer($server['host'], $server['port'], (bool) $server['persistent'])
or Kohana::log('error', 'Cache: Connection failed: ' . $server['host']);
}
// Add the server to the pool
$this->backend->addServer($server['host'], $server['port'], (bool) $server['persistent'])
or Kohana::log('error', 'Cache: Connection failed: '.$server['host']);
}
// Load tags
self::$tags = $this->backend->get(self::TAGS_KEY);
// Load tags
self::$tags = $this->backend->get(self::TAGS_KEY);
if (! is_array(self::$tags)) {
// Create a new tags array
self::$tags = array();
if ( ! is_array(self::$tags))
{
// Create a new tags array
self::$tags = array();
// Tags have been created
self::$tags_changed = true;
}
}
// Tags have been created
self::$tags_changed = TRUE;
}
}
public function __destruct()
{
if (self::$tags_changed === true) {
// Save the tags
$this->backend->set(self::TAGS_KEY, self::$tags, $this->flags, 0);
public function __destruct()
{
if (self::$tags_changed === TRUE)
{
// Save the tags
$this->backend->set(self::TAGS_KEY, self::$tags, $this->flags, 0);
// Tags are now unchanged
self::$tags_changed = false;
}
}
// Tags are now unchanged
self::$tags_changed = FALSE;
}
}
public function find($tag)
{
if (isset(self::$tags[$tag]) and $results = $this->backend->get(self::$tags[$tag])) {
// Return all the found caches
return $results;
} else {
// No matching tags
return array();
}
}
public function find($tag)
{
if (isset(self::$tags[$tag]) AND $results = $this->backend->get(self::$tags[$tag]))
{
// Return all the found caches
return $results;
}
else
{
// No matching tags
return array();
}
}
public function get($id)
{
return (($return = $this->backend->get($id)) === false) ? null : $return;
}
public function get($id)
{
return (($return = $this->backend->get($id)) === FALSE) ? NULL : $return;
}
public function set($id, $data, array $tags = null, $lifetime)
{
if (! empty($tags)) {
// Tags will be changed
self::$tags_changed = true;
public function set($id, $data, array $tags = NULL, $lifetime)
{
if ( ! empty($tags))
{
// Tags will be changed
self::$tags_changed = TRUE;
foreach ($tags as $tag) {
// Add the id to each tag
self::$tags[$tag][$id] = $id;
}
}
foreach ($tags as $tag)
{
// Add the id to each tag
self::$tags[$tag][$id] = $id;
}
}
if ($lifetime !== 0) {
// Memcache driver expects unix timestamp
$lifetime += time();
}
if ($lifetime !== 0)
{
// Memcache driver expects unix timestamp
$lifetime += time();
}
// Set a new value
return $this->backend->set($id, $data, $this->flags, $lifetime);
}
// Set a new value
return $this->backend->set($id, $data, $this->flags, $lifetime);
}
public function delete($id, $tag = false)
{
// Tags will be changed
self::$tags_changed = true;
public function delete($id, $tag = FALSE)
{
// Tags will be changed
self::$tags_changed = TRUE;
if ($id === true) {
if ($status = $this->backend->flush()) {
// Remove all tags, all items have been deleted
self::$tags = array();
if ($id === TRUE)
{
if ($status = $this->backend->flush())
{
// Remove all tags, all items have been deleted
self::$tags = array();
// We must sleep after flushing, or overwriting will not work!
// @see http://php.net/manual/en/function.memcache-flush.php#81420
sleep(1);
}
// We must sleep after flushing, or overwriting will not work!
// @see http://php.net/manual/en/function.memcache-flush.php#81420
sleep(1);
}
return $status;
} elseif ($tag === true) {
if (isset(self::$tags[$id])) {
foreach (self::$tags[$id] as $_id) {
// Delete each id in the tag
$this->backend->delete($_id);
}
return $status;
}
elseif ($tag === TRUE)
{
if (isset(self::$tags[$id]))
{
foreach (self::$tags[$id] as $_id)
{
// Delete each id in the tag
$this->backend->delete($_id);
}
// Delete the tag
unset(self::$tags[$id]);
}
// Delete the tag
unset(self::$tags[$id]);
}
return true;
} else {
foreach (self::$tags as $tag => $_ids) {
if (isset(self::$tags[$tag][$id])) {
// Remove the id from the tags
unset(self::$tags[$tag][$id]);
}
}
return TRUE;
}
else
{
foreach (self::$tags as $tag => $_ids)
{
if (isset(self::$tags[$tag][$id]))
{
// Remove the id from the tags
unset(self::$tags[$tag][$id]);
}
}
return $this->backend->delete($id);
}
}
return $this->backend->delete($id);
}
}
public function delete_expired()
{
// Tags will be changed
self::$tags_changed = true;
public function delete_expired()
{
// Tags will be changed
self::$tags_changed = TRUE;
foreach (self::$tags as $tag => $_ids) {
foreach ($_ids as $id) {
if (! $this->backend->get($id)) {
// This id has disappeared, delete it from the tags
unset(self::$tags[$tag][$id]);
}
}
foreach (self::$tags as $tag => $_ids)
{
foreach ($_ids as $id)
{
if ( ! $this->backend->get($id))
{
// This id has disappeared, delete it from the tags
unset(self::$tags[$tag][$id]);
}
}
if (empty(self::$tags[$tag])) {
// The tag no longer has any valid ids
unset(self::$tags[$tag]);
}
}
if (empty(self::$tags[$tag]))
{
// The tag no longer has any valid ids
unset(self::$tags[$tag]);
}
}
// Memcache handles garbage collection internally
return TRUE;
}
} // End Cache Memcache Driver
// Memcache handles garbage collection internally
return true;
}
}
// End Cache Memcache Driver

View File

@@ -1,4 +1,12 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* SQLite-based Cache driver.
*
@@ -9,249 +17,229 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Cache_Sqlite_Driver implements Cache_Driver {
class Cache_Sqlite_Driver implements Cache_Driver
{
// SQLite database instance
protected $db;
// SQLite database instance
protected $db;
// Database error messages
protected $error;
// Database error messages
protected $error;
/**
* Logs an SQLite error.
*/
protected static function log_error($code)
{
// Log an error
Kohana::log('error', 'Cache: SQLite error: ' . sqlite_error_string($error));
}
/**
* Logs an SQLite error.
*/
protected static function log_error($code)
{
// Log an error
Kohana::log('error', 'Cache: SQLite error: '.sqlite_error_string($error));
}
/**
* Tests that the storage location is a directory and is writable.
*/
public function __construct($filename)
{
// Get the directory name
$directory = str_replace('\\', '/', realpath(pathinfo($filename, PATHINFO_DIRNAME))) . '/';
/**
* Tests that the storage location is a directory and is writable.
*/
public function __construct($filename)
{
// Get the directory name
$directory = str_replace('\\', '/', realpath(pathinfo($filename, PATHINFO_DIRNAME))).'/';
// Set the filename from the real directory path
$filename = $directory . basename($filename);
// Set the filename from the real directory path
$filename = $directory.basename($filename);
// Make sure the cache directory is writable
if (! is_dir($directory) or ! is_writable($directory)) {
throw new Kohana_Exception('cache.unwritable', $directory);
}
// Make sure the cache directory is writable
if ( ! is_dir($directory) OR ! is_writable($directory))
throw new Kohana_Exception('cache.unwritable', $directory);
// Make sure the cache database is writable
if (is_file($filename) and ! is_writable($filename)) {
throw new Kohana_Exception('cache.unwritable', $filename);
}
// Make sure the cache database is writable
if (is_file($filename) AND ! is_writable($filename))
throw new Kohana_Exception('cache.unwritable', $filename);
// Open up an instance of the database
$this->db = new SQLiteDatabase($filename, '0666', $error);
// Open up an instance of the database
$this->db = new SQLiteDatabase($filename, '0666', $error);
// Throw an exception if there's an error
if (! empty($error)) {
throw new Kohana_Exception('cache.driver_error', sqlite_error_string($error));
}
// Throw an exception if there's an error
if ( ! empty($error))
throw new Kohana_Exception('cache.driver_error', sqlite_error_string($error));
$query = "SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'caches'";
$tables = $this->db->query($query, SQLITE_BOTH, $error);
$query = "SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'caches'";
$tables = $this->db->query($query, SQLITE_BOTH, $error);
// Throw an exception if there's an error
if (! empty($error)) {
throw new Kohana_Exception('cache.driver_error', sqlite_error_string($error));
}
// Throw an exception if there's an error
if ( ! empty($error))
throw new Kohana_Exception('cache.driver_error', sqlite_error_string($error));
if ($tables->numRows() == 0) {
Kohana::log('error', 'Cache: Initializing new SQLite cache database');
if ($tables->numRows() == 0)
{
Kohana::log('error', 'Cache: Initializing new SQLite cache database');
// Issue a CREATE TABLE command
$this->db->unbufferedQuery(Kohana::config('cache_sqlite.schema'));
}
}
// Issue a CREATE TABLE command
$this->db->unbufferedQuery(Kohana::config('cache_sqlite.schema'));
}
}
/**
* Checks if a cache id is already set.
*
* @param string cache id
* @return boolean
*/
public function exists($id)
{
// Find the id that matches
$query = "SELECT id FROM caches WHERE id = '$id'";
/**
* Checks if a cache id is already set.
*
* @param string cache id
* @return boolean
*/
public function exists($id)
{
// Find the id that matches
$query = "SELECT id FROM caches WHERE id = '$id'";
return ($this->db->query($query)->numRows() > 0);
}
return ($this->db->query($query)->numRows() > 0);
}
/**
* Sets a cache item to the given data, tags, and lifetime.
*
* @param string cache id to set
* @param string data in the cache
* @param array cache tags
* @param integer lifetime
* @return bool
*/
public function set($id, $data, array $tags = null, $lifetime)
{
// Serialize and escape the data
$data = sqlite_escape_string(serialize($data));
/**
* Sets a cache item to the given data, tags, and lifetime.
*
* @param string cache id to set
* @param string data in the cache
* @param array cache tags
* @param integer lifetime
* @return bool
*/
public function set($id, $data, array $tags = NULL, $lifetime)
{
// Serialize and escape the data
$data = sqlite_escape_string(serialize($data));
if (! empty($tags)) {
// Escape the tags, adding brackets so the tag can be explicitly matched
$tags = sqlite_escape_string('<' . implode('>,<', $tags) . '>');
}
if ( ! empty($tags))
{
// Escape the tags, adding brackets so the tag can be explicitly matched
$tags = sqlite_escape_string('<'.implode('>,<', $tags).'>');
}
// Cache Sqlite driver expects unix timestamp
if ($lifetime !== 0) {
$lifetime += time();
}
// Cache Sqlite driver expects unix timestamp
if ($lifetime !== 0)
{
$lifetime += time();
}
$query = $this->exists($id)
? "UPDATE caches SET tags = '$tags', expiration = '$lifetime', cache = '$data' WHERE id = '$id'"
: "INSERT INTO caches VALUES('$id', '$tags', '$lifetime', '$data')";
$query = $this->exists($id)
? "UPDATE caches SET tags = '$tags', expiration = '$lifetime', cache = '$data' WHERE id = '$id'"
: "INSERT INTO caches VALUES('$id', '$tags', '$lifetime', '$data')";
// Run the query
$this->db->unbufferedQuery($query, SQLITE_BOTH, $error);
// Run the query
$this->db->unbufferedQuery($query, SQLITE_BOTH, $error);
if (! empty($error)) {
self::log_error($error);
return false;
} else {
return true;
}
}
if ( ! empty($error))
{
self::log_error($error);
return FALSE;
}
else
{
return TRUE;
}
}
/**
* Finds an array of ids for a given tag.
*
* @param string tag name
* @return array of ids that match the tag
*/
public function find($tag)
{
$query = "SELECT id,cache FROM caches WHERE tags LIKE '%<{$tag}>%'";
$query = $this->db->query($query, SQLITE_BOTH, $error);
/**
* Finds an array of ids for a given tag.
*
* @param string tag name
* @return array of ids that match the tag
*/
public function find($tag)
{
$query = "SELECT id,cache FROM caches WHERE tags LIKE '%<{$tag}>%'";
$query = $this->db->query($query, SQLITE_BOTH, $error);
// An array will always be returned
$result = array();
// An array will always be returned
$result = array();
if (! empty($error)) {
self::log_error($error);
} elseif ($query->numRows() > 0) {
// Disable notices for unserializing
$ER = error_reporting(~E_NOTICE);
if ( ! empty($error))
{
self::log_error($error);
}
elseif ($query->numRows() > 0)
{
// Disable notices for unserializing
$ER = error_reporting(~E_NOTICE);
while ($row = $query->fetchObject()) {
// Add each cache to the array
$result[$row->id] = unserialize($row->cache);
}
while ($row = $query->fetchObject())
{
// Add each cache to the array
$result[$row->id] = unserialize($row->cache);
}
// Turn notices back on
error_reporting($ER);
}
// Turn notices back on
error_reporting($ER);
}
return $result;
}
return $result;
}
/**
* Fetches a cache item. This will delete the item if it is expired or if
* the hash does not match the stored hash.
*
* @param string cache id
* @return mixed|NULL
*/
public function get($id)
{
$query = "SELECT id, expiration, cache FROM caches WHERE id = '$id' LIMIT 0, 1";
$query = $this->db->query($query, SQLITE_BOTH, $error);
/**
* Fetches a cache item. This will delete the item if it is expired or if
* the hash does not match the stored hash.
*
* @param string cache id
* @return mixed|NULL
*/
public function get($id)
{
$query = "SELECT id, expiration, cache FROM caches WHERE id = '$id' LIMIT 0, 1";
$query = $this->db->query($query, SQLITE_BOTH, $error);
if (! empty($error)) {
self::log_error($error);
} elseif ($cache = $query->fetchObject()) {
// Make sure the expiration is valid and that the hash matches
if ($cache->expiration != 0 and $cache->expiration <= time()) {
// Cache is not valid, delete it now
$this->delete($cache->id);
} else {
// Disable notices for unserializing
$ER = error_reporting(~E_NOTICE);
if ( ! empty($error))
{
self::log_error($error);
}
elseif ($cache = $query->fetchObject())
{
// Make sure the expiration is valid and that the hash matches
if ($cache->expiration != 0 AND $cache->expiration <= time())
{
// Cache is not valid, delete it now
$this->delete($cache->id);
}
else
{
// Disable notices for unserializing
$ER = error_reporting(~E_NOTICE);
// Return the valid cache data
$data = $cache->cache;
// Return the valid cache data
$data = $cache->cache;
// Turn notices back on
error_reporting($ER);
}
}
// Turn notices back on
error_reporting($ER);
}
}
// No valid cache found
return NULL;
}
// No valid cache found
return null;
}
/**
* Deletes a cache item by id or tag
*
* @param string cache id or tag, or TRUE for "all items"
* @param bool delete a tag
* @return bool
*/
public function delete($id, $tag = FALSE)
{
if ($id === TRUE)
{
// Delete all caches
$where = '1';
}
elseif ($tag === TRUE)
{
// Delete by tag
$where = "tags LIKE '%<{$id}>%'";
}
else
{
// Delete by id
$where = "id = '$id'";
}
/**
* Deletes a cache item by id or tag
*
* @param string cache id or tag, or TRUE for "all items"
* @param bool delete a tag
* @return bool
*/
public function delete($id, $tag = false)
{
if ($id === true) {
// Delete all caches
$where = '1';
} elseif ($tag === true) {
// Delete by tag
$where = "tags LIKE '%<{$id}>%'";
} else {
// Delete by id
$where = "id = '$id'";
}
$this->db->unbufferedQuery('DELETE FROM caches WHERE '.$where, SQLITE_BOTH, $error);
$this->db->unbufferedQuery('DELETE FROM caches WHERE ' . $where, SQLITE_BOTH, $error);
if ( ! empty($error))
{
self::log_error($error);
return FALSE;
}
else
{
return TRUE;
}
}
if (! empty($error)) {
self::log_error($error);
return false;
} else {
return true;
}
}
/**
* Deletes all cache files that are older than the current time.
*/
public function delete_expired()
{
// Delete all expired caches
$query = 'DELETE FROM caches WHERE expiration != 0 AND expiration <= '.time();
/**
* Deletes all cache files that are older than the current time.
*/
public function delete_expired()
{
// Delete all expired caches
$query = 'DELETE FROM caches WHERE expiration != 0 AND expiration <= ' . time();
$this->db->unbufferedQuery($query);
$this->db->unbufferedQuery($query);
return TRUE;
}
} // End Cache SQLite Driver
return true;
}
}
// End Cache SQLite Driver

View File

@@ -1,4 +1,12 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* Xcache Cache driver.
*
@@ -9,111 +17,98 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Cache_Xcache_Driver implements Cache_Driver {
class Cache_Xcache_Driver implements Cache_Driver
{
public function __construct()
{
if (! extension_loaded('xcache')) {
throw new Kohana_Exception('cache.extension_not_loaded', 'xcache');
}
}
public function __construct()
{
if ( ! extension_loaded('xcache'))
throw new Kohana_Exception('cache.extension_not_loaded', 'xcache');
}
public function get($id)
{
if (xcache_isset($id)) {
return xcache_get($id);
}
public function get($id)
{
if (xcache_isset($id))
return xcache_get($id);
return null;
}
return NULL;
}
public function set($id, $data, array $tags = null, $lifetime)
{
if (! empty($tags)) {
Kohana::log('error', 'Cache: tags are unsupported by the Xcache driver');
}
public function set($id, $data, array $tags = NULL, $lifetime)
{
if ( ! empty($tags))
{
Kohana::log('error', 'Cache: tags are unsupported by the Xcache driver');
}
return xcache_set($id, $data, $lifetime);
}
return xcache_set($id, $data, $lifetime);
}
public function find($tag)
{
Kohana::log('error', 'Cache: tags are unsupported by the Xcache driver');
return false;
}
public function find($tag)
{
Kohana::log('error', 'Cache: tags are unsupported by the Xcache driver');
return FALSE;
}
public function delete($id, $tag = false)
{
if ($tag !== false) {
Kohana::log('error', 'Cache: tags are unsupported by the Xcache driver');
return true;
} elseif ($id !== true) {
if (xcache_isset($id)) {
return xcache_unset($id);
}
public function delete($id, $tag = FALSE)
{
if ($tag !== FALSE)
{
Kohana::log('error', 'Cache: tags are unsupported by the Xcache driver');
return TRUE;
}
elseif ($id !== TRUE)
{
if (xcache_isset($id))
return xcache_unset($id);
return false;
} else {
// Do the login
$this->auth();
$result = true;
for ($i = 0, $max = xcache_count(XC_TYPE_VAR); $i < $max; $i++) {
if (xcache_clear_cache(XC_TYPE_VAR, $i) !== null) {
$result = false;
break;
}
}
return FALSE;
}
else
{
// Do the login
$this->auth();
$result = TRUE;
for ($i = 0, $max = xcache_count(XC_TYPE_VAR); $i < $max; $i++)
{
if (xcache_clear_cache(XC_TYPE_VAR, $i) !== NULL)
{
$result = FALSE;
break;
}
}
// Undo the login
$this->auth(true);
return $result;
}
// Undo the login
$this->auth(TRUE);
return $result;
}
return true;
}
return TRUE;
}
public function delete_expired()
{
return true;
}
public function delete_expired()
{
return TRUE;
}
private function auth($reverse = false)
{
static $backup = array();
private function auth($reverse = FALSE)
{
static $backup = array();
$keys = array('PHP_AUTH_USER', 'PHP_AUTH_PW');
$keys = array('PHP_AUTH_USER', 'PHP_AUTH_PW');
foreach ($keys as $key) {
if ($reverse) {
if (isset($backup[$key])) {
$_SERVER[$key] = $backup[$key];
unset($backup[$key]);
} else {
unset($_SERVER[$key]);
}
} else {
$value = getenv($key);
foreach ($keys as $key)
{
if ($reverse)
{
if (isset($backup[$key]))
{
$_SERVER[$key] = $backup[$key];
unset($backup[$key]);
}
else
{
unset($_SERVER[$key]);
}
}
else
{
$value = getenv($key);
if (! empty($value)) {
$backup[$key] = $value;
}
if ( ! empty($value))
{
$backup[$key] = $value;
}
$_SERVER[$key] = Kohana::config('cache_xcache.'.$key);
}
}
}
} // End Cache Xcache Driver
$_SERVER[$key] = Kohana::config('cache_xcache.' . $key);
}
}
}
}
// End Cache Xcache Driver

View File

@@ -1,4 +1,11 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* Captcha driver class.
*
@@ -9,219 +16,223 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
abstract class Captcha_Driver {
abstract class Captcha_Driver
{
// The correct Captcha challenge answer
protected $response;
// The correct Captcha challenge answer
protected $response;
// Image resource identifier and type ("png", "gif" or "jpeg")
protected $image;
protected $image_type = 'png';
// Image resource identifier and type ("png", "gif" or "jpeg")
protected $image;
protected $image_type = 'png';
/**
* Constructs a new challenge.
*
* @return void
*/
public function __construct()
{
// Generate a new challenge
$this->response = $this->generate_challenge();
/**
* Constructs a new challenge.
*
* @return void
*/
public function __construct()
{
// Generate a new challenge
$this->response = $this->generate_challenge();
// Store the correct Captcha response in a session
Event::add('system.post_controller', array($this, 'update_response_session'));
}
// Store the correct Captcha response in a session
Event::add('system.post_controller', array($this, 'update_response_session'));
}
/**
* Generate a new Captcha challenge.
*
* @return string the challenge answer
*/
abstract public function generate_challenge();
/**
* Generate a new Captcha challenge.
*
* @return string the challenge answer
*/
abstract public function generate_challenge();
/**
* Output the Captcha challenge.
*
* @param boolean html output
* @return mixed the rendered Captcha (e.g. an image, riddle, etc.)
*/
abstract public function render($html);
/**
* Output the Captcha challenge.
*
* @param boolean html output
* @return mixed the rendered Captcha (e.g. an image, riddle, etc.)
*/
abstract public function render($html);
/**
* Stores the response for the current Captcha challenge in a session so it is available
* on the next page load for Captcha::valid(). This method is called after controller
* execution (in the system.post_controller event) in order not to overwrite itself too soon.
*
* @return void
*/
public function update_response_session()
{
Session::instance()->set('captcha_response', sha1(strtoupper($this->response)));
}
/**
* Stores the response for the current Captcha challenge in a session so it is available
* on the next page load for Captcha::valid(). This method is called after controller
* execution (in the system.post_controller event) in order not to overwrite itself too soon.
*
* @return void
*/
public function update_response_session()
{
Session::instance()->set('captcha_response', sha1(strtoupper($this->response)));
}
/**
* Validates a Captcha response from a user.
*
* @param string captcha response
* @return boolean
*/
public function valid($response)
{
return (sha1(strtoupper($response)) === Session::instance()->get('captcha_response'));
}
/**
* Validates a Captcha response from a user.
*
* @param string captcha response
* @return boolean
*/
public function valid($response)
{
return (sha1(strtoupper($response)) === Session::instance()->get('captcha_response'));
}
/**
* Returns the image type.
*
* @param string filename
* @return string|FALSE image type ("png", "gif" or "jpeg")
*/
public function image_type($filename)
{
switch (strtolower(substr(strrchr($filename, '.'), 1))) {
case 'png':
return 'png';
/**
* Returns the image type.
*
* @param string filename
* @return string|FALSE image type ("png", "gif" or "jpeg")
*/
public function image_type($filename)
{
switch (strtolower(substr(strrchr($filename, '.'), 1)))
{
case 'png':
return 'png';
case 'gif':
return 'gif';
case 'gif':
return 'gif';
case 'jpg':
case 'jpeg':
// Return "jpeg" and not "jpg" because of the GD2 function names
return 'jpeg';
case 'jpg':
case 'jpeg':
// Return "jpeg" and not "jpg" because of the GD2 function names
return 'jpeg';
default:
return false;
}
}
default:
return FALSE;
}
}
/**
* Creates an image resource with the dimensions specified in config.
* If a background image is supplied, the image dimensions are used.
*
* @throws Kohana_Exception if no GD2 support
* @param string path to the background image file
* @return void
*/
public function image_create($background = null)
{
// Check for GD2 support
if (! function_exists('imagegd2')) {
throw new Kohana_Exception('captcha.requires_GD2');
}
/**
* Creates an image resource with the dimensions specified in config.
* If a background image is supplied, the image dimensions are used.
*
* @throws Kohana_Exception if no GD2 support
* @param string path to the background image file
* @return void
*/
public function image_create($background = NULL)
{
// Check for GD2 support
if ( ! function_exists('imagegd2'))
throw new Kohana_Exception('captcha.requires_GD2');
// Create a new image (black)
$this->image = imagecreatetruecolor(Captcha::$config['width'], Captcha::$config['height']);
// Create a new image (black)
$this->image = imagecreatetruecolor(Captcha::$config['width'], Captcha::$config['height']);
// Use a background image
if (! empty($background)) {
// Create the image using the right function for the filetype
$function = 'imagecreatefrom' . $this->image_type($background);
$this->background_image = $function($background);
// Use a background image
if ( ! empty($background))
{
// Create the image using the right function for the filetype
$function = 'imagecreatefrom'.$this->image_type($background);
$this->background_image = $function($background);
// Resize the image if needed
if (
imagesx($this->background_image) !== Captcha::$config['width']
or imagesy($this->background_image) !== Captcha::$config['height']
) {
imagecopyresampled(
$this->image,
$this->background_image,
0,
0,
0,
0,
Captcha::$config['width'],
Captcha::$config['height'],
imagesx($this->background_image),
imagesy($this->background_image)
);
}
// Resize the image if needed
if (imagesx($this->background_image) !== Captcha::$config['width']
OR imagesy($this->background_image) !== Captcha::$config['height'])
{
imagecopyresampled
(
$this->image, $this->background_image, 0, 0, 0, 0,
Captcha::$config['width'], Captcha::$config['height'],
imagesx($this->background_image), imagesy($this->background_image)
);
}
// Free up resources
imagedestroy($this->background_image);
}
}
// Free up resources
imagedestroy($this->background_image);
}
}
/**
* Fills the background with a gradient.
*
* @param resource gd image color identifier for start color
* @param resource gd image color identifier for end color
* @param string direction: 'horizontal' or 'vertical', 'random' by default
* @return void
*/
public function image_gradient($color1, $color2, $direction = null)
{
$directions = array('horizontal', 'vertical');
/**
* Fills the background with a gradient.
*
* @param resource gd image color identifier for start color
* @param resource gd image color identifier for end color
* @param string direction: 'horizontal' or 'vertical', 'random' by default
* @return void
*/
public function image_gradient($color1, $color2, $direction = NULL)
{
$directions = array('horizontal', 'vertical');
// Pick a random direction if needed
if (! in_array($direction, $directions)) {
$direction = $directions[array_rand($directions)];
// Pick a random direction if needed
if ( ! in_array($direction, $directions))
{
$direction = $directions[array_rand($directions)];
// Switch colors
if (mt_rand(0, 1) === 1) {
$temp = $color1;
$color1 = $color2;
$color2 = $temp;
}
}
// Switch colors
if (mt_rand(0, 1) === 1)
{
$temp = $color1;
$color1 = $color2;
$color2 = $temp;
}
}
// Extract RGB values
$color1 = imagecolorsforindex($this->image, $color1);
$color2 = imagecolorsforindex($this->image, $color2);
// Extract RGB values
$color1 = imagecolorsforindex($this->image, $color1);
$color2 = imagecolorsforindex($this->image, $color2);
// Preparations for the gradient loop
$steps = ($direction === 'horizontal') ? Captcha::$config['width'] : Captcha::$config['height'];
// Preparations for the gradient loop
$steps = ($direction === 'horizontal') ? Captcha::$config['width'] : Captcha::$config['height'];
$r1 = ($color1['red'] - $color2['red']) / $steps;
$g1 = ($color1['green'] - $color2['green']) / $steps;
$b1 = ($color1['blue'] - $color2['blue']) / $steps;
$r1 = ($color1['red'] - $color2['red']) / $steps;
$g1 = ($color1['green'] - $color2['green']) / $steps;
$b1 = ($color1['blue'] - $color2['blue']) / $steps;
if ($direction === 'horizontal') {
$x1 =& $i;
$y1 = 0;
$x2 =& $i;
$y2 = Captcha::$config['height'];
} else {
$x1 = 0;
$y1 =& $i;
$x2 = Captcha::$config['width'];
$y2 =& $i;
}
if ($direction === 'horizontal')
{
$x1 =& $i;
$y1 = 0;
$x2 =& $i;
$y2 = Captcha::$config['height'];
}
else
{
$x1 = 0;
$y1 =& $i;
$x2 = Captcha::$config['width'];
$y2 =& $i;
}
// Execute the gradient loop
for ($i = 0; $i <= $steps; $i++) {
$r2 = $color1['red'] - floor($i * $r1);
$g2 = $color1['green'] - floor($i * $g1);
$b2 = $color1['blue'] - floor($i * $b1);
$color = imagecolorallocate($this->image, $r2, $g2, $b2);
// Execute the gradient loop
for ($i = 0; $i <= $steps; $i++)
{
$r2 = $color1['red'] - floor($i * $r1);
$g2 = $color1['green'] - floor($i * $g1);
$b2 = $color1['blue'] - floor($i * $b1);
$color = imagecolorallocate($this->image, $r2, $g2, $b2);
imageline($this->image, $x1, $y1, $x2, $y2, $color);
}
}
imageline($this->image, $x1, $y1, $x2, $y2, $color);
}
}
/**
* Returns the img html element or outputs the image to the browser.
*
* @param boolean html output
* @return mixed html string or void
*/
public function image_render($html)
{
// Output html element
if ($html) {
return '<img alt="Captcha" src="' .
url::site('captcha/' . Captcha::$config['group']) .
'" width="' . Captcha::$config['width'] .
'" height="' . Captcha::$config['height'] . '" />';
}
/**
* Returns the img html element or outputs the image to the browser.
*
* @param boolean html output
* @return mixed html string or void
*/
public function image_render($html)
{
// Output html element
if ($html)
return '<img alt="Captcha" src="'.url::site('captcha/'.Captcha::$config['group']).'" width="'.Captcha::$config['width'].'" height="'.Captcha::$config['height'].'" />';
// Send the correct HTTP header
header('Content-Type: image/' . $this->image_type);
// Send the correct HTTP header
header('Content-Type: image/'.$this->image_type);
// Pick the correct output function
$function = 'image' . $this->image_type;
$function($this->image);
// Pick the correct output function
$function = 'image'.$this->image_type;
$function($this->image);
// Free up resources
imagedestroy($this->image);
}
} // End Captcha Driver
// Free up resources
imagedestroy($this->image);
}
}
// End Captcha Driver

View File

@@ -1,4 +1,12 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* Captcha driver for "alpha" style.
*
@@ -9,84 +17,87 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Captcha_Alpha_Driver extends Captcha_Driver {
class Captcha_Alpha_Driver extends Captcha_Driver
{
/**
* Generates a new Captcha challenge.
*
* @return string the challenge answer
*/
public function generate_challenge()
{
// Complexity setting is used as character count
return text::random('distinct', max(1, Captcha::$config['complexity']));
}
/**
* Generates a new Captcha challenge.
*
* @return string the challenge answer
*/
public function generate_challenge()
{
// Complexity setting is used as character count
return text::random('distinct', max(1, Captcha::$config['complexity']));
}
/**
* Outputs the Captcha image.
*
* @param boolean html output
* @return mixed
*/
public function render($html)
{
// Creates $this->image
$this->image_create(Captcha::$config['background']);
/**
* Outputs the Captcha image.
*
* @param boolean html output
* @return mixed
*/
public function render($html)
{
// Creates $this->image
$this->image_create(Captcha::$config['background']);
// Add a random gradient
if (empty(Captcha::$config['background'])) {
$color1 = imagecolorallocate($this->image, mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100));
$color2 = imagecolorallocate($this->image, mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100));
$this->image_gradient($color1, $color2);
}
// Add a random gradient
if (empty(Captcha::$config['background']))
{
$color1 = imagecolorallocate($this->image, mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100));
$color2 = imagecolorallocate($this->image, mt_rand(0, 100), mt_rand(0, 100), mt_rand(0, 100));
$this->image_gradient($color1, $color2);
}
// Add a few random circles
for ($i = 0, $count = mt_rand(10, Captcha::$config['complexity'] * 3); $i < $count; $i++) {
$color = imagecolorallocatealpha($this->image, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255), mt_rand(80, 120));
$size = mt_rand(5, Captcha::$config['height'] / 3);
imagefilledellipse($this->image, mt_rand(0, Captcha::$config['width']), mt_rand(0, Captcha::$config['height']), $size, $size, $color);
}
// Add a few random circles
for ($i = 0, $count = mt_rand(10, Captcha::$config['complexity'] * 3); $i < $count; $i++)
{
$color = imagecolorallocatealpha($this->image, mt_rand(0, 255), mt_rand(0, 255), mt_rand(0, 255), mt_rand(80, 120));
$size = mt_rand(5, Captcha::$config['height'] / 3);
imagefilledellipse($this->image, mt_rand(0, Captcha::$config['width']), mt_rand(0, Captcha::$config['height']), $size, $size, $color);
}
// Calculate character font-size and spacing
$default_size = min(Captcha::$config['width'], Captcha::$config['height'] * 2) / strlen($this->response);
$spacing = (int) (Captcha::$config['width'] * 0.9 / strlen($this->response));
// Calculate character font-size and spacing
$default_size = min(Captcha::$config['width'], Captcha::$config['height'] * 2) / strlen($this->response);
$spacing = (int) (Captcha::$config['width'] * 0.9 / strlen($this->response));
// Background alphabetic character attributes
$color_limit = mt_rand(96, 160);
$chars = 'ABEFGJKLPQRTVY';
// Background alphabetic character attributes
$color_limit = mt_rand(96, 160);
$chars = 'ABEFGJKLPQRTVY';
// Draw each Captcha character with varying attributes
for ($i = 0, $strlen = strlen($this->response); $i < $strlen; $i++) {
// Use different fonts if available
$font = Captcha::$config['fontpath'] . Captcha::$config['fonts'][array_rand(Captcha::$config['fonts'])];
// Draw each Captcha character with varying attributes
for ($i = 0, $strlen = strlen($this->response); $i < $strlen; $i++)
{
// Use different fonts if available
$font = Captcha::$config['fontpath'].Captcha::$config['fonts'][array_rand(Captcha::$config['fonts'])];
$angle = mt_rand(-40, 20);
// Scale the character size on image height
$size = $default_size / 10 * mt_rand(8, 12);
$box = imageftbbox($size, $angle, $font, $this->response[$i]);
$angle = mt_rand(-40, 20);
// Scale the character size on image height
$size = $default_size / 10 * mt_rand(8, 12);
$box = imageftbbox($size, $angle, $font, $this->response[$i]);
// Calculate character starting coordinates
$x = $spacing / 4 + $i * $spacing;
$y = Captcha::$config['height'] / 2 + ($box[2] - $box[5]) / 4;
// Calculate character starting coordinates
$x = $spacing / 4 + $i * $spacing;
$y = Captcha::$config['height'] / 2 + ($box[2] - $box[5]) / 4;
// Draw captcha text character
// Allocate random color, size and rotation attributes to text
$color = imagecolorallocate($this->image, mt_rand(150, 255), mt_rand(200, 255), mt_rand(0, 255));
// Draw captcha text character
// Allocate random color, size and rotation attributes to text
$color = imagecolorallocate($this->image, mt_rand(150, 255), mt_rand(200, 255), mt_rand(0, 255));
// Write text character to image
imagefttext($this->image, $size, $angle, $x, $y, $color, $font, $this->response[$i]);
// Write text character to image
imagefttext($this->image, $size, $angle, $x, $y, $color, $font, $this->response[$i]);
// Draw "ghost" alphabetic character
$text_color = imagecolorallocatealpha(
$this->image,
mt_rand($color_limit + 8, 255),
mt_rand($color_limit + 8, 255),
mt_rand($color_limit + 8, 255),
mt_rand(70, 120)
);
$char = $chars[mt_rand(0, 14)];
imagettftext($this->image, $size * 2, mt_rand(-45, 45), ($x - (mt_rand(5, 10))), ($y + (mt_rand(5, 10))), $text_color, $font, $char);
}
// Draw "ghost" alphabetic character
$text_color = imagecolorallocatealpha($this->image, mt_rand($color_limit + 8, 255), mt_rand($color_limit + 8, 255), mt_rand($color_limit + 8, 255), mt_rand(70, 120));
$char = $chars[mt_rand(0, 14)];
imagettftext($this->image, $size * 2, mt_rand(-45, 45), ($x - (mt_rand(5, 10))), ($y + (mt_rand(5, 10))), $text_color, $font, $char);
}
// Output
return $this->image_render($html);
}
} // End Captcha Alpha Driver Class
// Output
return $this->image_render($html);
}
}
// End Captcha Alpha Driver Class

View File

@@ -1,4 +1,12 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* Captcha driver for "basic" style.
*
@@ -9,73 +17,70 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Captcha_Basic_Driver extends Captcha_Driver {
class Captcha_Basic_Driver extends Captcha_Driver
{
/**
* Generates a new Captcha challenge.
*
* @return string the challenge answer
*/
public function generate_challenge()
{
// Complexity setting is used as character count
return text::random('distinct', max(1, Captcha::$config['complexity']));
}
/**
* Generates a new Captcha challenge.
*
* @return string the challenge answer
*/
public function generate_challenge()
{
// Complexity setting is used as character count
return text::random('distinct', max(1, Captcha::$config['complexity']));
}
/**
* Outputs the Captcha image.
*
* @param boolean html output
* @return mixed
*/
public function render($html)
{
// Creates $this->image
$this->image_create(Captcha::$config['background']);
/**
* Outputs the Captcha image.
*
* @param boolean html output
* @return mixed
*/
public function render($html)
{
// Creates $this->image
$this->image_create(Captcha::$config['background']);
// Add a random gradient
if (empty(Captcha::$config['background'])) {
$color1 = imagecolorallocate($this->image, mt_rand(200, 255), mt_rand(200, 255), mt_rand(150, 255));
$color2 = imagecolorallocate($this->image, mt_rand(200, 255), mt_rand(200, 255), mt_rand(150, 255));
$this->image_gradient($color1, $color2);
}
// Add a random gradient
if (empty(Captcha::$config['background']))
{
$color1 = imagecolorallocate($this->image, mt_rand(200, 255), mt_rand(200, 255), mt_rand(150, 255));
$color2 = imagecolorallocate($this->image, mt_rand(200, 255), mt_rand(200, 255), mt_rand(150, 255));
$this->image_gradient($color1, $color2);
}
// Add a few random lines
for ($i = 0, $count = mt_rand(5, Captcha::$config['complexity'] * 4); $i < $count; $i++) {
$color = imagecolorallocatealpha($this->image, mt_rand(0, 255), mt_rand(0, 255), mt_rand(100, 255), mt_rand(50, 120));
imageline($this->image, mt_rand(0, Captcha::$config['width']), 0, mt_rand(0, Captcha::$config['width']), Captcha::$config['height'], $color);
}
// Add a few random lines
for ($i = 0, $count = mt_rand(5, Captcha::$config['complexity'] * 4); $i < $count; $i++)
{
$color = imagecolorallocatealpha($this->image, mt_rand(0, 255), mt_rand(0, 255), mt_rand(100, 255), mt_rand(50, 120));
imageline($this->image, mt_rand(0, Captcha::$config['width']), 0, mt_rand(0, Captcha::$config['width']), Captcha::$config['height'], $color);
}
// Calculate character font-size and spacing
$default_size = min(Captcha::$config['width'], Captcha::$config['height'] * 2) / (strlen($this->response) + 1);
$spacing = (int) (Captcha::$config['width'] * 0.9 / strlen($this->response));
// Calculate character font-size and spacing
$default_size = min(Captcha::$config['width'], Captcha::$config['height'] * 2) / (strlen($this->response) + 1);
$spacing = (int) (Captcha::$config['width'] * 0.9 / strlen($this->response));
// Draw each Captcha character with varying attributes
for ($i = 0, $strlen = strlen($this->response); $i < $strlen; $i++) {
// Use different fonts if available
$font = Captcha::$config['fontpath'] . Captcha::$config['fonts'][array_rand(Captcha::$config['fonts'])];
// Draw each Captcha character with varying attributes
for ($i = 0, $strlen = strlen($this->response); $i < $strlen; $i++)
{
// Use different fonts if available
$font = Captcha::$config['fontpath'].Captcha::$config['fonts'][array_rand(Captcha::$config['fonts'])];
// Allocate random color, size and rotation attributes to text
$color = imagecolorallocate($this->image, mt_rand(0, 150), mt_rand(0, 150), mt_rand(0, 150));
$angle = mt_rand(-40, 20);
// Allocate random color, size and rotation attributes to text
$color = imagecolorallocate($this->image, mt_rand(0, 150), mt_rand(0, 150), mt_rand(0, 150));
$angle = mt_rand(-40, 20);
// Scale the character size on image height
$size = $default_size / 10 * mt_rand(8, 12);
$box = imageftbbox($size, $angle, $font, $this->response[$i]);
// Scale the character size on image height
$size = $default_size / 10 * mt_rand(8, 12);
$box = imageftbbox($size, $angle, $font, $this->response[$i]);
// Calculate character starting coordinates
$x = $spacing / 4 + $i * $spacing;
$y = Captcha::$config['height'] / 2 + ($box[2] - $box[5]) / 4;
// Calculate character starting coordinates
$x = $spacing / 4 + $i * $spacing;
$y = Captcha::$config['height'] / 2 + ($box[2] - $box[5]) / 4;
// Write text character to image
imagefttext($this->image, $size, $angle, $x, $y, $color, $font, $this->response[$i]);
}
// Write text character to image
imagefttext($this->image, $size, $angle, $x, $y, $color, $font, $this->response[$i]);
}
// Output
return $this->image_render($html);
}
} // End Captcha Basic Driver Class
// Output
return $this->image_render($html);
}
}
// End Captcha Basic Driver Class

View File

@@ -1,4 +1,12 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* Captcha driver for "black" style.
*
@@ -9,64 +17,84 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Captcha_Black_Driver extends Captcha_Driver {
class Captcha_Black_Driver extends Captcha_Driver
{
/**
* Generates a new Captcha challenge.
*
* @return string the challenge answer
*/
public function generate_challenge()
{
// Complexity setting is used as character count
return text::random('distinct', max(1, ceil(Captcha::$config['complexity'] / 1.5)));
}
/**
* Generates a new Captcha challenge.
*
* @return string the challenge answer
*/
public function generate_challenge()
{
// Complexity setting is used as character count
return text::random('distinct', max(1, ceil(Captcha::$config['complexity'] / 1.5)));
}
/**
* Outputs the Captcha image.
*
* @param boolean html output
* @return mixed
*/
public function render($html)
{
// Creates a black image to start from
$this->image_create(Captcha::$config['background']);
/**
* Outputs the Captcha image.
*
* @param boolean html output
* @return mixed
*/
public function render($html)
{
// Creates a black image to start from
$this->image_create(Captcha::$config['background']);
// Add random white/gray arcs, amount depends on complexity setting
$count = (Captcha::$config['width'] + Captcha::$config['height']) / 2;
$count = $count / 5 * min(10, Captcha::$config['complexity']);
for ($i = 0; $i < $count; $i++) {
imagesetthickness($this->image, mt_rand(1, 2));
$color = imagecolorallocatealpha($this->image, 255, 255, 255, mt_rand(0, 120));
imagearc(
$this->image,
mt_rand(
-Captcha::$config['width'],
Captcha::$config['width']
),
mt_rand(
-Captcha::$config['height'],
Captcha::$config['height']
),
mt_rand(
-Captcha::$config['width'],
Captcha::$config['width']
),
mt_rand(
-Captcha::$config['height'],
Captcha::$config['height']
),
mt_rand(0, 360),
mt_rand(0, 360),
$color
);
}
// Add random white/gray arcs, amount depends on complexity setting
$count = (Captcha::$config['width'] + Captcha::$config['height']) / 2;
$count = $count / 5 * min(10, Captcha::$config['complexity']);
for ($i = 0; $i < $count; $i++)
{
imagesetthickness($this->image, mt_rand(1, 2));
$color = imagecolorallocatealpha($this->image, 255, 255, 255, mt_rand(0, 120));
imagearc($this->image, mt_rand(-Captcha::$config['width'], Captcha::$config['width']), mt_rand(-Captcha::$config['height'], Captcha::$config['height']), mt_rand(-Captcha::$config['width'], Captcha::$config['width']), mt_rand(-Captcha::$config['height'], Captcha::$config['height']), mt_rand(0, 360), mt_rand(0, 360), $color);
}
// Use different fonts if available
$font = Captcha::$config['fontpath'] . Captcha::$config['fonts'][array_rand(Captcha::$config['fonts'])];
// Use different fonts if available
$font = Captcha::$config['fontpath'].Captcha::$config['fonts'][array_rand(Captcha::$config['fonts'])];
// Draw the character's white shadows
$size = (int) min(Captcha::$config['height'] / 2, Captcha::$config['width'] * 0.8 / strlen($this->response));
$angle = mt_rand(-15 + strlen($this->response), 15 - strlen($this->response));
$x = mt_rand(1, Captcha::$config['width'] * 0.9 - $size * strlen($this->response));
$y = ((Captcha::$config['height'] - $size) / 2) + $size;
$color = imagecolorallocate($this->image, 255, 255, 255);
imagefttext($this->image, $size, $angle, $x + 1, $y + 1, $color, $font, $this->response);
// Draw the character's white shadows
$size = (int) min(Captcha::$config['height'] / 2, Captcha::$config['width'] * 0.8 / strlen($this->response));
$angle = mt_rand(-15 + strlen($this->response), 15 - strlen($this->response));
$x = mt_rand(1, Captcha::$config['width'] * 0.9 - $size * strlen($this->response));
$y = ((Captcha::$config['height'] - $size) / 2) + $size;
$color = imagecolorallocate($this->image, 255, 255, 255);
imagefttext($this->image, $size, $angle, $x + 1, $y + 1, $color, $font, $this->response);
// Add more shadows for lower complexities
(Captcha::$config['complexity'] < 10) and imagefttext($this->image, $size, $angle, $x - 1, $y - 1, $color, $font, $this->response);
(Captcha::$config['complexity'] < 8) and imagefttext($this->image, $size, $angle, $x - 2, $y + 2, $color, $font, $this->response);
(Captcha::$config['complexity'] < 6) and imagefttext($this->image, $size, $angle, $x + 2, $y - 2, $color, $font, $this->response);
(Captcha::$config['complexity'] < 4) and imagefttext($this->image, $size, $angle, $x + 3, $y + 3, $color, $font, $this->response);
(Captcha::$config['complexity'] < 2) and imagefttext($this->image, $size, $angle, $x - 3, $y - 3, $color, $font, $this->response);
// Add more shadows for lower complexities
(Captcha::$config['complexity'] < 10) and imagefttext($this->image, $size, $angle, $x - 1, $y - 1, $color, $font , $this->response);
(Captcha::$config['complexity'] < 8) and imagefttext($this->image, $size, $angle, $x - 2, $y + 2, $color, $font , $this->response);
(Captcha::$config['complexity'] < 6) and imagefttext($this->image, $size, $angle, $x + 2, $y - 2, $color, $font , $this->response);
(Captcha::$config['complexity'] < 4) and imagefttext($this->image, $size, $angle, $x + 3, $y + 3, $color, $font , $this->response);
(Captcha::$config['complexity'] < 2) and imagefttext($this->image, $size, $angle, $x - 3, $y - 3, $color, $font , $this->response);
// Finally draw the foreground characters
$color = imagecolorallocate($this->image, 0, 0, 0);
imagefttext($this->image, $size, $angle, $x, $y, $color, $font, $this->response);
// Finally draw the foreground characters
$color = imagecolorallocate($this->image, 0, 0, 0);
imagefttext($this->image, $size, $angle, $x, $y, $color, $font, $this->response);
// Output
return $this->image_render($html);
}
} // End Captcha Black Driver Class
// Output
return $this->image_render($html);
}
}
// End Captcha Black Driver Class

View File

@@ -1,4 +1,12 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* Captcha driver for "math" style.
*
@@ -9,53 +17,48 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Captcha_Math_Driver extends Captcha_Driver {
class Captcha_Math_Driver extends Captcha_Driver
{
private $math_exercice;
private $math_exercice;
/**
* Generates a new Captcha challenge.
*
* @return string the challenge answer
*/
public function generate_challenge()
{
// Easy
if (Captcha::$config['complexity'] < 4) {
$numbers[] = mt_rand(1, 5);
$numbers[] = mt_rand(1, 4);
} elseif (Captcha::$config['complexity'] < 7) {
// Normal
$numbers[] = mt_rand(10, 20);
$numbers[] = mt_rand(1, 10);
} else {
// Difficult, well, not really ;)
$numbers[] = mt_rand(100, 200);
$numbers[] = mt_rand(10, 20);
$numbers[] = mt_rand(1, 10);
}
/**
* Generates a new Captcha challenge.
*
* @return string the challenge answer
*/
public function generate_challenge()
{
// Easy
if (Captcha::$config['complexity'] < 4)
{
$numbers[] = mt_rand(1, 5);
$numbers[] = mt_rand(1, 4);
}
// Normal
elseif (Captcha::$config['complexity'] < 7)
{
$numbers[] = mt_rand(10, 20);
$numbers[] = mt_rand(1, 10);
}
// Difficult, well, not really ;)
else
{
$numbers[] = mt_rand(100, 200);
$numbers[] = mt_rand(10, 20);
$numbers[] = mt_rand(1, 10);
}
// Store the question for output
$this->math_exercice = implode(' + ', $numbers) . ' = ';
// Store the question for output
$this->math_exercice = implode(' + ', $numbers).' = ';
// Return the answer
return array_sum($numbers);
}
// Return the answer
return array_sum($numbers);
}
/**
* Outputs the Captcha riddle.
*
* @param boolean html output
* @return mixed
*/
public function render($html)
{
return $this->math_exercice;
}
} // End Captcha Math Driver Class
/**
* Outputs the Captcha riddle.
*
* @param boolean html output
* @return mixed
*/
public function render($html)
{
return $this->math_exercice;
}
}
// End Captcha Math Driver Class

View File

@@ -1,4 +1,12 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* Captcha driver for "riddle" style.
*
@@ -9,39 +17,39 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Captcha_Riddle_Driver extends Captcha_Driver {
class Captcha_Riddle_Driver extends Captcha_Driver
{
private $riddle;
private $riddle;
/**
* Generates a new Captcha challenge.
*
* @return string the challenge answer
*/
public function generate_challenge()
{
// Load riddles from the current language
$riddles = Kohana::lang('captcha.riddles');
/**
* Generates a new Captcha challenge.
*
* @return string the challenge answer
*/
public function generate_challenge()
{
// Load riddles from the current language
$riddles = Kohana::lang('captcha.riddles');
// Pick a random riddle
$riddle = $riddles[array_rand($riddles)];
// Pick a random riddle
$riddle = $riddles[array_rand($riddles)];
// Store the question for output
$this->riddle = $riddle[0];
// Store the question for output
$this->riddle = $riddle[0];
// Return the answer
return $riddle[1];
}
// Return the answer
return $riddle[1];
}
/**
* Outputs the Captcha riddle.
*
* @param boolean html output
* @return mixed
*/
public function render($html)
{
return $this->riddle;
}
} // End Captcha Riddle Driver Class
/**
* Outputs the Captcha riddle.
*
* @param boolean html output
* @return mixed
*/
public function render($html)
{
return $this->riddle;
}
}
// End Captcha Riddle Driver Class

View File

@@ -1,4 +1,12 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* Captcha driver for "word" style.
*
@@ -9,29 +17,29 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Captcha_Word_Driver extends Captcha_Basic_Driver {
class Captcha_Word_Driver extends Captcha_Basic_Driver
{
/**
* Generates a new Captcha challenge.
*
* @return string the challenge answer
*/
public function generate_challenge()
{
// Load words from the current language and randomize them
$words = Kohana::lang('captcha.words');
shuffle($words);
/**
* Generates a new Captcha challenge.
*
* @return string the challenge answer
*/
public function generate_challenge()
{
// Load words from the current language and randomize them
$words = Kohana::lang('captcha.words');
shuffle($words);
// Loop over each word...
foreach ($words as $word) {
// ...until we find one of the desired length
if (abs(Captcha::$config['complexity'] - strlen($word)) < 2) {
return strtoupper($word);
}
}
// Loop over each word...
foreach ($words as $word)
{
// ...until we find one of the desired length
if (abs(Captcha::$config['complexity'] - strlen($word)) < 2)
return strtoupper($word);
}
// Return any random word as final fallback
return strtoupper($words[array_rand($words)]);
}
} // End Captcha Word Driver Class
// Return any random word as final fallback
return strtoupper($words[array_rand($words)]);
}
}
// End Captcha Word Driver Class

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,13 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* MSSQL Database Driver
*
@@ -9,454 +18,417 @@
*/
class Database_Mssql_Driver extends Database_Driver
{
/**
* Database connection link
*/
protected $link;
/**
* Database connection link
*/
protected $link;
/**
* Database configuration
*/
protected $db_config;
/**
* Database configuration
*/
protected $db_config;
/**
* Sets the config for the class.
*
* @param array database configuration
*/
public function __construct($config)
{
$this->db_config = $config;
/**
* Sets the config for the class.
*
* @param array database configuration
*/
public function __construct($config)
{
$this->db_config = $config;
Kohana::log('debug', 'MSSQL Database Driver Initialized');
}
Kohana::log('debug', 'MSSQL Database Driver Initialized');
}
/**
* Closes the database connection.
*/
public function __destruct()
{
is_resource($this->link) and mssql_close($this->link);
}
/**
* Closes the database connection.
*/
public function __destruct()
{
is_resource($this->link) and mssql_close($this->link);
}
/**
* Make the connection
*
* @return return connection
*/
public function connect()
{
// Check if link already exists
if (is_resource($this->link))
return $this->link;
/**
* Make the connection
*
* @return return connection
*/
public function connect()
{
// Check if link already exists
if (is_resource($this->link)) {
return $this->link;
}
// Import the connect variables
extract($this->db_config['connection']);
// Import the connect variables
extract($this->db_config['connection']);
// Persistent connections enabled?
$connect = ($this->db_config['persistent'] == TRUE) ? 'mssql_pconnect' : 'mssql_connect';
// Persistent connections enabled?
$connect = ($this->db_config['persistent'] == true) ? 'mssql_pconnect' : 'mssql_connect';
// Build the connection info
$host = isset($host) ? $host : $socket;
// Build the connection info
$host = isset($host) ? $host : $socket;
// Windows uses a comma instead of a colon
$port = (isset($port) AND is_string($port)) ? (KOHANA_IS_WIN ? ',' : ':').$port : '';
// Windows uses a comma instead of a colon
$port = (isset($port) and is_string($port)) ? (KOHANA_IS_WIN ? ',' : ':') . $port : '';
// Make the connection and select the database
if (($this->link = $connect($host.$port, $user, $pass, TRUE)) AND mssql_select_db($database, $this->link))
{
/* This is being removed so I can use it, will need to come up with a more elegant workaround in the future...
*
if ($charset = $this->db_config['character_set'])
{
$this->set_charset($charset);
}
*/
// Make the connection and select the database
if (($this->link = $connect($host . $port, $user, $pass, true)) and mssql_select_db($database, $this->link)) {
/* This is being removed so I can use it, will need to come up with a more elegant workaround in the future...
*
if ($charset = $this->db_config['character_set'])
{
$this->set_charset($charset);
}
*/
// Clear password after successful connect
$this->db_config['connection']['pass'] = NULL;
// Clear password after successful connect
$this->db_config['connection']['pass'] = null;
return $this->link;
}
return $this->link;
}
return FALSE;
}
return false;
}
public function query($sql)
{
// Only cache if it's turned on, and only cache if it's not a write statement
if ($this->db_config['cache'] AND ! preg_match('#\b(?:INSERT|UPDATE|REPLACE|SET)\b#i', $sql))
{
$hash = $this->query_hash($sql);
public function query($sql)
{
// Only cache if it's turned on, and only cache if it's not a write statement
if ($this->db_config['cache'] and ! preg_match('#\b(?:INSERT|UPDATE|REPLACE|SET)\b#i', $sql)) {
$hash = $this->query_hash($sql);
if ( ! isset($this->query_cache[$hash]))
{
// Set the cached object
$this->query_cache[$hash] = new Mssql_Result(mssql_query($sql, $this->link), $this->link, $this->db_config['object'], $sql);
}
else
{
// Rewind cached result
$this->query_cache[$hash]->rewind();
}
if (! isset($this->query_cache[$hash])) {
// Set the cached object
$this->query_cache[$hash] = new Mssql_Result(mssql_query($sql, $this->link), $this->link, $this->db_config['object'], $sql);
} else {
// Rewind cached result
$this->query_cache[$hash]->rewind();
}
// Return the cached query
return $this->query_cache[$hash];
}
// Return the cached query
return $this->query_cache[$hash];
}
return new Mssql_Result(mssql_query($sql, $this->link), $this->link, $this->db_config['object'], $sql);
}
return new Mssql_Result(mssql_query($sql, $this->link), $this->link, $this->db_config['object'], $sql);
}
public function escape_table($table)
{
if (stripos($table, ' AS ') !== FALSE)
{
// Force 'AS' to uppercase
$table = str_ireplace(' AS ', ' AS ', $table);
public function escape_table($table)
{
if (stripos($table, ' AS ') !== false) {
// Force 'AS' to uppercase
$table = str_ireplace(' AS ', ' AS ', $table);
// Runs escape_table on both sides of an AS statement
$table = array_map(array($this, __FUNCTION__), explode(' AS ', $table));
// Runs escape_table on both sides of an AS statement
$table = array_map(array($this, __FUNCTION__), explode(' AS ', $table));
// Re-create the AS statement
return implode(' AS ', $table);
}
return '['.str_replace('.', '[.]', $table).']';
}
// Re-create the AS statement
return implode(' AS ', $table);
}
return '[' . str_replace('.', '[.]', $table) . ']';
}
public function escape_column($column)
{
if (!$this->db_config['escape'])
return $column;
public function escape_column($column)
{
if (!$this->db_config['escape']) {
return $column;
}
if ($column == '*')
return $column;
if ($column == '*') {
return $column;
}
// This matches any functions we support to SELECT.
if ( preg_match('/(avg|count|sum|max|min)\(\s*(.*)\s*\)(\s*as\s*(.+)?)?/i', $column, $matches))
{
if ( count($matches) == 3)
{
return $matches[1].'('.$this->escape_column($matches[2]).')';
}
else if ( count($matches) == 5)
{
return $matches[1].'('.$this->escape_column($matches[2]).') AS '.$this->escape_column($matches[2]);
}
}
// This matches any functions we support to SELECT.
if (preg_match('/(avg|count|sum|max|min)\(\s*(.*)\s*\)(\s*as\s*(.+)?)?/i', $column, $matches)) {
if (count($matches) == 3) {
return $matches[1] . '(' . $this->escape_column($matches[2]) . ')';
} elseif (count($matches) == 5) {
return $matches[1] . '(' . $this->escape_column($matches[2]) . ') AS ' . $this->escape_column($matches[2]);
}
}
// This matches any modifiers we support to SELECT.
if ( ! preg_match('/\b(?:rand|all|distinct(?:row)?|high_priority|sql_(?:small_result|b(?:ig_result|uffer_result)|no_cache|ca(?:che|lc_found_rows)))\s/i', $column))
{
if (stripos($column, ' AS ') !== FALSE)
{
// Force 'AS' to uppercase
$column = str_ireplace(' AS ', ' AS ', $column);
// This matches any modifiers we support to SELECT.
if (! preg_match('/\b(?:rand|all|distinct(?:row)?|high_priority|sql_(?:small_result|b(?:ig_result|uffer_result)|no_cache|ca(?:che|lc_found_rows)))\s/i', $column)) {
if (stripos($column, ' AS ') !== false) {
// Force 'AS' to uppercase
$column = str_ireplace(' AS ', ' AS ', $column);
// Runs escape_column on both sides of an AS statement
$column = array_map(array($this, __FUNCTION__), explode(' AS ', $column));
// Runs escape_column on both sides of an AS statement
$column = array_map(array($this, __FUNCTION__), explode(' AS ', $column));
// Re-create the AS statement
return implode(' AS ', $column);
}
// Re-create the AS statement
return implode(' AS ', $column);
}
return preg_replace('/[^.*]+/', '[$0]', $column);
}
return preg_replace('/[^.*]+/', '[$0]', $column);
}
$parts = explode(' ', $column);
$column = '';
$parts = explode(' ', $column);
$column = '';
for ($i = 0, $c = count($parts); $i < $c; $i++)
{
// The column is always last
if ($i == ($c - 1))
{
$column .= preg_replace('/[^.*]+/', '[$0]', $parts[$i]);
}
else // otherwise, it's a modifier
{
$column .= $parts[$i].' ';
}
}
return $column;
}
for ($i = 0, $c = count($parts); $i < $c; $i++) {
// The column is always last
if ($i == ($c - 1)) {
$column .= preg_replace('/[^.*]+/', '[$0]', $parts[$i]);
} else // otherwise, it's a modifier
{
$column .= $parts[$i] . ' ';
}
}
return $column;
}
/**
* Limit in SQL Server 2000 only uses the keyword
* 'TOP'; 2007 may have an offset keyword, but
* I am unsure - for pagination style limit,offset
* functionality, a fancy query needs to be built.
*
* @param unknown_type $limit
* @return unknown
*/
public function limit($limit, $offset=null)
{
return 'TOP '.$limit;
}
/**
* Limit in SQL Server 2000 only uses the keyword
* 'TOP'; 2007 may have an offset keyword, but
* I am unsure - for pagination style limit,offset
* functionality, a fancy query needs to be built.
*
* @param unknown_type $limit
* @return unknown
*/
public function limit($limit, $offset = null)
{
return 'TOP ' . $limit;
}
public function compile_select($database)
{
$sql = ($database['distinct'] == TRUE) ? 'SELECT DISTINCT ' : 'SELECT ';
$sql .= (count($database['select']) > 0) ? implode(', ', $database['select']) : '*';
public function compile_select($database)
{
$sql = ($database['distinct'] == true) ? 'SELECT DISTINCT ' : 'SELECT ';
$sql .= (count($database['select']) > 0) ? implode(', ', $database['select']) : '*';
if (count($database['from']) > 0)
{
// Escape the tables
$froms = array();
foreach ($database['from'] as $from)
$froms[] = $this->escape_column($from);
$sql .= "\nFROM ";
$sql .= implode(', ', $froms);
}
if (count($database['from']) > 0) {
// Escape the tables
$froms = array();
foreach ($database['from'] as $from) {
$froms[] = $this->escape_column($from);
}
$sql .= "\nFROM ";
$sql .= implode(', ', $froms);
}
if (count($database['join']) > 0)
{
foreach($database['join'] AS $join)
{
$sql .= "\n".$join['type'].'JOIN '.implode(', ', $join['tables']).' ON '.$join['conditions'];
}
}
if (count($database['join']) > 0) {
foreach ($database['join'] as $join) {
$sql .= "\n" . $join['type'] . 'JOIN ' . implode(', ', $join['tables']) . ' ON ' . $join['conditions'];
}
}
if (count($database['where']) > 0)
{
$sql .= "\nWHERE ";
}
if (count($database['where']) > 0) {
$sql .= "\nWHERE ";
}
$sql .= implode("\n", $database['where']);
$sql .= implode("\n", $database['where']);
if (count($database['groupby']) > 0)
{
$sql .= "\nGROUP BY ";
$sql .= implode(', ', $database['groupby']);
}
if (count($database['groupby']) > 0) {
$sql .= "\nGROUP BY ";
$sql .= implode(', ', $database['groupby']);
}
if (count($database['having']) > 0)
{
$sql .= "\nHAVING ";
$sql .= implode("\n", $database['having']);
}
if (count($database['having']) > 0) {
$sql .= "\nHAVING ";
$sql .= implode("\n", $database['having']);
}
if (count($database['orderby']) > 0)
{
$sql .= "\nORDER BY ";
$sql .= implode(', ', $database['orderby']);
}
if (count($database['orderby']) > 0) {
$sql .= "\nORDER BY ";
$sql .= implode(', ', $database['orderby']);
}
if (is_numeric($database['limit']))
{
$sql .= "\n";
$sql .= $this->limit($database['limit']);
}
if (is_numeric($database['limit'])) {
$sql .= "\n";
$sql .= $this->limit($database['limit']);
}
return $sql;
}
return $sql;
}
public function escape_str($str)
{
if (!$this->db_config['escape'])
return $str;
public function escape_str($str)
{
if (!$this->db_config['escape']) {
return $str;
}
is_resource($this->link) or $this->connect();
//mssql_real_escape_string($str, $this->link); <-- this function doesn't exist
is_resource($this->link) or $this->connect();
//mssql_real_escape_string($str, $this->link); <-- this function doesn't exist
$characters = array('/\x00/', '/\x1a/', '/\n/', '/\r/', '/\\\/', '/\'/');
$replace = array('\\\x00', '\\x1a', '\\n', '\\r', '\\\\', "''");
return preg_replace($characters, $replace, $str);
}
$characters = array('/\x00/', '/\x1a/', '/\n/', '/\r/', '/\\\/', '/\'/');
$replace = array('\\\x00', '\\x1a', '\\n', '\\r', '\\\\', "''");
return preg_replace($characters, $replace, $str);
}
public function list_tables()
{
$sql = 'SHOW TABLES FROM ['.$this->db_config['connection']['database'].']';
$result = $this->query($sql)->result(FALSE, MSSQL_ASSOC);
public function list_tables()
{
$sql = 'SHOW TABLES FROM [' . $this->db_config['connection']['database'] . ']';
$result = $this->query($sql)->result(false, MSSQL_ASSOC);
$retval = array();
foreach ($result as $row)
{
$retval[] = current($row);
}
$retval = array();
foreach ($result as $row) {
$retval[] = current($row);
}
return $retval;
}
return $retval;
}
public function show_error()
{
return mssql_get_last_message($this->link);
}
public function show_error()
{
return mssql_get_last_message($this->link);
}
public function list_fields($table)
{
$result = array();
public function list_fields($table)
{
$result = array();
foreach ($this->field_data($table) as $row)
{
// Make an associative array
$result[$row->Field] = $this->sql_type($row->Type);
}
foreach ($this->field_data($table) as $row) {
// Make an associative array
$result[$row->Field] = $this->sql_type($row->Type);
}
return $result;
}
return $result;
}
public function field_data($table)
{
$query = $this->query("SELECT COLUMN_NAME AS Field, DATA_TYPE as Type FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = '".$this->escape_table($table)."'", $this->link);
public function field_data($table)
{
$query = $this->query(
"SELECT COLUMN_NAME AS Field, DATA_TYPE as Type FROM INFORMATION_SCHEMA.Columns WHERE TABLE_NAME = '" .
$this->escape_table($table) . "'",
$this->link
);
return $query->result_array(TRUE);
}
return $query->result_array(true);
}
}
/**
* MSSQL Result
*/
class Mssql_Result extends Database_Result {
class Mssql_Result extends Database_Result
{
// Fetch function and return type
protected $fetch_type = 'mssql_fetch_object';
protected $return_type = MSSQL_ASSOC;
// Fetch function and return type
protected $fetch_type = 'mssql_fetch_object';
protected $return_type = MSSQL_ASSOC;
/**
* Sets up the result variables.
*
* @param resource query result
* @param resource database link
* @param boolean return objects or arrays
* @param string SQL query that was run
*/
public function __construct($result, $link, $object = true, $sql = '')
{
$this->result = $result;
/**
* Sets up the result variables.
*
* @param resource query result
* @param resource database link
* @param boolean return objects or arrays
* @param string SQL query that was run
*/
public function __construct($result, $link, $object = TRUE, $sql)
{
$this->result = $result;
// If the query is a resource, it was a SELECT, SHOW, DESCRIBE, EXPLAIN query
if (is_resource($result)) {
$this->current_row = 0;
$this->total_rows = mssql_num_rows($this->result);
$this->fetch_type = ($object === true) ? 'mssql_fetch_object' : 'mssql_fetch_array';
} elseif (is_bool($result)) {
if ($result == false) {
// SQL error
throw new Kohana_Database_Exception('database.error', mssql_get_last_message($link) . ' - ' . $sql);
} else {
// Its an DELETE, INSERT, REPLACE, or UPDATE querys
$last_id = mssql_query('SELECT @@IDENTITY AS last_id', $link);
$result = mssql_fetch_assoc($last_id);
$this->insert_id = $result['last_id'];
$this->total_rows = mssql_rows_affected($link);
}
}
// If the query is a resource, it was a SELECT, SHOW, DESCRIBE, EXPLAIN query
if (is_resource($result))
{
$this->current_row = 0;
$this->total_rows = mssql_num_rows($this->result);
$this->fetch_type = ($object === TRUE) ? 'mssql_fetch_object' : 'mssql_fetch_array';
}
elseif (is_bool($result))
{
if ($result == FALSE)
{
// SQL error
throw new Kohana_Database_Exception('database.error', mssql_get_last_message($link).' - '.$sql);
}
else
{
// Its an DELETE, INSERT, REPLACE, or UPDATE querys
$last_id = mssql_query('SELECT @@IDENTITY AS last_id', $link);
$result = mssql_fetch_assoc($last_id);
$this->insert_id = $result['last_id'];
$this->total_rows = mssql_rows_affected($link);
}
}
// Set result type
$this->result($object);
// Set result type
$this->result($object);
// Store the SQL
$this->sql = $sql;
}
// Store the SQL
$this->sql = $sql;
}
/**
* Destruct, the cleanup crew!
*/
public function __destruct()
{
if (is_resource($this->result)) {
mssql_free_result($this->result);
}
}
/**
* Destruct, the cleanup crew!
*/
public function __destruct()
{
if (is_resource($this->result))
{
mssql_free_result($this->result);
}
}
public function result($object = true, $type = MSSQL_ASSOC)
{
$this->fetch_type = ((bool) $object) ? 'mssql_fetch_object' : 'mssql_fetch_array';
public function result($object = TRUE, $type = MSSQL_ASSOC)
{
$this->fetch_type = ((bool) $object) ? 'mssql_fetch_object' : 'mssql_fetch_array';
// This check has to be outside the previous statement, because we do not
// know the state of fetch_type when $object = NULL
// NOTE - The class set by $type must be defined before fetching the result,
// autoloading is disabled to save a lot of stupid overhead.
if ($this->fetch_type == 'mssql_fetch_object') {
$this->return_type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
} else {
$this->return_type = $type;
}
// This check has to be outside the previous statement, because we do not
// know the state of fetch_type when $object = NULL
// NOTE - The class set by $type must be defined before fetching the result,
// autoloading is disabled to save a lot of stupid overhead.
if ($this->fetch_type == 'mssql_fetch_object')
{
$this->return_type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
}
else
{
$this->return_type = $type;
}
return $this;
}
return $this;
}
public function as_array($object = null, $type = MSSQL_ASSOC)
{
return $this->result_array($object, $type);
}
public function as_array($object = NULL, $type = MSSQL_ASSOC)
{
return $this->result_array($object, $type);
}
public function result_array($object = null, $type = MSSQL_ASSOC)
{
$rows = array();
public function result_array($object = NULL, $type = MSSQL_ASSOC)
{
$rows = array();
if (is_string($object)) {
$fetch = $object;
} elseif (is_bool($object)) {
if ($object === true) {
$fetch = 'mssql_fetch_object';
if (is_string($object))
{
$fetch = $object;
}
elseif (is_bool($object))
{
if ($object === TRUE)
{
$fetch = 'mssql_fetch_object';
// NOTE - The class set by $type must be defined before fetching the result,
// autoloading is disabled to save a lot of stupid overhead.
$type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
} else {
$fetch = 'mssql_fetch_array';
}
} else {
// Use the default config values
$fetch = $this->fetch_type;
// NOTE - The class set by $type must be defined before fetching the result,
// autoloading is disabled to save a lot of stupid overhead.
$type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
}
else
{
$fetch = 'mssql_fetch_array';
}
}
else
{
// Use the default config values
$fetch = $this->fetch_type;
if ($fetch == 'mssql_fetch_object') {
$type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
}
}
if ($fetch == 'mssql_fetch_object')
{
$type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
}
}
if (mssql_num_rows($this->result)) {
// Reset the pointer location to make sure things work properly
mssql_data_seek($this->result, 0);
if (mssql_num_rows($this->result))
{
// Reset the pointer location to make sure things work properly
mssql_data_seek($this->result, 0);
while ($row = $fetch($this->result, $type)) {
$rows[] = $row;
}
}
while ($row = $fetch($this->result, $type))
{
$rows[] = $row;
}
}
return isset($rows) ? $rows : array();
}
return isset($rows) ? $rows : array();
}
public function list_fields()
{
$field_names = array();
while ($field = mssql_fetch_field($this->result)) {
$field_names[] = $field->name;
}
public function list_fields()
{
$field_names = array();
while ($field = mssql_fetch_field($this->result))
{
$field_names[] = $field->name;
}
return $field_names;
}
return $field_names;
}
public function seek($offset)
{
if (! $this->offsetExists($offset)) {
return false;
}
public function seek($offset)
{
if ( ! $this->offsetExists($offset))
return FALSE;
return mssql_data_seek($this->result, $offset);
}
} // End mssql_Result Class
return mssql_data_seek($this->result, $offset);
}
}
// End mssql_Result Class

View File

@@ -1,4 +1,13 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* MySQL Database Driver
*
@@ -9,488 +18,438 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Database_Mysql_Driver extends Database_Driver {
class Database_Mysql_Driver extends Database_Driver
{
/**
* Database connection link
*/
protected $link;
/**
* Database connection link
*/
protected $link;
/**
* Database configuration
*/
protected $db_config;
/**
* Database configuration
*/
protected $db_config;
/**
* Sets the config for the class.
*
* @param array database configuration
*/
public function __construct($config)
{
$this->db_config = $config;
/**
* Sets the config for the class.
*
* @param array database configuration
*/
public function __construct($config)
{
$this->db_config = $config;
Kohana::log('debug', 'MySQL Database Driver Initialized');
}
Kohana::log('debug', 'MySQL Database Driver Initialized');
}
/**
* Closes the database connection.
*/
public function __destruct()
{
is_resource($this->link) and mysql_close($this->link);
}
/**
* Closes the database connection.
*/
public function __destruct()
{
is_resource($this->link) and mysql_close($this->link);
}
public function connect()
{
// Check if link already exists
if (is_resource($this->link)) {
return $this->link;
}
public function connect()
{
// Check if link already exists
if (is_resource($this->link))
return $this->link;
// Import the connect variables
extract($this->db_config['connection']);
// Import the connect variables
extract($this->db_config['connection']);
// Persistent connections enabled?
$connect = ($this->db_config['persistent'] == true) ? 'mysql_pconnect' : 'mysql_connect';
// Persistent connections enabled?
$connect = ($this->db_config['persistent'] == TRUE) ? 'mysql_pconnect' : 'mysql_connect';
// Build the connection info
$host = isset($host) ? $host : $socket;
$port = isset($port) ? ':' . $port : '';
// Build the connection info
$host = isset($host) ? $host : $socket;
$port = isset($port) ? ':'.$port : '';
// Make the connection and select the database
if (($this->link = $connect($host . $port, $user, $pass, true)) and mysql_select_db($database, $this->link)) {
if ($charset = $this->db_config['character_set']) {
$this->set_charset($charset);
}
// Make the connection and select the database
if (($this->link = $connect($host.$port, $user, $pass, TRUE)) AND mysql_select_db($database, $this->link))
{
if ($charset = $this->db_config['character_set'])
{
$this->set_charset($charset);
}
// Clear password after successful connect
$this->db_config['connection']['pass'] = null;
// Clear password after successful connect
$this->db_config['connection']['pass'] = NULL;
return $this->link;
}
return $this->link;
}
return false;
}
return FALSE;
}
public function query($sql)
{
// Only cache if it's turned on, and only cache if it's not a write statement
if ($this->db_config['cache'] and ! preg_match('#\b(?:INSERT|UPDATE|REPLACE|SET|DELETE|TRUNCATE)\b#i', $sql)) {
$hash = $this->query_hash($sql);
public function query($sql)
{
// Only cache if it's turned on, and only cache if it's not a write statement
if ($this->db_config['cache'] AND ! preg_match('#\b(?:INSERT|UPDATE|REPLACE|SET|DELETE|TRUNCATE)\b#i', $sql))
{
$hash = $this->query_hash($sql);
if (! isset($this->query_cache[$hash])) {
// Set the cached object
$this->query_cache[$hash] = new Mysql_Result(mysql_query($sql, $this->link), $this->link, $this->db_config['object'], $sql);
} else {
// Rewind cached result
$this->query_cache[$hash]->rewind();
}
if ( ! isset($this->query_cache[$hash]))
{
// Set the cached object
$this->query_cache[$hash] = new Mysql_Result(mysql_query($sql, $this->link), $this->link, $this->db_config['object'], $sql);
}
else
{
// Rewind cached result
$this->query_cache[$hash]->rewind();
}
// Return the cached query
return $this->query_cache[$hash];
}
// Return the cached query
return $this->query_cache[$hash];
}
return new Mysql_Result(mysql_query($sql, $this->link), $this->link, $this->db_config['object'], $sql);
}
return new Mysql_Result(mysql_query($sql, $this->link), $this->link, $this->db_config['object'], $sql);
}
public function set_charset($charset)
{
$this->query('SET NAMES ' . $this->escape_str($charset));
}
public function set_charset($charset)
{
$this->query('SET NAMES '.$this->escape_str($charset));
}
public function escape_table($table)
{
if (!$this->db_config['escape']) {
return $table;
}
public function escape_table($table)
{
if (!$this->db_config['escape'])
return $table;
if (stripos($table, ' AS ') !== false) {
// Force 'AS' to uppercase
$table = str_ireplace(' AS ', ' AS ', $table);
if (stripos($table, ' AS ') !== FALSE)
{
// Force 'AS' to uppercase
$table = str_ireplace(' AS ', ' AS ', $table);
// Runs escape_table on both sides of an AS statement
$table = array_map(array($this, __FUNCTION__), explode(' AS ', $table));
// Runs escape_table on both sides of an AS statement
$table = array_map(array($this, __FUNCTION__), explode(' AS ', $table));
// Re-create the AS statement
return implode(' AS ', $table);
}
return '`' . str_replace('.', '`.`', $table) . '`';
}
// Re-create the AS statement
return implode(' AS ', $table);
}
return '`'.str_replace('.', '`.`', $table).'`';
}
public function escape_column($column)
{
if (!$this->db_config['escape']) {
return $column;
}
public function escape_column($column)
{
if (!$this->db_config['escape'])
return $column;
if ($column == '*') {
return $column;
}
if ($column == '*')
return $column;
// This matches any functions we support to SELECT.
if (preg_match('/(avg|count|sum|max|min)\(\s*(.*)\s*\)(\s*as\s*(.+)?)?/i', $column, $matches)) {
if (count($matches) == 3) {
return $matches[1] . '(' . $this->escape_column($matches[2]) . ')';
} elseif (count($matches) == 5) {
return $matches[1] . '(' . $this->escape_column($matches[2]) . ') AS ' . $this->escape_column($matches[2]);
}
}
// This matches any functions we support to SELECT.
if ( preg_match('/(avg|count|sum|max|min)\(\s*(.*)\s*\)(\s*as\s*(.+)?)?/i', $column, $matches))
{
if ( count($matches) == 3)
{
return $matches[1].'('.$this->escape_column($matches[2]).')';
}
else if ( count($matches) == 5)
{
return $matches[1].'('.$this->escape_column($matches[2]).') AS '.$this->escape_column($matches[2]);
}
}
// This matches any modifiers we support to SELECT.
if ( ! preg_match('/\b(?:rand|all|distinct(?:row)?|high_priority|sql_(?:small_result|b(?:ig_result|uffer_result)|no_cache|ca(?:che|lc_found_rows)))\s/i', $column))
{
if (stripos($column, ' AS ') !== FALSE)
{
// Force 'AS' to uppercase
$column = str_ireplace(' AS ', ' AS ', $column);
// This matches any modifiers we support to SELECT.
if (! preg_match('/\b(?:rand|all|distinct(?:row)?|high_priority|sql_(?:small_result|b(?:ig_result|uffer_result)|no_cache|ca(?:che|lc_found_rows)))\s/i', $column)) {
if (stripos($column, ' AS ') !== false) {
// Force 'AS' to uppercase
$column = str_ireplace(' AS ', ' AS ', $column);
// Runs escape_column on both sides of an AS statement
$column = array_map(array($this, __FUNCTION__), explode(' AS ', $column));
// Runs escape_column on both sides of an AS statement
$column = array_map(array($this, __FUNCTION__), explode(' AS ', $column));
// Re-create the AS statement
return implode(' AS ', $column);
}
// Re-create the AS statement
return implode(' AS ', $column);
}
return preg_replace('/[^.*]+/', '`$0`', $column);
}
return preg_replace('/[^.*]+/', '`$0`', $column);
}
$parts = explode(' ', $column);
$column = '';
$parts = explode(' ', $column);
$column = '';
for ($i = 0, $c = count($parts); $i < $c; $i++)
{
// The column is always last
if ($i == ($c - 1))
{
$column .= preg_replace('/[^.*]+/', '`$0`', $parts[$i]);
}
else // otherwise, it's a modifier
{
$column .= $parts[$i].' ';
}
}
return $column;
}
for ($i = 0, $c = count($parts); $i < $c; $i++) {
// The column is always last
if ($i == ($c - 1)) {
$column .= preg_replace('/[^.*]+/', '`$0`', $parts[$i]);
} else // otherwise, it's a modifier
{
$column .= $parts[$i] . ' ';
}
}
return $column;
}
public function regex($field, $match, $type, $num_regexs)
{
$prefix = ($num_regexs == 0) ? '' : $type;
public function regex($field, $match, $type, $num_regexs)
{
$prefix = ($num_regexs == 0) ? '' : $type;
return $prefix.' '.$this->escape_column($field).' REGEXP \''.$this->escape_str($match).'\'';
}
return $prefix . ' ' . $this->escape_column($field) . ' REGEXP \'' . $this->escape_str($match) . '\'';
}
public function notregex($field, $match, $type, $num_regexs)
{
$prefix = $num_regexs == 0 ? '' : $type;
public function notregex($field, $match, $type, $num_regexs)
{
$prefix = $num_regexs == 0 ? '' : $type;
return $prefix.' '.$this->escape_column($field).' NOT REGEXP \''.$this->escape_str($match) . '\'';
}
return $prefix . ' ' . $this->escape_column($field) . ' NOT REGEXP \'' . $this->escape_str($match) . '\'';
}
public function merge($table, $keys, $values)
{
// Escape the column names
foreach ($keys as $key => $value)
{
$keys[$key] = $this->escape_column($value);
}
return 'REPLACE INTO '.$this->escape_table($table).' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';
}
public function merge($table, $keys, $values)
{
// Escape the column names
foreach ($keys as $key => $value) {
$keys[$key] = $this->escape_column($value);
}
return 'REPLACE INTO ' . $this->escape_table($table) . ' (' . implode(', ', $keys) . ') VALUES (' . implode(', ', $values) . ')';
}
public function limit($limit, $offset = 0)
{
return 'LIMIT '.$offset.', '.$limit;
}
public function limit($limit, $offset = 0)
{
return 'LIMIT ' . $offset . ', ' . $limit;
}
public function compile_select($database)
{
$sql = ($database['distinct'] == TRUE) ? 'SELECT DISTINCT ' : 'SELECT ';
$sql .= (count($database['select']) > 0) ? implode(', ', $database['select']) : '*';
public function compile_select($database)
{
$sql = ($database['distinct'] == true) ? 'SELECT DISTINCT ' : 'SELECT ';
$sql .= (count($database['select']) > 0) ? implode(', ', $database['select']) : '*';
if (count($database['from']) > 0)
{
// Escape the tables
$froms = array();
foreach ($database['from'] as $from)
{
$froms[] = $this->escape_column($from);
}
$sql .= "\nFROM (";
$sql .= implode(', ', $froms).")";
}
if (count($database['from']) > 0) {
// Escape the tables
$froms = array();
foreach ($database['from'] as $from) {
$froms[] = $this->escape_column($from);
}
$sql .= "\nFROM (";
$sql .= implode(', ', $froms) . ")";
}
if (count($database['join']) > 0)
{
foreach($database['join'] AS $join)
{
$sql .= "\n".$join['type'].'JOIN '.implode(', ', $join['tables']).' ON '.$join['conditions'];
}
}
if (count($database['join']) > 0) {
foreach ($database['join'] as $join) {
$sql .= "\n" . $join['type'] . 'JOIN ' . implode(', ', $join['tables']) . ' ON ' . $join['conditions'];
}
}
if (count($database['where']) > 0)
{
$sql .= "\nWHERE ";
}
if (count($database['where']) > 0) {
$sql .= "\nWHERE ";
}
$sql .= implode("\n", $database['where']);
$sql .= implode("\n", $database['where']);
if (count($database['groupby']) > 0)
{
$sql .= "\nGROUP BY ";
$sql .= implode(', ', $database['groupby']);
}
if (count($database['groupby']) > 0) {
$sql .= "\nGROUP BY ";
$sql .= implode(', ', $database['groupby']);
}
if (count($database['having']) > 0)
{
$sql .= "\nHAVING ";
$sql .= implode("\n", $database['having']);
}
if (count($database['having']) > 0) {
$sql .= "\nHAVING ";
$sql .= implode("\n", $database['having']);
}
if (count($database['orderby']) > 0)
{
$sql .= "\nORDER BY ";
$sql .= implode(', ', $database['orderby']);
}
if (count($database['orderby']) > 0) {
$sql .= "\nORDER BY ";
$sql .= implode(', ', $database['orderby']);
}
if (is_numeric($database['limit']))
{
$sql .= "\n";
$sql .= $this->limit($database['limit'], $database['offset']);
}
if (is_numeric($database['limit'])) {
$sql .= "\n";
$sql .= $this->limit($database['limit'], $database['offset']);
}
return $sql;
}
return $sql;
}
public function escape_str($str)
{
if (!$this->db_config['escape'])
return $str;
public function escape_str($str)
{
if (!$this->db_config['escape']) {
return $str;
}
is_resource($this->link) or $this->connect();
is_resource($this->link) or $this->connect();
return mysql_real_escape_string($str, $this->link);
}
return mysql_real_escape_string($str, $this->link);
}
public function list_tables()
{
$tables = array();
public function list_tables()
{
$tables = array();
if ($query = $this->query('SHOW TABLES FROM '.$this->escape_table($this->db_config['connection']['database'])))
{
foreach ($query->result(FALSE) as $row)
{
$tables[] = current($row);
}
}
if ($query = $this->query('SHOW TABLES FROM ' . $this->escape_table($this->db_config['connection']['database']))) {
foreach ($query->result(false) as $row) {
$tables[] = current($row);
}
}
return $tables;
}
return $tables;
}
public function show_error()
{
return mysql_error($this->link);
}
public function show_error()
{
return mysql_error($this->link);
}
public function list_fields($table)
{
$result = NULL;
public function list_fields($table)
{
$result = null;
foreach ($this->field_data($table) as $row)
{
// Make an associative array
$result[$row->Field] = $this->sql_type($row->Type);
foreach ($this->field_data($table) as $row) {
// Make an associative array
$result[$row->Field] = $this->sql_type($row->Type);
if ($row->Key === 'PRI' AND $row->Extra === 'auto_increment')
{
// For sequenced (AUTO_INCREMENT) tables
$result[$row->Field]['sequenced'] = TRUE;
}
if ($row->Key === 'PRI' and $row->Extra === 'auto_increment') {
// For sequenced (AUTO_INCREMENT) tables
$result[$row->Field]['sequenced'] = true;
}
if ($row->Null === 'YES')
{
// Set NULL status
$result[$row->Field]['null'] = TRUE;
}
}
if ($row->Null === 'YES') {
// Set NULL status
$result[$row->Field]['null'] = true;
}
}
if (!isset($result))
throw new Kohana_Database_Exception('database.table_not_found', $table);
if (!isset($result)) {
throw new Kohana_Database_Exception('database.table_not_found', $table);
}
return $result;
}
return $result;
}
public function field_data($table)
{
$result = $this->query('SHOW COLUMNS FROM '.$this->escape_table($table));
public function field_data($table)
{
$result = $this->query('SHOW COLUMNS FROM ' . $this->escape_table($table));
return $result->result_array(TRUE);
}
} // End Database_Mysql_Driver Class
return $result->result_array(true);
}
}
// End Database_Mysql_Driver Class
/**
* MySQL Result
*/
class Mysql_Result extends Database_Result {
class Mysql_Result extends Database_Result
{
// Fetch function and return type
protected $fetch_type = 'mysql_fetch_object';
protected $return_type = MYSQL_ASSOC;
// Fetch function and return type
protected $fetch_type = 'mysql_fetch_object';
protected $return_type = MYSQL_ASSOC;
/**
* Sets up the result variables.
*
* @param resource query result
* @param resource database link
* @param boolean return objects or arrays
* @param string SQL query that was run
*/
public function __construct($result, $link, $object = true, $sql = '')
{
$this->result = $result;
/**
* Sets up the result variables.
*
* @param resource query result
* @param resource database link
* @param boolean return objects or arrays
* @param string SQL query that was run
*/
public function __construct($result, $link, $object = TRUE, $sql)
{
$this->result = $result;
// If the query is a resource, it was a SELECT, SHOW, DESCRIBE, EXPLAIN query
if (is_resource($result)) {
$this->current_row = 0;
$this->total_rows = mysql_num_rows($this->result);
$this->fetch_type = ($object === true) ? 'mysql_fetch_object' : 'mysql_fetch_array';
} elseif (is_bool($result)) {
if ($result == false) {
// SQL error
throw new Kohana_Database_Exception('database.error', mysql_error($link) . ' - ' . $sql);
} else {
// Its an DELETE, INSERT, REPLACE, or UPDATE query
$this->insert_id = mysql_insert_id($link);
$this->total_rows = mysql_affected_rows($link);
}
}
// If the query is a resource, it was a SELECT, SHOW, DESCRIBE, EXPLAIN query
if (is_resource($result))
{
$this->current_row = 0;
$this->total_rows = mysql_num_rows($this->result);
$this->fetch_type = ($object === TRUE) ? 'mysql_fetch_object' : 'mysql_fetch_array';
}
elseif (is_bool($result))
{
if ($result == FALSE)
{
// SQL error
throw new Kohana_Database_Exception('database.error', mysql_error($link).' - '.$sql);
}
else
{
// Its an DELETE, INSERT, REPLACE, or UPDATE query
$this->insert_id = mysql_insert_id($link);
$this->total_rows = mysql_affected_rows($link);
}
}
// Set result type
$this->result($object);
// Set result type
$this->result($object);
// Store the SQL
$this->sql = $sql;
}
// Store the SQL
$this->sql = $sql;
}
/**
* Destruct, the cleanup crew!
*/
public function __destruct()
{
if (is_resource($this->result)) {
mysql_free_result($this->result);
}
}
/**
* Destruct, the cleanup crew!
*/
public function __destruct()
{
if (is_resource($this->result))
{
mysql_free_result($this->result);
}
}
public function result($object = true, $type = MYSQL_ASSOC)
{
$this->fetch_type = ((bool) $object) ? 'mysql_fetch_object' : 'mysql_fetch_array';
public function result($object = TRUE, $type = MYSQL_ASSOC)
{
$this->fetch_type = ((bool) $object) ? 'mysql_fetch_object' : 'mysql_fetch_array';
// This check has to be outside the previous statement, because we do not
// know the state of fetch_type when $object = NULL
// NOTE - The class set by $type must be defined before fetching the result,
// autoloading is disabled to save a lot of stupid overhead.
if ($this->fetch_type == 'mysql_fetch_object' and $object === true) {
$this->return_type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
} else {
$this->return_type = $type;
}
// This check has to be outside the previous statement, because we do not
// know the state of fetch_type when $object = NULL
// NOTE - The class set by $type must be defined before fetching the result,
// autoloading is disabled to save a lot of stupid overhead.
if ($this->fetch_type == 'mysql_fetch_object' AND $object === TRUE)
{
$this->return_type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
}
else
{
$this->return_type = $type;
}
return $this;
}
return $this;
}
public function as_array($object = null, $type = MYSQL_ASSOC)
{
return $this->result_array($object, $type);
}
public function as_array($object = NULL, $type = MYSQL_ASSOC)
{
return $this->result_array($object, $type);
}
public function result_array($object = null, $type = MYSQL_ASSOC)
{
$rows = array();
public function result_array($object = NULL, $type = MYSQL_ASSOC)
{
$rows = array();
if (is_string($object)) {
$fetch = $object;
} elseif (is_bool($object)) {
if ($object === true) {
$fetch = 'mysql_fetch_object';
if (is_string($object))
{
$fetch = $object;
}
elseif (is_bool($object))
{
if ($object === TRUE)
{
$fetch = 'mysql_fetch_object';
$type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
} else {
$fetch = 'mysql_fetch_array';
}
} else {
// Use the default config values
$fetch = $this->fetch_type;
$type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
}
else
{
$fetch = 'mysql_fetch_array';
}
}
else
{
// Use the default config values
$fetch = $this->fetch_type;
if ($fetch == 'mysql_fetch_object') {
$type = (is_string($this->return_type) and Kohana::auto_load($this->return_type)) ? $this->return_type : 'stdClass';
}
}
if ($fetch == 'mysql_fetch_object')
{
$type = (is_string($this->return_type) AND Kohana::auto_load($this->return_type)) ? $this->return_type : 'stdClass';
}
}
if (mysql_num_rows($this->result)) {
// Reset the pointer location to make sure things work properly
mysql_data_seek($this->result, 0);
if (mysql_num_rows($this->result))
{
// Reset the pointer location to make sure things work properly
mysql_data_seek($this->result, 0);
while ($row = $fetch($this->result, $type)) {
$rows[] = $row;
}
}
while ($row = $fetch($this->result, $type))
{
$rows[] = $row;
}
}
return isset($rows) ? $rows : array();
}
return isset($rows) ? $rows : array();
}
public function list_fields()
{
$field_names = array();
while ($field = mysql_fetch_field($this->result)) {
$field_names[] = $field->name;
}
public function list_fields()
{
$field_names = array();
while ($field = mysql_fetch_field($this->result))
{
$field_names[] = $field->name;
}
return $field_names;
}
return $field_names;
}
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 = $offset;
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 = $offset;
return TRUE;
}
else
{
return FALSE;
}
}
} // End Mysql_Result Class
return true;
} else {
return false;
}
}
}
// End Mysql_Result Class

View File

@@ -1,4 +1,13 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* MySQLi Database Driver
*
@@ -9,350 +18,319 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Database_Mysqli_Driver extends Database_Mysql_Driver {
class Database_Mysqli_Driver extends Database_Mysql_Driver
{
// Database connection link
protected $link;
protected $db_config;
protected $statements = array();
// Database connection link
protected $link;
protected $db_config;
protected $statements = array();
/**
* Sets the config for the class.
*
* @param array database configuration
*/
public function __construct($config)
{
$this->db_config = $config;
/**
* Sets the config for the class.
*
* @param array database configuration
*/
public function __construct($config)
{
$this->db_config = $config;
Kohana::log('debug', 'MySQLi Database Driver Initialized');
}
Kohana::log('debug', 'MySQLi Database Driver Initialized');
}
/**
* Closes the database connection.
*/
public function __destruct()
{
is_object($this->link) and $this->link->close();
}
/**
* Closes the database connection.
*/
public function __destruct()
{
is_object($this->link) and $this->link->close();
}
public function connect()
{
// Check if link already exists
if (is_object($this->link)) {
return $this->link;
}
public function connect()
{
// Check if link already exists
if (is_object($this->link))
return $this->link;
// Import the connect variables
extract($this->db_config['connection']);
// Import the connect variables
extract($this->db_config['connection']);
// Build the connection info
$host = isset($host) ? $host : $socket;
// Build the connection info
$host = isset($host) ? $host : $socket;
// Make the connection and select the database
if ($this->link = new mysqli($host, $user, $pass, $database, $port)) {
if ($charset = $this->db_config['character_set']) {
$this->set_charset($charset);
}
// Make the connection and select the database
if ($this->link = new mysqli($host, $user, $pass, $database, $port))
{
if ($charset = $this->db_config['character_set'])
{
$this->set_charset($charset);
}
// Clear password after successful connect
$this->db_config['connection']['pass'] = null;
// Clear password after successful connect
$this->db_config['connection']['pass'] = NULL;
return $this->link;
}
return $this->link;
}
return false;
}
return FALSE;
}
public function query($sql)
{
// Only cache if it's turned on, and only cache if it's not a write statement
if ($this->db_config['cache'] and ! preg_match('#\b(?:INSERT|UPDATE|REPLACE|SET|DELETE|TRUNCATE)\b#i', $sql)) {
$hash = $this->query_hash($sql);
public function query($sql)
{
// Only cache if it's turned on, and only cache if it's not a write statement
if ($this->db_config['cache'] AND ! preg_match('#\b(?:INSERT|UPDATE|REPLACE|SET|DELETE|TRUNCATE)\b#i', $sql))
{
$hash = $this->query_hash($sql);
if (! isset($this->query_cache[$hash])) {
// Set the cached object
$this->query_cache[$hash] = new Kohana_Mysqli_Result($this->link, $this->db_config['object'], $sql);
} else {
// Rewind cached result
$this->query_cache[$hash]->rewind();
}
if ( ! isset($this->query_cache[$hash]))
{
// Set the cached object
$this->query_cache[$hash] = new Kohana_Mysqli_Result($this->link, $this->db_config['object'], $sql);
}
else
{
// Rewind cached result
$this->query_cache[$hash]->rewind();
}
// Return the cached query
return $this->query_cache[$hash];
}
// Return the cached query
return $this->query_cache[$hash];
}
return new Kohana_Mysqli_Result($this->link, $this->db_config['object'], $sql);
}
return new Kohana_Mysqli_Result($this->link, $this->db_config['object'], $sql);
}
public function set_charset($charset)
{
if ($this->link->set_charset($charset) === false) {
throw new Kohana_Database_Exception('database.error', $this->show_error());
}
}
public function set_charset($charset)
{
if ($this->link->set_charset($charset) === FALSE)
throw new Kohana_Database_Exception('database.error', $this->show_error());
}
public function escape_str($str)
{
if (!$this->db_config['escape']) {
return $str;
}
public function escape_str($str)
{
if (!$this->db_config['escape'])
return $str;
is_object($this->link) or $this->connect();
is_object($this->link) or $this->connect();
return $this->link->real_escape_string($str);
}
return $this->link->real_escape_string($str);
}
public function show_error()
{
return $this->link->error;
}
} // End Database_Mysqli_Driver Class
public function show_error()
{
return $this->link->error;
}
}
// End Database_Mysqli_Driver Class
/**
* MySQLi Result
*/
class Kohana_Mysqli_Result extends Database_Result {
class Kohana_Mysqli_Result extends Database_Result
{
// Database connection
protected $link;
// Database connection
protected $link;
// Data fetching types
protected $fetch_type = 'mysqli_fetch_object';
protected $return_type = MYSQLI_ASSOC;
// Data fetching types
protected $fetch_type = 'mysqli_fetch_object';
protected $return_type = MYSQLI_ASSOC;
/**
* Sets up the result variables.
*
* @param object database link
* @param boolean return objects or arrays
* @param string SQL query that was run
*/
public function __construct($link, $object = true, $sql = '')
{
$this->link = $link;
/**
* Sets up the result variables.
*
* @param object database link
* @param boolean return objects or arrays
* @param string SQL query that was run
*/
public function __construct($link, $object = TRUE, $sql)
{
$this->link = $link;
if (! $this->link->multi_query($sql)) {
// SQL error
throw new Kohana_Database_Exception('database.error', $this->link->error . ' - ' . $sql);
} else {
$this->result = $this->link->store_result();
if ( ! $this->link->multi_query($sql))
{
// SQL error
throw new Kohana_Database_Exception('database.error', $this->link->error.' - '.$sql);
}
else
{
$this->result = $this->link->store_result();
// If the query is an object, it was a SELECT, SHOW, DESCRIBE, EXPLAIN query
if (is_object($this->result)) {
$this->current_row = 0;
$this->total_rows = $this->result->num_rows;
$this->fetch_type = ($object === true) ? 'fetch_object' : 'fetch_array';
} elseif ($this->link->error) {
// SQL error
throw new Kohana_Database_Exception('database.error', $this->link->error . ' - ' . $sql);
} else {
// Its an DELETE, INSERT, REPLACE, or UPDATE query
$this->insert_id = $this->link->insert_id;
$this->total_rows = $this->link->affected_rows;
}
}
// If the query is an object, it was a SELECT, SHOW, DESCRIBE, EXPLAIN query
if (is_object($this->result))
{
$this->current_row = 0;
$this->total_rows = $this->result->num_rows;
$this->fetch_type = ($object === TRUE) ? 'fetch_object' : 'fetch_array';
}
elseif ($this->link->error)
{
// SQL error
throw new Kohana_Database_Exception('database.error', $this->link->error.' - '.$sql);
}
else
{
// Its an DELETE, INSERT, REPLACE, or UPDATE query
$this->insert_id = $this->link->insert_id;
$this->total_rows = $this->link->affected_rows;
}
}
// Set result type
$this->result($object);
// Set result type
$this->result($object);
// Store the SQL
$this->sql = $sql;
}
// Store the SQL
$this->sql = $sql;
}
/**
* Magic __destruct function, frees the result.
*/
public function __destruct()
{
if (is_object($this->result)) {
$this->result->free_result();
/**
* Magic __destruct function, frees the result.
*/
public function __destruct()
{
if (is_object($this->result))
{
$this->result->free_result();
// this is kinda useless, but needs to be done to avoid the "Commands out of sync; you
// can't run this command now" error. Basically, we get all results after the first one
// (the one we actually need) and free them.
if (is_resource($this->link) and $this->link->more_results()) {
do {
if ($result = $this->link->store_result()) {
$result->free_result();
}
} while ($this->link->next_result());
}
}
}
// this is kinda useless, but needs to be done to avoid the "Commands out of sync; you
// can't run this command now" error. Basically, we get all results after the first one
// (the one we actually need) and free them.
if (is_resource($this->link) AND $this->link->more_results())
{
do
{
if ($result = $this->link->store_result())
{
$result->free_result();
}
} while ($this->link->next_result());
}
}
}
public function result($object = true, $type = MYSQLI_ASSOC)
{
$this->fetch_type = ((bool) $object) ? 'fetch_object' : 'fetch_array';
public function result($object = TRUE, $type = MYSQLI_ASSOC)
{
$this->fetch_type = ((bool) $object) ? 'fetch_object' : 'fetch_array';
// This check has to be outside the previous statement, because we do not
// know the state of fetch_type when $object = NULL
// NOTE - The class set by $type must be defined before fetching the result,
// autoloading is disabled to save a lot of stupid overhead.
if ($this->fetch_type == 'fetch_object') {
$this->return_type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
} else {
$this->return_type = $type;
}
// This check has to be outside the previous statement, because we do not
// know the state of fetch_type when $object = NULL
// NOTE - The class set by $type must be defined before fetching the result,
// autoloading is disabled to save a lot of stupid overhead.
if ($this->fetch_type == 'fetch_object')
{
$this->return_type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
}
else
{
$this->return_type = $type;
}
return $this;
}
return $this;
}
public function as_array($object = null, $type = MYSQLI_ASSOC)
{
return $this->result_array($object, $type);
}
public function as_array($object = NULL, $type = MYSQLI_ASSOC)
{
return $this->result_array($object, $type);
}
public function result_array($object = null, $type = MYSQLI_ASSOC)
{
$rows = array();
public function result_array($object = NULL, $type = MYSQLI_ASSOC)
{
$rows = array();
if (is_string($object)) {
$fetch = $object;
} elseif (is_bool($object)) {
if ($object === true) {
$fetch = 'fetch_object';
if (is_string($object))
{
$fetch = $object;
}
elseif (is_bool($object))
{
if ($object === TRUE)
{
$fetch = 'fetch_object';
// NOTE - The class set by $type must be defined before fetching the result,
// autoloading is disabled to save a lot of stupid overhead.
$type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
} else {
$fetch = 'fetch_array';
}
} else {
// Use the default config values
$fetch = $this->fetch_type;
// NOTE - The class set by $type must be defined before fetching the result,
// autoloading is disabled to save a lot of stupid overhead.
$type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
}
else
{
$fetch = 'fetch_array';
}
}
else
{
// Use the default config values
$fetch = $this->fetch_type;
if ($fetch == 'fetch_object') {
$type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
}
}
if ($fetch == 'fetch_object')
{
$type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
}
}
if ($this->result->num_rows) {
// Reset the pointer location to make sure things work properly
$this->result->data_seek(0);
if ($this->result->num_rows)
{
// Reset the pointer location to make sure things work properly
$this->result->data_seek(0);
while ($row = $this->result->$fetch($type)) {
$rows[] = $row;
}
}
while ($row = $this->result->$fetch($type))
{
$rows[] = $row;
}
}
return isset($rows) ? $rows : array();
}
return isset($rows) ? $rows : array();
}
public function list_fields()
{
$field_names = array();
while ($field = $this->result->fetch_field()) {
$field_names[] = $field->name;
}
public function list_fields()
{
$field_names = array();
while ($field = $this->result->fetch_field())
{
$field_names[] = $field->name;
}
return $field_names;
}
return $field_names;
}
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;
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;
}
return TRUE;
}
return false;
}
return FALSE;
}
public function offsetGet($offset)
{
if (! $this->seek($offset)) {
return false;
}
public function offsetGet($offset)
{
if ( ! $this->seek($offset))
return FALSE;
// Return the row
$fetch = $this->fetch_type;
return $this->result->$fetch($this->return_type);
}
} // End Mysqli_Result Class
// Return the row
$fetch = $this->fetch_type;
return $this->result->$fetch($this->return_type);
}
}
// End Mysqli_Result Class
/**
* MySQLi Prepared Statement (experimental)
*/
class Kohana_Mysqli_Statement {
class Kohana_Mysqli_Statement
{
protected $link = null;
protected $stmt;
protected $var_names = array();
protected $var_values = array();
protected $link = NULL;
protected $stmt;
protected $var_names = array();
protected $var_values = array();
public function __construct($sql, $link)
{
$this->link = $link;
public function __construct($sql, $link)
{
$this->link = $link;
$this->stmt = $this->link->prepare($sql);
$this->stmt = $this->link->prepare($sql);
return $this;
}
return $this;
}
public function __destruct()
{
$this->stmt->close();
}
public function __destruct()
{
$this->stmt->close();
}
// Sets the bind parameters
public function bind_params($param_types, $params)
{
$this->var_names = array_keys($params);
$this->var_values = array_values($params);
call_user_func_array(array($this->stmt, 'bind_param'), array_merge($param_types, $var_names));
// Sets the bind parameters
public function bind_params($param_types, $params)
{
$this->var_names = array_keys($params);
$this->var_values = array_values($params);
call_user_func_array(array($this->stmt, 'bind_param'), array_merge($param_types, $var_names));
return $this;
}
return $this;
}
public function bind_result($params)
{
call_user_func_array(array($this->stmt, 'bind_result'), $params);
}
public function bind_result($params)
{
call_user_func_array(array($this->stmt, 'bind_result'), $params);
}
// Runs the statement
public function execute()
{
foreach ($this->var_names as $key => $name)
{
$$name = $this->var_values[$key];
}
$this->stmt->execute();
return $this->stmt;
}
// Runs the statement
public function execute()
{
foreach ($this->var_names as $key => $name) {
$$name = $this->var_values[$key];
}
$this->stmt->execute();
return $this->stmt;
}
}

View File

@@ -1,4 +1,13 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/*
* Class: Database_PdoSqlite_Driver
* Provides specific database items for Sqlite.
@@ -11,476 +20,418 @@
* license - <no>
*/
class Database_Pdosqlite_Driver extends Database_Driver {
class Database_Pdosqlite_Driver extends Database_Driver
{
// Database connection link
protected $link;
protected $db_config;
// Database connection link
protected $link;
protected $db_config;
/*
* Constructor: __construct
* Sets up the config for the class.
*
* Parameters:
* config - database configuration
*
*/
public function __construct($config)
{
$this->db_config = $config;
/*
* Constructor: __construct
* Sets up the config for the class.
*
* Parameters:
* config - database configuration
*
*/
public function __construct($config)
{
$this->db_config = $config;
Kohana::log('debug', 'PDO:Sqlite Database Driver Initialized');
}
Kohana::log('debug', 'PDO:Sqlite Database Driver Initialized');
}
public function connect()
{
// Import the connect variables
extract($this->db_config['connection']);
public function connect()
{
// Import the connect variables
extract($this->db_config['connection']);
try {
$this->link = new PDO(
'sqlite:' . $socket . $database,
$user,
$pass,
array(PDO::ATTR_PERSISTENT => $this->db_config['persistent'])
);
try
{
$this->link = new PDO('sqlite:'.$socket.$database, $user, $pass,
array(PDO::ATTR_PERSISTENT => $this->db_config['persistent']));
$this->link->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL);
//$this->link->query('PRAGMA count_changes=1;');
$this->link->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL);
//$this->link->query('PRAGMA count_changes=1;');
if ($charset = $this->db_config['character_set']) {
$this->set_charset($charset);
}
} catch (PDOException $e) {
throw new Kohana_Database_Exception('database.error', $e->getMessage());
}
if ($charset = $this->db_config['character_set'])
{
$this->set_charset($charset);
}
}
catch (PDOException $e)
{
throw new Kohana_Database_Exception('database.error', $e->getMessage());
}
// Clear password after successful connect
$this->db_config['connection']['pass'] = null;
// Clear password after successful connect
$this->db_config['connection']['pass'] = NULL;
return $this->link;
}
return $this->link;
}
public function query($sql)
{
try {
$sth = $this->link->prepare($sql);
} catch (PDOException $e) {
throw new Kohana_Database_Exception('database.error', $e->getMessage());
}
return new Pdosqlite_Result($sth, $this->link, $this->db_config['object'], $sql);
}
public function query($sql)
{
try
{
$sth = $this->link->prepare($sql);
}
catch (PDOException $e)
{
throw new Kohana_Database_Exception('database.error', $e->getMessage());
}
return new Pdosqlite_Result($sth, $this->link, $this->db_config['object'], $sql);
}
public function set_charset($charset)
{
$this->link->query('PRAGMA encoding = ' . $this->escape_str($charset));
}
public function set_charset($charset)
{
$this->link->query('PRAGMA encoding = '.$this->escape_str($charset));
}
public function escape_table($table)
{
if (! $this->db_config['escape']) {
return $table;
}
public function escape_table($table)
{
if ( ! $this->db_config['escape'])
return $table;
return '`' . str_replace('.', '`.`', $table) . '`';
}
return '`'.str_replace('.', '`.`', $table).'`';
}
public function escape_column($column)
{
if (! $this->db_config['escape']) {
return $column;
}
public function escape_column($column)
{
if ( ! $this->db_config['escape'])
return $column;
if ($column == '*') {
return $column;
}
if ($column == '*')
return $column;
// This matches any functions we support to SELECT.
if (preg_match('/(avg|count|sum|max|min)\(\s*(.*)\s*\)(\s*as\s*(.+)?)?/i', $column, $matches)) {
if (count($matches) == 3) {
return $matches[1] . '(' . $this->escape_column($matches[2]) . ')';
} elseif (count($matches) == 5) {
return $matches[1] . '(' . $this->escape_column($matches[2]) . ') AS ' . $this->escape_column($matches[2]);
}
}
// This matches any functions we support to SELECT.
if ( preg_match('/(avg|count|sum|max|min)\(\s*(.*)\s*\)(\s*as\s*(.+)?)?/i', $column, $matches))
{
if ( count($matches) == 3)
{
return $matches[1].'('.$this->escape_column($matches[2]).')';
}
else if ( count($matches) == 5)
{
return $matches[1].'('.$this->escape_column($matches[2]).') AS '.$this->escape_column($matches[2]);
}
}
// This matches any modifiers we support to SELECT.
if (! preg_match('/\b(?:rand|all|distinct(?:row)?|high_priority|sql_(?:small_result|b(?:ig_result|uffer_result)|no_cache|ca(?:che|lc_found_rows)))\s/i', $column)) {
if (stripos($column, ' AS ') !== false) {
// Force 'AS' to uppercase
$column = str_ireplace(' AS ', ' AS ', $column);
// This matches any modifiers we support to SELECT.
if ( ! preg_match('/\b(?:rand|all|distinct(?:row)?|high_priority|sql_(?:small_result|b(?:ig_result|uffer_result)|no_cache|ca(?:che|lc_found_rows)))\s/i', $column))
{
if (stripos($column, ' AS ') !== FALSE)
{
// Force 'AS' to uppercase
$column = str_ireplace(' AS ', ' AS ', $column);
// Runs escape_column on both sides of an AS statement
$column = array_map(array($this, __FUNCTION__), explode(' AS ', $column));
// Runs escape_column on both sides of an AS statement
$column = array_map(array($this, __FUNCTION__), explode(' AS ', $column));
// Re-create the AS statement
return implode(' AS ', $column);
}
// Re-create the AS statement
return implode(' AS ', $column);
}
return preg_replace('/[^.*]+/', '`$0`', $column);
}
return preg_replace('/[^.*]+/', '`$0`', $column);
}
$parts = explode(' ', $column);
$column = '';
$parts = explode(' ', $column);
$column = '';
for ($i = 0, $c = count($parts); $i < $c; $i++) {
// The column is always last
if ($i == ($c - 1)) {
$column .= preg_replace('/[^.*]+/', '`$0`', $parts[$i]);
} else // otherwise, it's a modifier
{
$column .= $parts[$i] . ' ';
}
}
return $column;
}
for ($i = 0, $c = count($parts); $i < $c; $i++)
{
// The column is always last
if ($i == ($c - 1))
{
$column .= preg_replace('/[^.*]+/', '`$0`', $parts[$i]);
}
else // otherwise, it's a modifier
{
$column .= $parts[$i].' ';
}
}
return $column;
}
public function limit($limit, $offset = 0)
{
return 'LIMIT ' . $offset . ', ' . $limit;
}
public function limit($limit, $offset = 0)
{
return 'LIMIT '.$offset.', '.$limit;
}
public function compile_select($database)
{
$sql = ($database['distinct'] == true) ? 'SELECT DISTINCT ' : 'SELECT ';
$sql .= (count($database['select']) > 0) ? implode(', ', $database['select']) : '*';
public function compile_select($database)
{
$sql = ($database['distinct'] == TRUE) ? 'SELECT DISTINCT ' : 'SELECT ';
$sql .= (count($database['select']) > 0) ? implode(', ', $database['select']) : '*';
if (count($database['from']) > 0) {
$sql .= "\nFROM ";
$sql .= implode(', ', $database['from']);
}
if (count($database['from']) > 0)
{
$sql .= "\nFROM ";
$sql .= implode(', ', $database['from']);
}
if (count($database['join']) > 0) {
foreach ($database['join'] as $join) {
$sql .= "\n" . $join['type'] . 'JOIN ' . implode(', ', $join['tables']) . ' ON ' . $join['conditions'];
}
}
if (count($database['join']) > 0)
{
foreach($database['join'] AS $join)
{
$sql .= "\n".$join['type'].'JOIN '.implode(', ', $join['tables']).' ON '.$join['conditions'];
}
}
if (count($database['where']) > 0) {
$sql .= "\nWHERE ";
}
if (count($database['where']) > 0)
{
$sql .= "\nWHERE ";
}
$sql .= implode("\n", $database['where']);
$sql .= implode("\n", $database['where']);
if (count($database['groupby']) > 0) {
$sql .= "\nGROUP BY ";
$sql .= implode(', ', $database['groupby']);
}
if (count($database['groupby']) > 0)
{
$sql .= "\nGROUP BY ";
$sql .= implode(', ', $database['groupby']);
}
if (count($database['having']) > 0) {
$sql .= "\nHAVING ";
$sql .= implode("\n", $database['having']);
}
if (count($database['having']) > 0)
{
$sql .= "\nHAVING ";
$sql .= implode("\n", $database['having']);
}
if (count($database['orderby']) > 0) {
$sql .= "\nORDER BY ";
$sql .= implode(', ', $database['orderby']);
}
if (count($database['orderby']) > 0)
{
$sql .= "\nORDER BY ";
$sql .= implode(', ', $database['orderby']);
}
if (is_numeric($database['limit'])) {
$sql .= "\n";
$sql .= $this->limit($database['limit'], $database['offset']);
}
if (is_numeric($database['limit']))
{
$sql .= "\n";
$sql .= $this->limit($database['limit'], $database['offset']);
}
return $sql;
}
return $sql;
}
public function escape_str($str)
{
if (! $this->db_config['escape']) {
return $str;
}
public function escape_str($str)
{
if ( ! $this->db_config['escape'])
return $str;
if (function_exists('sqlite_escape_string')) {
$res = sqlite_escape_string($str);
} else {
$res = str_replace("'", "''", $str);
}
return $res;
}
if (function_exists('sqlite_escape_string'))
{
$res = sqlite_escape_string($str);
}
else
{
$res = str_replace("'", "''", $str);
}
return $res;
}
public function list_tables()
{
$sql = "SELECT `name` FROM `sqlite_master` WHERE `type`='table' ORDER BY `name`;";
try {
$result = $this->query($sql)->result(false, PDO::FETCH_ASSOC);
$tables = array();
foreach ($result as $row) {
$tables[] = current($row);
}
} catch (PDOException $e) {
throw new Kohana_Database_Exception('database.error', $e->getMessage());
}
return $tables;
}
public function list_tables()
{
$sql = "SELECT `name` FROM `sqlite_master` WHERE `type`='table' ORDER BY `name`;";
try
{
$result = $this->query($sql)->result(FALSE, PDO::FETCH_ASSOC);
$tables = array();
foreach ($result as $row)
{
$tables[] = current($row);
}
}
catch (PDOException $e)
{
throw new Kohana_Database_Exception('database.error', $e->getMessage());
}
return $tables;
}
public function show_error()
{
$err = $this->link->errorInfo();
return isset($err[2]) ? $err[2] : 'Unknown error!';
}
public function show_error()
{
$err = $this->link->errorInfo();
return isset($err[2]) ? $err[2] : 'Unknown error!';
}
public function list_fields($table, $query = false)
{
static $tables;
if (is_object($query)) {
if (empty($tables[$table])) {
$tables[$table] = array();
public function list_fields($table, $query = FALSE)
{
static $tables;
if (is_object($query))
{
if (empty($tables[$table]))
{
$tables[$table] = array();
foreach ($query->result() as $row) {
$tables[$table][] = $row->name;
}
}
foreach ($query->result() as $row)
{
$tables[$table][] = $row->name;
}
}
return $tables[$table];
} else {
$result = $this->link->query('PRAGMA table_info(' . $this->escape_table($table) . ')');
return $tables[$table];
}
else
{
$result = $this->link->query( 'PRAGMA table_info('.$this->escape_table($table).')' );
foreach ($result as $row) {
$tables[$table][$row['name']] = $this->sql_type($row['type']);
}
foreach ($result as $row)
{
$tables[$table][$row['name']] = $this->sql_type($row['type']);
}
return $tables[$table];
}
}
return $tables[$table];
}
}
public function field_data($table)
{
Kohana::log('error', 'This method is under developing');
}
/**
* Version number query string
*
* @access public
* @return string
*/
function version()
{
return $this->link->getAttribute(constant("PDO::ATTR_SERVER_VERSION"));
}
} // End Database_PdoSqlite_Driver Class
public function field_data($table)
{
Kohana::log('error', 'This method is under developing');
}
/**
* Version number query string
*
* @access public
* @return string
*/
public function version()
{
return $this->link->getAttribute(constant("PDO::ATTR_SERVER_VERSION"));
}
}
// End Database_PdoSqlite_Driver Class
/*
* PDO-sqlite Result
*/
class Pdosqlite_Result extends Database_Result {
class Pdosqlite_Result extends Database_Result
{
// Data fetching types
protected $fetch_type = PDO::FETCH_OBJ;
protected $return_type = PDO::FETCH_ASSOC;
// Data fetching types
protected $fetch_type = PDO::FETCH_OBJ;
protected $return_type = PDO::FETCH_ASSOC;
/**
* Sets up the result variables.
*
* @param resource query result
* @param resource database link
* @param boolean return objects or arrays
* @param string SQL query that was run
*/
public function __construct($result, $link, $object = true, $sql = '')
{
if (is_object($result) or $result = $link->prepare($sql)) {
// run the query. Return true if success, false otherwise
if (! $result->execute()) {
// Throw Kohana Exception with error message. See PDOStatement errorInfo() method
$arr_infos = $result->errorInfo();
throw new Kohana_Database_Exception('database.error', $arr_infos[2]);
}
/**
* Sets up the result variables.
*
* @param resource query result
* @param resource database link
* @param boolean return objects or arrays
* @param string SQL query that was run
*/
public function __construct($result, $link, $object = TRUE, $sql)
{
if (is_object($result) OR $result = $link->prepare($sql))
{
// run the query. Return true if success, false otherwise
if( ! $result->execute())
{
// Throw Kohana Exception with error message. See PDOStatement errorInfo() method
$arr_infos = $result->errorInfo();
throw new Kohana_Database_Exception('database.error', $arr_infos[2]);
}
if (preg_match('/^SELECT|PRAGMA|EXPLAIN/i', $sql)) {
$this->result = $result;
$this->current_row = 0;
if (preg_match('/^SELECT|PRAGMA|EXPLAIN/i', $sql))
{
$this->result = $result;
$this->current_row = 0;
$this->total_rows = $this->sqlite_row_count();
$this->total_rows = $this->sqlite_row_count();
$this->fetch_type = ($object === true) ? PDO::FETCH_OBJ : PDO::FETCH_ASSOC;
} elseif (preg_match('/^DELETE|INSERT|UPDATE/i', $sql)) {
$this->insert_id = $link->lastInsertId();
$this->fetch_type = ($object === TRUE) ? PDO::FETCH_OBJ : PDO::FETCH_ASSOC;
}
elseif (preg_match('/^DELETE|INSERT|UPDATE/i', $sql))
{
$this->insert_id = $link->lastInsertId();
$this->total_rows = $result->rowCount();
}
} else {
// SQL error
throw new Kohana_Database_Exception('database.error', $link->errorInfo() . ' - ' . $sql);
}
$this->total_rows = $result->rowCount();
}
}
else
{
// SQL error
throw new Kohana_Database_Exception('database.error', $link->errorInfo().' - '.$sql);
}
// Set result type
$this->result($object);
// Set result type
$this->result($object);
// Store the SQL
$this->sql = $sql;
}
// Store the SQL
$this->sql = $sql;
}
private function sqlite_row_count()
{
$count = 0;
while ($this->result->fetch()) {
$count++;
}
private function sqlite_row_count()
{
$count = 0;
while ($this->result->fetch())
{
$count++;
}
// The query must be re-fetched now.
$this->result->execute();
// The query must be re-fetched now.
$this->result->execute();
return $count;
}
return $count;
}
/*
* Destructor: __destruct
* Magic __destruct function, frees the result.
*/
public function __destruct()
{
if (is_object($this->result)) {
$this->result->closeCursor();
$this->result = null;
}
}
/*
* Destructor: __destruct
* Magic __destruct function, frees the result.
*/
public function __destruct()
{
if (is_object($this->result))
{
$this->result->closeCursor();
$this->result = NULL;
}
}
public function result($object = true, $type = PDO::FETCH_BOTH)
{
$this->fetch_type = (bool) $object ? PDO::FETCH_OBJ : PDO::FETCH_BOTH;
public function result($object = TRUE, $type = PDO::FETCH_BOTH)
{
$this->fetch_type = (bool) $object ? PDO::FETCH_OBJ : PDO::FETCH_BOTH;
if ($this->fetch_type == PDO::FETCH_OBJ) {
$this->return_type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
} else {
$this->return_type = $type;
}
if ($this->fetch_type == PDO::FETCH_OBJ)
{
$this->return_type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
}
else
{
$this->return_type = $type;
}
return $this;
}
return $this;
}
public function as_array($object = null, $type = PDO::FETCH_ASSOC)
{
return $this->result_array($object, $type);
}
public function as_array($object = NULL, $type = PDO::FETCH_ASSOC)
{
return $this->result_array($object, $type);
}
public function result_array($object = null, $type = PDO::FETCH_ASSOC)
{
$rows = array();
public function result_array($object = NULL, $type = PDO::FETCH_ASSOC)
{
$rows = array();
if (is_string($object)) {
$fetch = $object;
} elseif (is_bool($object)) {
if ($object === true) {
$fetch = PDO::FETCH_OBJ;
if (is_string($object))
{
$fetch = $object;
}
elseif (is_bool($object))
{
if ($object === TRUE)
{
$fetch = PDO::FETCH_OBJ;
// NOTE - The class set by $type must be defined before fetching the result,
// autoloading is disabled to save a lot of stupid overhead.
$type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
} else {
$fetch = PDO::FETCH_OBJ;
}
} else {
// Use the default config values
$fetch = $this->fetch_type;
// NOTE - The class set by $type must be defined before fetching the result,
// autoloading is disabled to save a lot of stupid overhead.
$type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
}
else
{
$fetch = PDO::FETCH_OBJ;
}
}
else
{
// Use the default config values
$fetch = $this->fetch_type;
if ($fetch == PDO::FETCH_OBJ) {
$type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
}
}
try {
while ($row = $this->result->fetch($fetch)) {
$rows[] = $row;
}
} catch (PDOException $e) {
throw new Kohana_Database_Exception('database.error', $e->getMessage());
return false;
}
return $rows;
}
if ($fetch == PDO::FETCH_OBJ)
{
$type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
}
}
try
{
while ($row = $this->result->fetch($fetch))
{
$rows[] = $row;
}
}
catch(PDOException $e)
{
throw new Kohana_Database_Exception('database.error', $e->getMessage());
return FALSE;
}
return $rows;
}
public function list_fields()
{
$field_names = array();
for ($i = 0, $max = $this->result->columnCount(); $i < $max; $i++) {
$info = $this->result->getColumnMeta($i);
$field_names[] = $info['name'];
}
return $field_names;
}
public function list_fields()
{
$field_names = array();
for ($i = 0, $max = $this->result->columnCount(); $i < $max; $i++)
{
$info = $this->result->getColumnMeta($i);
$field_names[] = $info['name'];
}
return $field_names;
}
public function seek($offset)
{
// To request a scrollable cursor for your PDOStatement object, you must
// set the PDO::ATTR_CURSOR attribute to PDO::CURSOR_SCROLL when you
// prepare the statement.
Kohana::log('error', get_class($this) . ' does not support scrollable cursors, ' . __FUNCTION__ . ' call ignored');
public function seek($offset)
{
// To request a scrollable cursor for your PDOStatement object, you must
// set the PDO::ATTR_CURSOR attribute to PDO::CURSOR_SCROLL when you
// prepare the statement.
Kohana::log('error', get_class($this).' does not support scrollable cursors, '.__FUNCTION__.' call ignored');
return false;
}
return FALSE;
}
public function offsetGet($offset)
{
try {
return $this->result->fetch($this->fetch_type, PDO::FETCH_ORI_ABS, $offset);
} catch (PDOException $e) {
throw new Kohana_Database_Exception('database.error', $e->getMessage());
}
}
public function offsetGet($offset)
{
try
{
return $this->result->fetch($this->fetch_type, PDO::FETCH_ORI_ABS, $offset);
}
catch(PDOException $e)
{
throw new Kohana_Database_Exception('database.error', $e->getMessage());
}
}
public function rewind()
{
// Same problem that seek() has, see above.
return $this->seek(0);
}
} // End PdoSqlite_Result Class
public function rewind()
{
// Same problem that seek() has, see above.
return $this->seek(0);
}
}
// End PdoSqlite_Result Class

View File

@@ -1,4 +1,13 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Classes.ClassDeclaration.MultipleClasses
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* PostgreSQL 8.1+ Database Driver
*
@@ -9,530 +18,486 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Database_Pgsql_Driver extends Database_Driver {
class Database_Pgsql_Driver extends Database_Driver
{
// Database connection link
protected $link;
protected $db_config;
// Database connection link
protected $link;
protected $db_config;
/**
* Sets the config for the class.
*
* @param array database configuration
*/
public function __construct($config)
{
$this->db_config = $config;
/**
* Sets the config for the class.
*
* @param array database configuration
*/
public function __construct($config)
{
$this->db_config = $config;
Kohana::log('debug', 'PgSQL Database Driver Initialized');
}
Kohana::log('debug', 'PgSQL Database Driver Initialized');
}
public function connect()
{
// Check if link already exists
if (is_resource($this->link)) {
return $this->link;
}
public function connect()
{
// Check if link already exists
if (is_resource($this->link))
return $this->link;
// Import the connect variables
extract($this->db_config['connection']);
// Import the connect variables
extract($this->db_config['connection']);
// Persistent connections enabled?
$connect = ($this->db_config['persistent'] == true) ? 'pg_pconnect' : 'pg_connect';
// Persistent connections enabled?
$connect = ($this->db_config['persistent'] == TRUE) ? 'pg_pconnect' : 'pg_connect';
// Build the connection info
$port = isset($port) ? 'port=\'' . $port . '\'' : '';
$host = isset($host) ? 'host=\'' . $host . '\' ' . $port : ''; // if no host, connect with the socket
// Build the connection info
$port = isset($port) ? 'port=\''.$port.'\'' : '';
$host = isset($host) ? 'host=\''.$host.'\' '.$port : ''; // if no host, connect with the socket
$connection_string = $host . ' dbname=\'' . $database . '\' user=\'' . $user . '\' password=\'' . $pass . '\'';
// Make the connection and select the database
if ($this->link = $connect($connection_string)) {
if ($charset = $this->db_config['character_set']) {
echo $this->set_charset($charset);
}
$connection_string = $host.' dbname=\''.$database.'\' user=\''.$user.'\' password=\''.$pass.'\'';
// Make the connection and select the database
if ($this->link = $connect($connection_string))
{
if ($charset = $this->db_config['character_set'])
{
echo $this->set_charset($charset);
}
// Clear password after successful connect
$this->db_config['connection']['pass'] = null;
// Clear password after successful connect
$this->db_config['connection']['pass'] = NULL;
return $this->link;
}
return $this->link;
}
return false;
}
return FALSE;
}
public function query($sql)
{
// Only cache if it's turned on, and only cache if it's not a write statement
if ($this->db_config['cache'] and ! preg_match('#\b(?:INSERT|UPDATE|SET)\b#i', $sql)) {
$hash = $this->query_hash($sql);
public function query($sql)
{
// Only cache if it's turned on, and only cache if it's not a write statement
if ($this->db_config['cache'] AND ! preg_match('#\b(?:INSERT|UPDATE|SET)\b#i', $sql))
{
$hash = $this->query_hash($sql);
if (! isset($this->query_cache[$hash])) {
// Set the cached object
$this->query_cache[$hash] = new Pgsql_Result(pg_query($this->link, $sql), $this->link, $this->db_config['object'], $sql);
} else {
// Rewind cached result
$this->query_cache[$hash]->rewind();
}
if ( ! isset($this->query_cache[$hash]))
{
// Set the cached object
$this->query_cache[$hash] = new Pgsql_Result(pg_query($this->link, $sql), $this->link, $this->db_config['object'], $sql);
}
else
{
// Rewind cached result
$this->query_cache[$hash]->rewind();
}
return $this->query_cache[$hash];
}
return $this->query_cache[$hash];
}
// Suppress warning triggered when a database error occurs (e.g., a constraint violation)
return new Pgsql_Result(@pg_query($this->link, $sql), $this->link, $this->db_config['object'], $sql);
}
// Suppress warning triggered when a database error occurs (e.g., a constraint violation)
return new Pgsql_Result(@pg_query($this->link, $sql), $this->link, $this->db_config['object'], $sql);
}
public function set_charset($charset)
{
$this->query('SET client_encoding TO ' . pg_escape_string($this->link, $charset));
}
public function set_charset($charset)
{
$this->query('SET client_encoding TO '.pg_escape_string($this->link, $charset));
}
public function escape_table($table)
{
if (!$this->db_config['escape']) {
return $table;
}
public function escape_table($table)
{
if (!$this->db_config['escape'])
return $table;
return '"' . str_replace('.', '"."', $table) . '"';
}
return '"'.str_replace('.', '"."', $table).'"';
}
public function escape_column($column)
{
if (!$this->db_config['escape']) {
return $column;
}
public function escape_column($column)
{
if (!$this->db_config['escape'])
return $column;
if ($column == '*') {
return $column;
}
if ($column == '*')
return $column;
// This matches any functions we support to SELECT.
if (preg_match('/(avg|count|sum|max|min)\(\s*(.*)\s*\)(\s*as\s*(.+)?)?/i', $column, $matches)) {
if (count($matches) == 3) {
return $matches[1] . '(' . $this->escape_column($matches[2]) . ')';
} elseif (count($matches) == 5) {
return $matches[1] . '(' . $this->escape_column($matches[2]) . ') AS ' . $this->escape_column($matches[2]);
}
}
// This matches any functions we support to SELECT.
if ( preg_match('/(avg|count|sum|max|min)\(\s*(.*)\s*\)(\s*as\s*(.+)?)?/i', $column, $matches))
{
if ( count($matches) == 3)
{
return $matches[1].'('.$this->escape_column($matches[2]).')';
}
else if ( count($matches) == 5)
{
return $matches[1].'('.$this->escape_column($matches[2]).') AS '.$this->escape_column($matches[2]);
}
}
// This matches any modifiers we support to SELECT.
if (! preg_match('/\b(?:all|distinct)\s/i', $column)) {
if (stripos($column, ' AS ') !== false) {
// Force 'AS' to uppercase
$column = str_ireplace(' AS ', ' AS ', $column);
// This matches any modifiers we support to SELECT.
if ( ! preg_match('/\b(?:all|distinct)\s/i', $column))
{
if (stripos($column, ' AS ') !== FALSE)
{
// Force 'AS' to uppercase
$column = str_ireplace(' AS ', ' AS ', $column);
// Runs escape_column on both sides of an AS statement
$column = array_map(array($this, __FUNCTION__), explode(' AS ', $column));
// Runs escape_column on both sides of an AS statement
$column = array_map(array($this, __FUNCTION__), explode(' AS ', $column));
// Re-create the AS statement
return implode(' AS ', $column);
}
// Re-create the AS statement
return implode(' AS ', $column);
}
return preg_replace('/[^.*]+/', '"$0"', $column);
}
return preg_replace('/[^.*]+/', '"$0"', $column);
}
$parts = explode(' ', $column);
$column = '';
$parts = explode(' ', $column);
$column = '';
for ($i = 0, $c = count($parts); $i < $c; $i++) {
// The column is always last
if ($i == ($c - 1)) {
$column .= preg_replace('/[^.*]+/', '"$0"', $parts[$i]);
} else // otherwise, it's a modifier
{
$column .= $parts[$i] . ' ';
}
}
return $column;
}
for ($i = 0, $c = count($parts); $i < $c; $i++)
{
// The column is always last
if ($i == ($c - 1))
{
$column .= preg_replace('/[^.*]+/', '"$0"', $parts[$i]);
}
else // otherwise, it's a modifier
{
$column .= $parts[$i].' ';
}
}
return $column;
}
public function regex($field, $match, $type, $num_regexs)
{
$prefix = ($num_regexs == 0) ? '' : $type;
public function regex($field, $match, $type, $num_regexs)
{
$prefix = ($num_regexs == 0) ? '' : $type;
return $prefix . ' ' . $this->escape_column($field) . ' ~* \'' . $this->escape_str($match) . '\'';
}
return $prefix.' '.$this->escape_column($field).' ~* \''.$this->escape_str($match).'\'';
}
public function notregex($field, $match, $type, $num_regexs)
{
$prefix = $num_regexs == 0 ? '' : $type;
public function notregex($field, $match, $type, $num_regexs)
{
$prefix = $num_regexs == 0 ? '' : $type;
return $prefix . ' ' . $this->escape_column($field) . ' !~* \'' . $this->escape_str($match) . '\'';
}
return $prefix.' '.$this->escape_column($field).' !~* \''.$this->escape_str($match) . '\'';
}
public function limit($limit, $offset = 0)
{
return 'LIMIT ' . $limit . ' OFFSET ' . $offset;
}
public function limit($limit, $offset = 0)
{
return 'LIMIT '.$limit.' OFFSET '.$offset;
}
public function compile_select($database)
{
$sql = ($database['distinct'] == true) ? 'SELECT DISTINCT ' : 'SELECT ';
$sql .= (count($database['select']) > 0) ? implode(', ', $database['select']) : '*';
public function compile_select($database)
{
$sql = ($database['distinct'] == TRUE) ? 'SELECT DISTINCT ' : 'SELECT ';
$sql .= (count($database['select']) > 0) ? implode(', ', $database['select']) : '*';
if (count($database['from']) > 0) {
$sql .= "\nFROM ";
$sql .= implode(', ', $database['from']);
}
if (count($database['from']) > 0)
{
$sql .= "\nFROM ";
$sql .= implode(', ', $database['from']);
}
if (count($database['join']) > 0) {
foreach ($database['join'] as $join) {
$sql .= "\n" . $join['type'] . 'JOIN ' . implode(', ', $join['tables']) . ' ON ' . $join['conditions'];
}
}
if (count($database['join']) > 0)
{
foreach($database['join'] AS $join)
{
$sql .= "\n".$join['type'].'JOIN '.implode(', ', $join['tables']).' ON '.$join['conditions'];
}
}
if (count($database['where']) > 0) {
$sql .= "\nWHERE ";
}
if (count($database['where']) > 0)
{
$sql .= "\nWHERE ";
}
$sql .= implode("\n", $database['where']);
$sql .= implode("\n", $database['where']);
if (count($database['groupby']) > 0) {
$sql .= "\nGROUP BY ";
$sql .= implode(', ', $database['groupby']);
}
if (count($database['groupby']) > 0)
{
$sql .= "\nGROUP BY ";
$sql .= implode(', ', $database['groupby']);
}
if (count($database['having']) > 0) {
$sql .= "\nHAVING ";
$sql .= implode("\n", $database['having']);
}
if (count($database['having']) > 0)
{
$sql .= "\nHAVING ";
$sql .= implode("\n", $database['having']);
}
if (count($database['orderby']) > 0) {
$sql .= "\nORDER BY ";
$sql .= implode(', ', $database['orderby']);
}
if (count($database['orderby']) > 0)
{
$sql .= "\nORDER BY ";
$sql .= implode(', ', $database['orderby']);
}
if (is_numeric($database['limit'])) {
$sql .= "\n";
$sql .= $this->limit($database['limit'], $database['offset']);
}
if (is_numeric($database['limit']))
{
$sql .= "\n";
$sql .= $this->limit($database['limit'], $database['offset']);
}
return $sql;
}
return $sql;
}
public function escape_str($str)
{
if (!$this->db_config['escape']) {
return $str;
}
public function escape_str($str)
{
if (!$this->db_config['escape'])
return $str;
is_resource($this->link) or $this->connect();
is_resource($this->link) or $this->connect();
return pg_escape_string($this->link, $str);
}
return pg_escape_string($this->link, $str);
}
public function list_tables()
{
$sql = 'SELECT table_schema || \'.\' || table_name FROM information_schema.tables WHERE table_schema NOT IN (\'pg_catalog\', \'information_schema\')';
$result = $this->query($sql)->result(false, PGSQL_ASSOC);
public function list_tables()
{
$sql = 'SELECT table_schema || \'.\' || table_name FROM information_schema.tables WHERE table_schema NOT IN (\'pg_catalog\', \'information_schema\')';
$result = $this->query($sql)->result(FALSE, PGSQL_ASSOC);
$retval = array();
foreach ($result as $row) {
$retval[] = current($row);
}
$retval = array();
foreach ($result as $row)
{
$retval[] = current($row);
}
return $retval;
}
return $retval;
}
public function show_error()
{
return pg_last_error($this->link);
}
public function show_error()
{
return pg_last_error($this->link);
}
public function list_fields($table)
{
$result = null;
public function list_fields($table)
{
$result = NULL;
foreach ($this->field_data($table) as $row) {
// Make an associative array
$result[$row->column_name] = $this->sql_type($row->data_type);
foreach ($this->field_data($table) as $row)
{
// Make an associative array
$result[$row->column_name] = $this->sql_type($row->data_type);
if (!strncmp($row->column_default, 'nextval(', 8)) {
$result[$row->column_name]['sequenced'] = true;
}
if (!strncmp($row->column_default, 'nextval(', 8))
{
$result[$row->column_name]['sequenced'] = TRUE;
}
if ($row->is_nullable === 'YES') {
$result[$row->column_name]['null'] = true;
}
}
if ($row->is_nullable === 'YES')
{
$result[$row->column_name]['null'] = TRUE;
}
}
if (!isset($result)) {
throw new Kohana_Database_Exception('database.table_not_found', $table);
}
if (!isset($result))
throw new Kohana_Database_Exception('database.table_not_found', $table);
return $result;
}
return $result;
}
public function field_data($table)
{
// http://www.postgresql.org/docs/8.3/static/infoschema-columns.html
$result = $this->query('
public function field_data($table)
{
// http://www.postgresql.org/docs/8.3/static/infoschema-columns.html
$result = $this->query('
SELECT column_name, column_default, is_nullable, data_type, udt_name,
character_maximum_length, numeric_precision, numeric_precision_radix, numeric_scale
FROM information_schema.columns
WHERE table_name = \''. $this->escape_str($table) .'\'
WHERE table_name = \'' . $this->escape_str($table) . '\'
ORDER BY ordinal_position
');
return $result->result_array(TRUE);
}
} // End Database_Pgsql_Driver Class
return $result->result_array(true);
}
}
// End Database_Pgsql_Driver Class
/**
* PostgreSQL Result
*/
class Pgsql_Result extends Database_Result {
class Pgsql_Result extends Database_Result
{
// Data fetching types
protected $fetch_type = 'pgsql_fetch_object';
protected $return_type = PGSQL_ASSOC;
// Data fetching types
protected $fetch_type = 'pgsql_fetch_object';
protected $return_type = PGSQL_ASSOC;
/**
* Sets up the result variables.
*
* @param resource query result
* @param resource database link
* @param boolean return objects or arrays
* @param string SQL query that was run
*/
public function __construct($result, $link, $object = true, $sql = '')
{
$this->link = $link;
$this->result = $result;
/**
* Sets up the result variables.
*
* @param resource query result
* @param resource database link
* @param boolean return objects or arrays
* @param string SQL query that was run
*/
public function __construct($result, $link, $object = TRUE, $sql)
{
$this->link = $link;
$this->result = $result;
// If the query is a resource, it was a SELECT, SHOW, DESCRIBE, EXPLAIN query
if (is_resource($result)) {
// Its an DELETE, INSERT, REPLACE, or UPDATE query
if (preg_match('/^(?:delete|insert|replace|update)\b/iD', trim($sql), $matches)) {
$this->insert_id = (strtolower($matches[0]) == 'insert') ? $this->insert_id() : false;
$this->total_rows = pg_affected_rows($this->result);
} else {
$this->current_row = 0;
$this->total_rows = pg_num_rows($this->result);
$this->fetch_type = ($object === true) ? 'pg_fetch_object' : 'pg_fetch_array';
}
} else {
throw new Kohana_Database_Exception('database.error', pg_last_error() . ' - ' . $sql);
}
// If the query is a resource, it was a SELECT, SHOW, DESCRIBE, EXPLAIN query
if (is_resource($result))
{
// Its an DELETE, INSERT, REPLACE, or UPDATE query
if (preg_match('/^(?:delete|insert|replace|update)\b/iD', trim($sql), $matches))
{
$this->insert_id = (strtolower($matches[0]) == 'insert') ? $this->insert_id() : FALSE;
$this->total_rows = pg_affected_rows($this->result);
}
else
{
$this->current_row = 0;
$this->total_rows = pg_num_rows($this->result);
$this->fetch_type = ($object === TRUE) ? 'pg_fetch_object' : 'pg_fetch_array';
}
}
else
{
throw new Kohana_Database_Exception('database.error', pg_last_error().' - '.$sql);
}
// Set result type
$this->result($object);
// Set result type
$this->result($object);
// Store the SQL
$this->sql = $sql;
}
// Store the SQL
$this->sql = $sql;
}
/**
* Magic __destruct function, frees the result.
*/
public function __destruct()
{
if (is_resource($this->result)) {
pg_free_result($this->result);
}
}
/**
* Magic __destruct function, frees the result.
*/
public function __destruct()
{
if (is_resource($this->result))
{
pg_free_result($this->result);
}
}
public function result($object = true, $type = PGSQL_ASSOC)
{
$this->fetch_type = ((bool) $object) ? 'pg_fetch_object' : 'pg_fetch_array';
public function result($object = TRUE, $type = PGSQL_ASSOC)
{
$this->fetch_type = ((bool) $object) ? 'pg_fetch_object' : 'pg_fetch_array';
// This check has to be outside the previous statement, because we do not
// know the state of fetch_type when $object = NULL
// NOTE - The class set by $type must be defined before fetching the result,
// autoloading is disabled to save a lot of stupid overhead.
if ($this->fetch_type == 'pg_fetch_object') {
$this->return_type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
} else {
$this->return_type = $type;
}
// This check has to be outside the previous statement, because we do not
// know the state of fetch_type when $object = NULL
// NOTE - The class set by $type must be defined before fetching the result,
// autoloading is disabled to save a lot of stupid overhead.
if ($this->fetch_type == 'pg_fetch_object')
{
$this->return_type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
}
else
{
$this->return_type = $type;
}
return $this;
}
return $this;
}
public function as_array($object = null, $type = PGSQL_ASSOC)
{
return $this->result_array($object, $type);
}
public function as_array($object = NULL, $type = PGSQL_ASSOC)
{
return $this->result_array($object, $type);
}
public function result_array($object = null, $type = PGSQL_ASSOC)
{
$rows = array();
public function result_array($object = NULL, $type = PGSQL_ASSOC)
{
$rows = array();
if (is_string($object)) {
$fetch = $object;
} elseif (is_bool($object)) {
if ($object === true) {
$fetch = 'pg_fetch_object';
if (is_string($object))
{
$fetch = $object;
}
elseif (is_bool($object))
{
if ($object === TRUE)
{
$fetch = 'pg_fetch_object';
// NOTE - The class set by $type must be defined before fetching the result,
// autoloading is disabled to save a lot of stupid overhead.
$type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
} else {
$fetch = 'pg_fetch_array';
}
} else {
// Use the default config values
$fetch = $this->fetch_type;
// NOTE - The class set by $type must be defined before fetching the result,
// autoloading is disabled to save a lot of stupid overhead.
$type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
}
else
{
$fetch = 'pg_fetch_array';
}
}
else
{
// Use the default config values
$fetch = $this->fetch_type;
if ($fetch == 'pg_fetch_object') {
$type = (is_string($type) and Kohana::auto_load($type)) ? $type : 'stdClass';
}
}
if ($fetch == 'pg_fetch_object')
{
$type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
}
}
if ($this->total_rows) {
pg_result_seek($this->result, 0);
if ($this->total_rows)
{
pg_result_seek($this->result, 0);
while ($row = $fetch($this->result, null, $type)) {
$rows[] = $row;
}
}
while ($row = $fetch($this->result, NULL, $type))
{
$rows[] = $row;
}
}
return $rows;
}
return $rows;
}
public function insert_id()
{
if ($this->insert_id === null) {
$query = 'SELECT LASTVAL() AS insert_id';
public function insert_id()
{
if ($this->insert_id === NULL)
{
$query = 'SELECT LASTVAL() AS insert_id';
// Disable error reporting for this, just to silence errors on
// tables that have no serial column.
$ER = error_reporting(0);
// Disable error reporting for this, just to silence errors on
// tables that have no serial column.
$ER = error_reporting(0);
$result = pg_query($this->link, $query);
$insert_id = pg_fetch_array($result, null, PGSQL_ASSOC);
$result = pg_query($this->link, $query);
$insert_id = pg_fetch_array($result, NULL, PGSQL_ASSOC);
$this->insert_id = $insert_id['insert_id'];
$this->insert_id = $insert_id['insert_id'];
// Reset error reporting
error_reporting($ER);
}
// Reset error reporting
error_reporting($ER);
}
return $this->insert_id;
}
return $this->insert_id;
}
public function seek($offset)
{
if ($this->offsetExists($offset) and pg_result_seek($this->result, $offset)) {
// Set the current row to the offset
$this->current_row = $offset;
public function seek($offset)
{
if ($this->offsetExists($offset) AND pg_result_seek($this->result, $offset))
{
// Set the current row to the offset
$this->current_row = $offset;
return true;
}
return TRUE;
}
return false;
}
return FALSE;
}
public function list_fields()
{
$field_names = array();
public function list_fields()
{
$field_names = array();
$fields = pg_num_fields($this->result);
for ($i = 0; $i < $fields; ++$i) {
$field_names[] = pg_field_name($this->result, $i);
}
$fields = pg_num_fields($this->result);
for ($i = 0; $i < $fields; ++$i)
{
$field_names[] = pg_field_name($this->result, $i);
}
return $field_names;
}
return $field_names;
}
/**
* ArrayAccess: offsetGet
*/
public function offsetGet($offset)
{
if (! $this->seek($offset)) {
return false;
}
/**
* ArrayAccess: offsetGet
*/
public function offsetGet($offset)
{
if ( ! $this->seek($offset))
return FALSE;
// Return the row by calling the defined fetching callback
$fetch = $this->fetch_type;
return $fetch($this->result, NULL, $this->return_type);
}
} // End Pgsql_Result Class
// Return the row by calling the defined fetching callback
$fetch = $this->fetch_type;
return $fetch($this->result, null, $this->return_type);
}
}
// End Pgsql_Result Class
/**
* PostgreSQL Prepared Statement (experimental)
*/
class Kohana_Pgsql_Statement {
class Kohana_Pgsql_Statement
{
protected $link = null;
protected $stmt;
protected $link = NULL;
protected $stmt;
public function __construct($sql, $link)
{
$this->link = $link;
public function __construct($sql, $link)
{
$this->link = $link;
$this->stmt = $this->link->prepare($sql);
$this->stmt = $this->link->prepare($sql);
return $this;
}
return $this;
}
public function __destruct()
{
$this->stmt->close();
}
public function __destruct()
{
$this->stmt->close();
}
// Sets the bind parameters
public function bind_params()
{
$argv = func_get_args();
return $this;
}
// Sets the bind parameters
public function bind_params()
{
$argv = func_get_args();
return $this;
}
// sets the statement values to the bound parameters
public function set_vals()
{
return $this;
}
// sets the statement values to the bound parameters
public function set_vals()
{
return $this;
}
// Runs the statement
public function execute()
{
return $this;
}
// Runs the statement
public function execute()
{
return $this;
}
}

View File

@@ -1,4 +1,12 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* Image API driver.
*
@@ -9,141 +17,131 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
abstract class Image_Driver {
abstract class Image_Driver
{
// Reference to the current image
protected $image;
// Reference to the current image
protected $image;
// Reference to the temporary processing image
protected $tmp_image;
// Reference to the temporary processing image
protected $tmp_image;
// Processing errors
protected $errors = array();
// Processing errors
protected $errors = array();
/**
* Executes a set of actions, defined in pairs.
*
* @param array actions
* @return boolean
*/
public function execute($actions)
{
foreach ($actions as $func => $args) {
if (! $this->$func($args)) {
return false;
}
}
/**
* Executes a set of actions, defined in pairs.
*
* @param array actions
* @return boolean
*/
public function execute($actions)
{
foreach ($actions as $func => $args)
{
if ( ! $this->$func($args))
return FALSE;
}
return true;
}
return TRUE;
}
/**
* Sanitize and normalize a geometry array based on the temporary image
* width and height. Valid properties are: width, height, top, left.
*
* @param array geometry properties
* @return void
*/
protected function sanitize_geometry(&$geometry)
{
list($width, $height) = $this->properties();
/**
* Sanitize and normalize a geometry array based on the temporary image
* width and height. Valid properties are: width, height, top, left.
*
* @param array geometry properties
* @return void
*/
protected function sanitize_geometry( & $geometry)
{
list($width, $height) = $this->properties();
// Turn off error reporting
$reporting = error_reporting(0);
// Turn off error reporting
$reporting = error_reporting(0);
// Width and height cannot exceed current image size
$geometry['width'] = min($geometry['width'], $width);
$geometry['height'] = min($geometry['height'], $height);
// Width and height cannot exceed current image size
$geometry['width'] = min($geometry['width'], $width);
$geometry['height'] = min($geometry['height'], $height);
// Set standard coordinates if given, otherwise use pixel values
if ($geometry['top'] === 'center') {
$geometry['top'] = floor(($height / 2) - ($geometry['height'] / 2));
} elseif ($geometry['top'] === 'top') {
$geometry['top'] = 0;
} elseif ($geometry['top'] === 'bottom') {
$geometry['top'] = $height - $geometry['height'];
}
// Set standard coordinates if given, otherwise use pixel values
if ($geometry['top'] === 'center')
{
$geometry['top'] = floor(($height / 2) - ($geometry['height'] / 2));
}
elseif ($geometry['top'] === 'top')
{
$geometry['top'] = 0;
}
elseif ($geometry['top'] === 'bottom')
{
$geometry['top'] = $height - $geometry['height'];
}
// Set standard coordinates if given, otherwise use pixel values
if ($geometry['left'] === 'center') {
$geometry['left'] = floor(($width / 2) - ($geometry['width'] / 2));
} elseif ($geometry['left'] === 'left') {
$geometry['left'] = 0;
} elseif ($geometry['left'] === 'right') {
$geometry['left'] = $width - $geometry['height'];
}
// Set standard coordinates if given, otherwise use pixel values
if ($geometry['left'] === 'center')
{
$geometry['left'] = floor(($width / 2) - ($geometry['width'] / 2));
}
elseif ($geometry['left'] === 'left')
{
$geometry['left'] = 0;
}
elseif ($geometry['left'] === 'right')
{
$geometry['left'] = $width - $geometry['height'];
}
// Restore error reporting
error_reporting($reporting);
}
// Restore error reporting
error_reporting($reporting);
}
/**
* Return the current width and height of the temporary image. This is mainly
* needed for sanitizing the geometry.
*
* @return array width, height
*/
abstract protected function properties();
/**
* Return the current width and height of the temporary image. This is mainly
* needed for sanitizing the geometry.
*
* @return array width, height
*/
abstract protected function properties();
/**
* Process an image with a set of actions.
*
* @param string image filename
* @param array actions to execute
* @param string destination directory path
* @param string destination filename
* @return boolean
*/
abstract public function process($image, $actions, $dir, $file);
/**
* Process an image with a set of actions.
*
* @param string image filename
* @param array actions to execute
* @param string destination directory path
* @param string destination filename
* @return boolean
*/
abstract public function process($image, $actions, $dir, $file);
/**
* Flip an image. Valid directions are horizontal and vertical.
*
* @param integer direction to flip
* @return boolean
*/
abstract public function flip($direction);
/**
* Flip an image. Valid directions are horizontal and vertical.
*
* @param integer direction to flip
* @return boolean
*/
abstract function flip($direction);
/**
* Crop an image. Valid properties are: width, height, top, left.
*
* @param array new properties
* @return boolean
*/
abstract public function crop($properties);
/**
* Crop an image. Valid properties are: width, height, top, left.
*
* @param array new properties
* @return boolean
*/
abstract function crop($properties);
/**
* Resize an image. Valid properties are: width, height, and master.
*
* @param array new properties
* @return boolean
*/
abstract public function resize($properties);
/**
* Resize an image. Valid properties are: width, height, and master.
*
* @param array new properties
* @return boolean
*/
abstract public function resize($properties);
/**
* Rotate an image. Valid amounts are -180 to 180.
*
* @param integer amount to rotate
* @return boolean
*/
abstract public function rotate($amount);
/**
* Rotate an image. Valid amounts are -180 to 180.
*
* @param integer amount to rotate
* @return boolean
*/
abstract public function rotate($amount);
/**
* Sharpen and image. Valid amounts are 1 to 100.
*
* @param integer amount to sharpen
* @return boolean
*/
abstract public function sharpen($amount);
} // End Image Driver
/**
* Sharpen and image. Valid amounts are 1 to 100.
*
* @param integer amount to sharpen
* @return boolean
*/
abstract public function sharpen($amount);
}
// End Image Driver

View File

@@ -1,4 +1,12 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* GD Image Driver.
*
@@ -9,371 +17,347 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Image_GD_Driver extends Image_Driver {
class Image_GD_Driver extends Image_Driver
{
// A transparent PNG as a string
protected static $blank_png;
protected static $blank_png_width;
protected static $blank_png_height;
// A transparent PNG as a string
protected static $blank_png;
protected static $blank_png_width;
protected static $blank_png_height;
public function __construct()
{
// Make sure that GD2 is available
if (! function_exists('gd_info')) {
throw new Kohana_Exception('image.gd.requires_v2');
}
public function __construct()
{
// Make sure that GD2 is available
if ( ! function_exists('gd_info'))
throw new Kohana_Exception('image.gd.requires_v2');
// Get the GD information
$info = gd_info();
// Get the GD information
$info = gd_info();
// Make sure that the GD2 is installed
if (strpos($info['GD Version'], '2.') === false) {
throw new Kohana_Exception('image.gd.requires_v2');
}
}
// Make sure that the GD2 is installed
if (strpos($info['GD Version'], '2.') === FALSE)
throw new Kohana_Exception('image.gd.requires_v2');
}
public function process($image, $actions, $dir, $file, $render = false)
{
// Set the "create" function
switch ($image['type']) {
case IMAGETYPE_JPEG:
$create = 'imagecreatefromjpeg';
break;
case IMAGETYPE_GIF:
$create = 'imagecreatefromgif';
break;
case IMAGETYPE_PNG:
$create = 'imagecreatefrompng';
break;
}
public function process($image, $actions, $dir, $file, $render = FALSE)
{
// Set the "create" function
switch ($image['type'])
{
case IMAGETYPE_JPEG:
$create = 'imagecreatefromjpeg';
break;
case IMAGETYPE_GIF:
$create = 'imagecreatefromgif';
break;
case IMAGETYPE_PNG:
$create = 'imagecreatefrompng';
break;
}
// Set the "save" function
switch (strtolower(substr(strrchr($file, '.'), 1))) {
case 'jpg':
case 'jpeg':
$save = 'imagejpeg';
break;
case 'gif':
$save = 'imagegif';
break;
case 'png':
$save = 'imagepng';
break;
}
// Set the "save" function
switch (strtolower(substr(strrchr($file, '.'), 1)))
{
case 'jpg':
case 'jpeg':
$save = 'imagejpeg';
break;
case 'gif':
$save = 'imagegif';
break;
case 'png':
$save = 'imagepng';
break;
}
// Make sure the image type is supported for import
if (empty($create) or ! function_exists($create)) {
throw new Kohana_Exception('image.type_not_allowed', $image['file']);
}
// Make sure the image type is supported for import
if (empty($create) OR ! function_exists($create))
throw new Kohana_Exception('image.type_not_allowed', $image['file']);
// Make sure the image type is supported for saving
if (empty($save) or ! function_exists($save)) {
throw new Kohana_Exception('image.type_not_allowed', $dir . $file);
}
// Make sure the image type is supported for saving
if (empty($save) OR ! function_exists($save))
throw new Kohana_Exception('image.type_not_allowed', $dir.$file);
// Load the image
$this->image = $image;
// Load the image
$this->image = $image;
// Create the GD image resource
$this->tmp_image = $create($image['file']);
// Create the GD image resource
$this->tmp_image = $create($image['file']);
// Get the quality setting from the actions
$quality = arr::remove('quality', $actions);
// Get the quality setting from the actions
$quality = arr::remove('quality', $actions);
if ($status = $this->execute($actions)) {
// Prevent the alpha from being lost
imagealphablending($this->tmp_image, true);
imagesavealpha($this->tmp_image, true);
if ($status = $this->execute($actions))
{
// Prevent the alpha from being lost
imagealphablending($this->tmp_image, TRUE);
imagesavealpha($this->tmp_image, TRUE);
switch ($save) {
case 'imagejpeg':
// Default the quality to 95
($quality === null) and $quality = 95;
break;
case 'imagegif':
// Remove the quality setting, GIF doesn't use it
unset($quality);
break;
case 'imagepng':
// Always use a compression level of 9 for PNGs. This does not
// affect quality, it only increases the level of compression!
$quality = 9;
break;
}
switch ($save)
{
case 'imagejpeg':
// Default the quality to 95
($quality === NULL) and $quality = 95;
break;
case 'imagegif':
// Remove the quality setting, GIF doesn't use it
unset($quality);
break;
case 'imagepng':
// Always use a compression level of 9 for PNGs. This does not
// affect quality, it only increases the level of compression!
$quality = 9;
break;
}
if ($render === false) {
// Set the status to the save return value, saving with the quality requested
$status = isset($quality) ? $save($this->tmp_image, $dir . $file, $quality) : $save($this->tmp_image, $dir . $file);
} else {
// Output the image directly to the browser
switch ($save) {
case 'imagejpeg':
header('Content-Type: image/jpeg');
break;
case 'imagegif':
header('Content-Type: image/gif');
break;
case 'imagepng':
header('Content-Type: image/png');
break;
}
if ($render === FALSE)
{
// Set the status to the save return value, saving with the quality requested
$status = isset($quality) ? $save($this->tmp_image, $dir.$file, $quality) : $save($this->tmp_image, $dir.$file);
}
else
{
// Output the image directly to the browser
switch ($save)
{
case 'imagejpeg':
header('Content-Type: image/jpeg');
break;
case 'imagegif':
header('Content-Type: image/gif');
break;
case 'imagepng':
header('Content-Type: image/png');
break;
}
$status = isset($quality) ? $save($this->tmp_image, null, $quality) : $save($this->tmp_image);
}
$status = isset($quality) ? $save($this->tmp_image, NULL, $quality) : $save($this->tmp_image);
}
// Destroy the temporary image
imagedestroy($this->tmp_image);
}
// Destroy the temporary image
imagedestroy($this->tmp_image);
}
return $status;
}
return $status;
}
public function flip($direction)
{
// Get the current width and height
$width = imagesx($this->tmp_image);
$height = imagesy($this->tmp_image);
public function flip($direction)
{
// Get the current width and height
$width = imagesx($this->tmp_image);
$height = imagesy($this->tmp_image);
// Create the flipped image
$flipped = $this->imagecreatetransparent($width, $height);
// Create the flipped image
$flipped = $this->imagecreatetransparent($width, $height);
if ($direction === Image::HORIZONTAL) {
for ($x = 0; $x < $width; $x++) {
$status = imagecopy($flipped, $this->tmp_image, $x, 0, $width - $x - 1, 0, 1, $height);
}
} elseif ($direction === Image::VERTICAL) {
for ($y = 0; $y < $height; $y++) {
$status = imagecopy($flipped, $this->tmp_image, 0, $y, 0, $height - $y - 1, $width, 1);
}
} else {
// Do nothing
return true;
}
if ($direction === Image::HORIZONTAL)
{
for ($x = 0; $x < $width; $x++)
{
$status = imagecopy($flipped, $this->tmp_image, $x, 0, $width - $x - 1, 0, 1, $height);
}
}
elseif ($direction === Image::VERTICAL)
{
for ($y = 0; $y < $height; $y++)
{
$status = imagecopy($flipped, $this->tmp_image, 0, $y, 0, $height - $y - 1, $width, 1);
}
}
else
{
// Do nothing
return TRUE;
}
if ($status === true) {
// Swap the new image for the old one
imagedestroy($this->tmp_image);
$this->tmp_image = $flipped;
}
if ($status === TRUE)
{
// Swap the new image for the old one
imagedestroy($this->tmp_image);
$this->tmp_image = $flipped;
}
return $status;
}
return $status;
}
public function crop($properties)
{
// Sanitize the cropping settings
$this->sanitize_geometry($properties);
public function crop($properties)
{
// Sanitize the cropping settings
$this->sanitize_geometry($properties);
// Get the current width and height
$width = imagesx($this->tmp_image);
$height = imagesy($this->tmp_image);
// Get the current width and height
$width = imagesx($this->tmp_image);
$height = imagesy($this->tmp_image);
// Create the temporary image to copy to
$img = $this->imagecreatetransparent($properties['width'], $properties['height']);
// Create the temporary image to copy to
$img = $this->imagecreatetransparent($properties['width'], $properties['height']);
// Execute the crop
if ($status = imagecopyresampled($img, $this->tmp_image, 0, 0, $properties['left'], $properties['top'], $width, $height, $width, $height)) {
// Swap the new image for the old one
imagedestroy($this->tmp_image);
$this->tmp_image = $img;
}
// Execute the crop
if ($status = imagecopyresampled($img, $this->tmp_image, 0, 0, $properties['left'], $properties['top'], $width, $height, $width, $height))
{
// Swap the new image for the old one
imagedestroy($this->tmp_image);
$this->tmp_image = $img;
}
return $status;
}
return $status;
}
public function resize($properties)
{
// Get the current width and height
$width = imagesx($this->tmp_image);
$height = imagesy($this->tmp_image);
public function resize($properties)
{
// Get the current width and height
$width = imagesx($this->tmp_image);
$height = imagesy($this->tmp_image);
if (substr($properties['width'], -1) === '%') {
// Recalculate the percentage to a pixel size
$properties['width'] = round($width * (substr($properties['width'], 0, -1) / 100));
}
if (substr($properties['width'], -1) === '%')
{
// Recalculate the percentage to a pixel size
$properties['width'] = round($width * (substr($properties['width'], 0, -1) / 100));
}
if (substr($properties['height'], -1) === '%') {
// Recalculate the percentage to a pixel size
$properties['height'] = round($height * (substr($properties['height'], 0, -1) / 100));
}
if (substr($properties['height'], -1) === '%')
{
// Recalculate the percentage to a pixel size
$properties['height'] = round($height * (substr($properties['height'], 0, -1) / 100));
}
// Recalculate the width and height, if they are missing
empty($properties['width']) and $properties['width'] = round($width * $properties['height'] / $height);
empty($properties['height']) and $properties['height'] = round($height * $properties['width'] / $width);
if ($properties['master'] === Image::AUTO)
{
// Change an automatic master dim to the correct type
$properties['master'] = (($width / $properties['width']) > ($height / $properties['height'])) ? Image::WIDTH : Image::HEIGHT;
}
// Recalculate the width and height, if they are missing
empty($properties['width']) and $properties['width'] = round($width * $properties['height'] / $height);
empty($properties['height']) and $properties['height'] = round($height * $properties['width'] / $width);
if (empty($properties['height']) OR $properties['master'] === Image::WIDTH)
{
// Recalculate the height based on the width
$properties['height'] = round($height * $properties['width'] / $width);
}
if ($properties['master'] === Image::AUTO) {
// Change an automatic master dim to the correct type
$properties['master'] = (($width / $properties['width']) > ($height / $properties['height'])) ? Image::WIDTH : Image::HEIGHT;
}
if (empty($properties['width']) OR $properties['master'] === Image::HEIGHT)
{
// Recalculate the width based on the height
$properties['width'] = round($width * $properties['height'] / $height);
}
if (empty($properties['height']) or $properties['master'] === Image::WIDTH) {
// Recalculate the height based on the width
$properties['height'] = round($height * $properties['width'] / $width);
}
// Test if we can do a resize without resampling to speed up the final resize
if ($properties['width'] > $width / 2 AND $properties['height'] > $height / 2)
{
// Presize width and height
$pre_width = $width;
$pre_height = $height;
if (empty($properties['width']) or $properties['master'] === Image::HEIGHT) {
// Recalculate the width based on the height
$properties['width'] = round($width * $properties['height'] / $height);
}
// The maximum reduction is 10% greater than the final size
$max_reduction_width = round($properties['width'] * 1.1);
$max_reduction_height = round($properties['height'] * 1.1);
// Test if we can do a resize without resampling to speed up the final resize
if ($properties['width'] > $width / 2 and $properties['height'] > $height / 2) {
// Presize width and height
$pre_width = $width;
$pre_height = $height;
// Reduce the size using an O(2n) algorithm, until it reaches the maximum reduction
while ($pre_width / 2 > $max_reduction_width AND $pre_height / 2 > $max_reduction_height)
{
$pre_width /= 2;
$pre_height /= 2;
}
// The maximum reduction is 10% greater than the final size
$max_reduction_width = round($properties['width'] * 1.1);
$max_reduction_height = round($properties['height'] * 1.1);
// Create the temporary image to copy to
$img = $this->imagecreatetransparent($pre_width, $pre_height);
// Reduce the size using an O(2n) algorithm, until it reaches the maximum reduction
while ($pre_width / 2 > $max_reduction_width and $pre_height / 2 > $max_reduction_height) {
$pre_width /= 2;
$pre_height /= 2;
}
if ($status = imagecopyresized($img, $this->tmp_image, 0, 0, 0, 0, $pre_width, $pre_height, $width, $height))
{
// Swap the new image for the old one
imagedestroy($this->tmp_image);
$this->tmp_image = $img;
}
// Create the temporary image to copy to
$img = $this->imagecreatetransparent($pre_width, $pre_height);
// Set the width and height to the presize
$width = $pre_width;
$height = $pre_height;
}
if ($status = imagecopyresized($img, $this->tmp_image, 0, 0, 0, 0, $pre_width, $pre_height, $width, $height)) {
// Swap the new image for the old one
imagedestroy($this->tmp_image);
$this->tmp_image = $img;
}
// Create the temporary image to copy to
$img = $this->imagecreatetransparent($properties['width'], $properties['height']);
// Set the width and height to the presize
$width = $pre_width;
$height = $pre_height;
}
// Execute the resize
if ($status = imagecopyresampled($img, $this->tmp_image, 0, 0, 0, 0, $properties['width'], $properties['height'], $width, $height))
{
// Swap the new image for the old one
imagedestroy($this->tmp_image);
$this->tmp_image = $img;
}
// Create the temporary image to copy to
$img = $this->imagecreatetransparent($properties['width'], $properties['height']);
return $status;
}
// Execute the resize
if ($status = imagecopyresampled($img, $this->tmp_image, 0, 0, 0, 0, $properties['width'], $properties['height'], $width, $height)) {
// Swap the new image for the old one
imagedestroy($this->tmp_image);
$this->tmp_image = $img;
}
public function rotate($amount)
{
// Use current image to rotate
$img = $this->tmp_image;
return $status;
}
// White, with an alpha of 0
$transparent = imagecolorallocatealpha($img, 255, 255, 255, 127);
public function rotate($amount)
{
// Use current image to rotate
$img = $this->tmp_image;
// Rotate, setting the transparent color
$img = imagerotate($img, 360 - $amount, $transparent, -1);
// White, with an alpha of 0
$transparent = imagecolorallocatealpha($img, 255, 255, 255, 127);
// Fill the background with the transparent "color"
imagecolortransparent($img, $transparent);
// Rotate, setting the transparent color
$img = imagerotate($img, 360 - $amount, $transparent, -1);
// Merge the images
if ($status = imagecopymerge($this->tmp_image, $img, 0, 0, 0, 0, imagesx($this->tmp_image), imagesy($this->tmp_image), 100))
{
// Prevent the alpha from being lost
imagealphablending($img, TRUE);
imagesavealpha($img, TRUE);
// Fill the background with the transparent "color"
imagecolortransparent($img, $transparent);
// Swap the new image for the old one
imagedestroy($this->tmp_image);
$this->tmp_image = $img;
}
// Merge the images
if ($status = imagecopymerge($this->tmp_image, $img, 0, 0, 0, 0, imagesx($this->tmp_image), imagesy($this->tmp_image), 100)) {
// Prevent the alpha from being lost
imagealphablending($img, true);
imagesavealpha($img, true);
return $status;
}
// Swap the new image for the old one
imagedestroy($this->tmp_image);
$this->tmp_image = $img;
}
public function sharpen($amount)
{
// Make sure that the sharpening function is available
if ( ! function_exists('imageconvolution'))
throw new Kohana_Exception('image.unsupported_method', __FUNCTION__);
return $status;
}
// Amount should be in the range of 18-10
$amount = round(abs(-18 + ($amount * 0.08)), 2);
public function sharpen($amount)
{
// Make sure that the sharpening function is available
if (! function_exists('imageconvolution')) {
throw new Kohana_Exception('image.unsupported_method', __FUNCTION__);
}
// Gaussian blur matrix
$matrix = array
(
array(-1, -1, -1),
array(-1, $amount, -1),
array(-1, -1, -1),
);
// Amount should be in the range of 18-10
$amount = round(abs(-18 + ($amount * 0.08)), 2);
// Perform the sharpen
return imageconvolution($this->tmp_image, $matrix, $amount - 8, 0);
}
// Gaussian blur matrix
$matrix = array
(
array(-1, -1, -1),
array(-1, $amount, -1),
array(-1, -1, -1),
);
protected function properties()
{
return array(imagesx($this->tmp_image), imagesy($this->tmp_image));
}
// Perform the sharpen
return imageconvolution($this->tmp_image, $matrix, $amount - 8, 0);
}
/**
* Returns an image with a transparent background. Used for rotating to
* prevent unfilled backgrounds.
*
* @param integer image width
* @param integer image height
* @return resource
*/
protected function imagecreatetransparent($width, $height)
{
if (self::$blank_png === NULL)
{
// Decode the blank PNG if it has not been done already
self::$blank_png = imagecreatefromstring(base64_decode
(
'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29'.
'mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAADqSURBVHjaYvz//z/DYAYAAcTEMMgBQAANegcCBN'.
'CgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQ'.
'AANegcCBNCgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB3IEAADXoH'.
'AgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB'.
'3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAgAEAMpcDTTQWJVEAAAAASUVORK5CYII='
));
protected function properties()
{
return array(imagesx($this->tmp_image), imagesy($this->tmp_image));
}
// Set the blank PNG width and height
self::$blank_png_width = imagesx(self::$blank_png);
self::$blank_png_height = imagesy(self::$blank_png);
}
/**
* Returns an image with a transparent background. Used for rotating to
* prevent unfilled backgrounds.
*
* @param integer image width
* @param integer image height
* @return resource
*/
protected function imagecreatetransparent($width, $height)
{
if (self::$blank_png === null) {
// Decode the blank PNG if it has not been done already
self::$blank_png = imagecreatefromstring(base64_decode(
'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29' .
'mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAADqSURBVHjaYvz//z/DYAYAAcTEMMgBQAANegcCBN' .
'CgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQ' .
'AANegcCBNCgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB3IEAADXoH' .
'AgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB' .
'3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAgAEAMpcDTTQWJVEAAAAASUVORK5CYII='
));
$img = imagecreatetruecolor($width, $height);
// Set the blank PNG width and height
self::$blank_png_width = imagesx(self::$blank_png);
self::$blank_png_height = imagesy(self::$blank_png);
}
// Resize the blank image
imagecopyresized($img, self::$blank_png, 0, 0, 0, 0, $width, $height, self::$blank_png_width, self::$blank_png_height);
$img = imagecreatetruecolor($width, $height);
// Prevent the alpha from being lost
imagealphablending($img, FALSE);
imagesavealpha($img, TRUE);
// Resize the blank image
imagecopyresized($img, self::$blank_png, 0, 0, 0, 0, $width, $height, self::$blank_png_width, self::$blank_png_height);
return $img;
}
// Prevent the alpha from being lost
imagealphablending($img, false);
imagesavealpha($img, true);
} // End Image GD Driver
return $img;
}
}
// End Image GD Driver

View File

@@ -1,4 +1,12 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* GraphicsMagick Image Driver.
*
@@ -7,205 +15,200 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Image_GraphicsMagick_Driver extends Image_Driver {
class Image_GraphicsMagick_Driver extends Image_Driver
{
// Directory that GM is installed in
protected $dir = '';
// Directory that GM is installed in
protected $dir = '';
// Command extension (exe for windows)
protected $ext = '';
// Command extension (exe for windows)
protected $ext = '';
// Temporary image filename
protected $tmp_image;
// Temporary image filename
protected $tmp_image;
/**
* Attempts to detect the GraphicsMagick installation directory.
*
* @throws Kohana_Exception
* @param array configuration
* @return void
*/
public function __construct($config)
{
if (empty($config['directory'])) {
// Attempt to locate GM by using "which" (only works for *nix!)
if (! is_file($path = exec('which gm'))) {
throw new Kohana_Exception('image.graphicsmagick.not_found');
}
/**
* Attempts to detect the GraphicsMagick installation directory.
*
* @throws Kohana_Exception
* @param array configuration
* @return void
*/
public function __construct($config)
{
if (empty($config['directory']))
{
// Attempt to locate GM by using "which" (only works for *nix!)
if ( ! is_file($path = exec('which gm')))
throw new Kohana_Exception('image.graphicsmagick.not_found');
$config['directory'] = dirname($path);
}
$config['directory'] = dirname($path);
}
// Set the command extension
$this->ext = (PHP_SHLIB_SUFFIX === 'dll') ? '.exe' : '';
// Set the command extension
$this->ext = (PHP_SHLIB_SUFFIX === 'dll') ? '.exe' : '';
// Check to make sure the provided path is correct
if ( ! is_file(realpath($config['directory']).'/gm'.$this->ext))
throw new Kohana_Exception('image.graphicsmagick.not_found', 'gm'.$this->ext);
// Check to make sure the provided path is correct
if (! is_file(realpath($config['directory']) . '/gm' . $this->ext)) {
throw new Kohana_Exception('image.graphicsmagick.not_found', 'gm' . $this->ext);
}
// Set the installation directory
$this->dir = str_replace('\\', '/', realpath($config['directory'])).'/';
}
// Set the installation directory
$this->dir = str_replace('\\', '/', realpath($config['directory'])) . '/';
}
/**
* Creates a temporary image and executes the given actions. By creating a
* temporary copy of the image before manipulating it, this process is atomic.
*/
public function process($image, $actions, $dir, $file, $render = FALSE)
{
// We only need the filename
$image = $image['file'];
/**
* Creates a temporary image and executes the given actions. By creating a
* temporary copy of the image before manipulating it, this process is atomic.
*/
public function process($image, $actions, $dir, $file, $render = false)
{
// We only need the filename
$image = $image['file'];
// Unique temporary filename
$this->tmp_image = $dir.'k2img--'.sha1(time().$dir.$file).substr($file, strrpos($file, '.'));
// Unique temporary filename
$this->tmp_image = $dir . 'k2img--' . sha1(time() . $dir . $file) . substr($file, strrpos($file, '.'));
// Copy the image to the temporary file
copy($image, $this->tmp_image);
// Copy the image to the temporary file
copy($image, $this->tmp_image);
// Quality change is done last
$quality = (int) arr::remove('quality', $actions);
// Quality change is done last
$quality = (int) arr::remove('quality', $actions);
// Use 95 for the default quality
empty($quality) and $quality = 95;
// Use 95 for the default quality
empty($quality) and $quality = 95;
// All calls to these will need to be escaped, so do it now
$this->cmd_image = escapeshellarg($this->tmp_image);
$this->new_image = ($render)? $this->cmd_image : escapeshellarg($dir.$file);
// All calls to these will need to be escaped, so do it now
$this->cmd_image = escapeshellarg($this->tmp_image);
$this->new_image = ($render) ? $this->cmd_image : escapeshellarg($dir . $file);
if ($status = $this->execute($actions))
{
// Use convert to change the image into its final version. This is
// done to allow the file type to change correctly, and to handle
// the quality conversion in the most effective way possible.
if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' -quality '.$quality.'% '.$this->cmd_image.' '.$this->new_image))
{
$this->errors[] = $error;
}
else
{
// Output the image directly to the browser
if ($render !== FALSE)
{
$contents = file_get_contents($this->tmp_image);
switch (substr($file, strrpos($file, '.') + 1))
{
case 'jpg':
case 'jpeg':
header('Content-Type: image/jpeg');
break;
case 'gif':
header('Content-Type: image/gif');
break;
case 'png':
header('Content-Type: image/png');
break;
}
echo $contents;
}
}
}
if ($status = $this->execute($actions)) {
// Use convert to change the image into its final version. This is
// done to allow the file type to change correctly, and to handle
// the quality conversion in the most effective way possible.
if ($error = exec(escapeshellcmd($this->dir . 'gm' . $this->ext . ' convert') . ' -quality ' . $quality . '% ' . $this->cmd_image . ' ' . $this->new_image)) {
$this->errors[] = $error;
} else {
// Output the image directly to the browser
if ($render !== false) {
$contents = file_get_contents($this->tmp_image);
switch (substr($file, strrpos($file, '.') + 1)) {
case 'jpg':
case 'jpeg':
header('Content-Type: image/jpeg');
break;
case 'gif':
header('Content-Type: image/gif');
break;
case 'png':
header('Content-Type: image/png');
break;
}
echo $contents;
}
}
}
// Remove the temporary image
unlink($this->tmp_image);
$this->tmp_image = '';
// Remove the temporary image
unlink($this->tmp_image);
$this->tmp_image = '';
return $status;
}
return $status;
}
public function crop($prop)
{
// Sanitize and normalize the properties into geometry
$this->sanitize_geometry($prop);
public function crop($prop)
{
// Sanitize and normalize the properties into geometry
$this->sanitize_geometry($prop);
// Set the IM geometry based on the properties
$geometry = escapeshellarg($prop['width'].'x'.$prop['height'].'+'.$prop['left'].'+'.$prop['top']);
// Set the IM geometry based on the properties
$geometry = escapeshellarg($prop['width'] . 'x' . $prop['height'] . '+' . $prop['left'] . '+' . $prop['top']);
if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' -crop '.$geometry.' '.$this->cmd_image.' '.$this->cmd_image))
{
$this->errors[] = $error;
return FALSE;
}
if ($error = exec(escapeshellcmd($this->dir . 'gm' . $this->ext . ' convert') . ' -crop ' . $geometry . ' ' . $this->cmd_image . ' ' . $this->cmd_image)) {
$this->errors[] = $error;
return false;
}
return TRUE;
}
return true;
}
public function flip($dir)
{
// Convert the direction into a GM command
$dir = ($dir === Image::HORIZONTAL) ? '-flop' : '-flip';
public function flip($dir)
{
// Convert the direction into a GM command
$dir = ($dir === Image::HORIZONTAL) ? '-flop' : '-flip';
if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' '.$dir.' '.$this->cmd_image.' '.$this->cmd_image))
{
$this->errors[] = $error;
return FALSE;
}
if ($error = exec(escapeshellcmd($this->dir . 'gm' . $this->ext . ' convert') . ' ' . $dir . ' ' . $this->cmd_image . ' ' . $this->cmd_image)) {
$this->errors[] = $error;
return false;
}
return TRUE;
}
return true;
}
public function resize($prop)
{
switch ($prop['master'])
{
case Image::WIDTH: // Wx
$dim = escapeshellarg($prop['width'].'x');
break;
case Image::HEIGHT: // xH
$dim = escapeshellarg('x'.$prop['height']);
break;
case Image::AUTO: // WxH
$dim = escapeshellarg($prop['width'].'x'.$prop['height']);
break;
case Image::NONE: // WxH!
$dim = escapeshellarg($prop['width'].'x'.$prop['height'].'!');
break;
}
public function resize($prop)
{
switch ($prop['master']) {
case Image::WIDTH: // Wx
$dim = escapeshellarg($prop['width'] . 'x');
break;
case Image::HEIGHT: // xH
$dim = escapeshellarg('x' . $prop['height']);
break;
case Image::AUTO: // WxH
$dim = escapeshellarg($prop['width'] . 'x' . $prop['height']);
break;
case Image::NONE: // WxH!
$dim = escapeshellarg($prop['width'] . 'x' . $prop['height'] . '!');
break;
}
// Use "convert" to change the width and height
if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' -resize '.$dim.' '.$this->cmd_image.' '.$this->cmd_image))
{
$this->errors[] = $error;
return FALSE;
}
// Use "convert" to change the width and height
if ($error = exec(escapeshellcmd($this->dir . 'gm' . $this->ext . ' convert') . ' -resize ' . $dim . ' ' . $this->cmd_image . ' ' . $this->cmd_image)) {
$this->errors[] = $error;
return false;
}
return TRUE;
}
return true;
}
public function rotate($amt)
{
if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' -rotate '.escapeshellarg($amt).' -background transparent '.$this->cmd_image.' '.$this->cmd_image))
{
$this->errors[] = $error;
return FALSE;
}
public function rotate($amt)
{
if (
$error = exec(escapeshellcmd($this->dir . 'gm' . $this->ext . ' convert') .
' -rotate ' . escapeshellarg($amt) .
' -background transparent ' .
$this->cmd_image .
' ' . $this->cmd_image)
) {
$this->errors[] = $error;
return false;
}
return TRUE;
}
return true;
}
public function sharpen($amount)
{
// Set the sigma, radius, and amount. The amount formula allows a nice
// spread between 1 and 100 without pixelizing the image badly.
$sigma = 0.5;
$radius = $sigma * 2;
$amount = round(($amount / 80) * 3.14, 2);
public function sharpen($amount)
{
// Set the sigma, radius, and amount. The amount formula allows a nice
// spread between 1 and 100 without pixelizing the image badly.
$sigma = 0.5;
$radius = $sigma * 2;
$amount = round(($amount / 80) * 3.14, 2);
// Convert the amount to an GM command
$sharpen = escapeshellarg($radius.'x'.$sigma.'+'.$amount.'+0');
// Convert the amount to an GM command
$sharpen = escapeshellarg($radius . 'x' . $sigma . '+' . $amount . '+0');
if ($error = exec(escapeshellcmd($this->dir.'gm'.$this->ext.' convert').' -unsharp '.$sharpen.' '.$this->cmd_image.' '.$this->cmd_image))
{
$this->errors[] = $error;
return FALSE;
}
if ($error = exec(escapeshellcmd($this->dir . 'gm' . $this->ext . ' convert') . ' -unsharp ' . $sharpen . ' ' . $this->cmd_image . ' ' . $this->cmd_image)) {
$this->errors[] = $error;
return false;
}
return TRUE;
}
return true;
}
protected function properties()
{
return array_slice(getimagesize($this->tmp_image), 0, 2, FALSE);
}
} // End Image GraphicsMagick Driver
protected function properties()
{
return array_slice(getimagesize($this->tmp_image), 0, 2, false);
}
}
// End Image GraphicsMagick Driver

View File

@@ -1,4 +1,13 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* ImageMagick Image Driver.
*
@@ -9,204 +18,200 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Image_ImageMagick_Driver extends Image_Driver {
class Image_ImageMagick_Driver extends Image_Driver
{
// Directory that IM is installed in
protected $dir = '';
// Directory that IM is installed in
protected $dir = '';
// Command extension (exe for windows)
protected $ext = '';
// Command extension (exe for windows)
protected $ext = '';
// Temporary image filename
protected $tmp_image;
// Temporary image filename
protected $tmp_image;
/**
* Attempts to detect the ImageMagick installation directory.
*
* @throws Kohana_Exception
* @param array configuration
* @return void
*/
public function __construct($config)
{
if (empty($config['directory'])) {
// Attempt to locate IM by using "which" (only works for *nix!)
if (! is_file($path = exec('which convert'))) {
throw new Kohana_Exception('image.imagemagick.not_found');
}
/**
* Attempts to detect the ImageMagick installation directory.
*
* @throws Kohana_Exception
* @param array configuration
* @return void
*/
public function __construct($config)
{
if (empty($config['directory']))
{
// Attempt to locate IM by using "which" (only works for *nix!)
if ( ! is_file($path = exec('which convert')))
throw new Kohana_Exception('image.imagemagick.not_found');
$config['directory'] = dirname($path);
}
$config['directory'] = dirname($path);
}
// Set the command extension
$this->ext = (PHP_SHLIB_SUFFIX === 'dll') ? '.exe' : '';
// Set the command extension
$this->ext = (PHP_SHLIB_SUFFIX === 'dll') ? '.exe' : '';
// Check to make sure the provided path is correct
if (! is_file(realpath($config['directory']) . '/convert' . $this->ext)) {
throw new Kohana_Exception('image.imagemagick.not_found', 'convert' . $this->ext);
}
// Check to make sure the provided path is correct
if ( ! is_file(realpath($config['directory']).'/convert'.$this->ext))
throw new Kohana_Exception('image.imagemagick.not_found', 'convert'.$this->ext);
// Set the installation directory
$this->dir = str_replace('\\', '/', realpath($config['directory'])) . '/';
}
// Set the installation directory
$this->dir = str_replace('\\', '/', realpath($config['directory'])).'/';
}
/**
* Creates a temporary image and executes the given actions. By creating a
* temporary copy of the image before manipulating it, this process is atomic.
*/
public function process($image, $actions, $dir, $file, $render = false)
{
// We only need the filename
$image = $image['file'];
/**
* Creates a temporary image and executes the given actions. By creating a
* temporary copy of the image before manipulating it, this process is atomic.
*/
public function process($image, $actions, $dir, $file, $render = FALSE)
{
// We only need the filename
$image = $image['file'];
// Unique temporary filename
$this->tmp_image = $dir . 'k2img--' . sha1(time() . $dir . $file) . substr($file, strrpos($file, '.'));
// Unique temporary filename
$this->tmp_image = $dir.'k2img--'.sha1(time().$dir.$file).substr($file, strrpos($file, '.'));
// Copy the image to the temporary file
copy($image, $this->tmp_image);
// Copy the image to the temporary file
copy($image, $this->tmp_image);
// Quality change is done last
$quality = (int) arr::remove('quality', $actions);
// Quality change is done last
$quality = (int) arr::remove('quality', $actions);
// Use 95 for the default quality
empty($quality) and $quality = 95;
// Use 95 for the default quality
empty($quality) and $quality = 95;
// All calls to these will need to be escaped, so do it now
$this->cmd_image = escapeshellarg($this->tmp_image);
$this->new_image = ($render) ? $this->cmd_image : escapeshellarg($dir . $file);
// All calls to these will need to be escaped, so do it now
$this->cmd_image = escapeshellarg($this->tmp_image);
$this->new_image = ($render)? $this->cmd_image : escapeshellarg($dir.$file);
if ($status = $this->execute($actions)) {
// Use convert to change the image into its final version. This is
// done to allow the file type to change correctly, and to handle
// the quality conversion in the most effective way possible.
if ($error = exec(escapeshellcmd($this->dir . 'convert' . $this->ext) . ' -quality ' . $quality . '% ' . $this->cmd_image . ' ' . $this->new_image)) {
$this->errors[] = $error;
} else {
// Output the image directly to the browser
if ($render !== false) {
$contents = file_get_contents($this->tmp_image);
switch (substr($file, strrpos($file, '.') + 1)) {
case 'jpg':
case 'jpeg':
header('Content-Type: image/jpeg');
break;
case 'gif':
header('Content-Type: image/gif');
break;
case 'png':
header('Content-Type: image/png');
break;
}
echo $contents;
}
}
}
if ($status = $this->execute($actions))
{
// Use convert to change the image into its final version. This is
// done to allow the file type to change correctly, and to handle
// the quality conversion in the most effective way possible.
if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -quality '.$quality.'% '.$this->cmd_image.' '.$this->new_image))
{
$this->errors[] = $error;
}
else
{
// Output the image directly to the browser
if ($render !== FALSE)
{
$contents = file_get_contents($this->tmp_image);
switch (substr($file, strrpos($file, '.') + 1))
{
case 'jpg':
case 'jpeg':
header('Content-Type: image/jpeg');
break;
case 'gif':
header('Content-Type: image/gif');
break;
case 'png':
header('Content-Type: image/png');
break;
}
echo $contents;
}
}
}
// Remove the temporary image
unlink($this->tmp_image);
$this->tmp_image = '';
// Remove the temporary image
unlink($this->tmp_image);
$this->tmp_image = '';
return $status;
}
return $status;
}
public function crop($prop)
{
// Sanitize and normalize the properties into geometry
$this->sanitize_geometry($prop);
public function crop($prop)
{
// Sanitize and normalize the properties into geometry
$this->sanitize_geometry($prop);
// Set the IM geometry based on the properties
$geometry = escapeshellarg($prop['width'] . 'x' . $prop['height'] . '+' . $prop['left'] . '+' . $prop['top']);
// Set the IM geometry based on the properties
$geometry = escapeshellarg($prop['width'].'x'.$prop['height'].'+'.$prop['left'].'+'.$prop['top']);
if ($error = exec(escapeshellcmd($this->dir . 'convert' . $this->ext) . ' -crop ' . $geometry . ' ' . $this->cmd_image . ' ' . $this->cmd_image)) {
$this->errors[] = $error;
return false;
}
if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -crop '.$geometry.' '.$this->cmd_image.' '.$this->cmd_image))
{
$this->errors[] = $error;
return FALSE;
}
return true;
}
return TRUE;
}
public function flip($dir)
{
// Convert the direction into a IM command
$dir = ($dir === Image::HORIZONTAL) ? '-flop' : '-flip';
public function flip($dir)
{
// Convert the direction into a IM command
$dir = ($dir === Image::HORIZONTAL) ? '-flop' : '-flip';
if ($error = exec(escapeshellcmd($this->dir . 'convert' . $this->ext) . ' ' . $dir . ' ' . $this->cmd_image . ' ' . $this->cmd_image)) {
$this->errors[] = $error;
return false;
}
if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' '.$dir.' '.$this->cmd_image.' '.$this->cmd_image))
{
$this->errors[] = $error;
return FALSE;
}
return true;
}
return TRUE;
}
public function resize($prop)
{
switch ($prop['master']) {
case Image::WIDTH: // Wx
$dim = escapeshellarg($prop['width'] . 'x');
break;
case Image::HEIGHT: // xH
$dim = escapeshellarg('x' . $prop['height']);
break;
case Image::AUTO: // WxH
$dim = escapeshellarg($prop['width'] . 'x' . $prop['height']);
break;
case Image::NONE: // WxH!
$dim = escapeshellarg($prop['width'] . 'x' . $prop['height'] . '!');
break;
}
public function resize($prop)
{
switch ($prop['master'])
{
case Image::WIDTH: // Wx
$dim = escapeshellarg($prop['width'].'x');
break;
case Image::HEIGHT: // xH
$dim = escapeshellarg('x'.$prop['height']);
break;
case Image::AUTO: // WxH
$dim = escapeshellarg($prop['width'].'x'.$prop['height']);
break;
case Image::NONE: // WxH!
$dim = escapeshellarg($prop['width'].'x'.$prop['height'].'!');
break;
}
// Use "convert" to change the width and height
if ($error = exec(escapeshellcmd($this->dir . 'convert' . $this->ext) . ' -resize ' . $dim . ' ' . $this->cmd_image . ' ' . $this->cmd_image)) {
$this->errors[] = $error;
return false;
}
// Use "convert" to change the width and height
if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -resize '.$dim.' '.$this->cmd_image.' '.$this->cmd_image))
{
$this->errors[] = $error;
return FALSE;
}
return true;
}
return TRUE;
}
public function rotate($amt)
{
if (
$error = exec(escapeshellcmd($this->dir . 'convert' . $this->ext) .
' -rotate ' .
escapeshellarg($amt) .
' -background transparent ' .
$this->cmd_image . ' ' .
$this->cmd_image)
) {
$this->errors[] = $error;
return false;
}
public function rotate($amt)
{
if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -rotate '.escapeshellarg($amt).' -background transparent '.$this->cmd_image.' '.$this->cmd_image))
{
$this->errors[] = $error;
return FALSE;
}
return true;
}
return TRUE;
}
public function sharpen($amount)
{
// Set the sigma, radius, and amount. The amount formula allows a nice
// spread between 1 and 100 without pixelizing the image badly.
$sigma = 0.5;
$radius = $sigma * 2;
$amount = round(($amount / 80) * 3.14, 2);
public function sharpen($amount)
{
// Set the sigma, radius, and amount. The amount formula allows a nice
// spread between 1 and 100 without pixelizing the image badly.
$sigma = 0.5;
$radius = $sigma * 2;
$amount = round(($amount / 80) * 3.14, 2);
// Convert the amount to an IM command
$sharpen = escapeshellarg($radius . 'x' . $sigma . '+' . $amount . '+0');
// Convert the amount to an IM command
$sharpen = escapeshellarg($radius.'x'.$sigma.'+'.$amount.'+0');
if ($error = exec(escapeshellcmd($this->dir . 'convert' . $this->ext) . ' -unsharp ' . $sharpen . ' ' . $this->cmd_image . ' ' . $this->cmd_image)) {
$this->errors[] = $error;
return false;
}
if ($error = exec(escapeshellcmd($this->dir.'convert'.$this->ext).' -unsharp '.$sharpen.' '.$this->cmd_image.' '.$this->cmd_image))
{
$this->errors[] = $error;
return FALSE;
}
return true;
}
return TRUE;
}
protected function properties()
{
return array_slice(getimagesize($this->tmp_image), 0, 2, FALSE);
}
} // End Image ImageMagick Driver
protected function properties()
{
return array_slice(getimagesize($this->tmp_image), 0, 2, false);
}
}
// End Image ImageMagick Driver

View File

@@ -1,4 +1,12 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* Session driver interface
*
@@ -9,62 +17,62 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
interface Session_Driver {
interface Session_Driver
{
/**
* Opens a session.
*
* @param string save path
* @param string session name
* @return boolean
*/
public function open($path, $name);
/**
* Opens a session.
*
* @param string save path
* @param string session name
* @return boolean
*/
public function open($path, $name);
/**
* Closes a session.
*
* @return boolean
*/
public function close();
/**
* Closes a session.
*
* @return boolean
*/
public function close();
/**
* Reads a session.
*
* @param string session id
* @return string
*/
public function read($id);
/**
* Reads a session.
*
* @param string session id
* @return string
*/
public function read($id);
/**
* Writes a session.
*
* @param string session id
* @param string session data
* @return boolean
*/
public function write($id, $data);
/**
* Writes a session.
*
* @param string session id
* @param string session data
* @return boolean
*/
public function write($id, $data);
/**
* Destroys a session.
*
* @param string session id
* @return boolean
*/
public function destroy($id);
/**
* Destroys a session.
*
* @param string session id
* @return boolean
*/
public function destroy($id);
/**
* Regenerates the session id.
*
* @return string
*/
public function regenerate();
/**
* Regenerates the session id.
*
* @return string
*/
public function regenerate();
/**
* Garbage collection.
*
* @param integer session expiration period
* @return boolean
*/
public function gc($maxlifetime);
} // End Session Driver Interface
/**
* Garbage collection.
*
* @param integer session expiration period
* @return boolean
*/
public function gc($maxlifetime);
}
// End Session Driver Interface

View File

@@ -1,4 +1,12 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* Session cache driver.
*
@@ -17,89 +25,85 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Session_Cache_Driver implements Session_Driver {
class Session_Cache_Driver implements Session_Driver
{
protected $cache;
protected $encrypt;
protected $cache;
protected $encrypt;
public function __construct()
{
// Load Encrypt library
if (Kohana::config('session.encryption')) {
$this->encrypt = new Encrypt();
}
public function __construct()
{
// Load Encrypt library
if (Kohana::config('session.encryption'))
{
$this->encrypt = new Encrypt;
}
Kohana::log('debug', 'Session Cache Driver Initialized');
}
Kohana::log('debug', 'Session Cache Driver Initialized');
}
public function open($path, $name)
{
$config = Kohana::config('session.storage');
public function open($path, $name)
{
$config = Kohana::config('session.storage');
if (empty($config)) {
// Load the default group
$config = Kohana::config('cache.default');
} elseif (is_string($config)) {
$name = $config;
if (empty($config))
{
// Load the default group
$config = Kohana::config('cache.default');
}
elseif (is_string($config))
{
$name = $config;
// Test the config group name
if (($config = Kohana::config('cache.' . $config)) === null) {
throw new Kohana_Exception('cache.undefined_group', $name);
}
}
// Test the config group name
if (($config = Kohana::config('cache.'.$config)) === NULL)
throw new Kohana_Exception('cache.undefined_group', $name);
}
$config['lifetime'] = (Kohana::config('session.expiration') == 0) ? 86400 : Kohana::config('session.expiration');
$this->cache = new Cache($config);
$config['lifetime'] = (Kohana::config('session.expiration') == 0) ? 86400 : Kohana::config('session.expiration');
$this->cache = new Cache($config);
return is_object($this->cache);
}
return is_object($this->cache);
}
public function close()
{
return true;
}
public function close()
{
return TRUE;
}
public function read($id)
{
$id = 'session_' . $id;
if ($data = $this->cache->get($id)) {
return Kohana::config('session.encryption') ? $this->encrypt->decode($data) : $data;
}
public function read($id)
{
$id = 'session_'.$id;
if ($data = $this->cache->get($id))
{
return Kohana::config('session.encryption') ? $this->encrypt->decode($data) : $data;
}
// Return value must be string, NOT a boolean
return '';
}
// Return value must be string, NOT a boolean
return '';
}
public function write($id, $data)
{
$id = 'session_' . $id;
$data = Kohana::config('session.encryption') ? $this->encrypt->encode($data) : $data;
public function write($id, $data)
{
$id = 'session_'.$id;
$data = Kohana::config('session.encryption') ? $this->encrypt->encode($data) : $data;
return $this->cache->set($id, $data);
}
return $this->cache->set($id, $data);
}
public function destroy($id)
{
$id = 'session_' . $id;
return $this->cache->delete($id);
}
public function destroy($id)
{
$id = 'session_'.$id;
return $this->cache->delete($id);
}
public function regenerate()
{
session_regenerate_id(true);
public function regenerate()
{
session_regenerate_id(TRUE);
// Return new session id
return session_id();
}
// Return new session id
return session_id();
}
public function gc($maxlifetime)
{
// Just return, caches are automatically cleaned up
return TRUE;
}
} // End Session Cache Driver
public function gc($maxlifetime)
{
// Just return, caches are automatically cleaned up
return true;
}
}
// End Session Cache Driver

View File

@@ -1,4 +1,12 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* Session cookie driver.
*
@@ -9,72 +17,71 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Session_Cookie_Driver implements Session_Driver {
class Session_Cookie_Driver implements Session_Driver
{
protected $cookie_name;
protected $encrypt; // Library
protected $cookie_name;
protected $encrypt; // Library
public function __construct()
{
$this->cookie_name = Kohana::config('session.name') . '_data';
public function __construct()
{
$this->cookie_name = Kohana::config('session.name').'_data';
if (Kohana::config('session.encryption')) {
$this->encrypt = Encrypt::instance();
}
if (Kohana::config('session.encryption'))
{
$this->encrypt = Encrypt::instance();
}
Kohana::log('debug', 'Session Cookie Driver Initialized');
}
Kohana::log('debug', 'Session Cookie Driver Initialized');
}
public function open($path, $name)
{
return true;
}
public function open($path, $name)
{
return TRUE;
}
public function close()
{
return true;
}
public function close()
{
return TRUE;
}
public function read($id)
{
$data = (string) cookie::get($this->cookie_name);
public function read($id)
{
$data = (string) cookie::get($this->cookie_name);
if ($data == '') {
return $data;
}
if ($data == '')
return $data;
return empty($this->encrypt) ? base64_decode($data) : $this->encrypt->decode($data);
}
return empty($this->encrypt) ? base64_decode($data) : $this->encrypt->decode($data);
}
public function write($id, $data)
{
$data = empty($this->encrypt) ? base64_encode($data) : $this->encrypt->encode($data);
public function write($id, $data)
{
$data = empty($this->encrypt) ? base64_encode($data) : $this->encrypt->encode($data);
if (strlen($data) > 4048) {
Kohana::log('error', 'Session (' . $id . ') data exceeds the 4KB limit, ignoring write.');
return false;
}
if (strlen($data) > 4048)
{
Kohana::log('error', 'Session ('.$id.') data exceeds the 4KB limit, ignoring write.');
return FALSE;
}
return cookie::set($this->cookie_name, $data, Kohana::config('session.expiration'));
}
return cookie::set($this->cookie_name, $data, Kohana::config('session.expiration'));
}
public function destroy($id)
{
return cookie::delete($this->cookie_name);
}
public function destroy($id)
{
return cookie::delete($this->cookie_name);
}
public function regenerate()
{
session_regenerate_id(true);
public function regenerate()
{
session_regenerate_id(TRUE);
// Return new id
return session_id();
}
// Return new id
return session_id();
}
public function gc($maxlifetime)
{
return TRUE;
}
} // End Session Cookie Driver Class
public function gc($maxlifetime)
{
return true;
}
}
// End Session Cookie Driver Class

View File

@@ -1,4 +1,12 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');
<?php
// phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
// phpcs:disable PSR1.Files.SideEffects
defined('SYSPATH') or die('No direct access allowed.');
// phpcs:enable PSR1.Files.SideEffects
// phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
/**
* Session database driver.
*
@@ -9,155 +17,145 @@
* @copyright (c) 2007-2008 Kohana Team
* @license http://kohanaphp.com/license.html
*/
class Session_Database_Driver implements Session_Driver {
class Session_Database_Driver implements Session_Driver
{
/*
CREATE TABLE sessions
(
session_id VARCHAR(127) NOT NULL,
last_activity INT(10) UNSIGNED NOT NULL,
data TEXT NOT NULL,
PRIMARY KEY (session_id)
);
*/
/*
CREATE TABLE sessions
(
session_id VARCHAR(127) NOT NULL,
last_activity INT(10) UNSIGNED NOT NULL,
data TEXT NOT NULL,
PRIMARY KEY (session_id)
);
*/
// Database settings
protected $db = 'default';
protected $table = 'sessions';
// Database settings
protected $db = 'default';
protected $table = 'sessions';
// Encryption
protected $encrypt;
// Encryption
protected $encrypt;
// Session settings
protected $session_id;
protected $written = false;
// Session settings
protected $session_id;
protected $written = FALSE;
public function __construct()
{
// Load configuration
$config = Kohana::config('session');
public function __construct()
{
// Load configuration
$config = Kohana::config('session');
if (! empty($config['encryption'])) {
// Load encryption
$this->encrypt = Encrypt::instance();
}
if ( ! empty($config['encryption']))
{
// Load encryption
$this->encrypt = Encrypt::instance();
}
if (is_array($config['storage'])) {
if (! empty($config['storage']['group'])) {
// Set the group name
$this->db = $config['storage']['group'];
}
if (is_array($config['storage']))
{
if ( ! empty($config['storage']['group']))
{
// Set the group name
$this->db = $config['storage']['group'];
}
if (! empty($config['storage']['table'])) {
// Set the table name
$this->table = $config['storage']['table'];
}
}
if ( ! empty($config['storage']['table']))
{
// Set the table name
$this->table = $config['storage']['table'];
}
}
// Load database
$this->db = Database::instance($this->db);
// Load database
$this->db = Database::instance($this->db);
Kohana::log('debug', 'Session Database Driver Initialized');
}
Kohana::log('debug', 'Session Database Driver Initialized');
}
public function open($path, $name)
{
return true;
}
public function open($path, $name)
{
return TRUE;
}
public function close()
{
return true;
}
public function close()
{
return TRUE;
}
public function read($id)
{
// Load the session
$query = $this->db->from($this->table)->where('session_id', $id)->limit(1)->get()->result(true);
public function read($id)
{
// Load the session
$query = $this->db->from($this->table)->where('session_id', $id)->limit(1)->get()->result(TRUE);
if ($query->count() === 0) {
// No current session
$this->session_id = null;
if ($query->count() === 0)
{
// No current session
$this->session_id = NULL;
return '';
}
return '';
}
// Set the current session id
$this->session_id = $id;
// Set the current session id
$this->session_id = $id;
// Load the data
$data = $query->current()->data;
// Load the data
$data = $query->current()->data;
return ($this->encrypt === null) ? base64_decode($data) : $this->encrypt->decode($data);
}
return ($this->encrypt === NULL) ? base64_decode($data) : $this->encrypt->decode($data);
}
public function write($id, $data)
{
$data = array
(
'session_id' => $id,
'last_activity' => time(),
'data' => ($this->encrypt === null) ? base64_encode($data) : $this->encrypt->encode($data)
);
public function write($id, $data)
{
$data = array
(
'session_id' => $id,
'last_activity' => time(),
'data' => ($this->encrypt === NULL) ? base64_encode($data) : $this->encrypt->encode($data)
);
if ($this->session_id === null) {
// Insert a new session
$query = $this->db->insert($this->table, $data);
} elseif ($id === $this->session_id) {
// Do not update the session_id
unset($data['session_id']);
if ($this->session_id === NULL)
{
// Insert a new session
$query = $this->db->insert($this->table, $data);
}
elseif ($id === $this->session_id)
{
// Do not update the session_id
unset($data['session_id']);
// Update the existing session
$query = $this->db->update($this->table, $data, array('session_id' => $id));
} else {
// Update the session and id
$query = $this->db->update($this->table, $data, array('session_id' => $this->session_id));
// Update the existing session
$query = $this->db->update($this->table, $data, array('session_id' => $id));
}
else
{
// Update the session and id
$query = $this->db->update($this->table, $data, array('session_id' => $this->session_id));
// Set the new session id
$this->session_id = $id;
}
// Set the new session id
$this->session_id = $id;
}
return (bool) $query->count();
}
return (bool) $query->count();
}
public function destroy($id)
{
// Delete the requested session
$this->db->delete($this->table, array('session_id' => $id));
public function destroy($id)
{
// Delete the requested session
$this->db->delete($this->table, array('session_id' => $id));
// Session id is no longer valid
$this->session_id = null;
// Session id is no longer valid
$this->session_id = NULL;
return true;
}
return TRUE;
}
public function regenerate()
{
// Generate a new session id
session_regenerate_id();
public function regenerate()
{
// Generate a new session id
session_regenerate_id();
// Return new session id
return session_id();
}
// Return new session id
return session_id();
}
public function gc($maxlifetime)
{
// Delete all expired sessions
$query = $this->db->delete($this->table, array('last_activity <' => time() - $maxlifetime));
public function gc($maxlifetime)
{
// Delete all expired sessions
$query = $this->db->delete($this->table, array('last_activity <' => time() - $maxlifetime));
Kohana::log('debug', 'Session garbage collected: ' . $query->count() . ' row(s) deleted.');
Kohana::log('debug', 'Session garbage collected: '.$query->count().' row(s) deleted.');
return TRUE;
}
} // End Session Database Driver
return true;
}
}
// End Session Database Driver