- * @version $Revision: 1.3 $
- * @since PHP 4.2.0
- * @require PHP 4.0.0 (user_error)
- */
-if (!function_exists('ini_get_all')) {
- function ini_get_all($extension = null)
- {
- // Sanity check
- if (!is_scalar($extension)) {
- user_error('ini_get_all() expects parameter 1 to be string, ' .
- gettype($extension) . ' given', E_USER_WARNING);
- return false;
- }
-
- // Get the location of php.ini
- ob_start();
- phpinfo(INFO_GENERAL);
- $info = ob_get_contents();
- ob_clean();
- $info = explode("\n", $info);
- $line = array_values(preg_grep('#php.ini#', $info));
- list (, $value) = explode('', $line[0]);
- $inifile = trim(strip_tags($value));
-
- // Parse
- if ($extension !== null) {
- $ini_all = parse_ini_file($inifile, true);
-
- // Lowercase extension keys
- foreach ($ini_all as $key => $value) {
- $ini_arr[strtolower($key)] = $value;
- }
-
- $ini = $ini_arr[$extension];
- } else {
- $ini = parse_ini_file($inifile);
- }
-
- // Order
- $ini_lc = array_map('strtolower', array_keys($ini));
- array_multisort($ini_lc, SORT_ASC, SORT_STRING, $ini);
-
- // Format
- $info = array();
- foreach ($ini as $key => $value) {
- $info[$key] = array(
- 'global_value' => $value,
- 'local_value' => ini_get($key),
- // No way to know this
- 'access' => -1
- );
- }
-
- return $info;
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/is_a.php b/data/module/Compat/Compat/Function/is_a.php
deleted file mode 100644
index 2a431d6f089..00000000000
--- a/data/module/Compat/Compat/Function/is_a.php
+++ /dev/null
@@ -1,47 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: is_a.php,v 1.16 2005/01/26 04:55:13 aidan Exp $
-
-
-/**
- * Replace function is_a()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.is_a
- * @author Aidan Lister
- * @version $Revision: 1.16 $
- * @since PHP 4.2.0
- * @require PHP 4.0.0 (user_error) (is_subclass_of)
- */
-if (!function_exists('is_a')) {
- function is_a($object, $class)
- {
- if (!is_object($object)) {
- return false;
- }
-
- if (get_class($object) == strtolower($class)) {
- return true;
- } else {
- return is_subclass_of($object, $class);
- }
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/md5_file.php b/data/module/Compat/Compat/Function/md5_file.php
deleted file mode 100644
index ee0eff20f03..00000000000
--- a/data/module/Compat/Compat/Function/md5_file.php
+++ /dev/null
@@ -1,82 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: md5_file.php,v 1.3 2005/11/22 08:29:19 aidan Exp $
-
-
-/**
- * Replace md5_file()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/md5_file
- * @author Aidan Lister
- * @version $Revision: 1.3 $
- * @since PHP 4.2.0
- * @require PHP 4.0.0 (user_error)
- */
-if (!function_exists('md5_file')) {
- function md5_file($filename, $raw_output = false)
- {
- // Sanity check
- if (!is_scalar($filename)) {
- user_error('md5_file() expects parameter 1 to be string, ' .
- gettype($filename) . ' given', E_USER_WARNING);
- return;
- }
-
- if (!is_scalar($raw_output)) {
- user_error('md5_file() expects parameter 2 to be bool, ' .
- gettype($raw_output) . ' given', E_USER_WARNING);
- return;
- }
-
- if (!file_exists($filename)) {
- user_error('md5_file() Unable to open file', E_USER_WARNING);
- return false;
- }
-
- // Read the file
- if (false === $fh = fopen($filename, 'rb')) {
- user_error('md5_file() failed to open stream: No such file or directory',
- E_USER_WARNING);
- return false;
- }
-
- clearstatcache();
- if ($fsize = @filesize($filename)) {
- $data = fread($fh, $fsize);
- } else {
- $data = '';
- while (!feof($fh)) {
- $data .= fread($fh, 8192);
- }
- }
-
- fclose($fh);
-
- // Return
- $data = md5($data);
- if ($raw_output === true) {
- $data = pack('H*', $data);
- }
-
- return $data;
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/mhash.php b/data/module/Compat/Compat/Function/mhash.php
deleted file mode 100644
index 128c68ee121..00000000000
--- a/data/module/Compat/Compat/Function/mhash.php
+++ /dev/null
@@ -1,115 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: mhash.php,v 1.1 2005/05/10 07:56:44 aidan Exp $
-
-
-if (!defined('MHASH_CRC32')) {
- define('MHASH_CRC32', 0);
-}
-
-if (!defined('MHASH_MD5')) {
- define('MHASH_MD5', 1);
-}
-
-if (!defined('MHASH_SHA1')) {
- define('MHASH_SHA1', 2);
-}
-
-if (!defined('MHASH_HAVAL256')) {
- define('MHASH_HAVAL256', 3);
-}
-
-if (!defined('MHASH_RIPEMD160')) {
- define('MHASH_RIPEMD160', 5);
-}
-
-if (!defined('MHASH_TIGER')) {
- define('MHASH_TIGER', 7);
-}
-
-if (!defined('MHASH_GOST')) {
- define('MHASH_GOST', 8);
-}
-
-if (!defined('MHASH_CRC32B')) {
- define('MHASH_CRC32B', 9);
-}
-
-if (!defined('MHASH_HAVAL192')) {
- define('MHASH_HAVAL192', 11);
-}
-
-if (!defined('MHASH_HAVAL160')) {
- define('MHASH_HAVAL160', 12);
-}
-
-if (!defined('MHASH_HAVAL128')) {
- define('MHASH_HAVAL128', 13);
-}
-
-if (!defined('MHASH_TIGER128')) {
- define('MHASH_TIGER128', 14);
-}
-
-if (!defined('MHASH_TIGER160')) {
- define('MHASH_TIGER160', 15);
-}
-
-if (!defined('MHASH_MD4')) {
- define('MHASH_MD4', 16);
-}
-
-if (!defined('MHASH_SHA256')) {
- define('MHASH_SHA256', 17);
-}
-
-if (!defined('MHASH_ADLER32')) {
- define('MHASH_ADLER32', 18);
-}
-
-
-/**
- * Replace mhash()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.mhash
- * @author Aidan Lister
- * @version $Revision: 1.1 $
- * @since PHP 4.1.0
- * @require PHP 4.0.0 (user_error)
- */
-if (!function_exists('mhash')) {
- function mhash($hashtype, $data, $key = '')
- {
- switch ($hashtype) {
- case MHASH_MD5:
- $key = str_pad((strlen($key) > 64 ? pack("H*", md5($key)) : $key), 64, chr(0x00));
- $k_opad = $key ^ (str_pad('', 64, chr(0x5c)));
- $k_ipad = $key ^ (str_pad('', 64, chr(0x36)));
- return pack("H*", md5($k_opad . pack("H*", md5($k_ipad . $data))));
-
- default:
- return false;
-
- break;
- }
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/mime_content_type.php b/data/module/Compat/Compat/Function/mime_content_type.php
deleted file mode 100644
index 625d24a435c..00000000000
--- a/data/module/Compat/Compat/Function/mime_content_type.php
+++ /dev/null
@@ -1,63 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: mime_content_type.php,v 1.3 2005/12/07 21:08:57 aidan Exp $
-
-
-/**
-* Replace mime_content_type()
-*
-* You will need the `file` command installed and present in your $PATH. If
-* `file` is not available, the type 'application/octet-stream' is returned
-* for all files.
-*
-* @category PHP
-* @package PHP_Compat
-* @link http://php.net/function.mime_content_type
-* @version $Revision: 1.3 $
-* @author Ian Eure
-* @since PHP 4.3.0
-* @require PHP 4.0.3 (escapeshellarg)
-*/
-if (!function_exists('mime_content_type')) {
- function mime_content_type($filename)
- {
- // Sanity check
- if (!file_exists($filename)) {
- return false;
- }
-
- $filename = escapeshellarg($filename);
- $out = `file -iL $filename 2>/dev/null`;
- if (empty($out)) {
- return 'application/octet-stream';
- }
-
- // Strip off filename
- $t = substr($out, strpos($out, ':') + 2);
-
- if (strpos($t, ';') !== false) {
- // Strip MIME parameters
- $t = substr($t, 0, strpos($t, ';'));
- }
-
- // Strip any remaining whitespace
- return trim($t);
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/ob_clean.php b/data/module/Compat/Compat/Function/ob_clean.php
deleted file mode 100644
index 554d03fe42d..00000000000
--- a/data/module/Compat/Compat/Function/ob_clean.php
+++ /dev/null
@@ -1,46 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: ob_clean.php,v 1.6 2005/01/26 04:55:13 aidan Exp $
-
-
-/**
- * Replace ob_clean()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.ob_clean
- * @author Aidan Lister
- * @author Thiemo Mttig (http://maettig.com/)
- * @version $Revision: 1.6 $
- * @since PHP 4.2.0
- * @require PHP 4.0.0 (user_error)
- */
-if (!function_exists('ob_clean')) {
- function ob_clean()
- {
- if (@ob_end_clean()) {
- return ob_start();
- }
-
- user_error("ob_clean() failed to delete buffer. No buffer to delete.", E_USER_NOTICE);
-
- return false;
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/ob_flush.php b/data/module/Compat/Compat/Function/ob_flush.php
deleted file mode 100644
index eea99198001..00000000000
--- a/data/module/Compat/Compat/Function/ob_flush.php
+++ /dev/null
@@ -1,46 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: ob_flush.php,v 1.6 2005/01/26 04:55:13 aidan Exp $
-
-
-/**
- * Replace ob_flush()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.ob_flush
- * @author Aidan Lister
- * @author Thiemo Mttig (http://maettig.com/)
- * @version $Revision: 1.6 $
- * @since PHP 4.2.0
- * @require PHP 4.0.0 (user_error)
- */
-if (!function_exists('ob_flush')) {
- function ob_flush()
- {
- if (@ob_end_flush()) {
- return ob_start();
- }
-
- user_error("ob_flush() Failed to flush buffer. No buffer to flush.", E_USER_NOTICE);
-
- return false;
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/ob_get_clean.php b/data/module/Compat/Compat/Function/ob_get_clean.php
deleted file mode 100644
index 32d66edb487..00000000000
--- a/data/module/Compat/Compat/Function/ob_get_clean.php
+++ /dev/null
@@ -1,46 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: ob_get_clean.php,v 1.6 2005/01/26 04:55:13 aidan Exp $
-
-
-/**
- * Replace ob_get_clean()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.ob_get_clean
- * @author Aidan Lister
- * @author Thiemo Mttig (http://maettig.com/)
- * @version $Revision: 1.6 $
- * @since PHP 4.3.0
- * @require PHP 4.0.0 (user_error)
- */
-if (!function_exists('ob_get_clean')) {
- function ob_get_clean()
- {
- $contents = ob_get_contents();
-
- if ($contents !== false) {
- ob_end_clean();
- }
-
- return $contents;
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/ob_get_flush.php b/data/module/Compat/Compat/Function/ob_get_flush.php
deleted file mode 100644
index da3e8c5fa94..00000000000
--- a/data/module/Compat/Compat/Function/ob_get_flush.php
+++ /dev/null
@@ -1,46 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: ob_get_flush.php,v 1.6 2005/01/26 04:55:13 aidan Exp $
-
-
-/**
- * Replace ob_get_flush()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.ob_get_flush
- * @author Aidan Lister
- * @author Thiemo Mttig (http://maettig.com/)
- * @version $Revision: 1.6 $
- * @since PHP 4.3.0
- * @require PHP 4.0.0 (user_error)
- */
-if (!function_exists('ob_get_flush')) {
- function ob_get_flush()
- {
- $contents = ob_get_contents();
-
- if ($contents !== false) {
- ob_end_flush();
- }
-
- return $contents;
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/pg_affected_rows.php b/data/module/Compat/Compat/Function/pg_affected_rows.php
deleted file mode 100644
index 09df5c244a8..00000000000
--- a/data/module/Compat/Compat/Function/pg_affected_rows.php
+++ /dev/null
@@ -1,40 +0,0 @@
- |
-// | Mocha (http://us4.php.net/pg_escape_bytea) |
-// +----------------------------------------------------------------------+
-//
-// $Id: pg_affected_rows.php,v 1.1 2005/05/10 07:56:51 aidan Exp $
-
-
-/**
- * Replace pg_affected_rows()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.pg_affectd_rows
- * @author Ian Eure
- * @version $Revision@
- * @since PHP 4.2.0
- * @require PHP 4.0.0
- */
-if (!function_exists('pg_affected_rows')) {
- function pg_affected_rows($resource)
- {
- return pg_cmdtuples($resource);
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/pg_escape_bytea.php b/data/module/Compat/Compat/Function/pg_escape_bytea.php
deleted file mode 100644
index d8e824998bd..00000000000
--- a/data/module/Compat/Compat/Function/pg_escape_bytea.php
+++ /dev/null
@@ -1,43 +0,0 @@
- |
-// | Mocha (http://us4.php.net/pg_escape_bytea) |
-// +----------------------------------------------------------------------+
-//
-// $Id: pg_escape_bytea.php,v 1.1 2005/05/10 07:56:51 aidan Exp $
-
-
-/**
- * Replace pg_escape_bytea()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.pg_escape_bytea
- * @author Ian Eure
- * @version $Revision@
- * @since PHP 4.2.0
- * @require PHP 4.0.0
- */
-if (!function_exists('pg_escape_bytea')) {
- function pg_escape_bytea($data)
- {
- return str_replace(
- array(chr(92), chr(0), chr(39)),
- array('\\\134', '\\\000', '\\\047'),
- $data);
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/pg_unescape_bytea.php b/data/module/Compat/Compat/Function/pg_unescape_bytea.php
deleted file mode 100644
index 5dc9d0440af..00000000000
--- a/data/module/Compat/Compat/Function/pg_unescape_bytea.php
+++ /dev/null
@@ -1,43 +0,0 @@
- |
-// | Tobias |
-// +----------------------------------------------------------------------+
-//
-// $Id: pg_unescape_bytea.php,v 1.2 2005/12/07 21:08:57 aidan Exp $
-
-
-/**
- * Replace pg_unescape_bytea()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.pg_unescape_bytea
- * @author Ian Eure
- * @version $Revision@
- * @since PHP 4.2.0
- * @require PHP 4.0.0
- */
-if (!function_exists('pg_unescape_bytea')) {
- function pg_unescape_bytea(&$data)
- {
- return str_replace(
- array('$', '"'),
- array('\\$', '\\"'),
- $data);
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/php_strip_whitespace.php b/data/module/Compat/Compat/Function/php_strip_whitespace.php
deleted file mode 100644
index ca66121898c..00000000000
--- a/data/module/Compat/Compat/Function/php_strip_whitespace.php
+++ /dev/null
@@ -1,86 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: php_strip_whitespace.php,v 1.10 2005/01/26 04:55:13 aidan Exp $
-
-
-/**
- * Replace php_strip_whitespace()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.php_strip_whitespace
- * @author Aidan Lister
- * @version $Revision: 1.10 $
- * @since PHP 5
- * @require PHP 4.0.0 (user_error) + Tokenizer extension
- */
-if (!function_exists('php_strip_whitespace')) {
- function php_strip_whitespace($file)
- {
- // Sanity check
- if (!is_scalar($file)) {
- user_error('php_strip_whitespace() expects parameter 1 to be string, ' .
- gettype($file) . ' given', E_USER_WARNING);
- return;
- }
-
- // Load file / tokens
- $source = implode('', file($file));
- $tokens = token_get_all($source);
-
- // Init
- $source = '';
- $was_ws = false;
-
- // Process
- foreach ($tokens as $token) {
- if (is_string($token)) {
- // Single character tokens
- $source .= $token;
- } else {
- list($id, $text) = $token;
-
- switch ($id) {
- // Skip all comments
- case T_COMMENT:
- case T_ML_COMMENT:
- case T_DOC_COMMENT:
- break;
-
- // Remove whitespace
- case T_WHITESPACE:
- // We don't want more than one whitespace in a row replaced
- if ($was_ws !== true) {
- $source .= ' ';
- }
- $was_ws = true;
- break;
-
- default:
- $was_ws = false;
- $source .= $text;
- break;
- }
- }
- }
-
- return $source;
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/restore_include_path.php b/data/module/Compat/Compat/Function/restore_include_path.php
deleted file mode 100644
index 9bfc3ae7026..00000000000
--- a/data/module/Compat/Compat/Function/restore_include_path.php
+++ /dev/null
@@ -1,38 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: restore_include_path.php,v 1.4 2005/12/07 21:08:57 aidan Exp $
-
-
-/**
- * Replace restore_include_path()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.restore_include_path
- * @author Stephan Schmidt
- * @version $Revision: 1.4 $
- * @since PHP 4.3.0
- */
-if (!function_exists('restore_include_path')) {
- function restore_include_path()
- {
- return ini_restore('include_path');
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/scandir.php b/data/module/Compat/Compat/Function/scandir.php
deleted file mode 100644
index 3147552c48d..00000000000
--- a/data/module/Compat/Compat/Function/scandir.php
+++ /dev/null
@@ -1,69 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: scandir.php,v 1.18 2005/01/26 04:55:13 aidan Exp $
-
-
-/**
- * Replace scandir()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.scandir
- * @author Aidan Lister
- * @version $Revision: 1.18 $
- * @since PHP 5
- * @require PHP 4.0.0 (user_error)
- */
-if (!function_exists('scandir')) {
- function scandir($directory, $sorting_order = 0)
- {
- if (!is_string($directory)) {
- user_error('scandir() expects parameter 1 to be string, ' .
- gettype($directory) . ' given', E_USER_WARNING);
- return;
- }
-
- if (!is_int($sorting_order) && !is_bool($sorting_order)) {
- user_error('scandir() expects parameter 2 to be long, ' .
- gettype($sorting_order) . ' given', E_USER_WARNING);
- return;
- }
-
- if (!is_dir($directory) || (false === $fh = @opendir($directory))) {
- user_error('scandir() failed to open dir: Invalid argument', E_USER_WARNING);
- return false;
- }
-
- $files = array ();
- while (false !== ($filename = readdir($fh))) {
- $files[] = $filename;
- }
-
- closedir($fh);
-
- if ($sorting_order == 1) {
- rsort($files);
- } else {
- sort($files);
- }
-
- return $files;
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/set_include_path.php b/data/module/Compat/Compat/Function/set_include_path.php
deleted file mode 100644
index a520faaa384..00000000000
--- a/data/module/Compat/Compat/Function/set_include_path.php
+++ /dev/null
@@ -1,38 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: set_include_path.php,v 1.4 2005/12/07 21:08:57 aidan Exp $
-
-
-/**
- * Replace set_include_path()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.set_include_path
- * @author Stephan Schmidt
- * @version $Revision: 1.4 $
- * @since PHP 4.3.0
- */
-if (!function_exists('set_include_path')) {
- function set_include_path($new_include_path)
- {
- return ini_set('include_path', $new_include_path);
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/sha1.php b/data/module/Compat/Compat/Function/sha1.php
deleted file mode 100644
index a04a8b352af..00000000000
--- a/data/module/Compat/Compat/Function/sha1.php
+++ /dev/null
@@ -1,117 +0,0 @@
-, Arpad Ray
- * @link http://php.net/function.sha1
- * @author revulo
- * @since PHP 4.3.0
- * @require PHP 4.0.0
- */
-function php_compat_sha1($str, $raw_output = false)
-{
- $h0 = (int)0x67452301;
- $h1 = (int)0xefcdab89;
- $h2 = (int)0x98badcfe;
- $h3 = (int)0x10325476;
- $h4 = (int)0xc3d2e1f0;
-
- $len = strlen($str);
-
- $str .= "\x80";
- $str .= str_repeat("\0", 63 - ($len + 8) % 64);
- $str .= pack('N2', $len >> 29, $len << 3);
-
- for ($i = 0; $i < strlen($str); $i += 64) {
-
- $w = array();
- for ($j = 0; $j < 16; ++$j) {
- $index = $i + $j * 4;
- $w[$j] = ord($str[$index]) << 24
- | ord($str[$index + 1]) << 16
- | ord($str[$index + 2]) << 8
- | ord($str[$index + 3]);
- }
- for ($j = 16; $j < 80; ++$j) {
- $w[$j] = php_compat_sha1_rotl_helper($w[$j - 3] ^ $w[$j - 8] ^ $w[$j - 14] ^ $w[$j - 16], 1);
- }
-
- $a = $h0;
- $b = $h1;
- $c = $h2;
- $d = $h3;
- $e = $h4;
-
- for ($j = 0; $j < 80; ++$j) {
- if ($j < 20) {
- $f = ($b & $c) | (~$b & $d);
- $k = (int)0x5a827999;
- } else if ($j < 40) {
- $f = $b ^ $c ^ $d;
- $k = (int)0x6ed9eba1;
- } else if ($j < 60) {
- $f = ($b & $c) | ($b & $d) | ($c & $d);
- $k = (int)0x8f1bbcdc;
- } else {
- $f = $b ^ $c ^ $d;
- $k = (int)0xca62c1d6;
- }
-
- $t = php_compat_sha1_add32_helper(
- php_compat_sha1_add32_helper(
- php_compat_sha1_add32_helper(
- php_compat_sha1_add32_helper(
- php_compat_sha1_rotl_helper($a, 5), $f), $e), $k), $w[$j]);
-
- $e = $d;
- $d = $c;
- $c = php_compat_sha1_rotl_helper($b, 30);
- $b = $a;
- $a = $t;
- }
-
- $h0 = php_compat_sha1_add32_helper($h0, $a);
- $h1 = php_compat_sha1_add32_helper($h1, $b);
- $h2 = php_compat_sha1_add32_helper($h2, $c);
- $h3 = php_compat_sha1_add32_helper($h3, $d);
- $h4 = php_compat_sha1_add32_helper($h4, $e);
- }
-
- $h0 &= (int)0xffffffff;
- $h1 &= (int)0xffffffff;
- $h2 &= (int)0xffffffff;
- $h3 &= (int)0xffffffff;
- $h4 &= (int)0xffffffff;
-
- $hash = sprintf('%08x%08x%08x%08x%08x', $h0, $h1, $h2, $h3, $h4);
-
- if ($raw_output) {
- return pack('H*', $hash);
- } else {
- return $hash;
- }
-}
-
-function php_compat_sha1_add32_helper($x, $y)
-{
- $lsw = ($x & 0xffff) + ($y & 0xffff);
- $msw = ($x >> 16) + ($y >> 16) + ($lsw >> 16);
- return ($msw << 16) | ($lsw & 0xffff);
-}
-
-function php_compat_sha1_rotl_helper($x, $n)
-{
- return ($x << $n) | ($x >> (32 - $n)) & (0x7fffffff >> (31 - $n));
-}
-
-// Define
-if (!function_exists('sha1')) {
- function sha1($str, $raw_output = false)
- {
- return php_compat_sha1($str, $raw_output);
- }
-}
diff --git a/data/module/Compat/Compat/Function/sha256.php b/data/module/Compat/Compat/Function/sha256.php
deleted file mode 100644
index a19d0c51bb0..00000000000
--- a/data/module/Compat/Compat/Function/sha256.php
+++ /dev/null
@@ -1,156 +0,0 @@
-, Arpad Ray
- * @link http://php.net/function.hash
- * @author revulo
- * @require PHP 4.0.0
- */
-function php_compat_sha256($str, $raw_output = false)
-{
- $h0 = (int)0x6a09e667;
- $h1 = (int)0xbb67ae85;
- $h2 = (int)0x3c6ef372;
- $h3 = (int)0xa54ff53a;
- $h4 = (int)0x510e527f;
- $h5 = (int)0x9b05688c;
- $h6 = (int)0x1f83d9ab;
- $h7 = (int)0x5be0cd19;
-
- $k = array(
- (int)0x428a2f98, (int)0x71374491, (int)0xb5c0fbcf, (int)0xe9b5dba5,
- (int)0x3956c25b, (int)0x59f111f1, (int)0x923f82a4, (int)0xab1c5ed5,
- (int)0xd807aa98, (int)0x12835b01, (int)0x243185be, (int)0x550c7dc3,
- (int)0x72be5d74, (int)0x80deb1fe, (int)0x9bdc06a7, (int)0xc19bf174,
- (int)0xe49b69c1, (int)0xefbe4786, (int)0x0fc19dc6, (int)0x240ca1cc,
- (int)0x2de92c6f, (int)0x4a7484aa, (int)0x5cb0a9dc, (int)0x76f988da,
- (int)0x983e5152, (int)0xa831c66d, (int)0xb00327c8, (int)0xbf597fc7,
- (int)0xc6e00bf3, (int)0xd5a79147, (int)0x06ca6351, (int)0x14292967,
- (int)0x27b70a85, (int)0x2e1b2138, (int)0x4d2c6dfc, (int)0x53380d13,
- (int)0x650a7354, (int)0x766a0abb, (int)0x81c2c92e, (int)0x92722c85,
- (int)0xa2bfe8a1, (int)0xa81a664b, (int)0xc24b8b70, (int)0xc76c51a3,
- (int)0xd192e819, (int)0xd6990624, (int)0xf40e3585, (int)0x106aa070,
- (int)0x19a4c116, (int)0x1e376c08, (int)0x2748774c, (int)0x34b0bcb5,
- (int)0x391c0cb3, (int)0x4ed8aa4a, (int)0x5b9cca4f, (int)0x682e6ff3,
- (int)0x748f82ee, (int)0x78a5636f, (int)0x84c87814, (int)0x8cc70208,
- (int)0x90befffa, (int)0xa4506ceb, (int)0xbef9a3f7, (int)0xc67178f2
- );
-
- $len = strlen($str);
-
- $str .= "\x80";
- $str .= str_repeat("\0", 63 - ($len + 8) % 64);
- $str .= pack('N2', $len >> 29, $len << 3);
-
- for ($i = 0; $i < strlen($str); $i += 64) {
-
- $w = array();
- for ($j = 0; $j < 16; ++$j) {
- $index = $i + $j * 4;
- $w[$j] = ord($str[$index]) << 24
- | ord($str[$index + 1]) << 16
- | ord($str[$index + 2]) << 8
- | ord($str[$index + 3]);
- }
- for ($j = 16; $j < 64; ++$j) {
- $s0 = php_compat_sha256_rotr_helper($w[$j - 15], 7)
- ^ php_compat_sha256_rotr_helper($w[$j - 15], 18)
- ^ php_compat_sha256_shr_helper ($w[$j - 15], 3);
-
- $s1 = php_compat_sha256_rotr_helper($w[$j - 2], 17)
- ^ php_compat_sha256_rotr_helper($w[$j - 2], 19)
- ^ php_compat_sha256_shr_helper ($w[$j - 2], 10);
-
- $w[$j] = php_compat_sha256_add32_helper(
- php_compat_sha256_add32_helper(
- php_compat_sha256_add32_helper($w[$j - 16], $s0), $w[$j - 7]), $s1);
- }
-
- $a = $h0;
- $b = $h1;
- $c = $h2;
- $d = $h3;
- $e = $h4;
- $f = $h5;
- $g = $h6;
- $h = $h7;
-
- for ($j = 0; $j < 64; ++$j) {
- $s1 = php_compat_sha256_rotr_helper($e, 6)
- ^ php_compat_sha256_rotr_helper($e, 11)
- ^ php_compat_sha256_rotr_helper($e, 25);
-
- $ch = ($e & $f) ^ (~$e & $g);
-
- $s0 = php_compat_sha256_rotr_helper($a, 2)
- ^ php_compat_sha256_rotr_helper($a, 13)
- ^ php_compat_sha256_rotr_helper($a, 22);
-
- $maj = ($a & $b) ^ ($a & $c) ^ ($b & $c);
-
- $t1 = php_compat_sha256_add32_helper(
- php_compat_sha256_add32_helper(
- php_compat_sha256_add32_helper(
- php_compat_sha256_add32_helper($h, $s1), $ch), $k[$j]), $w[$j]);
-
- $t2 = php_compat_sha256_add32_helper($s0, $maj);
-
- $h = $g;
- $g = $f;
- $f = $e;
- $e = php_compat_sha256_add32_helper($d, $t1);
- $d = $c;
- $c = $b;
- $b = $a;
- $a = php_compat_sha256_add32_helper($t1, $t2);
- }
-
- $h0 = php_compat_sha256_add32_helper($h0, $a);
- $h1 = php_compat_sha256_add32_helper($h1, $b);
- $h2 = php_compat_sha256_add32_helper($h2, $c);
- $h3 = php_compat_sha256_add32_helper($h3, $d);
- $h4 = php_compat_sha256_add32_helper($h4, $e);
- $h5 = php_compat_sha256_add32_helper($h5, $f);
- $h6 = php_compat_sha256_add32_helper($h6, $g);
- $h7 = php_compat_sha256_add32_helper($h7, $h);
- }
-
- $h0 &= (int)0xffffffff;
- $h1 &= (int)0xffffffff;
- $h2 &= (int)0xffffffff;
- $h3 &= (int)0xffffffff;
- $h4 &= (int)0xffffffff;
- $h5 &= (int)0xffffffff;
- $h6 &= (int)0xffffffff;
- $h7 &= (int)0xffffffff;
-
- $hash = sprintf('%08x%08x%08x%08x%08x%08x%08x%08x', $h0, $h1, $h2, $h3, $h4, $h5, $h6, $h7);
-
- if ($raw_output) {
- return pack('H*', $hash);
- } else {
- return $hash;
- }
-}
-
-function php_compat_sha256_add32_helper($x, $y)
-{
- $lsw = ($x & 0xffff) + ($y & 0xffff);
- $msw = ($x >> 16) + ($y >> 16) + ($lsw >> 16);
- return ($msw << 16) | ($lsw & 0xffff);
-}
-
-function php_compat_sha256_shr_helper($x, $n)
-{
- return ($x >> $n) & (0x7fffffff >> ($n - 1));
-}
-
-function php_compat_sha256_rotr_helper($x, $n)
-{
- return ($x << (32 - $n)) | ($x >> $n) & (0x7fffffff >> ($n - 1));
-}
diff --git a/data/module/Compat/Compat/Function/str_ireplace.php b/data/module/Compat/Compat/Function/str_ireplace.php
deleted file mode 100644
index aa3cf4aa8f0..00000000000
--- a/data/module/Compat/Compat/Function/str_ireplace.php
+++ /dev/null
@@ -1,113 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: str_ireplace.php,v 1.18 2005/01/26 04:55:13 aidan Exp $
-
-
-/**
- * Replace str_ireplace()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.str_ireplace
- * @author Aidan Lister
- * @version $Revision: 1.18 $
- * @since PHP 5
- * @require PHP 4.0.0 (user_error)
- * @note count not by returned by reference, to enable
- * change '$count = null' to '&$count'
- */
-if (!function_exists('str_ireplace')) {
- function str_ireplace($search, $replace, $subject, $count = null)
- {
- // Sanity check
- if (is_string($search) && is_array($replace)) {
- user_error('Array to string conversion', E_USER_NOTICE);
- $replace = (string) $replace;
- }
-
- // If search isn't an array, make it one
- if (!is_array($search)) {
- $search = array ($search);
- }
- $search = array_values($search);
-
- // If replace isn't an array, make it one, and pad it to the length of search
- if (!is_array($replace)) {
- $replace_string = $replace;
-
- $replace = array ();
- for ($i = 0, $c = count($search); $i < $c; $i++) {
- $replace[$i] = $replace_string;
- }
- }
- $replace = array_values($replace);
-
- // Check the replace array is padded to the correct length
- $length_replace = count($replace);
- $length_search = count($search);
- if ($length_replace < $length_search) {
- for ($i = $length_replace; $i < $length_search; $i++) {
- $replace[$i] = '';
- }
- }
-
- // If subject is not an array, make it one
- $was_array = false;
- if (!is_array($subject)) {
- $was_array = true;
- $subject = array ($subject);
- }
-
- // Loop through each subject
- $count = 0;
- foreach ($subject as $subject_key => $subject_value) {
- // Loop through each search
- foreach ($search as $search_key => $search_value) {
- // Split the array into segments, in between each part is our search
- $segments = explode(strtolower($search_value), strtolower($subject_value));
-
- // The number of replacements done is the number of segments minus the first
- $count += count($segments) - 1;
- $pos = 0;
-
- // Loop through each segment
- foreach ($segments as $segment_key => $segment_value) {
- // Replace the lowercase segments with the upper case versions
- $segments[$segment_key] = substr($subject_value, $pos, strlen($segment_value));
- // Increase the position relative to the initial string
- $pos += strlen($segment_value) + strlen($search_value);
- }
-
- // Put our original string back together
- $subject_value = implode($replace[$search_key], $segments);
- }
-
- $result[$subject_key] = $subject_value;
- }
-
- // Check if subject was initially a string and return it as a string
- if ($was_array === true) {
- return $result[0];
- }
-
- // Otherwise, just return the array
- return $result;
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/str_rot13.php b/data/module/Compat/Compat/Function/str_rot13.php
deleted file mode 100644
index 25bebc25496..00000000000
--- a/data/module/Compat/Compat/Function/str_rot13.php
+++ /dev/null
@@ -1,43 +0,0 @@
- |
-// | Aidan Lister |
-// +----------------------------------------------------------------------+
-//
-// $Id: str_rot13.php,v 1.4 2005/01/26 04:55:13 aidan Exp $
-
-
-/**
- * Replace str_rot13()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.str_rot13
- * @author Alan Morey
- * @author Aidan Lister
- * @version $Revision: 1.4 $
- * @since PHP 4.0.0
- */
-if (!function_exists('str_rot13')) {
- function str_rot13($str)
- {
- $from = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
- $to = 'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM';
-
- return strtr($str, $from, $to);
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/str_shuffle.php b/data/module/Compat/Compat/Function/str_shuffle.php
deleted file mode 100644
index 0ab3ece24d6..00000000000
--- a/data/module/Compat/Compat/Function/str_shuffle.php
+++ /dev/null
@@ -1,52 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: str_shuffle.php,v 1.6 2005/08/14 03:24:16 aidan Exp $
-
-
-/**
- * Replace str_shuffle()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.str_shuffle
- * @author Aidan Lister
- * @version $Revision: 1.6 $
- * @since PHP 4.3.0
- * @require PHP 4.0.0 (user_error)
- */
-if (!function_exists('str_shuffle')) {
- function str_shuffle($str)
- {
- // Init
- $str = (string) $str;
-
- // Seed
- list($usec, $sec) = explode(' ', microtime());
- $seed = (float) $sec + ((float) $usec * 100000);
- mt_srand($seed);
-
- // Shuffle
- for ($new = '', $len = strlen($str); $len > 0; $str{$p} = $str{$len}) {
- $new .= $str{$p = mt_rand(0, --$len)};
- }
-
- return $new;
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/str_split.php b/data/module/Compat/Compat/Function/str_split.php
deleted file mode 100644
index 10d74550460..00000000000
--- a/data/module/Compat/Compat/Function/str_split.php
+++ /dev/null
@@ -1,71 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: str_split.php,v 1.15 2005/06/18 12:15:32 aidan Exp $
-
-
-/**
- * Replace str_split()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.str_split
- * @author Aidan Lister
- * @version $Revision: 1.15 $
- * @since PHP 5
- * @require PHP 4.0.0 (user_error)
- */
-if (!function_exists('str_split')) {
- function str_split($string, $split_length = 1)
- {
- if (!is_scalar($split_length)) {
- user_error('str_split() expects parameter 2 to be long, ' .
- gettype($split_length) . ' given', E_USER_WARNING);
- return false;
- }
-
- $split_length = (int) $split_length;
- if ($split_length < 1) {
- user_error('str_split() The length of each segment must be greater than zero', E_USER_WARNING);
- return false;
- }
-
- // Select split method
- if ($split_length < 65536) {
- // Faster, but only works for less than 2^16
- preg_match_all('/.{1,' . $split_length . '}/s', $string, $matches);
- return $matches[0];
- } else {
- // Required due to preg limitations
- $arr = array();
- $idx = 0;
- $pos = 0;
- $len = strlen($string);
-
- while ($len > 0) {
- $blk = ($len < $split_length) ? $len : $split_length;
- $arr[$idx++] = substr($string, $pos, $blk);
- $pos += $blk;
- $len -= $blk;
- }
-
- return $arr;
- }
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/str_word_count.php b/data/module/Compat/Compat/Function/str_word_count.php
deleted file mode 100644
index 623afa837f1..00000000000
--- a/data/module/Compat/Compat/Function/str_word_count.php
+++ /dev/null
@@ -1,68 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: str_word_count.php,v 1.9 2005/02/28 11:45:28 aidan Exp $
-
-
-/**
- * Replace str_word_count()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.str_word_count
- * @author Aidan Lister
- * @version $Revision: 1.9 $
- * @since PHP 4.3.0
- * @require PHP 4.0.0 (user_error)
- */
-if (!function_exists('str_word_count')) {
- function str_word_count($string, $format = null)
- {
- if ($format !== 1 && $format !== 2 && $format !== null) {
- user_error('str_word_count() The specified format parameter, "' . $format . '" is invalid',
- E_USER_WARNING);
- return false;
- }
-
- $word_string = preg_replace('/[0-9]+/', '', $string);
- $word_array = preg_split('/[^A-Za-z0-9_\']+/', $word_string, -1, PREG_SPLIT_NO_EMPTY);
-
- switch ($format) {
- case null:
- $result = count($word_array);
- break;
-
- case 1:
- $result = $word_array;
- break;
-
- case 2:
- $lastmatch = 0;
- $word_assoc = array();
- foreach ($word_array as $word) {
- $word_assoc[$lastmatch = strpos($string, $word, $lastmatch)] = $word;
- $lastmatch += strlen($word);
- }
- $result = $word_assoc;
- break;
- }
-
- return $result;
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/stripos.php b/data/module/Compat/Compat/Function/stripos.php
deleted file mode 100644
index efac325eede..00000000000
--- a/data/module/Compat/Compat/Function/stripos.php
+++ /dev/null
@@ -1,73 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: stripos.php,v 1.13 2005/05/30 20:33:03 aidan Exp $
-
-
-/**
- * Replace stripos()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.stripos
- * @author Aidan Lister
- * @version $Revision: 1.13 $
- * @since PHP 5
- * @require PHP 4.0.0 (user_error)
- */
-if (!function_exists('stripos')) {
- function stripos($haystack, $needle, $offset = null)
- {
- if (!is_scalar($haystack)) {
- user_error('stripos() expects parameter 1 to be string, ' .
- gettype($haystack) . ' given', E_USER_WARNING);
- return false;
- }
-
- if (!is_scalar($needle)) {
- user_error('stripos() needle is not a string or an integer.', E_USER_WARNING);
- return false;
- }
-
- if (!is_int($offset) && !is_bool($offset) && !is_null($offset)) {
- user_error('stripos() expects parameter 3 to be long, ' .
- gettype($offset) . ' given', E_USER_WARNING);
- return false;
- }
-
- // Manipulate the string if there is an offset
- $fix = 0;
- if (!is_null($offset)) {
- if ($offset > 0) {
- $haystack = substr($haystack, $offset, strlen($haystack) - $offset);
- $fix = $offset;
- }
- }
-
- $segments = explode(strtolower($needle), strtolower($haystack), 2);
-
- // Check there was a match
- if (count($segments) === 1) {
- return false;
- }
-
- $position = strlen($segments[0]) + $fix;
- return $position;
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/strpbrk.php b/data/module/Compat/Compat/Function/strpbrk.php
deleted file mode 100644
index 4c6a1158e8a..00000000000
--- a/data/module/Compat/Compat/Function/strpbrk.php
+++ /dev/null
@@ -1,63 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: strpbrk.php,v 1.4 2005/01/26 04:55:13 aidan Exp $
-
-
-/**
- * Replace strpbrk()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.strpbrk
- * @author Stephan Schmidt
- * @version $Revision: 1.4 $
- * @since PHP 5
- * @require PHP 4.0.0 (user_error)
- */
-if (!function_exists('strpbrk')) {
- function strpbrk($haystack, $char_list)
- {
- if (!is_scalar($haystack)) {
- user_error('strpbrk() expects parameter 1 to be string, ' .
- gettype($haystack) . ' given', E_USER_WARNING);
- return false;
- }
-
- if (!is_scalar($char_list)) {
- user_error('strpbrk() expects parameter 2 to be scalar, ' .
- gettype($needle) . ' given', E_USER_WARNING);
- return false;
- }
-
- $haystack = (string) $haystack;
- $char_list = (string) $char_list;
-
- $len = strlen($haystack);
- for ($i = 0; $i < $len; $i++) {
- $char = substr($haystack, $i, 1);
- if (strpos($char_list, $char) === false) {
- continue;
- }
- return substr($haystack, $i);
- }
-
- return false;
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/strripos.php b/data/module/Compat/Compat/Function/strripos.php
deleted file mode 100644
index c178a9af5bf..00000000000
--- a/data/module/Compat/Compat/Function/strripos.php
+++ /dev/null
@@ -1,79 +0,0 @@
- |
-// | Stephan Schmidt |
-// +----------------------------------------------------------------------+
-//
-// $Id: strripos.php,v 1.24 2005/08/10 10:19:59 aidan Exp $
-
-
-/**
- * Replace strripos()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.strripos
- * @author Aidan Lister
- * @version $Revision: 1.24 $
- * @since PHP 5
- * @require PHP 4.0.0 (user_error)
- */
-if (!function_exists('strripos')) {
- function strripos($haystack, $needle, $offset = null)
- {
- // Sanity check
- if (!is_scalar($haystack)) {
- user_error('strripos() expects parameter 1 to be scalar, ' .
- gettype($haystack) . ' given', E_USER_WARNING);
- return false;
- }
-
- if (!is_scalar($needle)) {
- user_error('strripos() expects parameter 2 to be scalar, ' .
- gettype($needle) . ' given', E_USER_WARNING);
- return false;
- }
-
- if (!is_int($offset) && !is_bool($offset) && !is_null($offset)) {
- user_error('strripos() expects parameter 3 to be long, ' .
- gettype($offset) . ' given', E_USER_WARNING);
- return false;
- }
-
- // Initialise variables
- $needle = strtolower($needle);
- $haystack = strtolower($haystack);
- $needle_fc = $needle{0};
- $needle_len = strlen($needle);
- $haystack_len = strlen($haystack);
- $offset = (int) $offset;
- $leftlimit = ($offset >= 0) ? $offset : 0;
- $p = ($offset >= 0) ?
- $haystack_len :
- $haystack_len + $offset + 1;
-
- // Reverse iterate haystack
- while (--$p >= $leftlimit) {
- if ($needle_fc === $haystack{$p} &&
- substr($haystack, $p, $needle_len) === $needle) {
- return $p;
- }
- }
-
- return false;
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/substr_compare.php b/data/module/Compat/Compat/Function/substr_compare.php
deleted file mode 100644
index edfa4ccb9d7..00000000000
--- a/data/module/Compat/Compat/Function/substr_compare.php
+++ /dev/null
@@ -1,74 +0,0 @@
- |
-// | Aidan Lister |
-// +----------------------------------------------------------------------+
-//
-// $Id: substr_compare.php,v 1.5 2005/01/26 04:55:13 aidan Exp $
-
-
-/**
- * Replace substr_compare()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.substr_compare
- * @author Tom Buskens
- * @author Aidan Lister
- * @version $Revision: 1.5 $
- * @since PHP 5
- * @require PHP 4.0.0 (user_error)
- */
-if (!function_exists('substr_compare')) {
- function substr_compare($main_str, $str, $offset, $length = null, $case_insensitive = false)
- {
- if (!is_string($main_str)) {
- user_error('substr_compare() expects parameter 1 to be string, ' .
- gettype($main_str) . ' given', E_USER_WARNING);
- return;
- }
-
- if (!is_string($str)) {
- user_error('substr_compare() expects parameter 2 to be string, ' .
- gettype($str) . ' given', E_USER_WARNING);
- return;
- }
-
- if (!is_int($offset)) {
- user_error('substr_compare() expects parameter 3 to be long, ' .
- gettype($offset) . ' given', E_USER_WARNING);
- return;
- }
-
- if (is_null($length)) {
- $length = strlen($main_str) - $offset;
- } elseif ($offset >= strlen($main_str)) {
- user_error('substr_compare() The start position cannot exceed initial string length',
- E_USER_WARNING);
- return false;
- }
-
- $main_str = substr($main_str, $offset, $length);
- $str = substr($str, 0, strlen($main_str));
-
- if ($case_insensitive === false) {
- return strcmp($main_str, $str);
- } else {
- return strcasecmp($main_str, $str);
- }
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/time_sleep_until.php b/data/module/Compat/Compat/Function/time_sleep_until.php
deleted file mode 100644
index d015dc3eb1e..00000000000
--- a/data/module/Compat/Compat/Function/time_sleep_until.php
+++ /dev/null
@@ -1,48 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: time_sleep_until.php,v 1.2 2005/12/07 21:08:57 aidan Exp $
-
-
-/**
- * Replace time_sleep_until()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/time_sleep_until
- * @author Arpad Ray
- * @version $Revision: 1.2 $
- * @since PHP 5.1.0
- * @require PHP 4.0.1 (trigger_error)
- */
-if (!function_exists('time_sleep_until')) {
- function time_sleep_until($timestamp)
- {
- list($usec, $sec) = explode(' ', microtime());
- $now = $sec + $usec;
- if ($timestamp <= $now) {
- user_error('Specified timestamp is in the past', E_USER_WARNING);
- return false;
- }
-
- $diff = $timestamp - $now;
- usleep($diff * 1000000);
- return true;
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/var_export.php b/data/module/Compat/Compat/Function/var_export.php
deleted file mode 100644
index b15fe82288e..00000000000
--- a/data/module/Compat/Compat/Function/var_export.php
+++ /dev/null
@@ -1,136 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: var_export.php,v 1.15 2005/12/05 14:24:27 aidan Exp $
-
-
-/**
- * Replace var_export()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.var_export
- * @author Aidan Lister
- * @version $Revision: 1.15 $
- * @since PHP 4.2.0
- * @require PHP 4.0.0 (user_error)
- */
-if (!function_exists('var_export')) {
- function var_export($var, $return = false, $level = 0)
- {
- // Init
- $indent = ' ';
- $doublearrow = ' => ';
- $lineend = ",\n";
- $stringdelim = '\'';
- $newline = "\n";
- $find = array(null, '\\', '\'');
- $replace = array('NULL', '\\\\', '\\\'');
- $out = '';
-
- // Indent
- $level++;
- for ($i = 1, $previndent = ''; $i < $level; $i++) {
- $previndent .= $indent;
- }
-
- // Handle each type
- switch (gettype($var)) {
- // Array
- case 'array':
- $out = 'array (' . $newline;
- foreach ($var as $key => $value) {
- // Key
- if (is_string($key)) {
- // Make key safe
- for ($i = 0, $c = count($find); $i < $c; $i++) {
- $var = str_replace($find[$i], $replace[$i], $var);
- }
- $key = $stringdelim . $key . $stringdelim;
- }
-
- // Value
- if (is_array($value)) {
- $export = var_export($value, true, $level);
- $value = $newline . $previndent . $indent . $export;
- } else {
- $value = var_export($value, true, $level);
- }
-
- // Piece line together
- $out .= $previndent . $indent . $key . $doublearrow . $value . $lineend;
- }
-
- // End string
- $out .= $previndent . ')';
- break;
-
- // String
- case 'string':
- // Make the string safe
- for ($i = 0, $c = count($find); $i < $c; $i++) {
- $var = str_replace($find[$i], $replace[$i], $var);
- }
- $out = $stringdelim . $var . $stringdelim;
- break;
-
- // Number
- case 'integer':
- case 'double':
- $out = (string) $var;
- break;
-
- // Boolean
- case 'boolean':
- $out = $var ? 'true' : 'false';
- break;
-
- // NULLs
- case 'NULL':
- case 'resource':
- $out = 'NULL';
- break;
-
- // Objects
- case 'object':
- // Start the object export
- $out = $newline . $previndent . 'class ' . get_class($var) . ' {' . $newline;
-
- // Export the object vars
- foreach (get_object_vars($var) as $key => $val) {
- $out .= $previndent . ' var $' . $key . ' = ';
- if (is_array($val)) {
- $export = var_export($val, true, $level);
- $out .= $newline . $previndent . $indent . $export . ';' . $newline;
- } else {
- $out .= var_export($val, true, $level) . ';' . $newline;
- }
- }
- $out .= $previndent . '}';
- break;
- }
-
- // Method of output
- if ($return === true) {
- return $out;
- } else {
- echo $out;
- }
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/version_compare.php b/data/module/Compat/Compat/Function/version_compare.php
deleted file mode 100644
index ea6b12f505d..00000000000
--- a/data/module/Compat/Compat/Function/version_compare.php
+++ /dev/null
@@ -1,182 +0,0 @@
- |
-// | Aidan Lister |
-// +----------------------------------------------------------------------+
-//
-// $Id: version_compare.php,v 1.13 2005/08/01 12:21:14 aidan Exp $
-
-
-/**
- * Replace version_compare()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.version_compare
- * @author Philippe Jausions
- * @author Aidan Lister
- * @version $Revision: 1.13 $
- * @since PHP 4.1.0
- * @require PHP 4.0.5 (user_error)
- */
-if (!function_exists('version_compare')) {
- function version_compare($version1, $version2, $operator = '<')
- {
- // Check input
- if (!is_scalar($version1)) {
- user_error('version_compare() expects parameter 1 to be string, ' .
- gettype($version1) . ' given', E_USER_WARNING);
- return;
- }
-
- if (!is_scalar($version2)) {
- user_error('version_compare() expects parameter 2 to be string, ' .
- gettype($version2) . ' given', E_USER_WARNING);
- return;
- }
-
- if (!is_scalar($operator)) {
- user_error('version_compare() expects parameter 3 to be string, ' .
- gettype($operator) . ' given', E_USER_WARNING);
- return;
- }
-
- // Standardise versions
- $v1 = explode('.',
- str_replace('..', '.',
- preg_replace('/([^0-9\.]+)/', '.$1.',
- str_replace(array('-', '_', '+'), '.',
- trim($version1)))));
-
- $v2 = explode('.',
- str_replace('..', '.',
- preg_replace('/([^0-9\.]+)/', '.$1.',
- str_replace(array('-', '_', '+'), '.',
- trim($version2)))));
-
- // Replace empty entries at the start of the array
- while (empty($v1[0]) && array_shift($v1)) {}
- while (empty($v2[0]) && array_shift($v2)) {}
-
- // Release state order
- // '#' stands for any number
- $versions = array(
- 'dev' => 0,
- 'alpha' => 1,
- 'a' => 1,
- 'beta' => 2,
- 'b' => 2,
- 'RC' => 3,
- '#' => 4,
- 'p' => 5,
- 'pl' => 5);
-
- // Loop through each segment in the version string
- $compare = 0;
- for ($i = 0, $x = min(count($v1), count($v2)); $i < $x; $i++) {
- if ($v1[$i] == $v2[$i]) {
- continue;
- }
- $i1 = $v1[$i];
- $i2 = $v2[$i];
- if (is_numeric($i1) && is_numeric($i2)) {
- $compare = ($i1 < $i2) ? -1 : 1;
- break;
- }
-
- // We use the position of '#' in the versions list
- // for numbers... (so take care of # in original string)
- if ($i1 == '#') {
- $i1 = '';
- } elseif (is_numeric($i1)) {
- $i1 = '#';
- }
-
- if ($i2 == '#') {
- $i2 = '';
- } elseif (is_numeric($i2)) {
- $i2 = '#';
- }
-
- if (isset($versions[$i1]) && isset($versions[$i2])) {
- $compare = ($versions[$i1] < $versions[$i2]) ? -1 : 1;
- } elseif (isset($versions[$i1])) {
- $compare = 1;
- } elseif (isset($versions[$i2])) {
- $compare = -1;
- } else {
- $compare = 0;
- }
-
- break;
- }
-
- // If previous loop didn't find anything, compare the "extra" segments
- if ($compare == 0) {
- if (count($v2) > count($v1)) {
- if (isset($versions[$v2[$i]])) {
- $compare = ($versions[$v2[$i]] < 4) ? 1 : -1;
- } else {
- $compare = -1;
- }
- } elseif (count($v2) < count($v1)) {
- if (isset($versions[$v1[$i]])) {
- $compare = ($versions[$v1[$i]] < 4) ? -1 : 1;
- } else {
- $compare = 1;
- }
- }
- }
-
- // Compare the versions
- if (func_num_args() > 2) {
- switch ($operator) {
- case '>':
- case 'gt':
- return (bool) ($compare > 0);
- break;
- case '>=':
- case 'ge':
- return (bool) ($compare >= 0);
- break;
- case '<=':
- case 'le':
- return (bool) ($compare <= 0);
- break;
- case '==':
- case '=':
- case 'eq':
- return (bool) ($compare == 0);
- break;
- case '<>':
- case '!=':
- case 'ne':
- return (bool) ($compare != 0);
- break;
- case '':
- case '<':
- case 'lt':
- return (bool) ($compare < 0);
- break;
- default:
- return;
- }
- }
-
- return $compare;
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/vprintf.php b/data/module/Compat/Compat/Function/vprintf.php
deleted file mode 100644
index 6a600a0afc3..00000000000
--- a/data/module/Compat/Compat/Function/vprintf.php
+++ /dev/null
@@ -1,45 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: vprintf.php,v 1.14 2005/01/26 04:55:13 aidan Exp $
-
-
-/**
- * Replace vprintf()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.vprintf
- * @author Aidan Lister
- * @version $Revision: 1.14 $
- * @since PHP 4.1.0
- * @require PHP 4.0.4 (call_user_func_array)
- */
-if (!function_exists('vprintf')) {
- function vprintf ($format, $args)
- {
- if (count($args) < 2) {
- user_error('vprintf() Too few arguments', E_USER_WARNING);
- return;
- }
-
- array_unshift($args, $format);
- return call_user_func_array('printf', $args);
- }
-}
-
-?>
diff --git a/data/module/Compat/Compat/Function/vsprintf.php b/data/module/Compat/Compat/Function/vsprintf.php
deleted file mode 100644
index 84ec73aca4a..00000000000
--- a/data/module/Compat/Compat/Function/vsprintf.php
+++ /dev/null
@@ -1,45 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: vsprintf.php,v 1.10 2005/01/26 04:55:13 aidan Exp $
-
-
-/**
- * Replace vsprintf()
- *
- * @category PHP
- * @package PHP_Compat
- * @link http://php.net/function.vsprintf
- * @author Aidan Lister
- * @version $Revision: 1.10 $
- * @since PHP 4.1.0
- * @require PHP 4.0.4 (call_user_func_array)
- */
-if (!function_exists('vsprintf')) {
- function vsprintf ($format, $args)
- {
- if (count($args) < 2) {
- user_error('vsprintf() Too few arguments', E_USER_WARNING);
- return;
- }
-
- array_unshift($args, $format);
- return call_user_func_array('sprintf', $args);
- }
-}
-
-?>
diff --git a/data/module/Compat/tests/constant/directory_separator.phpt b/data/module/Compat/tests/constant/directory_separator.phpt
deleted file mode 100644
index 412e0ca8c10..00000000000
--- a/data/module/Compat/tests/constant/directory_separator.phpt
+++ /dev/null
@@ -1,15 +0,0 @@
---TEST--
-Constant -- DIRECTORY_SEPARATOR
---SKIPIF--
-
---FILE--
-
---EXPECT--
-true
\ No newline at end of file
diff --git a/data/module/Compat/tests/constant/e_strict.phpt b/data/module/Compat/tests/constant/e_strict.phpt
deleted file mode 100644
index 5faffcd42c4..00000000000
--- a/data/module/Compat/tests/constant/e_strict.phpt
+++ /dev/null
@@ -1,13 +0,0 @@
---TEST--
-Constant -- E_STRICT
---SKIPIF--
-
---FILE--
-
---EXPECT--
-2048
\ No newline at end of file
diff --git a/data/module/Compat/tests/constant/file.phpt b/data/module/Compat/tests/constant/file.phpt
deleted file mode 100644
index f7d6de9d260..00000000000
--- a/data/module/Compat/tests/constant/file.phpt
+++ /dev/null
@@ -1,21 +0,0 @@
---TEST--
-Constant -- File System Constants
---SKIPIF--
-
---FILE--
-
---EXPECT--
-1
-2
-4
-8
-16
\ No newline at end of file
diff --git a/data/module/Compat/tests/constant/path_separator.phpt b/data/module/Compat/tests/constant/path_separator.phpt
deleted file mode 100644
index cd5b7c08085..00000000000
--- a/data/module/Compat/tests/constant/path_separator.phpt
+++ /dev/null
@@ -1,15 +0,0 @@
---TEST--
-Constant -- PATH_SEPARATOR
---SKIPIF--
-
---FILE--
-
---EXPECT--
-true
\ No newline at end of file
diff --git a/data/module/Compat/tests/constant/php_eol.phpt b/data/module/Compat/tests/constant/php_eol.phpt
deleted file mode 100644
index 57fee360642..00000000000
--- a/data/module/Compat/tests/constant/php_eol.phpt
+++ /dev/null
@@ -1,17 +0,0 @@
---TEST--
-Constant -- PHP_EOL
---SKIPIF--
-
---FILE--
-
---EXPECT--
-true
\ No newline at end of file
diff --git a/data/module/Compat/tests/constant/std.phpt b/data/module/Compat/tests/constant/std.phpt
deleted file mode 100644
index 0826bb92207..00000000000
--- a/data/module/Compat/tests/constant/std.phpt
+++ /dev/null
@@ -1,17 +0,0 @@
---TEST--
-Constant -- CLI Constants
---SKIPIF--
-
---FILE--
-
---EXPECT--
-true
-true
-true
\ No newline at end of file
diff --git a/data/module/Compat/tests/constant/t.phpt b/data/module/Compat/tests/constant/t.phpt
deleted file mode 100644
index 6fb65355a34..00000000000
--- a/data/module/Compat/tests/constant/t.phpt
+++ /dev/null
@@ -1,48 +0,0 @@
---TEST--
-Constant -- Tokenizer constants
---FILE--
-
---EXPECT--
-true
-true
-true
-true
-true
-true
-true
-true
-true
-true
-true
-true
-true
-true
\ No newline at end of file
diff --git a/data/module/Compat/tests/constant/upload_err.phpt b/data/module/Compat/tests/constant/upload_err.phpt
deleted file mode 100644
index 6bddce8a6f7..00000000000
--- a/data/module/Compat/tests/constant/upload_err.phpt
+++ /dev/null
@@ -1,20 +0,0 @@
---TEST--
-Constant -- Upload error constants
---FILE--
-
---EXPECT--
-0
-1
-2
-3
-4
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/array_change_key_case.phpt b/data/module/Compat/tests/function/array_change_key_case.phpt
deleted file mode 100644
index 5d36af6394d..00000000000
--- a/data/module/Compat/tests/function/array_change_key_case.phpt
+++ /dev/null
@@ -1,100 +0,0 @@
---TEST--
-Function -- array_change_key_case
---SKIPIF--
-
---FILE--
- 1, 'SecOnd' => 4);
-print_r(array_change_key_case($in));
-print_r(array_change_key_case($in, CASE_LOWER));
-print_r(array_change_key_case($in, CASE_UPPER));
-$in = array('FIRST' => 1, 'SECOND' => 4);
-print_r(array_change_key_case($in));
-print_r(array_change_key_case($in, CASE_LOWER));
-print_r(array_change_key_case($in, CASE_UPPER));
-$in = array('first' => 1, 'second' => 4);
-print_r(array_change_key_case($in));
-print_r(array_change_key_case($in, CASE_LOWER));
-print_r(array_change_key_case($in, CASE_UPPER));
-$in = array('foo', 'bar');
-print_r(array_change_key_case($in));
-print_r(array_change_key_case($in, CASE_LOWER));
-print_r(array_change_key_case($in, CASE_UPPER));
-$in = array();
-print_r(array_change_key_case($in));
-print_r(array_change_key_case($in, CASE_LOWER));
-print_r(array_change_key_case($in, CASE_UPPER));
-?>
---EXPECT--
-Array
-(
- [first] => 1
- [second] => 4
-)
-Array
-(
- [first] => 1
- [second] => 4
-)
-Array
-(
- [FIRST] => 1
- [SECOND] => 4
-)
-Array
-(
- [first] => 1
- [second] => 4
-)
-Array
-(
- [first] => 1
- [second] => 4
-)
-Array
-(
- [FIRST] => 1
- [SECOND] => 4
-)
-Array
-(
- [first] => 1
- [second] => 4
-)
-Array
-(
- [first] => 1
- [second] => 4
-)
-Array
-(
- [FIRST] => 1
- [SECOND] => 4
-)
-Array
-(
- [0] => foo
- [1] => bar
-)
-Array
-(
- [0] => foo
- [1] => bar
-)
-Array
-(
- [0] => foo
- [1] => bar
-)
-Array
-(
-)
-Array
-(
-)
-Array
-(
-)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/array_chunk.phpt b/data/module/Compat/tests/function/array_chunk.phpt
deleted file mode 100644
index f7fdd20e6ea..00000000000
--- a/data/module/Compat/tests/function/array_chunk.phpt
+++ /dev/null
@@ -1,174 +0,0 @@
---TEST--
-Function -- array_chunk
---SKIPIF--
-
---FILE--
- 'a', 3 => 'b', 4 => 'c', 5 => 'd', 6 => 'e');
-print_r(array_chunk($input_array, 2));
-print_r(array_chunk($input_array, 2, true));
-print_r(array_chunk($input_array, 3));
-print_r(array_chunk($input_array, 3, true));
-print_r(array_chunk($input_array, 4));
-print_r(array_chunk($input_array, 4, true));
-print_r(array_chunk($input_array, 5));
-print_r(array_chunk($input_array, 5, true));
-print_r(array_chunk($input_array, 6));
-print_r(array_chunk($input_array, 6, true));
-?>
---EXPECT--
-Array
-(
- [0] => Array
- (
- [0] => a
- [1] => b
- )
-
- [1] => Array
- (
- [0] => c
- [1] => d
- )
-
- [2] => Array
- (
- [0] => e
- )
-
-)
-Array
-(
- [0] => Array
- (
- [2] => a
- [3] => b
- )
-
- [1] => Array
- (
- [4] => c
- [5] => d
- )
-
- [2] => Array
- (
- [6] => e
- )
-
-)
-Array
-(
- [0] => Array
- (
- [0] => a
- [1] => b
- [2] => c
- )
-
- [1] => Array
- (
- [0] => d
- [1] => e
- )
-
-)
-Array
-(
- [0] => Array
- (
- [2] => a
- [3] => b
- [4] => c
- )
-
- [1] => Array
- (
- [5] => d
- [6] => e
- )
-
-)
-Array
-(
- [0] => Array
- (
- [0] => a
- [1] => b
- [2] => c
- [3] => d
- )
-
- [1] => Array
- (
- [0] => e
- )
-
-)
-Array
-(
- [0] => Array
- (
- [2] => a
- [3] => b
- [4] => c
- [5] => d
- )
-
- [1] => Array
- (
- [6] => e
- )
-
-)
-Array
-(
- [0] => Array
- (
- [0] => a
- [1] => b
- [2] => c
- [3] => d
- [4] => e
- )
-
-)
-Array
-(
- [0] => Array
- (
- [2] => a
- [3] => b
- [4] => c
- [5] => d
- [6] => e
- )
-
-)
-Array
-(
- [0] => Array
- (
- [0] => a
- [1] => b
- [2] => c
- [3] => d
- [4] => e
- )
-
-)
-Array
-(
- [0] => Array
- (
- [2] => a
- [3] => b
- [4] => c
- [5] => d
- [6] => e
- )
-
-)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/array_combine.phpt b/data/module/Compat/tests/function/array_combine.phpt
deleted file mode 100644
index 87fb897392b..00000000000
--- a/data/module/Compat/tests/function/array_combine.phpt
+++ /dev/null
@@ -1,22 +0,0 @@
---TEST--
-Function -- array_combine
---SKIPIF--
-
---FILE--
-
---EXPECT--
-Array
-(
- [green] => avocado
- [red] => apple
- [yellow] => banana
-)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/array_diff_assoc.phpt b/data/module/Compat/tests/function/array_diff_assoc.phpt
deleted file mode 100644
index 85b9c0eb4c9..00000000000
--- a/data/module/Compat/tests/function/array_diff_assoc.phpt
+++ /dev/null
@@ -1,21 +0,0 @@
---TEST--
-Function -- array_diff_assoc
---SKIPIF--
-
---FILE--
- "green", "b" => "brown", "c" => "blue", "red");
-$array2 = array("a" => "green", "yellow", "red");
-$result = array_diff_assoc($array1, $array2);
-print_r($result);
-?>
---EXPECT--
-Array
-(
- [b] => brown
- [c] => blue
- [0] => red
-)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/array_diff_key.phpt b/data/module/Compat/tests/function/array_diff_key.phpt
deleted file mode 100644
index cf8eae39bed..00000000000
--- a/data/module/Compat/tests/function/array_diff_key.phpt
+++ /dev/null
@@ -1,21 +0,0 @@
---TEST--
-Function -- array_diff_key
---SKIPIF--
-
---FILE--
- 1, 'red' => 2, 'green' => 3, 'purple' => 4);
-$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan' => 8);
-
-print_r(array_diff_key($array1, $array2));
-
-?>
---EXPECT--
-Array
-(
- [red] => 2
- [purple] => 4
-)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/array_diff_uassoc.phpt b/data/module/Compat/tests/function/array_diff_uassoc.phpt
deleted file mode 100644
index 55768f2ba23..00000000000
--- a/data/module/Compat/tests/function/array_diff_uassoc.phpt
+++ /dev/null
@@ -1,31 +0,0 @@
---TEST--
-Function -- array_diff_uassoc
---SKIPIF--
-
---FILE--
- $b) ? 1 : -1;
-}
-
-$array1 = array('a' => 'green', 'b' => 'brown', 'c' => 'blue', 'red');
-$array2 = array('a' => 'green', 'yellow', 'red');
-$result = array_diff_uassoc($array1, $array2, 'key_compare_func');
-print_r($result);
-
-?>
---EXPECT--
-Array
-(
- [b] => brown
- [c] => blue
- [0] => red
-)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/array_diff_ukey.phpt b/data/module/Compat/tests/function/array_diff_ukey.phpt
deleted file mode 100644
index 8abcbbfc760..00000000000
--- a/data/module/Compat/tests/function/array_diff_ukey.phpt
+++ /dev/null
@@ -1,32 +0,0 @@
---TEST--
-Function -- array_diff_ukey
---SKIPIF--
-
---FILE--
- $key2) {
- return 1;
- } else {
- return -1;
- }
-}
-
-$array1 = array('blue' => 1, 'red' => 2, 'green' => 3, 'purple' => 4);
-$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan' => 8);
-
-print_r(array_diff_ukey($array1, $array2, 'key_compare_func'));
-
-?>
---EXPECT--
-Array
-(
- [red] => 2
- [purple] => 4
-)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/array_intersect_assoc.phpt b/data/module/Compat/tests/function/array_intersect_assoc.phpt
deleted file mode 100644
index 87f5fa8bc23..00000000000
--- a/data/module/Compat/tests/function/array_intersect_assoc.phpt
+++ /dev/null
@@ -1,20 +0,0 @@
---TEST--
-Function -- array_intersect_assoc
---SKIPIF--
-
---FILE--
- "green", "b" => "brown", "c" => "blue", "red");
-$array2 = array("a" => "green", "yellow", "red");
-$result = array_intersect_assoc($array1, $array2);
-print_r($result);
-
-?>
---EXPECT--
-Array
-(
- [a] => green
-)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/array_intersect_key.phpt b/data/module/Compat/tests/function/array_intersect_key.phpt
deleted file mode 100644
index f19371bd5be..00000000000
--- a/data/module/Compat/tests/function/array_intersect_key.phpt
+++ /dev/null
@@ -1,21 +0,0 @@
---TEST--
-Function -- array_intersect_key
---SKIPIF--
-
---FILE--
- 1, 'red' => 2, 'green' => 3, 'purple' => 4);
-$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan' => 8);
-
-print_r(array_intersect_key($array1, $array2));
-
-?>
---EXPECT--
-Array
-(
- [blue] => 1
- [green] => 3
-)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/array_intersect_uassoc.phpt b/data/module/Compat/tests/function/array_intersect_uassoc.phpt
deleted file mode 100644
index 07c41e4e530..00000000000
--- a/data/module/Compat/tests/function/array_intersect_uassoc.phpt
+++ /dev/null
@@ -1,20 +0,0 @@
---TEST--
-Function -- array_intersect_uassoc
---SKIPIF--
-
---FILE--
- "green", "b" => "brown", "c" => "blue", "red");
-$array2 = array("a" => "GREEN", "B" => "brown", "yellow", "red");
-
-print_r(array_intersect_uassoc($array1, $array2, "strcasecmp"));
-
-?>
---EXPECT--
-Array
-(
- [b] => brown
-)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/array_intersect_ukey.phpt b/data/module/Compat/tests/function/array_intersect_ukey.phpt
deleted file mode 100644
index 2658f4ec3d1..00000000000
--- a/data/module/Compat/tests/function/array_intersect_ukey.phpt
+++ /dev/null
@@ -1,32 +0,0 @@
---TEST--
-Function -- array_intersect_ukey
---SKIPIF--
-
---FILE--
- $key2) {
- return 1;
- } else {
- return -1;
- }
-}
-
-$array1 = array('blue' => 1, 'red' => 2, 'green' => 3, 'purple' => 4);
-$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan' => 8);
-
-print_r(array_intersect_ukey($array1, $array2, 'key_compare_func'));
-
-?>
---EXPECT--
-Array
-(
- [blue] => 1
- [green] => 3
-)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/array_key_exists.phpt b/data/module/Compat/tests/function/array_key_exists.phpt
deleted file mode 100644
index a5da114cd5c..00000000000
--- a/data/module/Compat/tests/function/array_key_exists.phpt
+++ /dev/null
@@ -1,16 +0,0 @@
---TEST--
-Function -- array_key_exists
---SKIPIF--
-
---FILE--
- 1, "second" => 4);
-if (array_key_exists("first", $search_array)) {
- echo "The 'first' element is in the array";
-}
-?>
---EXPECT--
-The 'first' element is in the array
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/array_product.phpt b/data/module/Compat/tests/function/array_product.phpt
deleted file mode 100644
index cbf1133d83c..00000000000
--- a/data/module/Compat/tests/function/array_product.phpt
+++ /dev/null
@@ -1,55 +0,0 @@
---TEST--
-Function -- array_product
---SKIPIF--
-
---FILE--
-
---EXPECT--
-testing: (foo)
- result: (Warning) NULL
-
-
-testing: ()
- result: int(0)
-
-
-testing: (0)
- result: int(0)
-
-
-testing: (3)
- result: int(3)
-
-
-testing: (3 * 3)
- result: int(9)
-
-
-testing: (0.5 * 2 * 3)
- result: float(3)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/array_search.phpt b/data/module/Compat/tests/function/array_search.phpt
deleted file mode 100644
index 989c44c7f87..00000000000
--- a/data/module/Compat/tests/function/array_search.phpt
+++ /dev/null
@@ -1,17 +0,0 @@
---TEST--
-Function -- array_search
---SKIPIF--
-
---FILE--
- 'blue', 1 => 'red', 2 => 'green', 3 => 'red');
-
-var_dump(array_search('green', $array));
-var_dump(array_search('red', $array));
-?>
---EXPECT--
-int(2)
-int(1)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/array_udiff.phpt b/data/module/Compat/tests/function/array_udiff.phpt
deleted file mode 100644
index 1f4530bcb7c..00000000000
--- a/data/module/Compat/tests/function/array_udiff.phpt
+++ /dev/null
@@ -1,31 +0,0 @@
---TEST--
-Function -- array_udiff
---SKIPIF--
-
---FILE--
-priv_member = $val;
- }
-
- function comp_func_cr($a, $b)
- {
- if ($a->priv_member === $b->priv_member) return 0;
- return ($a->priv_member > $b->priv_member)? 1:-1;
- }
-}
-
-$a = array("0.1" => new cr(9), "0.5" => new cr(12), 0 => new cr(23), 1=> new cr(4), 2 => new cr(-15),);
-$b = array("0.2" => new cr(9), "0.5" => new cr(22), 0 => new cr(3), 1=> new cr(4), 2 => new cr(-15),);
-
-$result = array_udiff($a, $b, array("cr", "comp_func_cr"));
-echo serialize($result);
-?>
---EXPECT--
-a:2:{s:3:"0.5";O:2:"cr":1:{s:11:"priv_member";i:12;}i:0;O:2:"cr":1:{s:11:"priv_member";i:23;}}
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/array_udiff_assoc.phpt b/data/module/Compat/tests/function/array_udiff_assoc.phpt
deleted file mode 100644
index dcb1ebc4150..00000000000
--- a/data/module/Compat/tests/function/array_udiff_assoc.phpt
+++ /dev/null
@@ -1,31 +0,0 @@
---TEST--
-Function -- array_udiff_assoc
---SKIPIF--
-
---FILE--
-priv_member = $val;
- }
-
- function comp_func_cr($a, $b)
- {
- if ($a->priv_member === $b->priv_member) return 0;
- return ($a->priv_member > $b->priv_member)? 1:-1;
- }
-}
-
-$a = array("0.1" => new cr(9), "0.5" => new cr(12), 0 => new cr(23), 1=> new cr(4), 2 => new cr(-15),);
-$b = array("0.2" => new cr(9), "0.5" => new cr(22), 0 => new cr(3), 1=> new cr(4), 2 => new cr(-15),);
-
-$result = array_udiff_assoc($a, $b, array("cr", "comp_func_cr"));
-echo serialize($result);
-?>
---EXPECT--
-a:3:{s:3:"0.1";O:2:"cr":1:{s:11:"priv_member";i:9;}s:3:"0.5";O:2:"cr":1:{s:11:"priv_member";i:12;}i:0;O:2:"cr":1:{s:11:"priv_member";i:23;}}
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/array_udiff_uassoc.phpt b/data/module/Compat/tests/function/array_udiff_uassoc.phpt
deleted file mode 100644
index 6fb446fc682..00000000000
--- a/data/module/Compat/tests/function/array_udiff_uassoc.phpt
+++ /dev/null
@@ -1,56 +0,0 @@
---TEST--
-Function -- array_udiff_uassoc
---SKIPIF--
-
---FILE--
-val = $val;
- }
-
- function comp_func_cr($a, $b)
- {
- if ($a->val === $b->val) return 0;
- return ($a->val > $b->val) ? 1 : -1;
- }
-
- function comp_func_key($a, $b)
- {
- if ($a === $b) return 0;
- return ($a > $b) ? 1 : -1;
- }
-}
-
-$a = array('0.1' => new cr(9), '0.5' => new cr(12), 0 => new cr(23), 1 => new cr(4), 2 => new cr(-15));
-$b = array('0.2' => new cr(9), '0.5' => new cr(22), 0 => new cr(3), 1 => new cr(4), 2 => new cr(-15));
-
-$result = array_udiff_uassoc($a, $b, array('cr', 'comp_func_cr'), array('cr', 'comp_func_key'));
-print_r($result);
-?>
---EXPECT--
-Array
-(
- [0.1] => cr Object
- (
- [val] => 9
- )
-
- [0.5] => cr Object
- (
- [val] => 12
- )
-
- [0] => cr Object
- (
- [val] => 23
- )
-
-)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/array_uintersect.phpt b/data/module/Compat/tests/function/array_uintersect.phpt
deleted file mode 100644
index 0a3c4e6c726..00000000000
--- a/data/module/Compat/tests/function/array_uintersect.phpt
+++ /dev/null
@@ -1,21 +0,0 @@
---TEST--
-Function -- array_uintersect
---SKIPIF--
-
---FILE--
- 'green', 'b' => 'brown', 'c' => 'blue', 'red');
-$array2 = array('a' => 'GREEN', 'B' => 'brown', 'yellow', 'red');
-
-print_r(array_uintersect($array1, $array2, 'strcasecmp'));
-?>
---EXPECT--
-Array
-(
- [a] => green
- [b] => brown
- [0] => red
-)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/array_uintersect_assoc.phpt b/data/module/Compat/tests/function/array_uintersect_assoc.phpt
deleted file mode 100644
index 54486d3e2d8..00000000000
--- a/data/module/Compat/tests/function/array_uintersect_assoc.phpt
+++ /dev/null
@@ -1,19 +0,0 @@
---TEST--
-Function -- array_uintersect_assoc
---SKIPIF--
-
---FILE--
- 'green', 'b' => 'brown', 'c' => 'blue', 'red');
-$array2 = array('a' => 'GREEN', 'B' => 'brown', 'yellow', 'red');
-
-print_r(array_uintersect_assoc($array1, $array2, 'strcasecmp'));
-?>
---EXPECT--
-Array
-(
- [a] => green
-)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/array_uintersect_uassoc.phpt b/data/module/Compat/tests/function/array_uintersect_uassoc.phpt
deleted file mode 100644
index 34873770095..00000000000
--- a/data/module/Compat/tests/function/array_uintersect_uassoc.phpt
+++ /dev/null
@@ -1,20 +0,0 @@
---TEST--
-Function -- array_uintersect_uassoc
---SKIPIF--
-
---FILE--
- 'green', 'b' => 'brown', 'c' => 'blue', 'red');
-$array2 = array('a' => 'GREEN', 'B' => 'brown', 'yellow', 'red');
-
-print_r(array_uintersect_uassoc($array1, $array2, 'strcasecmp', 'strcasecmp'));
-?>
---EXPECT--
-Array
-(
- [a] => green
- [b] => brown
-)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/array_walk_recursive.phpt b/data/module/Compat/tests/function/array_walk_recursive.phpt
deleted file mode 100644
index 0e8f514134c..00000000000
--- a/data/module/Compat/tests/function/array_walk_recursive.phpt
+++ /dev/null
@@ -1,23 +0,0 @@
---TEST--
-Function -- array_walk_recursive
---SKIPIF--
-
---FILE--
- 'apple', 'b' => 'banana');
-$fruits = array('sweet' => $sweet, 'sour' => 'lemon');
-
-function test_print($item, $key)
-{
- echo "$key holds $item\n";
-}
-
-array_walk_recursive($fruits, 'test_print');
-?>
---EXPECT--
-a holds apple
-b holds banana
-sour holds lemon
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/bcinvert.phpt b/data/module/Compat/tests/function/bcinvert.phpt
deleted file mode 100644
index 57a907570cc..00000000000
--- a/data/module/Compat/tests/function/bcinvert.phpt
+++ /dev/null
@@ -1,13 +0,0 @@
---TEST--
-Function -- bcinvert
---SKIPIF--
-
---FILE--
-
---EXPECT--
-test
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/bcpowmod.phpt b/data/module/Compat/tests/function/bcpowmod.phpt
deleted file mode 100644
index bbc0f47f4e2..00000000000
--- a/data/module/Compat/tests/function/bcpowmod.phpt
+++ /dev/null
@@ -1,13 +0,0 @@
---TEST--
-Function -- bcpowmod
---SKIPIF--
-
---FILE--
-
---EXPECT--
-test
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/call_user_func_array.phpt b/data/module/Compat/tests/function/call_user_func_array.phpt
deleted file mode 100644
index a53f6616aa2..00000000000
--- a/data/module/Compat/tests/function/call_user_func_array.phpt
+++ /dev/null
@@ -1,20 +0,0 @@
---TEST--
-Function -- call_user_func_array
---SKIPIF--
-
---FILE--
-
---EXPECT--
-foo
-bar
-meta
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/clone.phpt b/data/module/Compat/tests/function/clone.phpt
deleted file mode 100644
index e358905d37e..00000000000
--- a/data/module/Compat/tests/function/clone.phpt
+++ /dev/null
@@ -1,69 +0,0 @@
---TEST--
-Function -- clone
---SKIPIF--
-
---FILE--
-foo = 'bar';
- }
-}
-
-class testclass3
-{
- var $bar;
-}
-
-class testclass4
-{
- var $foo;
- function __clone()
- {
- $this->foo = clone($this->foo);
- }
-}
-
-// Test 1: Initial value
-$aa = new testclass;
-echo $aa->foo, "\n"; // foo
-
-// Test 2: Not referenced
-$bb = clone($aa);
-$bb->foo = 'baz';
-echo $aa->foo, "\n"; // foo
-
-// Test 3: __clone method
-$cc = new testclass2;
-echo $cc->foo, "\n"; // foo
-$dd = clone($cc);
-echo $dd->foo, "\n"; // bar
-
-// Test 4: Bug #3649
-$a = new testclass3;
-$a->foo =& new testclass4;
-$a->foo->bar = 'hello';
-$aclone = clone($a);
-$aclone->b->bar = 'goodbye';
-echo $a->foo->bar, "\n";
-
-?>
---EXPECT--
-foo
-foo
-foo
-bar
-hello
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/constant.phpt b/data/module/Compat/tests/function/constant.phpt
deleted file mode 100644
index 03b40e73357..00000000000
--- a/data/module/Compat/tests/function/constant.phpt
+++ /dev/null
@@ -1,15 +0,0 @@
---TEST--
-Function -- constant
---SKIPIF--
-
---FILE--
-
---EXPECT--
-foo
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/convert_uudecode.phpt b/data/module/Compat/tests/function/convert_uudecode.phpt
deleted file mode 100644
index 30197f652c2..00000000000
--- a/data/module/Compat/tests/function/convert_uudecode.phpt
+++ /dev/null
@@ -1,14 +0,0 @@
---TEST--
-Function -- convert_uudecode
---SKIPIF--
-
---FILE--
-
---EXPECT--
-This is a simple test
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/convert_uuencode.phpt b/data/module/Compat/tests/function/convert_uuencode.phpt
deleted file mode 100644
index 1d19e82ecc7..00000000000
--- a/data/module/Compat/tests/function/convert_uuencode.phpt
+++ /dev/null
@@ -1,23 +0,0 @@
---TEST--
-Function -- convert_uuencode
---SKIPIF--
-
---FILE--
- $i; $i++) {
- $string .= str_repeat(chr($i), 10);
-}
-echo md5(convert_uuencode($string));
-
-?>
---EXPECT--
-d7974131c8970783f70851c83fe17767
-19acf7157a8345307ea5e5ea6878abb4
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/debug_print_backtrace.phpt b/data/module/Compat/tests/function/debug_print_backtrace.phpt
deleted file mode 100644
index d938d0132d3..00000000000
--- a/data/module/Compat/tests/function/debug_print_backtrace.phpt
+++ /dev/null
@@ -1,13 +0,0 @@
---TEST--
-Function -- debug_print_backtrace
---SKIPIF--
-
---FILE--
-
---EXPECT--
-test
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/file_get_contents.phpt b/data/module/Compat/tests/function/file_get_contents.phpt
deleted file mode 100644
index e4726b2b055..00000000000
--- a/data/module/Compat/tests/function/file_get_contents.phpt
+++ /dev/null
@@ -1,20 +0,0 @@
---TEST--
-Function -- file_get_contents
---SKIPIF--
-
---FILE--
-
---EXPECT--
-test test
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/file_put_contents.phpt b/data/module/Compat/tests/function/file_put_contents.phpt
deleted file mode 100644
index 80ba1111e05..00000000000
--- a/data/module/Compat/tests/function/file_put_contents.phpt
+++ /dev/null
@@ -1,47 +0,0 @@
---TEST--
-Function -- file_put_contents
---SKIPIF--
-
---FILE--
-
---EXPECT--
-4
-abcd
-6
-foobar
-6
-8
-foobartesttest
-8
-testtest
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/floatval.phpt b/data/module/Compat/tests/function/floatval.phpt
deleted file mode 100644
index 31a7f897817..00000000000
--- a/data/module/Compat/tests/function/floatval.phpt
+++ /dev/null
@@ -1,14 +0,0 @@
---TEST--
-Function -- floatval
---SKIPIF--
-
---FILE--
-
---EXPECT--
-float(12312.123)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/fprintf.phpt b/data/module/Compat/tests/function/fprintf.phpt
deleted file mode 100644
index 0c0f17e794a..00000000000
--- a/data/module/Compat/tests/function/fprintf.phpt
+++ /dev/null
@@ -1,20 +0,0 @@
---TEST--
-Function -- fprintf
---SKIPIF--
-
---FILE--
-
---EXPECT--
-The dog went to the park for 2 days
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/fputcsv.phpt b/data/module/Compat/tests/function/fputcsv.phpt
deleted file mode 100644
index bede70b8839..00000000000
--- a/data/module/Compat/tests/function/fputcsv.phpt
+++ /dev/null
@@ -1,13 +0,0 @@
---TEST--
-Function -- fputcsv
---SKIPIF--
-
---FILE--
-
---EXPECT--
-test
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/get_headers.phpt b/data/module/Compat/tests/function/get_headers.phpt
deleted file mode 100644
index c33c64ec11e..00000000000
--- a/data/module/Compat/tests/function/get_headers.phpt
+++ /dev/null
@@ -1,13 +0,0 @@
---TEST--
-Function -- get_headers
---SKIPIF--
-
---FILE--
-
---EXPECT--
-test
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/get_include_path.phpt b/data/module/Compat/tests/function/get_include_path.phpt
deleted file mode 100644
index 08e3b627c10..00000000000
--- a/data/module/Compat/tests/function/get_include_path.phpt
+++ /dev/null
@@ -1,15 +0,0 @@
---TEST--
-Function -- get_include_path
---SKIPIF--
-
---FILE--
-
---EXPECT--
-true
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/hash.phpt b/data/module/Compat/tests/function/hash.phpt
deleted file mode 100644
index ac7afb1aa58..00000000000
--- a/data/module/Compat/tests/function/hash.phpt
+++ /dev/null
@@ -1,21 +0,0 @@
---TEST--
-Function -- hash
---FILE--
-
---EXPECT--
-md5: bf33deeefaf5a9413160935be950cc07
-sha1: f0dc0e88cc1008e46762f40a1b4a4c0b6baedfa0
-sha256: a78149615dd1ef8aeb22a8254c36edd87713f2e79a052a89ff32ed94e827d47b
-md5(raw): bf33deeefaf5a9413160935be950cc07
-sha256(raw): a78149615dd1ef8aeb22a8254c36edd87713f2e79a052a89ff32ed94e827d47b
diff --git a/data/module/Compat/tests/function/hash_algos.phpt b/data/module/Compat/tests/function/hash_algos.phpt
deleted file mode 100644
index 26c1cbbf62c..00000000000
--- a/data/module/Compat/tests/function/hash_algos.phpt
+++ /dev/null
@@ -1,17 +0,0 @@
---TEST--
-Function -- hash_algos
---FILE--
-
---EXPECT--
-array(3) {
- [0]=>
- string(3) "md5"
- [1]=>
- string(4) "sha1"
- [2]=>
- string(6) "sha256"
-}
diff --git a/data/module/Compat/tests/function/hash_hmac.phpt b/data/module/Compat/tests/function/hash_hmac.phpt
deleted file mode 100644
index df42aaaf5b7..00000000000
--- a/data/module/Compat/tests/function/hash_hmac.phpt
+++ /dev/null
@@ -1,22 +0,0 @@
---TEST--
-Function -- hash_hmac
---FILE--
-
---EXPECT--
-md5: 2a632783e2812cf23de100d7d6a463ae
-sha1: 5bfdb62b97e2c987405463e9f7c193139c0e1fd0
-sha256: 49bde3496b9510a17d0edd8a4b0ac70148e32a1d51e881ec76faa96534125838
-md5(raw): 2a632783e2812cf23de100d7d6a463ae
-sha256(raw): 49bde3496b9510a17d0edd8a4b0ac70148e32a1d51e881ec76faa96534125838
diff --git a/data/module/Compat/tests/function/html_entity_decode.phpt b/data/module/Compat/tests/function/html_entity_decode.phpt
deleted file mode 100644
index e29bb225a96..00000000000
--- a/data/module/Compat/tests/function/html_entity_decode.phpt
+++ /dev/null
@@ -1,20 +0,0 @@
---TEST--
-Function -- html_entity_decode
---SKIPIF--
-
---FILE--
-
---EXPECT--
-I'll "walk" the dog now
-I'll "walk" the dog now
-I'll "walk" the dog now
-I'll "walk" the dog now
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/htmlspecialchars_decode.phpt b/data/module/Compat/tests/function/htmlspecialchars_decode.phpt
deleted file mode 100644
index 946ddb69d5f..00000000000
--- a/data/module/Compat/tests/function/htmlspecialchars_decode.phpt
+++ /dev/null
@@ -1,23 +0,0 @@
---TEST--
-Function -- htmlspecialchars_decode
---SKIPIF--
-
---FILE--
-
---EXPECT--
-Text & " ' < > End Text
-Text & " ' < > End Text
-Text & " ' < > End Text
-Text & " ' < > End Text
-Text & " ' < > End Text
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/http_build_query.phpt b/data/module/Compat/tests/function/http_build_query.phpt
deleted file mode 100644
index 524bd881644..00000000000
--- a/data/module/Compat/tests/function/http_build_query.phpt
+++ /dev/null
@@ -1,70 +0,0 @@
---TEST--
-Function -- http_build_query
---SKIPIF--
-
---INI--
-arg_separator.output=QQQ
---FILE--
-'bar',
- 'baz'=>'boom',
- 'cow'=>'milk',
- 'php'=>'hypertext processor');
-
-echo http_build_query($data), "\n";
-
-
-// With an object
-class myClass {
- var $foo;
- var $baz;
-
- function myClass()
- {
- $this->foo = 'bar';
- $this->baz = 'boom';
- }
-}
-
-$data = new myClass();
-echo http_build_query($data), "\n";
-
-
-// With numerically indexed elements
-$data = array('foo', 'bar', 'baz', 'boom', 'cow' => 'milk', 'php' =>'hypertext processor');
-echo http_build_query($data), "\n";
-echo http_build_query($data, 'myvar_'), "\n";
-
-
-// With a complex array
-$data = array('user' => array(
- 'name' => 'Bob Smith',
- 'age' => 47,
- 'sex' => 'M',
- 'dob' => '5/12/1956'),
- 'pastimes' => array(
- 'golf',
- 'opera',
- 'poker',
- 'rap'),
- 'children' => array(
- 'bobby' => array(
- 'age' => 12,
- 'sex' => 'M'),
- 'sally' => array(
- 'age' => 8,
- 'sex'=>'F')),
- 'CEO');
-
-echo http_build_query($data, 'flags_');
-?>
---EXPECT--
-foo=barQQQbaz=boomQQQcow=milkQQQphp=hypertext+processor
-foo=barQQQbaz=boom
-0=fooQQQ1=barQQQ2=bazQQQ3=boomQQQcow=milkQQQphp=hypertext+processor
-myvar_0=fooQQQmyvar_1=barQQQmyvar_2=bazQQQmyvar_3=boomQQQcow=milkQQQphp=hypertext+processor
-user[name]=Bob+SmithQQQuser[age]=47QQQuser[sex]=MQQQuser[dob]=5%2F12%2F1956QQQpastimes[0]=golfQQQpastimes[1]=operaQQQpastimes[2]=pokerQQQpastimes[3]=rapQQQchildren[bobby][age]=12QQQchildren[bobby][sex]=MQQQchildren[sally][age]=8QQQchildren[sally][sex]=FQQQflags_0=CEO
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/ibase_timefmt.phpt b/data/module/Compat/tests/function/ibase_timefmt.phpt
deleted file mode 100644
index da5e95e28e3..00000000000
--- a/data/module/Compat/tests/function/ibase_timefmt.phpt
+++ /dev/null
@@ -1,13 +0,0 @@
---TEST--
-Function -- ibase_timefmt
---SKIPIF--
-
---FILE--
-
---EXPECT--
-test
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/idate.phpt b/data/module/Compat/tests/function/idate.phpt
deleted file mode 100644
index 5fde61e6e96..00000000000
--- a/data/module/Compat/tests/function/idate.phpt
+++ /dev/null
@@ -1,159 +0,0 @@
---TEST--
-Function -- idate
---SKIPIF--
-
---FILE--
- 0\n";
- }
- echo "\n\n";
-}
-
-restore_error_handler();
-?>
---EXPECT--
-testing: string(1) "B"
-
-result: > 0
-
-
-testing: string(1) "d"
-
-result: > 0
-
-
-testing: string(1) "h"
-
-result: > 0
-
-
-testing: string(1) "H"
-
-result: > 0
-
-
-testing: string(1) "i"
-
-result: > 0
-
-
-testing: string(1) "I"
-
-result: int(0)
-
-
-testing: string(1) "L"
-
-result: int(0)
-
-
-testing: string(1) "m"
-
-result: > 0
-
-
-testing: string(1) "s"
-
-result: > 0
-
-
-testing: string(1) "t"
-
-result: > 0
-
-
-testing: string(1) "U"
-
-result: > 0
-
-
-testing: string(1) "w"
-
-result: > 0
-
-
-testing: string(1) "W"
-
-result: > 0
-
-
-testing: string(1) "y"
-
-result: > 0
-
-
-testing: string(1) "Y"
-
-result: > 0
-
-
-testing: string(1) "z"
-
-result: > 0
-
-
-testing: string(1) "Z"
-
-result: int(0)
-
-
-testing: string(3) "foo"
-
-result: (Warning) bool(false)
-
-
-testing: string(0) ""
-
-result: (Warning) bool(false)
-
-
-testing: string(1) "!"
-
-result: int(0)
-
-
-testing: string(1) "\"
-
-result: int(0)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/image_type_to_mime_type.phpt b/data/module/Compat/tests/function/image_type_to_mime_type.phpt
deleted file mode 100644
index 6659c5efa12..00000000000
--- a/data/module/Compat/tests/function/image_type_to_mime_type.phpt
+++ /dev/null
@@ -1,49 +0,0 @@
---TEST--
-Function -- image_type_to_mime_type
---SKIPIF--
-
---FILE--
-
---EXPECT--
-image/gif
-image/jpeg
-image/png
-application/x-shockwave-flash
-image/psd
-image/bmp
-image/tiff
-image/tiff
-application/octet-stream
-image/jp2
-application/octet-stream
-application/octet-stream
-application/x-shockwave-flash
-image/iff
-image/vnd.wap.wbmp
-image/xbm
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/inet_ntop.phpt b/data/module/Compat/tests/function/inet_ntop.phpt
deleted file mode 100644
index 95fc46e55af..00000000000
--- a/data/module/Compat/tests/function/inet_ntop.phpt
+++ /dev/null
@@ -1,38 +0,0 @@
---TEST--
-Function -- inet_ntop
---SKIPIF--
-
---FILE--
- '7f000001',
- '192.232.131.222' => 'c0e883de',
- '::1' => '00000000000000000000000000000001',
- '2001:260:0:10::1' => '20010260000000100000000000000001',
- 'fe80::200:4cff:fe43:172f' => 'fe8000000000000002004cfffe43172f'
-);
-
-foreach ($adds as $k => $v) {
- echo "\ntesting: $k\n ";
- var_dump(inet_ntop(pack('H*', $v)));
-}
-
-?>
---EXPECT--
-testing: 127.0.0.1
- string(9) "127.0.0.1"
-
-testing: 192.232.131.222
- string(15) "192.232.131.222"
-
-testing: ::1
- string(3) "::1"
-
-testing: 2001:260:0:10::1
- string(16) "2001:260:0:10::1"
-
-testing: fe80::200:4cff:fe43:172f
- string(24) "fe80::200:4cff:fe43:172f"
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/inet_pton.phpt b/data/module/Compat/tests/function/inet_pton.phpt
deleted file mode 100644
index 05c6fa53adc..00000000000
--- a/data/module/Compat/tests/function/inet_pton.phpt
+++ /dev/null
@@ -1,38 +0,0 @@
---TEST--
-Function -- inet_pton
---SKIPIF--
-
---FILE--
- '7f000001',
- '192.232.131.222' => 'c0e883de',
- '::1' => '00000000000000000000000000000001',
- '2001:260:0:10::1' => '20010260000000100000000000000001',
- 'fe80::200:4cff:fe43:172f' => 'fe8000000000000002004cfffe43172f'
-);
-
-foreach ($adds as $k => $v) {
- echo "\ntesting: $k\n ";
- echo bin2hex(inet_pton($k)), "\n";
-}
-
-?>
---EXPECT--
-testing: 127.0.0.1
- 7f000001
-
-testing: 192.232.131.222
- c0e883de
-
-testing: ::1
- 00000000000000000000000000000001
-
-testing: 2001:260:0:10::1
- 20010260000000100000000000000001
-
-testing: fe80::200:4cff:fe43:172f
- fe8000000000000002004cfffe43172f
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/ini_get_all.phpt b/data/module/Compat/tests/function/ini_get_all.phpt
deleted file mode 100644
index 3c4a796964b..00000000000
--- a/data/module/Compat/tests/function/ini_get_all.phpt
+++ /dev/null
@@ -1,20 +0,0 @@
---TEST--
-Function -- ini_get_all
---SKIPIF--
-
---FILE--
-
---EXPECT--
-true
-true
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/is_a.phpt b/data/module/Compat/tests/function/is_a.phpt
deleted file mode 100644
index 972bbcb43a4..00000000000
--- a/data/module/Compat/tests/function/is_a.phpt
+++ /dev/null
@@ -1,22 +0,0 @@
---TEST--
-Function -- is_a
---SKIPIF--
-
---FILE--
-
---EXPECT--
-true
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/is_scalar.phpt b/data/module/Compat/tests/function/is_scalar.phpt
deleted file mode 100644
index e31a9714fec..00000000000
--- a/data/module/Compat/tests/function/is_scalar.phpt
+++ /dev/null
@@ -1,13 +0,0 @@
---TEST--
-Function -- is_scalar
---SKIPIF--
-
---FILE--
-
---EXPECT--
-test
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/md5_file.phpt b/data/module/Compat/tests/function/md5_file.phpt
deleted file mode 100644
index f30bc2973e0..00000000000
--- a/data/module/Compat/tests/function/md5_file.phpt
+++ /dev/null
@@ -1,13 +0,0 @@
---TEST--
-Function -- md5_file
---SKIPIF--
-
---FILE--
-
---EXPECT--
-762a55bb01c6133a956599e6a51c49b0
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/mhash.phpt b/data/module/Compat/tests/function/mhash.phpt
deleted file mode 100644
index f81a59ea6eb..00000000000
--- a/data/module/Compat/tests/function/mhash.phpt
+++ /dev/null
@@ -1,20 +0,0 @@
---TEST--
-Function -- mhash
---SKIPIF--
-
---FILE--
-
---EXPECT--
-ae2e4b39f3b5ee2c8b585994294201ea
-750c783e6ab0b503eaa86e310a5db738
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/mime_content_type.phpt b/data/module/Compat/tests/function/mime_content_type.phpt
deleted file mode 100644
index 3f2674f00c4..00000000000
--- a/data/module/Compat/tests/function/mime_content_type.phpt
+++ /dev/null
@@ -1,13 +0,0 @@
---TEST--
-Function -- inet_pton
---SKIPIF--
-
---FILE--
-
---EXPECT--
-test
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/ob_clean.phpt b/data/module/Compat/tests/function/ob_clean.phpt
deleted file mode 100644
index 23a32c1f938..00000000000
--- a/data/module/Compat/tests/function/ob_clean.phpt
+++ /dev/null
@@ -1,17 +0,0 @@
---TEST--
-Function -- ob_clean
---SKIPIF--
-
---FILE--
-
---EXPECT--
-foo
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/ob_flush.phpt b/data/module/Compat/tests/function/ob_flush.phpt
deleted file mode 100644
index 1e98d615c25..00000000000
--- a/data/module/Compat/tests/function/ob_flush.phpt
+++ /dev/null
@@ -1,16 +0,0 @@
---TEST--
-Function -- ob_flush
---SKIPIF--
-
---FILE--
-
---EXPECT--
-foo
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/ob_get_clean.phpt b/data/module/Compat/tests/function/ob_get_clean.phpt
deleted file mode 100644
index e1ac66bd208..00000000000
--- a/data/module/Compat/tests/function/ob_get_clean.phpt
+++ /dev/null
@@ -1,16 +0,0 @@
---TEST--
-Function -- ob_get_clean
---SKIPIF--
-
---FILE--
-
---EXPECT--
-foo
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/ob_get_flush.phpt b/data/module/Compat/tests/function/ob_get_flush.phpt
deleted file mode 100644
index bc7c135b44b..00000000000
--- a/data/module/Compat/tests/function/ob_get_flush.phpt
+++ /dev/null
@@ -1,16 +0,0 @@
---TEST--
-Function -- ob_get_flush
---SKIPIF--
-
---FILE--
-
---EXPECT--
-foofoo
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/pg_affected_rows.phpt b/data/module/Compat/tests/function/pg_affected_rows.phpt
deleted file mode 100644
index e67285771ac..00000000000
--- a/data/module/Compat/tests/function/pg_affected_rows.phpt
+++ /dev/null
@@ -1,13 +0,0 @@
---TEST--
-Function -- pg_affected_rows
---SKIPIF--
-
---FILE--
-
---EXPECT--
-test
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/pg_escape_bytea.phpt b/data/module/Compat/tests/function/pg_escape_bytea.phpt
deleted file mode 100644
index 72c0b11b494..00000000000
--- a/data/module/Compat/tests/function/pg_escape_bytea.phpt
+++ /dev/null
@@ -1,13 +0,0 @@
---TEST--
-Function -- pg_escape_bytea
---SKIPIF--
-
---FILE--
-
---EXPECT--
-test
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/pg_unescape_bytea.phpt b/data/module/Compat/tests/function/pg_unescape_bytea.phpt
deleted file mode 100644
index eefed99ff86..00000000000
--- a/data/module/Compat/tests/function/pg_unescape_bytea.phpt
+++ /dev/null
@@ -1,13 +0,0 @@
---TEST--
-Function -- pg_unescape_bytea
---SKIPIF--
-
---FILE--
-
---EXPECT--
-test
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/php_strip_whitespace.phpt b/data/module/Compat/tests/function/php_strip_whitespace.phpt
deleted file mode 100644
index 619b89f12a6..00000000000
--- a/data/module/Compat/tests/function/php_strip_whitespace.phpt
+++ /dev/null
@@ -1,42 +0,0 @@
---TEST--
-Function -- php_strip_whitespace
---SKIPIF--
-
---FILE--
-';
-
-// Create a temp file
-$tmpfname = tempnam('/tmp', 'phpcompat');
-$fh = fopen($tmpfname, 'w');
-fwrite($fh, $string);
-
-// Test
-echo php_strip_whitespace($tmpfname);
-
-// Close
-fclose($fh);
-?>
---EXPECT--
-
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/restore_include_path.phpt b/data/module/Compat/tests/function/restore_include_path.phpt
deleted file mode 100644
index 9ffc02e4230..00000000000
--- a/data/module/Compat/tests/function/restore_include_path.phpt
+++ /dev/null
@@ -1,23 +0,0 @@
---TEST--
-Function -- restore_include_path
---SKIPIF--
-
---FILE--
-
---EXPECT--
-foo
-true
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/scandir.phpt b/data/module/Compat/tests/function/scandir.phpt
deleted file mode 100644
index 85a529fe999..00000000000
--- a/data/module/Compat/tests/function/scandir.phpt
+++ /dev/null
@@ -1,45 +0,0 @@
---TEST--
-Function -- scandir
---SKIPIF--
-
---FILE--
-
---EXPECT--
-Array
-(
- [0] => .
- [1] => ..
- [2] => test1
- [3] => test2
-)
-Array
-(
- [0] => test2
- [1] => test1
- [2] => ..
- [3] => .
-)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/set_include_path.phpt b/data/module/Compat/tests/function/set_include_path.phpt
deleted file mode 100644
index 8d963870e8f..00000000000
--- a/data/module/Compat/tests/function/set_include_path.phpt
+++ /dev/null
@@ -1,14 +0,0 @@
---TEST--
-Function -- set_include_path
---SKIPIF--
-
---FILE--
-
---EXPECT--
-foo
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/sha1.phpt b/data/module/Compat/tests/function/sha1.phpt
deleted file mode 100644
index 3e6de2742bf..00000000000
--- a/data/module/Compat/tests/function/sha1.phpt
+++ /dev/null
@@ -1,24 +0,0 @@
---TEST--
-Function -- sha1
---FILE--
-
---EXPECT--
-a9993e364706816aba3e25717850c26c9cd0d89d
-84983e441c3bd26ebaae4aa1f95129e5e54670f1
-86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
-e0c094e867ef46c350ef54a7f59dd60bed92ae83
-da39a3ee5e6b4b0d3255bfef95601890afd80709
diff --git a/data/module/Compat/tests/function/sha256.phpt b/data/module/Compat/tests/function/sha256.phpt
deleted file mode 100644
index 9f679be2370..00000000000
--- a/data/module/Compat/tests/function/sha256.phpt
+++ /dev/null
@@ -1,20 +0,0 @@
---TEST--
-Function -- sha256
---FILE--
-
---EXPECT--
-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
-ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb
-5e43c8704ac81f33d701c1ace046ba9f257062b4d17e78f3254cbf243177e4f2
-ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
-248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1
diff --git a/data/module/Compat/tests/function/str_ireplace.phpt b/data/module/Compat/tests/function/str_ireplace.phpt
deleted file mode 100644
index c04b90cabc1..00000000000
--- a/data/module/Compat/tests/function/str_ireplace.phpt
+++ /dev/null
@@ -1,113 +0,0 @@
---TEST--
-Function -- str_ireplace
---SKIPIF--
-
---FILE--
-
---EXPECT--
-The dog jumped over the fence
-Array
-(
- [0] => A Lady
- [1] => The Lady
- [2] => My Lady
-)
-Array
-(
- [0] => The dog jumped over the {object}
-)
-The dog jumped over the Array
-The frog jumped over the frog and the frog...
-The frog jumped over the gate
-The frog jumped over the gate and the ...
-The frog jumped over the gate and the {thing}...
-Array
-(
- [0] => A frog
- [1] => The gate
- [2] => My beer
-)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/str_rot13.phpt b/data/module/Compat/tests/function/str_rot13.phpt
deleted file mode 100644
index be6a3f71037..00000000000
--- a/data/module/Compat/tests/function/str_rot13.phpt
+++ /dev/null
@@ -1,14 +0,0 @@
---TEST--
-Function -- str_rot13
---SKIPIF--
-
---FILE--
-
---EXPECT--
-Gur dhvpx oebja sbk whzcrq bire gur ynml qbt.
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/str_shuffle.phpt b/data/module/Compat/tests/function/str_shuffle.phpt
deleted file mode 100644
index 46e434c2537..00000000000
--- a/data/module/Compat/tests/function/str_shuffle.phpt
+++ /dev/null
@@ -1,20 +0,0 @@
---TEST--
-Function -- str_shuffle
---SKIPIF--
-
---FILE--
-
---EXPECT--
-true
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/str_split.phpt b/data/module/Compat/tests/function/str_split.phpt
deleted file mode 100644
index 41fe70fadbc..00000000000
--- a/data/module/Compat/tests/function/str_split.phpt
+++ /dev/null
@@ -1,59 +0,0 @@
---TEST--
-Function -- str_split
---SKIPIF--
-
---FILE--
-
---EXPECT--
-Array
-(
- [0] => H
- [1] => e
- [2] => l
- [3] => l
- [4] => o
- [5] =>
- [6] => F
- [7] => r
- [8] => i
- [9] => e
- [10] => n
- [11] => d
-)
-Array
-(
- [0] => Hel
- [1] => lo
- [2] => Fri
- [3] => end
-)
-Array
-(
- [0] => Hello Friend
-)
-Array
-(
- [0] => Hello Frien
- [1] => d
-)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/str_word_count.phpt b/data/module/Compat/tests/function/str_word_count.phpt
deleted file mode 100644
index 285c43c02ee..00000000000
--- a/data/module/Compat/tests/function/str_word_count.phpt
+++ /dev/null
@@ -1,57 +0,0 @@
---TEST--
-Function -- str_word_count
---SKIPIF--
-
---FILE--
-
---EXPECT--
-int(12)
-Array
-(
- [0] => Hello
- [1] => friend
- [2] => you're
- [3] => sdf
- [4] => looking
- [5] => good
- [6] => to
- [7] => day
- [8] => yes
- [9] => sir
- [10] => you
- [11] => am
-)
-Array
-(
- [0] => Hello
- [6] => friend
- [14] => you're
- [23] => sdf
- [27] => looking
- [48] => good
- [53] => to
- [56] => day
- [61] => yes
- [66] => sir
- [71] => you
- [75] => am
-)
-Array
-(
- [0] => hello
- [6] => I
- [8] => am
- [11] => repeated
- [20] => repeated
-)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/stripos.phpt b/data/module/Compat/tests/function/stripos.phpt
deleted file mode 100644
index 4aa34a0b27d..00000000000
--- a/data/module/Compat/tests/function/stripos.phpt
+++ /dev/null
@@ -1,27 +0,0 @@
---TEST--
-Function -- stripos
---SKIPIF--
-
---FILE--
-
---EXPECT--
-int(11)
-int(11)
-int(11)
-int(41)
-bool(false)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/strpbrk.phpt b/data/module/Compat/tests/function/strpbrk.phpt
deleted file mode 100644
index 9590b750410..00000000000
--- a/data/module/Compat/tests/function/strpbrk.phpt
+++ /dev/null
@@ -1,16 +0,0 @@
---TEST--
-Function -- strpbrk
---SKIPIF--
-
---FILE--
-
---EXPECT--
-string(9) "not to be"
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/strripos.phpt b/data/module/Compat/tests/function/strripos.phpt
deleted file mode 100644
index 1376bdab93a..00000000000
--- a/data/module/Compat/tests/function/strripos.phpt
+++ /dev/null
@@ -1,48 +0,0 @@
---TEST--
-Function -- strripos
---SKIPIF--
-
---FILE--
-
---EXPECT--
-int(41)
-int(41)
-int(41)
-bool(false)
-int(41)
-int(11)
-int(11)
-bool(false)
-bool(false)
-int(1)
-int(3)
-int(0)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/substr_compare.phpt b/data/module/Compat/tests/function/substr_compare.phpt
deleted file mode 100644
index 7313b371437..00000000000
--- a/data/module/Compat/tests/function/substr_compare.phpt
+++ /dev/null
@@ -1,21 +0,0 @@
---TEST--
-Function -- substr_compare
---SKIPIF--
-
---FILE--
-
---EXPECT--
-0
-0
-0
-1
--1
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/time_sleep_until.phpt b/data/module/Compat/tests/function/time_sleep_until.phpt
deleted file mode 100644
index 565f65ae63a..00000000000
--- a/data/module/Compat/tests/function/time_sleep_until.phpt
+++ /dev/null
@@ -1,30 +0,0 @@
---TEST--
-Function -- time_sleep_until
---SKIPIF--
-
---FILE--
-
---EXPECT--
-3:3
-(Warning) -1:0
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/var_export.phpt b/data/module/Compat/tests/function/var_export.phpt
deleted file mode 100644
index 459ea357d66..00000000000
--- a/data/module/Compat/tests/function/var_export.phpt
+++ /dev/null
@@ -1,123 +0,0 @@
---TEST--
-Function -- var_export
---SKIPIF--
-
---FILE--
- null,
- 'O\'neil',
- 'He said "bar" ...' => 'He said "bar" ...',
- 'Yes \ No' =>'Yes \ No O\'neil',
- 'foo' => null,
- );
-var_export($a);
-echo "\n\n";
-
-// Classes
-$var = new stdClass;
-$var->foo = 'foo';
-$var->bar = 'bar';
-$var = array(array($var));
-var_export($var);
-
-?>
---EXPECT--
-true
-false
-NULL
-NULL
-array (
- 0 => 1,
- 1 =>
- array (
- 0 => 2,
- 1 =>
- array (
- 0 => 3,
- 1 => 4,
- ),
- 2 =>
- array (
- 0 => 5,
- 1 =>
- array (
- 0 => 6,
- 1 =>
- array (
- 0 => 7,
- ),
- ),
- ),
- ),
-)
-array (
- 0 => 1,
- 1 => 2,
- 2 =>
- array (
- 0 => 'a',
- 1 => 'b',
- 2 => 'c',
- ),
-)
-
-array (
- 0 => 1,
- 1 => 2,
- 2 =>
- array (
- 0 => 'a',
- 1 => 'b',
- 2 => 'c',
- ),
-)
-
-array (
- '' => NULL,
- 0 => 'O\'neil',
- 'He said "bar" ...' => 'He said "bar" ...',
- 'Yes \\ No' => 'Yes \\ No O\'neil',
- 'foo' => NULL,
-)
-
-array (
- 0 =>
- array (
- 0 =>
- class stdClass {
- var $foo = 'foo';
- var $bar = 'bar';
- },
- ),
-)
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/version_compare.phpt b/data/module/Compat/tests/function/version_compare.phpt
deleted file mode 100644
index 2af28faf162..00000000000
--- a/data/module/Compat/tests/function/version_compare.phpt
+++ /dev/null
@@ -1,615 +0,0 @@
---TEST--
-Function -- version_compare
---SKIPIF--
-
---FILE--
-",
- "ge", ">=",
- "eq", "=", "==",
- "ne", "<>", "!="
-);
-
-foreach ($special_forms as $f1) {
- foreach ($special_forms as $f2) {
- test("1.0$f1", "1.0$f2");
- }
-}
-
-// Operators
-print "testing operators\n";
-foreach ($special_forms as $f1) {
- foreach ($special_forms as $f2) {
- foreach ($operators as $op) {
- $v1 = "1.0$f1";
- $v2 = "1.0$f2";
- $test = version_compare($v1, $v2, $op) ? "true" : "false";
- printf("%7s %2s %-7s : %s\n", $v1, $op, $v2, $test);
- }
- }
-}
-
-function test($v1, $v2) {
- $compare = version_compare($v1, $v2);
- switch ($compare) {
- case -1:
- print "$v1 < $v2\n";
- break;
- case 1:
- print "$v1 > $v2\n";
- break;
- case 0:
- default:
- print "$v1 = $v2\n";
- break;
- }
-}
-
-?>
-testing basic
-1 < 2
-10 > 2
-1.0 < 1.1
-1.2 > 1.0.1
-1.2.p3 > 1.2.4
-1.2.y = 1.2.z
-testing compare
-1.0-dev = 1.0-dev
-1.0-dev < 1.0a1
-1.0-dev < 1.0b1
-1.0-dev < 1.0RC1
-1.0-dev < 1.0
-1.0-dev < 1.0pl1
-1.0a1 > 1.0-dev
-1.0a1 = 1.0a1
-1.0a1 < 1.0b1
-1.0a1 < 1.0RC1
-1.0a1 < 1.0
-1.0a1 < 1.0pl1
-1.0b1 > 1.0-dev
-1.0b1 > 1.0a1
-1.0b1 = 1.0b1
-1.0b1 < 1.0RC1
-1.0b1 < 1.0
-1.0b1 < 1.0pl1
-1.0RC1 > 1.0-dev
-1.0RC1 > 1.0a1
-1.0RC1 > 1.0b1
-1.0RC1 = 1.0RC1
-1.0RC1 < 1.0
-1.0RC1 < 1.0pl1
-1.0 > 1.0-dev
-1.0 > 1.0a1
-1.0 > 1.0b1
-1.0 > 1.0RC1
-1.0 = 1.0
-1.0 < 1.0pl1
-1.0pl1 > 1.0-dev
-1.0pl1 > 1.0a1
-1.0pl1 > 1.0b1
-1.0pl1 > 1.0RC1
-1.0pl1 > 1.0
-1.0pl1 = 1.0pl1
-testing operators
-1.0-dev lt 1.0-dev : false
-1.0-dev < 1.0-dev : false
-1.0-dev le 1.0-dev : true
-1.0-dev <= 1.0-dev : true
-1.0-dev gt 1.0-dev : false
-1.0-dev > 1.0-dev : false
-1.0-dev ge 1.0-dev : true
-1.0-dev >= 1.0-dev : true
-1.0-dev eq 1.0-dev : true
-1.0-dev = 1.0-dev : true
-1.0-dev == 1.0-dev : true
-1.0-dev ne 1.0-dev : false
-1.0-dev <> 1.0-dev : false
-1.0-dev != 1.0-dev : false
-1.0-dev lt 1.0a1 : true
-1.0-dev < 1.0a1 : true
-1.0-dev le 1.0a1 : true
-1.0-dev <= 1.0a1 : true
-1.0-dev gt 1.0a1 : false
-1.0-dev > 1.0a1 : false
-1.0-dev ge 1.0a1 : false
-1.0-dev >= 1.0a1 : false
-1.0-dev eq 1.0a1 : false
-1.0-dev = 1.0a1 : false
-1.0-dev == 1.0a1 : false
-1.0-dev ne 1.0a1 : true
-1.0-dev <> 1.0a1 : true
-1.0-dev != 1.0a1 : true
-1.0-dev lt 1.0b1 : true
-1.0-dev < 1.0b1 : true
-1.0-dev le 1.0b1 : true
-1.0-dev <= 1.0b1 : true
-1.0-dev gt 1.0b1 : false
-1.0-dev > 1.0b1 : false
-1.0-dev ge 1.0b1 : false
-1.0-dev >= 1.0b1 : false
-1.0-dev eq 1.0b1 : false
-1.0-dev = 1.0b1 : false
-1.0-dev == 1.0b1 : false
-1.0-dev ne 1.0b1 : true
-1.0-dev <> 1.0b1 : true
-1.0-dev != 1.0b1 : true
-1.0-dev lt 1.0RC1 : true
-1.0-dev < 1.0RC1 : true
-1.0-dev le 1.0RC1 : true
-1.0-dev <= 1.0RC1 : true
-1.0-dev gt 1.0RC1 : false
-1.0-dev > 1.0RC1 : false
-1.0-dev ge 1.0RC1 : false
-1.0-dev >= 1.0RC1 : false
-1.0-dev eq 1.0RC1 : false
-1.0-dev = 1.0RC1 : false
-1.0-dev == 1.0RC1 : false
-1.0-dev ne 1.0RC1 : true
-1.0-dev <> 1.0RC1 : true
-1.0-dev != 1.0RC1 : true
-1.0-dev lt 1.0 : true
-1.0-dev < 1.0 : true
-1.0-dev le 1.0 : true
-1.0-dev <= 1.0 : true
-1.0-dev gt 1.0 : false
-1.0-dev > 1.0 : false
-1.0-dev ge 1.0 : false
-1.0-dev >= 1.0 : false
-1.0-dev eq 1.0 : false
-1.0-dev = 1.0 : false
-1.0-dev == 1.0 : false
-1.0-dev ne 1.0 : true
-1.0-dev <> 1.0 : true
-1.0-dev != 1.0 : true
-1.0-dev lt 1.0pl1 : true
-1.0-dev < 1.0pl1 : true
-1.0-dev le 1.0pl1 : true
-1.0-dev <= 1.0pl1 : true
-1.0-dev gt 1.0pl1 : false
-1.0-dev > 1.0pl1 : false
-1.0-dev ge 1.0pl1 : false
-1.0-dev >= 1.0pl1 : false
-1.0-dev eq 1.0pl1 : false
-1.0-dev = 1.0pl1 : false
-1.0-dev == 1.0pl1 : false
-1.0-dev ne 1.0pl1 : true
-1.0-dev <> 1.0pl1 : true
-1.0-dev != 1.0pl1 : true
- 1.0a1 lt 1.0-dev : false
- 1.0a1 < 1.0-dev : false
- 1.0a1 le 1.0-dev : false
- 1.0a1 <= 1.0-dev : false
- 1.0a1 gt 1.0-dev : true
- 1.0a1 > 1.0-dev : true
- 1.0a1 ge 1.0-dev : true
- 1.0a1 >= 1.0-dev : true
- 1.0a1 eq 1.0-dev : false
- 1.0a1 = 1.0-dev : false
- 1.0a1 == 1.0-dev : false
- 1.0a1 ne 1.0-dev : true
- 1.0a1 <> 1.0-dev : true
- 1.0a1 != 1.0-dev : true
- 1.0a1 lt 1.0a1 : false
- 1.0a1 < 1.0a1 : false
- 1.0a1 le 1.0a1 : true
- 1.0a1 <= 1.0a1 : true
- 1.0a1 gt 1.0a1 : false
- 1.0a1 > 1.0a1 : false
- 1.0a1 ge 1.0a1 : true
- 1.0a1 >= 1.0a1 : true
- 1.0a1 eq 1.0a1 : true
- 1.0a1 = 1.0a1 : true
- 1.0a1 == 1.0a1 : true
- 1.0a1 ne 1.0a1 : false
- 1.0a1 <> 1.0a1 : false
- 1.0a1 != 1.0a1 : false
- 1.0a1 lt 1.0b1 : true
- 1.0a1 < 1.0b1 : true
- 1.0a1 le 1.0b1 : true
- 1.0a1 <= 1.0b1 : true
- 1.0a1 gt 1.0b1 : false
- 1.0a1 > 1.0b1 : false
- 1.0a1 ge 1.0b1 : false
- 1.0a1 >= 1.0b1 : false
- 1.0a1 eq 1.0b1 : false
- 1.0a1 = 1.0b1 : false
- 1.0a1 == 1.0b1 : false
- 1.0a1 ne 1.0b1 : true
- 1.0a1 <> 1.0b1 : true
- 1.0a1 != 1.0b1 : true
- 1.0a1 lt 1.0RC1 : true
- 1.0a1 < 1.0RC1 : true
- 1.0a1 le 1.0RC1 : true
- 1.0a1 <= 1.0RC1 : true
- 1.0a1 gt 1.0RC1 : false
- 1.0a1 > 1.0RC1 : false
- 1.0a1 ge 1.0RC1 : false
- 1.0a1 >= 1.0RC1 : false
- 1.0a1 eq 1.0RC1 : false
- 1.0a1 = 1.0RC1 : false
- 1.0a1 == 1.0RC1 : false
- 1.0a1 ne 1.0RC1 : true
- 1.0a1 <> 1.0RC1 : true
- 1.0a1 != 1.0RC1 : true
- 1.0a1 lt 1.0 : true
- 1.0a1 < 1.0 : true
- 1.0a1 le 1.0 : true
- 1.0a1 <= 1.0 : true
- 1.0a1 gt 1.0 : false
- 1.0a1 > 1.0 : false
- 1.0a1 ge 1.0 : false
- 1.0a1 >= 1.0 : false
- 1.0a1 eq 1.0 : false
- 1.0a1 = 1.0 : false
- 1.0a1 == 1.0 : false
- 1.0a1 ne 1.0 : true
- 1.0a1 <> 1.0 : true
- 1.0a1 != 1.0 : true
- 1.0a1 lt 1.0pl1 : true
- 1.0a1 < 1.0pl1 : true
- 1.0a1 le 1.0pl1 : true
- 1.0a1 <= 1.0pl1 : true
- 1.0a1 gt 1.0pl1 : false
- 1.0a1 > 1.0pl1 : false
- 1.0a1 ge 1.0pl1 : false
- 1.0a1 >= 1.0pl1 : false
- 1.0a1 eq 1.0pl1 : false
- 1.0a1 = 1.0pl1 : false
- 1.0a1 == 1.0pl1 : false
- 1.0a1 ne 1.0pl1 : true
- 1.0a1 <> 1.0pl1 : true
- 1.0a1 != 1.0pl1 : true
- 1.0b1 lt 1.0-dev : false
- 1.0b1 < 1.0-dev : false
- 1.0b1 le 1.0-dev : false
- 1.0b1 <= 1.0-dev : false
- 1.0b1 gt 1.0-dev : true
- 1.0b1 > 1.0-dev : true
- 1.0b1 ge 1.0-dev : true
- 1.0b1 >= 1.0-dev : true
- 1.0b1 eq 1.0-dev : false
- 1.0b1 = 1.0-dev : false
- 1.0b1 == 1.0-dev : false
- 1.0b1 ne 1.0-dev : true
- 1.0b1 <> 1.0-dev : true
- 1.0b1 != 1.0-dev : true
- 1.0b1 lt 1.0a1 : false
- 1.0b1 < 1.0a1 : false
- 1.0b1 le 1.0a1 : false
- 1.0b1 <= 1.0a1 : false
- 1.0b1 gt 1.0a1 : true
- 1.0b1 > 1.0a1 : true
- 1.0b1 ge 1.0a1 : true
- 1.0b1 >= 1.0a1 : true
- 1.0b1 eq 1.0a1 : false
- 1.0b1 = 1.0a1 : false
- 1.0b1 == 1.0a1 : false
- 1.0b1 ne 1.0a1 : true
- 1.0b1 <> 1.0a1 : true
- 1.0b1 != 1.0a1 : true
- 1.0b1 lt 1.0b1 : false
- 1.0b1 < 1.0b1 : false
- 1.0b1 le 1.0b1 : true
- 1.0b1 <= 1.0b1 : true
- 1.0b1 gt 1.0b1 : false
- 1.0b1 > 1.0b1 : false
- 1.0b1 ge 1.0b1 : true
- 1.0b1 >= 1.0b1 : true
- 1.0b1 eq 1.0b1 : true
- 1.0b1 = 1.0b1 : true
- 1.0b1 == 1.0b1 : true
- 1.0b1 ne 1.0b1 : false
- 1.0b1 <> 1.0b1 : false
- 1.0b1 != 1.0b1 : false
- 1.0b1 lt 1.0RC1 : true
- 1.0b1 < 1.0RC1 : true
- 1.0b1 le 1.0RC1 : true
- 1.0b1 <= 1.0RC1 : true
- 1.0b1 gt 1.0RC1 : false
- 1.0b1 > 1.0RC1 : false
- 1.0b1 ge 1.0RC1 : false
- 1.0b1 >= 1.0RC1 : false
- 1.0b1 eq 1.0RC1 : false
- 1.0b1 = 1.0RC1 : false
- 1.0b1 == 1.0RC1 : false
- 1.0b1 ne 1.0RC1 : true
- 1.0b1 <> 1.0RC1 : true
- 1.0b1 != 1.0RC1 : true
- 1.0b1 lt 1.0 : true
- 1.0b1 < 1.0 : true
- 1.0b1 le 1.0 : true
- 1.0b1 <= 1.0 : true
- 1.0b1 gt 1.0 : false
- 1.0b1 > 1.0 : false
- 1.0b1 ge 1.0 : false
- 1.0b1 >= 1.0 : false
- 1.0b1 eq 1.0 : false
- 1.0b1 = 1.0 : false
- 1.0b1 == 1.0 : false
- 1.0b1 ne 1.0 : true
- 1.0b1 <> 1.0 : true
- 1.0b1 != 1.0 : true
- 1.0b1 lt 1.0pl1 : true
- 1.0b1 < 1.0pl1 : true
- 1.0b1 le 1.0pl1 : true
- 1.0b1 <= 1.0pl1 : true
- 1.0b1 gt 1.0pl1 : false
- 1.0b1 > 1.0pl1 : false
- 1.0b1 ge 1.0pl1 : false
- 1.0b1 >= 1.0pl1 : false
- 1.0b1 eq 1.0pl1 : false
- 1.0b1 = 1.0pl1 : false
- 1.0b1 == 1.0pl1 : false
- 1.0b1 ne 1.0pl1 : true
- 1.0b1 <> 1.0pl1 : true
- 1.0b1 != 1.0pl1 : true
- 1.0RC1 lt 1.0-dev : false
- 1.0RC1 < 1.0-dev : false
- 1.0RC1 le 1.0-dev : false
- 1.0RC1 <= 1.0-dev : false
- 1.0RC1 gt 1.0-dev : true
- 1.0RC1 > 1.0-dev : true
- 1.0RC1 ge 1.0-dev : true
- 1.0RC1 >= 1.0-dev : true
- 1.0RC1 eq 1.0-dev : false
- 1.0RC1 = 1.0-dev : false
- 1.0RC1 == 1.0-dev : false
- 1.0RC1 ne 1.0-dev : true
- 1.0RC1 <> 1.0-dev : true
- 1.0RC1 != 1.0-dev : true
- 1.0RC1 lt 1.0a1 : false
- 1.0RC1 < 1.0a1 : false
- 1.0RC1 le 1.0a1 : false
- 1.0RC1 <= 1.0a1 : false
- 1.0RC1 gt 1.0a1 : true
- 1.0RC1 > 1.0a1 : true
- 1.0RC1 ge 1.0a1 : true
- 1.0RC1 >= 1.0a1 : true
- 1.0RC1 eq 1.0a1 : false
- 1.0RC1 = 1.0a1 : false
- 1.0RC1 == 1.0a1 : false
- 1.0RC1 ne 1.0a1 : true
- 1.0RC1 <> 1.0a1 : true
- 1.0RC1 != 1.0a1 : true
- 1.0RC1 lt 1.0b1 : false
- 1.0RC1 < 1.0b1 : false
- 1.0RC1 le 1.0b1 : false
- 1.0RC1 <= 1.0b1 : false
- 1.0RC1 gt 1.0b1 : true
- 1.0RC1 > 1.0b1 : true
- 1.0RC1 ge 1.0b1 : true
- 1.0RC1 >= 1.0b1 : true
- 1.0RC1 eq 1.0b1 : false
- 1.0RC1 = 1.0b1 : false
- 1.0RC1 == 1.0b1 : false
- 1.0RC1 ne 1.0b1 : true
- 1.0RC1 <> 1.0b1 : true
- 1.0RC1 != 1.0b1 : true
- 1.0RC1 lt 1.0RC1 : false
- 1.0RC1 < 1.0RC1 : false
- 1.0RC1 le 1.0RC1 : true
- 1.0RC1 <= 1.0RC1 : true
- 1.0RC1 gt 1.0RC1 : false
- 1.0RC1 > 1.0RC1 : false
- 1.0RC1 ge 1.0RC1 : true
- 1.0RC1 >= 1.0RC1 : true
- 1.0RC1 eq 1.0RC1 : true
- 1.0RC1 = 1.0RC1 : true
- 1.0RC1 == 1.0RC1 : true
- 1.0RC1 ne 1.0RC1 : false
- 1.0RC1 <> 1.0RC1 : false
- 1.0RC1 != 1.0RC1 : false
- 1.0RC1 lt 1.0 : true
- 1.0RC1 < 1.0 : true
- 1.0RC1 le 1.0 : true
- 1.0RC1 <= 1.0 : true
- 1.0RC1 gt 1.0 : false
- 1.0RC1 > 1.0 : false
- 1.0RC1 ge 1.0 : false
- 1.0RC1 >= 1.0 : false
- 1.0RC1 eq 1.0 : false
- 1.0RC1 = 1.0 : false
- 1.0RC1 == 1.0 : false
- 1.0RC1 ne 1.0 : true
- 1.0RC1 <> 1.0 : true
- 1.0RC1 != 1.0 : true
- 1.0RC1 lt 1.0pl1 : true
- 1.0RC1 < 1.0pl1 : true
- 1.0RC1 le 1.0pl1 : true
- 1.0RC1 <= 1.0pl1 : true
- 1.0RC1 gt 1.0pl1 : false
- 1.0RC1 > 1.0pl1 : false
- 1.0RC1 ge 1.0pl1 : false
- 1.0RC1 >= 1.0pl1 : false
- 1.0RC1 eq 1.0pl1 : false
- 1.0RC1 = 1.0pl1 : false
- 1.0RC1 == 1.0pl1 : false
- 1.0RC1 ne 1.0pl1 : true
- 1.0RC1 <> 1.0pl1 : true
- 1.0RC1 != 1.0pl1 : true
- 1.0 lt 1.0-dev : false
- 1.0 < 1.0-dev : false
- 1.0 le 1.0-dev : false
- 1.0 <= 1.0-dev : false
- 1.0 gt 1.0-dev : true
- 1.0 > 1.0-dev : true
- 1.0 ge 1.0-dev : true
- 1.0 >= 1.0-dev : true
- 1.0 eq 1.0-dev : false
- 1.0 = 1.0-dev : false
- 1.0 == 1.0-dev : false
- 1.0 ne 1.0-dev : true
- 1.0 <> 1.0-dev : true
- 1.0 != 1.0-dev : true
- 1.0 lt 1.0a1 : false
- 1.0 < 1.0a1 : false
- 1.0 le 1.0a1 : false
- 1.0 <= 1.0a1 : false
- 1.0 gt 1.0a1 : true
- 1.0 > 1.0a1 : true
- 1.0 ge 1.0a1 : true
- 1.0 >= 1.0a1 : true
- 1.0 eq 1.0a1 : false
- 1.0 = 1.0a1 : false
- 1.0 == 1.0a1 : false
- 1.0 ne 1.0a1 : true
- 1.0 <> 1.0a1 : true
- 1.0 != 1.0a1 : true
- 1.0 lt 1.0b1 : false
- 1.0 < 1.0b1 : false
- 1.0 le 1.0b1 : false
- 1.0 <= 1.0b1 : false
- 1.0 gt 1.0b1 : true
- 1.0 > 1.0b1 : true
- 1.0 ge 1.0b1 : true
- 1.0 >= 1.0b1 : true
- 1.0 eq 1.0b1 : false
- 1.0 = 1.0b1 : false
- 1.0 == 1.0b1 : false
- 1.0 ne 1.0b1 : true
- 1.0 <> 1.0b1 : true
- 1.0 != 1.0b1 : true
- 1.0 lt 1.0RC1 : false
- 1.0 < 1.0RC1 : false
- 1.0 le 1.0RC1 : false
- 1.0 <= 1.0RC1 : false
- 1.0 gt 1.0RC1 : true
- 1.0 > 1.0RC1 : true
- 1.0 ge 1.0RC1 : true
- 1.0 >= 1.0RC1 : true
- 1.0 eq 1.0RC1 : false
- 1.0 = 1.0RC1 : false
- 1.0 == 1.0RC1 : false
- 1.0 ne 1.0RC1 : true
- 1.0 <> 1.0RC1 : true
- 1.0 != 1.0RC1 : true
- 1.0 lt 1.0 : false
- 1.0 < 1.0 : false
- 1.0 le 1.0 : true
- 1.0 <= 1.0 : true
- 1.0 gt 1.0 : false
- 1.0 > 1.0 : false
- 1.0 ge 1.0 : true
- 1.0 >= 1.0 : true
- 1.0 eq 1.0 : true
- 1.0 = 1.0 : true
- 1.0 == 1.0 : true
- 1.0 ne 1.0 : false
- 1.0 <> 1.0 : false
- 1.0 != 1.0 : false
- 1.0 lt 1.0pl1 : true
- 1.0 < 1.0pl1 : true
- 1.0 le 1.0pl1 : true
- 1.0 <= 1.0pl1 : true
- 1.0 gt 1.0pl1 : false
- 1.0 > 1.0pl1 : false
- 1.0 ge 1.0pl1 : false
- 1.0 >= 1.0pl1 : false
- 1.0 eq 1.0pl1 : false
- 1.0 = 1.0pl1 : false
- 1.0 == 1.0pl1 : false
- 1.0 ne 1.0pl1 : true
- 1.0 <> 1.0pl1 : true
- 1.0 != 1.0pl1 : true
- 1.0pl1 lt 1.0-dev : false
- 1.0pl1 < 1.0-dev : false
- 1.0pl1 le 1.0-dev : false
- 1.0pl1 <= 1.0-dev : false
- 1.0pl1 gt 1.0-dev : true
- 1.0pl1 > 1.0-dev : true
- 1.0pl1 ge 1.0-dev : true
- 1.0pl1 >= 1.0-dev : true
- 1.0pl1 eq 1.0-dev : false
- 1.0pl1 = 1.0-dev : false
- 1.0pl1 == 1.0-dev : false
- 1.0pl1 ne 1.0-dev : true
- 1.0pl1 <> 1.0-dev : true
- 1.0pl1 != 1.0-dev : true
- 1.0pl1 lt 1.0a1 : false
- 1.0pl1 < 1.0a1 : false
- 1.0pl1 le 1.0a1 : false
- 1.0pl1 <= 1.0a1 : false
- 1.0pl1 gt 1.0a1 : true
- 1.0pl1 > 1.0a1 : true
- 1.0pl1 ge 1.0a1 : true
- 1.0pl1 >= 1.0a1 : true
- 1.0pl1 eq 1.0a1 : false
- 1.0pl1 = 1.0a1 : false
- 1.0pl1 == 1.0a1 : false
- 1.0pl1 ne 1.0a1 : true
- 1.0pl1 <> 1.0a1 : true
- 1.0pl1 != 1.0a1 : true
- 1.0pl1 lt 1.0b1 : false
- 1.0pl1 < 1.0b1 : false
- 1.0pl1 le 1.0b1 : false
- 1.0pl1 <= 1.0b1 : false
- 1.0pl1 gt 1.0b1 : true
- 1.0pl1 > 1.0b1 : true
- 1.0pl1 ge 1.0b1 : true
- 1.0pl1 >= 1.0b1 : true
- 1.0pl1 eq 1.0b1 : false
- 1.0pl1 = 1.0b1 : false
- 1.0pl1 == 1.0b1 : false
- 1.0pl1 ne 1.0b1 : true
- 1.0pl1 <> 1.0b1 : true
- 1.0pl1 != 1.0b1 : true
- 1.0pl1 lt 1.0RC1 : false
- 1.0pl1 < 1.0RC1 : false
- 1.0pl1 le 1.0RC1 : false
- 1.0pl1 <= 1.0RC1 : false
- 1.0pl1 gt 1.0RC1 : true
- 1.0pl1 > 1.0RC1 : true
- 1.0pl1 ge 1.0RC1 : true
- 1.0pl1 >= 1.0RC1 : true
- 1.0pl1 eq 1.0RC1 : false
- 1.0pl1 = 1.0RC1 : false
- 1.0pl1 == 1.0RC1 : false
- 1.0pl1 ne 1.0RC1 : true
- 1.0pl1 <> 1.0RC1 : true
- 1.0pl1 != 1.0RC1 : true
- 1.0pl1 lt 1.0 : false
- 1.0pl1 < 1.0 : false
- 1.0pl1 le 1.0 : false
- 1.0pl1 <= 1.0 : false
- 1.0pl1 gt 1.0 : true
- 1.0pl1 > 1.0 : true
- 1.0pl1 ge 1.0 : true
- 1.0pl1 >= 1.0 : true
- 1.0pl1 eq 1.0 : false
- 1.0pl1 = 1.0 : false
- 1.0pl1 == 1.0 : false
- 1.0pl1 ne 1.0 : true
- 1.0pl1 <> 1.0 : true
- 1.0pl1 != 1.0 : true
- 1.0pl1 lt 1.0pl1 : false
- 1.0pl1 < 1.0pl1 : false
- 1.0pl1 le 1.0pl1 : true
- 1.0pl1 <= 1.0pl1 : true
- 1.0pl1 gt 1.0pl1 : false
- 1.0pl1 > 1.0pl1 : false
- 1.0pl1 ge 1.0pl1 : true
- 1.0pl1 >= 1.0pl1 : true
- 1.0pl1 eq 1.0pl1 : true
- 1.0pl1 = 1.0pl1 : true
- 1.0pl1 == 1.0pl1 : true
- 1.0pl1 ne 1.0pl1 : false
- 1.0pl1 <> 1.0pl1 : false
- 1.0pl1 != 1.0pl1 : false
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/vprintf.phpt b/data/module/Compat/tests/function/vprintf.phpt
deleted file mode 100644
index 3f4e4fae04e..00000000000
--- a/data/module/Compat/tests/function/vprintf.phpt
+++ /dev/null
@@ -1,16 +0,0 @@
---TEST--
-Function -- vprintf
---SKIPIF--
-
---FILE--
-
---EXPECT--
-There are 2 monkeys in the car
\ No newline at end of file
diff --git a/data/module/Compat/tests/function/vsprintf.phpt b/data/module/Compat/tests/function/vsprintf.phpt
deleted file mode 100644
index 9876b7f07d3..00000000000
--- a/data/module/Compat/tests/function/vsprintf.phpt
+++ /dev/null
@@ -1,16 +0,0 @@
---TEST--
-Function -- vsprintf
---SKIPIF--
-
---FILE--
-
---EXPECT--
-There are 2 monkeys in the car
\ No newline at end of file
diff --git a/data/module/Compat/tests/loadconstant.phpt b/data/module/Compat/tests/loadconstant.phpt
deleted file mode 100644
index ea9340643da..00000000000
--- a/data/module/Compat/tests/loadconstant.phpt
+++ /dev/null
@@ -1,25 +0,0 @@
---TEST--
-Method -- PHP_Compat::loadConstant
---FILE--
- $result) {
- echo $comp . ': ';
- echo ($result === false) ? 'false' : 'true', "\n";
-}
-
-?>
---EXPECT--
-false
-an-invalid: false
-also-invalid: false
-more-invalid: false
-E_STRICT: true
\ No newline at end of file
diff --git a/data/module/Compat/tests/loadfunction.phpt b/data/module/Compat/tests/loadfunction.phpt
deleted file mode 100644
index f2d15a9e80e..00000000000
--- a/data/module/Compat/tests/loadfunction.phpt
+++ /dev/null
@@ -1,24 +0,0 @@
---TEST--
-Method -- PHP_Compat::loadFunction
---FILE--
- $result) {
- echo $comp . ': ';
- echo ($result === false) ? 'false' : 'true', "\n";
-}
-
-?>
---EXPECT--
-false
-an-invalid: false
-also-invalid: false
-more-invalid: false
\ No newline at end of file
diff --git a/data/module/Compat/tests/loadversion.phpt b/data/module/Compat/tests/loadversion.phpt
deleted file mode 100644
index 026e54d5a80..00000000000
--- a/data/module/Compat/tests/loadversion.phpt
+++ /dev/null
@@ -1,21 +0,0 @@
---TEST--
-Method -- PHP_Compat::loadVersion
---FILE--
-
---EXPECT--
-bool(true)
-bool(true)
-bool(true)
\ No newline at end of file
diff --git a/data/module/HTTP/Request.php b/data/module/HTTP/Request.php
deleted file mode 100644
index ef6109f22a6..00000000000
--- a/data/module/HTTP/Request.php
+++ /dev/null
@@ -1,1528 +0,0 @@
-
- * @author Alexey Borzov
- * @copyright 2002-2007 Richard Heyes
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id$
- * @link http://pear.php.net/package/HTTP_Request/
- */
-
-/**
- * PEAR and PEAR_Error classes (for error handling)
- */
-require_once 'PEAR.php';
-/**
- * Socket class
- */
-require_once 'Net/Socket.php';
-/**
- * URL handling class
- */
-require_once 'Net/URL.php';
-
-/**#@+
- * Constants for HTTP request methods
- */
-define('HTTP_REQUEST_METHOD_GET', 'GET', true);
-define('HTTP_REQUEST_METHOD_HEAD', 'HEAD', true);
-define('HTTP_REQUEST_METHOD_POST', 'POST', true);
-define('HTTP_REQUEST_METHOD_PUT', 'PUT', true);
-define('HTTP_REQUEST_METHOD_DELETE', 'DELETE', true);
-define('HTTP_REQUEST_METHOD_OPTIONS', 'OPTIONS', true);
-define('HTTP_REQUEST_METHOD_TRACE', 'TRACE', true);
-/**#@-*/
-
-/**#@+
- * Constants for HTTP request error codes
- */
-define('HTTP_REQUEST_ERROR_FILE', 1);
-define('HTTP_REQUEST_ERROR_URL', 2);
-define('HTTP_REQUEST_ERROR_PROXY', 4);
-define('HTTP_REQUEST_ERROR_REDIRECTS', 8);
-define('HTTP_REQUEST_ERROR_RESPONSE', 16);
-define('HTTP_REQUEST_ERROR_GZIP_METHOD', 32);
-define('HTTP_REQUEST_ERROR_GZIP_READ', 64);
-define('HTTP_REQUEST_ERROR_GZIP_DATA', 128);
-define('HTTP_REQUEST_ERROR_GZIP_CRC', 256);
-/**#@-*/
-
-/**#@+
- * Constants for HTTP protocol versions
- */
-define('HTTP_REQUEST_HTTP_VER_1_0', '1.0', true);
-define('HTTP_REQUEST_HTTP_VER_1_1', '1.1', true);
-/**#@-*/
-
-if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) {
- /**
- * Whether string functions are overloaded by their mbstring equivalents
- */
- define('HTTP_REQUEST_MBSTRING', true);
-} else {
- /**
- * @ignore
- */
- define('HTTP_REQUEST_MBSTRING', false);
-}
-
-/**
- * Class for performing HTTP requests
- *
- * Simple example (fetches yahoo.com and displays it):
- *
- * $a = &new HTTP_Request('http://www.yahoo.com/');
- * $a->sendRequest();
- * echo $a->getResponseBody();
- *
- *
- * @category HTTP
- * @package HTTP_Request
- * @author Richard Heyes
- * @author Alexey Borzov
- * @version Release: 1.4.4
- */
-class HTTP_Request
-{
- /**#@+
- * @access private
- */
- /**
- * Instance of Net_URL
- * @var Net_URL
- */
- var $_url;
-
- /**
- * Type of request
- * @var string
- */
- var $_method;
-
- /**
- * HTTP Version
- * @var string
- */
- var $_http;
-
- /**
- * Request headers
- * @var array
- */
- var $_requestHeaders;
-
- /**
- * Basic Auth Username
- * @var string
- */
- var $_user;
-
- /**
- * Basic Auth Password
- * @var string
- */
- var $_pass;
-
- /**
- * Socket object
- * @var Net_Socket
- */
- var $_sock;
-
- /**
- * Proxy server
- * @var string
- */
- var $_proxy_host;
-
- /**
- * Proxy port
- * @var integer
- */
- var $_proxy_port;
-
- /**
- * Proxy username
- * @var string
- */
- var $_proxy_user;
-
- /**
- * Proxy password
- * @var string
- */
- var $_proxy_pass;
-
- /**
- * Post data
- * @var array
- */
- var $_postData;
-
- /**
- * Request body
- * @var string
- */
- var $_body;
-
- /**
- * A list of methods that MUST NOT have a request body, per RFC 2616
- * @var array
- */
- var $_bodyDisallowed = array('TRACE');
-
- /**
- * Methods having defined semantics for request body
- *
- * Content-Length header (indicating that the body follows, section 4.3 of
- * RFC 2616) will be sent for these methods even if no body was added
- *
- * @var array
- */
- var $_bodyRequired = array('POST', 'PUT');
-
- /**
- * Files to post
- * @var array
- */
- var $_postFiles = array();
-
- /**
- * Connection timeout.
- * @var float
- */
- var $_timeout;
-
- /**
- * HTTP_Response object
- * @var HTTP_Response
- */
- var $_response;
-
- /**
- * Whether to allow redirects
- * @var boolean
- */
- var $_allowRedirects;
-
- /**
- * Maximum redirects allowed
- * @var integer
- */
- var $_maxRedirects;
-
- /**
- * Current number of redirects
- * @var integer
- */
- var $_redirects;
-
- /**
- * Whether to append brackets [] to array variables
- * @var bool
- */
- var $_useBrackets = true;
-
- /**
- * Attached listeners
- * @var array
- */
- var $_listeners = array();
-
- /**
- * Whether to save response body in response object property
- * @var bool
- */
- var $_saveBody = true;
-
- /**
- * Timeout for reading from socket (array(seconds, microseconds))
- * @var array
- */
- var $_readTimeout = null;
-
- /**
- * Options to pass to Net_Socket::connect. See stream_context_create
- * @var array
- */
- var $_socketOptions = null;
- /**#@-*/
-
- /**
- * Constructor
- *
- * Sets up the object
- * @param string The url to fetch/access
- * @param array Associative array of parameters which can have the following keys:
- *
- * - method - Method to use, GET, POST etc (string)
- * - http - HTTP Version to use, 1.0 or 1.1 (string)
- * - user - Basic Auth username (string)
- * - pass - Basic Auth password (string)
- * - proxy_host - Proxy server host (string)
- * - proxy_port - Proxy server port (integer)
- * - proxy_user - Proxy auth username (string)
- * - proxy_pass - Proxy auth password (string)
- * - timeout - Connection timeout in seconds (float)
- * - allowRedirects - Whether to follow redirects or not (bool)
- * - maxRedirects - Max number of redirects to follow (integer)
- * - useBrackets - Whether to append [] to array variable names (bool)
- * - saveBody - Whether to save response body in response object property (bool)
- * - readTimeout - Timeout for reading / writing data over the socket (array (seconds, microseconds))
- * - socketOptions - Options to pass to Net_Socket object (array)
- *
- * @access public
- */
- function HTTP_Request($url = '', $params = array())
- {
- $this->_method = HTTP_REQUEST_METHOD_GET;
- $this->_http = HTTP_REQUEST_HTTP_VER_1_1;
- $this->_requestHeaders = array();
- $this->_postData = array();
- $this->_body = null;
-
- $this->_user = null;
- $this->_pass = null;
-
- $this->_proxy_host = null;
- $this->_proxy_port = null;
- $this->_proxy_user = null;
- $this->_proxy_pass = null;
-
- $this->_allowRedirects = false;
- $this->_maxRedirects = 3;
- $this->_redirects = 0;
-
- $this->_timeout = null;
- $this->_response = null;
-
- foreach ($params as $key => $value) {
- $this->{'_' . $key} = $value;
- }
-
- if (!empty($url)) {
- $this->setURL($url);
- }
-
- // Default useragent
- $this->addHeader('User-Agent', 'PEAR HTTP_Request class ( http://pear.php.net/ )');
-
- // We don't do keep-alives by default
- $this->addHeader('Connection', 'close');
-
- // Basic authentication
- if (!empty($this->_user)) {
- $this->addHeader('Authorization', 'Basic ' . base64_encode($this->_user . ':' . $this->_pass));
- }
-
- // Proxy authentication (see bug #5913)
- if (!empty($this->_proxy_user)) {
- $this->addHeader('Proxy-Authorization', 'Basic ' . base64_encode($this->_proxy_user . ':' . $this->_proxy_pass));
- }
-
- // Use gzip encoding if possible
- if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http && extension_loaded('zlib')) {
- $this->addHeader('Accept-Encoding', 'gzip');
- }
- }
-
- /**
- * Generates a Host header for HTTP/1.1 requests
- *
- * @access private
- * @return string
- */
- function _generateHostHeader()
- {
- if ($this->_url->port != 80 AND strcasecmp($this->_url->protocol, 'http') == 0) {
- $host = $this->_url->host . ':' . $this->_url->port;
-
- } elseif ($this->_url->port != 443 AND strcasecmp($this->_url->protocol, 'https') == 0) {
- $host = $this->_url->host . ':' . $this->_url->port;
-
- } elseif ($this->_url->port == 443 AND strcasecmp($this->_url->protocol, 'https') == 0 AND strpos($this->_url->url, ':443') !== false) {
- $host = $this->_url->host . ':' . $this->_url->port;
-
- } else {
- $host = $this->_url->host;
- }
-
- return $host;
- }
-
- /**
- * Resets the object to its initial state (DEPRECATED).
- * Takes the same parameters as the constructor.
- *
- * @param string $url The url to be requested
- * @param array $params Associative array of parameters
- * (see constructor for details)
- * @access public
- * @deprecated deprecated since 1.2, call the constructor if this is necessary
- */
- function reset($url, $params = array())
- {
- $this->HTTP_Request($url, $params);
- }
-
- /**
- * Sets the URL to be requested
- *
- * @param string The url to be requested
- * @access public
- */
- function setURL($url)
- {
- $this->_url = &new Net_URL($url, $this->_useBrackets);
-
- if (!empty($this->_url->user) || !empty($this->_url->pass)) {
- $this->setBasicAuth($this->_url->user, $this->_url->pass);
- }
-
- if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http) {
- $this->addHeader('Host', $this->_generateHostHeader());
- }
-
- // set '/' instead of empty path rather than check later (see bug #8662)
- if (empty($this->_url->path)) {
- $this->_url->path = '/';
- }
- }
-
- /**
- * Returns the current request URL
- *
- * @return string Current request URL
- * @access public
- */
- function getUrl()
- {
- return empty($this->_url)? '': $this->_url->getUrl();
- }
-
- /**
- * Sets a proxy to be used
- *
- * @param string Proxy host
- * @param int Proxy port
- * @param string Proxy username
- * @param string Proxy password
- * @access public
- */
- function setProxy($host, $port = 8080, $user = null, $pass = null)
- {
- $this->_proxy_host = $host;
- $this->_proxy_port = $port;
- $this->_proxy_user = $user;
- $this->_proxy_pass = $pass;
-
- if (!empty($user)) {
- $this->addHeader('Proxy-Authorization', 'Basic ' . base64_encode($user . ':' . $pass));
- }
- }
-
- /**
- * Sets basic authentication parameters
- *
- * @param string Username
- * @param string Password
- */
- function setBasicAuth($user, $pass)
- {
- $this->_user = $user;
- $this->_pass = $pass;
-
- $this->addHeader('Authorization', 'Basic ' . base64_encode($user . ':' . $pass));
- }
-
- /**
- * Sets the method to be used, GET, POST etc.
- *
- * @param string Method to use. Use the defined constants for this
- * @access public
- */
- function setMethod($method)
- {
- $this->_method = $method;
- }
-
- /**
- * Sets the HTTP version to use, 1.0 or 1.1
- *
- * @param string Version to use. Use the defined constants for this
- * @access public
- */
- function setHttpVer($http)
- {
- $this->_http = $http;
- }
-
- /**
- * Adds a request header
- *
- * @param string Header name
- * @param string Header value
- * @access public
- */
- function addHeader($name, $value)
- {
- $this->_requestHeaders[strtolower($name)] = $value;
- }
-
- /**
- * Removes a request header
- *
- * @param string Header name to remove
- * @access public
- */
- function removeHeader($name)
- {
- if (isset($this->_requestHeaders[strtolower($name)])) {
- unset($this->_requestHeaders[strtolower($name)]);
- }
- }
-
- /**
- * Adds a querystring parameter
- *
- * @param string Querystring parameter name
- * @param string Querystring parameter value
- * @param bool Whether the value is already urlencoded or not, default = not
- * @access public
- */
- function addQueryString($name, $value, $preencoded = false)
- {
- $this->_url->addQueryString($name, $value, $preencoded);
- }
-
- /**
- * Sets the querystring to literally what you supply
- *
- * @param string The querystring data. Should be of the format foo=bar&x=y etc
- * @param bool Whether data is already urlencoded or not, default = already encoded
- * @access public
- */
- function addRawQueryString($querystring, $preencoded = true)
- {
- $this->_url->addRawQueryString($querystring, $preencoded);
- }
-
- /**
- * Adds postdata items
- *
- * @param string Post data name
- * @param string Post data value
- * @param bool Whether data is already urlencoded or not, default = not
- * @access public
- */
- function addPostData($name, $value, $preencoded = false)
- {
- if ($preencoded) {
- $this->_postData[$name] = $value;
- } else {
- $this->_postData[$name] = $this->_arrayMapRecursive('urlencode', $value);
- }
- }
-
- function addPostDataArray($array, $preencoded = false)
- {
- foreach($array as $key => $val){
- $this->addPostData($key, $val, $preencoded);
- }
- }
-
- /**
- * Recursively applies the callback function to the value
- *
- * @param mixed Callback function
- * @param mixed Value to process
- * @access private
- * @return mixed Processed value
- */
- function _arrayMapRecursive($callback, $value)
- {
- if (!is_array($value)) {
- return call_user_func($callback, $value);
- } else {
- $map = array();
- foreach ($value as $k => $v) {
- $map[$k] = $this->_arrayMapRecursive($callback, $v);
- }
- return $map;
- }
- }
-
- /**
- * Adds a file to form-based file upload
- *
- * Used to emulate file upload via a HTML form. The method also sets
- * Content-Type of HTTP request to 'multipart/form-data'.
- *
- * If you just want to send the contents of a file as the body of HTTP
- * request you should use setBody() method.
- *
- * @access public
- * @param string name of file-upload field
- * @param mixed file name(s)
- * @param mixed content-type(s) of file(s) being uploaded
- * @return bool true on success
- * @throws PEAR_Error
- */
- function addFile($inputName, $fileName, $contentType = 'application/octet-stream')
- {
- if (!is_array($fileName) && !is_readable($fileName)) {
- return PEAR::raiseError("File '{$fileName}' is not readable", HTTP_REQUEST_ERROR_FILE);
- } elseif (is_array($fileName)) {
- foreach ($fileName as $name) {
- if (!is_readable($name)) {
- return PEAR::raiseError("File '{$name}' is not readable", HTTP_REQUEST_ERROR_FILE);
- }
- }
- }
- $this->addHeader('Content-Type', 'multipart/form-data');
- $this->_postFiles[$inputName] = array(
- 'name' => $fileName,
- 'type' => $contentType
- );
- return true;
- }
-
- /**
- * Adds raw postdata (DEPRECATED)
- *
- * @param string The data
- * @param bool Whether data is preencoded or not, default = already encoded
- * @access public
- * @deprecated deprecated since 1.3.0, method setBody() should be used instead
- */
- function addRawPostData($postdata, $preencoded = true)
- {
- $this->_body = $preencoded ? $postdata : urlencode($postdata);
- }
-
- /**
- * Sets the request body (for POST, PUT and similar requests)
- *
- * @param string Request body
- * @access public
- */
- function setBody($body)
- {
- $this->_body = $body;
- }
-
- /**
- * Clears any postdata that has been added (DEPRECATED).
- *
- * Useful for multiple request scenarios.
- *
- * @access public
- * @deprecated deprecated since 1.2
- */
- function clearPostData()
- {
- $this->_postData = null;
- }
-
- /**
- * Appends a cookie to "Cookie:" header
- *
- * @param string $name cookie name
- * @param string $value cookie value
- * @access public
- */
- function addCookie($name, $value)
- {
- $cookies = isset($this->_requestHeaders['cookie']) ? $this->_requestHeaders['cookie']. '; ' : '';
- $this->addHeader('Cookie', $cookies . $name . '=' . $value);
- }
-
- /**
- * Clears any cookies that have been added (DEPRECATED).
- *
- * Useful for multiple request scenarios
- *
- * @access public
- * @deprecated deprecated since 1.2
- */
- function clearCookies()
- {
- $this->removeHeader('Cookie');
- }
-
- /**
- * Sends the request
- *
- * @access public
- * @param bool Whether to store response body in Response object property,
- * set this to false if downloading a LARGE file and using a Listener
- * @return mixed PEAR error on error, true otherwise
- */
- function sendRequest($saveBody = true)
- {
- if (!is_a($this->_url, 'Net_URL')) {
- return PEAR::raiseError('No URL given', HTTP_REQUEST_ERROR_URL);
- }
-
- $host = isset($this->_proxy_host) ? $this->_proxy_host : $this->_url->host;
- $port = isset($this->_proxy_port) ? $this->_proxy_port : $this->_url->port;
-
- if (strcasecmp($this->_url->protocol, 'https') == 0) {
- // Bug #14127, don't try connecting to HTTPS sites without OpenSSL
- if (version_compare(PHP_VERSION, '4.3.0', '<') || !extension_loaded('openssl')) {
- return PEAR::raiseError('Need PHP 4.3.0 or later with OpenSSL support for https:// requests',
- HTTP_REQUEST_ERROR_URL);
- } elseif (isset($this->_proxy_host)) {
- return PEAR::raiseError('HTTPS proxies are not supported', HTTP_REQUEST_ERROR_PROXY);
- }
- $host = 'ssl://' . $host;
- }
-
- // magic quotes may fuck up file uploads and chunked response processing
- $magicQuotes = ini_get('magic_quotes_runtime');
- ini_set('magic_quotes_runtime', false);
-
- // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive
- // connection token to a proxy server...
- if (isset($this->_proxy_host) && !empty($this->_requestHeaders['connection']) &&
- 'Keep-Alive' == $this->_requestHeaders['connection'])
- {
- $this->removeHeader('connection');
- }
-
- $keepAlive = (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http && empty($this->_requestHeaders['connection'])) ||
- (!empty($this->_requestHeaders['connection']) && 'Keep-Alive' == $this->_requestHeaders['connection']);
- $sockets = &PEAR::getStaticProperty('HTTP_Request', 'sockets');
- $sockKey = $host . ':' . $port;
- unset($this->_sock);
-
- // There is a connected socket in the "static" property?
- if ($keepAlive && !empty($sockets[$sockKey]) &&
- !empty($sockets[$sockKey]->fp))
- {
- $this->_sock =& $sockets[$sockKey];
- $err = null;
- } else {
- $this->_notify('connect');
- $this->_sock =& new Net_Socket();
- $err = $this->_sock->connect($host, $port, null, $this->_timeout, $this->_socketOptions);
- }
- PEAR::isError($err) or $err = $this->_sock->write($this->_buildRequest());
-
- if (!PEAR::isError($err)) {
- if (!empty($this->_readTimeout)) {
- $this->_sock->setTimeout($this->_readTimeout[0], $this->_readTimeout[1]);
- }
-
- $this->_notify('sentRequest');
-
- // Read the response
- $this->_response = &new HTTP_Response($this->_sock, $this->_listeners);
- $err = $this->_response->process(
- $this->_saveBody && $saveBody,
- HTTP_REQUEST_METHOD_HEAD != $this->_method
- );
-
- if ($keepAlive) {
- $keepAlive = (isset($this->_response->_headers['content-length'])
- || (isset($this->_response->_headers['transfer-encoding'])
- && strtolower($this->_response->_headers['transfer-encoding']) == 'chunked'));
- if ($keepAlive) {
- if (isset($this->_response->_headers['connection'])) {
- $keepAlive = strtolower($this->_response->_headers['connection']) == 'keep-alive';
- } else {
- $keepAlive = 'HTTP/'.HTTP_REQUEST_HTTP_VER_1_1 == $this->_response->_protocol;
- }
- }
- }
- }
-
- ini_set('magic_quotes_runtime', $magicQuotes);
-
- if (PEAR::isError($err)) {
- return $err;
- }
-
- if (!$keepAlive) {
- $this->disconnect();
- // Store the connected socket in "static" property
- } elseif (empty($sockets[$sockKey]) || empty($sockets[$sockKey]->fp)) {
- $sockets[$sockKey] =& $this->_sock;
- }
-
- // Check for redirection
- if ( $this->_allowRedirects
- AND $this->_redirects <= $this->_maxRedirects
- AND $this->getResponseCode() > 300
- AND $this->getResponseCode() < 399
- AND !empty($this->_response->_headers['location'])) {
-
-
- $redirect = $this->_response->_headers['location'];
-
- // Absolute URL
- if (preg_match('/^https?:\/\//i', $redirect)) {
- $this->_url = &new Net_URL($redirect);
- $this->addHeader('Host', $this->_generateHostHeader());
- // Absolute path
- } elseif ($redirect{0} == '/') {
- $this->_url->path = $redirect;
-
- // Relative path
- } elseif (substr($redirect, 0, 3) == '../' OR substr($redirect, 0, 2) == './') {
- if (substr($this->_url->path, -1) == '/') {
- $redirect = $this->_url->path . $redirect;
- } else {
- $redirect = dirname($this->_url->path) . '/' . $redirect;
- }
- $redirect = Net_URL::resolvePath($redirect);
- $this->_url->path = $redirect;
-
- // Filename, no path
- } else {
- if (substr($this->_url->path, -1) == '/') {
- $redirect = $this->_url->path . $redirect;
- } else {
- $redirect = dirname($this->_url->path) . '/' . $redirect;
- }
- $this->_url->path = $redirect;
- }
-
- $this->_redirects++;
- return $this->sendRequest($saveBody);
-
- // Too many redirects
- } elseif ($this->_allowRedirects AND $this->_redirects > $this->_maxRedirects) {
- return PEAR::raiseError('Too many redirects', HTTP_REQUEST_ERROR_REDIRECTS);
- }
-
- return true;
- }
-
- /**
- * Disconnect the socket, if connected. Only useful if using Keep-Alive.
- *
- * @access public
- */
- function disconnect()
- {
- if (!empty($this->_sock) && !empty($this->_sock->fp)) {
- $this->_notify('disconnect');
- $this->_sock->disconnect();
- }
- }
-
- /**
- * Returns the response code
- *
- * @access public
- * @return mixed Response code, false if not set
- */
- function getResponseCode()
- {
- return isset($this->_response->_code) ? $this->_response->_code : false;
- }
-
- /**
- * Returns the response reason phrase
- *
- * @access public
- * @return mixed Response reason phrase, false if not set
- */
- function getResponseReason()
- {
- return isset($this->_response->_reason) ? $this->_response->_reason : false;
- }
-
- /**
- * Returns either the named header or all if no name given
- *
- * @access public
- * @param string The header name to return, do not set to get all headers
- * @return mixed either the value of $headername (false if header is not present)
- * or an array of all headers
- */
- function getResponseHeader($headername = null)
- {
- if (!isset($headername)) {
- return isset($this->_response->_headers)? $this->_response->_headers: array();
- } else {
- $headername = strtolower($headername);
- return isset($this->_response->_headers[$headername]) ? $this->_response->_headers[$headername] : false;
- }
- }
-
- /**
- * Returns the body of the response
- *
- * @access public
- * @return mixed response body, false if not set
- */
- function getResponseBody()
- {
- return isset($this->_response->_body) ? $this->_response->_body : false;
- }
-
- /**
- * Returns cookies set in response
- *
- * @access public
- * @return mixed array of response cookies, false if none are present
- */
- function getResponseCookies()
- {
- return isset($this->_response->_cookies) ? $this->_response->_cookies : false;
- }
-
- /**
- * Builds the request string
- *
- * @access private
- * @return string The request string
- */
- function _buildRequest()
- {
- $separator = ini_get('arg_separator.output');
- ini_set('arg_separator.output', '&');
- $querystring = ($querystring = $this->_url->getQueryString()) ? '?' . $querystring : '';
- ini_set('arg_separator.output', $separator);
-
- $host = isset($this->_proxy_host) ? $this->_url->protocol . '://' . $this->_url->host : '';
- $port = (isset($this->_proxy_host) AND $this->_url->port != 80) ? ':' . $this->_url->port : '';
- $path = $this->_url->path . $querystring;
- $url = $host . $port . $path;
-
- if (!strlen($url)) {
- $url = '/';
- }
-
- $request = $this->_method . ' ' . $url . ' HTTP/' . $this->_http . "\r\n";
-
- if (in_array($this->_method, $this->_bodyDisallowed) ||
- (0 == strlen($this->_body) && (HTTP_REQUEST_METHOD_POST != $this->_method ||
- (empty($this->_postData) && empty($this->_postFiles)))))
- {
- $this->removeHeader('Content-Type');
- } else {
- if (empty($this->_requestHeaders['content-type'])) {
- // Add default content-type
- $this->addHeader('Content-Type', 'application/x-www-form-urlencoded');
- } elseif ('multipart/form-data' == $this->_requestHeaders['content-type']) {
- $boundary = 'HTTP_Request_' . md5(uniqid('request') . microtime());
- $this->addHeader('Content-Type', 'multipart/form-data; boundary=' . $boundary);
- }
- }
-
- // Request Headers
- if (!empty($this->_requestHeaders)) {
- foreach ($this->_requestHeaders as $name => $value) {
- $canonicalName = implode('-', array_map('ucfirst', explode('-', $name)));
- $request .= $canonicalName . ': ' . $value . "\r\n";
- }
- }
-
- // Method does not allow a body, simply add a final CRLF
- if (in_array($this->_method, $this->_bodyDisallowed)) {
-
- $request .= "\r\n";
-
- // Post data if it's an array
- } elseif (HTTP_REQUEST_METHOD_POST == $this->_method &&
- (!empty($this->_postData) || !empty($this->_postFiles))) {
-
- // "normal" POST request
- if (!isset($boundary)) {
- $postdata = implode('&', array_map(
- create_function('$a', 'return $a[0] . \'=\' . $a[1];'),
- $this->_flattenArray('', $this->_postData)
- ));
-
- // multipart request, probably with file uploads
- } else {
- $postdata = '';
- if (!empty($this->_postData)) {
- $flatData = $this->_flattenArray('', $this->_postData);
- foreach ($flatData as $item) {
- $postdata .= '--' . $boundary . "\r\n";
- $postdata .= 'Content-Disposition: form-data; name="' . $item[0] . '"';
- $postdata .= "\r\n\r\n" . urldecode($item[1]) . "\r\n";
- }
- }
- foreach ($this->_postFiles as $name => $value) {
- if (is_array($value['name'])) {
- $varname = $name . ($this->_useBrackets? '[]': '');
- } else {
- $varname = $name;
- $value['name'] = array($value['name']);
- }
- foreach ($value['name'] as $key => $filename) {
- $fp = fopen($filename, 'r');
- $basename = basename($filename);
- $type = is_array($value['type'])? @$value['type'][$key]: $value['type'];
-
- $postdata .= '--' . $boundary . "\r\n";
- $postdata .= 'Content-Disposition: form-data; name="' . $varname . '"; filename="' . $basename . '"';
- $postdata .= "\r\nContent-Type: " . $type;
- $postdata .= "\r\n\r\n" . fread($fp, filesize($filename)) . "\r\n";
- fclose($fp);
- }
- }
- $postdata .= '--' . $boundary . "--\r\n";
- }
- $request .= 'Content-Length: ' .
- (HTTP_REQUEST_MBSTRING? mb_strlen($postdata, 'iso-8859-1'): strlen($postdata)) .
- "\r\n\r\n";
- $request .= $postdata;
-
- // Explicitly set request body
- } elseif (0 < strlen($this->_body)) {
-
- $request .= 'Content-Length: ' .
- (HTTP_REQUEST_MBSTRING? mb_strlen($this->_body, 'iso-8859-1'): strlen($this->_body)) .
- "\r\n\r\n";
- $request .= $this->_body;
-
- // No body: send a Content-Length header nonetheless (request #12900),
- // but do that only for methods that require a body (bug #14740)
- } else {
-
- if (in_array($this->_method, $this->_bodyRequired)) {
- $request .= "Content-Length: 0\r\n";
- }
- $request .= "\r\n";
- }
-
- return $request;
- }
-
- /**
- * Helper function to change the (probably multidimensional) associative array
- * into the simple one.
- *
- * @param string name for item
- * @param mixed item's values
- * @return array array with the following items: array('item name', 'item value');
- * @access private
- */
- function _flattenArray($name, $values)
- {
- if (!is_array($values)) {
- return array(array($name, $values));
- } else {
- $ret = array();
- foreach ($values as $k => $v) {
- if (empty($name)) {
- $newName = $k;
- } elseif ($this->_useBrackets) {
- $newName = $name . '[' . $k . ']';
- } else {
- $newName = $name;
- }
- $ret = array_merge($ret, $this->_flattenArray($newName, $v));
- }
- return $ret;
- }
- }
-
-
- /**
- * Adds a Listener to the list of listeners that are notified of
- * the object's events
- *
- * Events sent by HTTP_Request object
- * - 'connect': on connection to server
- * - 'sentRequest': after the request was sent
- * - 'disconnect': on disconnection from server
- *
- * Events sent by HTTP_Response object
- * - 'gotHeaders': after receiving response headers (headers are passed in $data)
- * - 'tick': on receiving a part of response body (the part is passed in $data)
- * - 'gzTick': on receiving a gzip-encoded part of response body (ditto)
- * - 'gotBody': after receiving the response body (passes the decoded body in $data if it was gzipped)
- *
- * @param HTTP_Request_Listener listener to attach
- * @return boolean whether the listener was successfully attached
- * @access public
- */
- function attach(&$listener)
- {
- if (!is_a($listener, 'HTTP_Request_Listener')) {
- return false;
- }
- $this->_listeners[$listener->getId()] =& $listener;
- return true;
- }
-
-
- /**
- * Removes a Listener from the list of listeners
- *
- * @param HTTP_Request_Listener listener to detach
- * @return boolean whether the listener was successfully detached
- * @access public
- */
- function detach(&$listener)
- {
- if (!is_a($listener, 'HTTP_Request_Listener') ||
- !isset($this->_listeners[$listener->getId()])) {
- return false;
- }
- unset($this->_listeners[$listener->getId()]);
- return true;
- }
-
-
- /**
- * Notifies all registered listeners of an event.
- *
- * @param string Event name
- * @param mixed Additional data
- * @access private
- * @see HTTP_Request::attach()
- */
- function _notify($event, $data = null)
- {
- foreach (array_keys($this->_listeners) as $id) {
- $this->_listeners[$id]->update($this, $event, $data);
- }
- }
-}
-
-
-/**
- * Response class to complement the Request class
- *
- * @category HTTP
- * @package HTTP_Request
- * @author Richard Heyes
- * @author Alexey Borzov
- * @version Release: 1.4.4
- */
-class HTTP_Response
-{
- /**
- * Socket object
- * @var Net_Socket
- */
- var $_sock;
-
- /**
- * Protocol
- * @var string
- */
- var $_protocol;
-
- /**
- * Return code
- * @var string
- */
- var $_code;
-
- /**
- * Response reason phrase
- * @var string
- */
- var $_reason;
-
- /**
- * Response headers
- * @var array
- */
- var $_headers;
-
- /**
- * Cookies set in response
- * @var array
- */
- var $_cookies;
-
- /**
- * Response body
- * @var string
- */
- var $_body = '';
-
- /**
- * Used by _readChunked(): remaining length of the current chunk
- * @var string
- */
- var $_chunkLength = 0;
-
- /**
- * Attached listeners
- * @var array
- */
- var $_listeners = array();
-
- /**
- * Bytes left to read from message-body
- * @var null|int
- */
- var $_toRead;
-
- /**
- * Constructor
- *
- * @param Net_Socket socket to read the response from
- * @param array listeners attached to request
- */
- function HTTP_Response(&$sock, &$listeners)
- {
- $this->_sock =& $sock;
- $this->_listeners =& $listeners;
- }
-
-
- /**
- * Processes a HTTP response
- *
- * This extracts response code, headers, cookies and decodes body if it
- * was encoded in some way
- *
- * @access public
- * @param bool Whether to store response body in object property, set
- * this to false if downloading a LARGE file and using a Listener.
- * This is assumed to be true if body is gzip-encoded.
- * @param bool Whether the response can actually have a message-body.
- * Will be set to false for HEAD requests.
- * @throws PEAR_Error
- * @return mixed true on success, PEAR_Error in case of malformed response
- */
- function process($saveBody = true, $canHaveBody = true)
- {
- do {
- $line = $this->_sock->readLine();
- if (!preg_match('!^(HTTP/\d\.\d) (\d{3})(?: (.+))?!', $line, $s)) {
- return PEAR::raiseError('Malformed response', HTTP_REQUEST_ERROR_RESPONSE);
- } else {
- $this->_protocol = $s[1];
- $this->_code = intval($s[2]);
- $this->_reason = empty($s[3])? null: $s[3];
- }
- while ('' !== ($header = $this->_sock->readLine())) {
- $this->_processHeader($header);
- }
- } while (100 == $this->_code);
-
- $this->_notify('gotHeaders', $this->_headers);
-
- // RFC 2616, section 4.4:
- // 1. Any response message which "MUST NOT" include a message-body ...
- // is always terminated by the first empty line after the header fields
- // 3. ... If a message is received with both a
- // Transfer-Encoding header field and a Content-Length header field,
- // the latter MUST be ignored.
- $canHaveBody = $canHaveBody && $this->_code >= 200 &&
- $this->_code != 204 && $this->_code != 304;
-
- // If response body is present, read it and decode
- $chunked = isset($this->_headers['transfer-encoding']) && ('chunked' == $this->_headers['transfer-encoding']);
- $gzipped = isset($this->_headers['content-encoding']) && ('gzip' == $this->_headers['content-encoding']);
- $hasBody = false;
- if ($canHaveBody && ($chunked || !isset($this->_headers['content-length']) ||
- 0 != $this->_headers['content-length']))
- {
- if ($chunked || !isset($this->_headers['content-length'])) {
- $this->_toRead = null;
- } else {
- $this->_toRead = $this->_headers['content-length'];
- }
- while (!$this->_sock->eof() && (is_null($this->_toRead) || 0 < $this->_toRead)) {
- if ($chunked) {
- $data = $this->_readChunked();
- } elseif (is_null($this->_toRead)) {
- $data = $this->_sock->read(4096);
- } else {
- $data = $this->_sock->read(min(4096, $this->_toRead));
- $this->_toRead -= HTTP_REQUEST_MBSTRING? mb_strlen($data, 'iso-8859-1'): strlen($data);
- }
- if ('' == $data && (!$this->_chunkLength || $this->_sock->eof())) {
- break;
- } else {
- $hasBody = true;
- if ($saveBody || $gzipped) {
- $this->_body .= $data;
- }
- $this->_notify($gzipped? 'gzTick': 'tick', $data);
- }
- }
- }
-
- if ($hasBody) {
- // Uncompress the body if needed
- if ($gzipped) {
- $body = $this->_decodeGzip($this->_body);
- if (PEAR::isError($body)) {
- return $body;
- }
- $this->_body = $body;
- $this->_notify('gotBody', $this->_body);
- } else {
- $this->_notify('gotBody');
- }
- }
- return true;
- }
-
-
- /**
- * Processes the response header
- *
- * @access private
- * @param string HTTP header
- */
- function _processHeader($header)
- {
- if (false === strpos($header, ':')) {
- return;
- }
- list($headername, $headervalue) = explode(':', $header, 2);
- $headername = strtolower($headername);
- $headervalue = ltrim($headervalue);
-
- if ('set-cookie' != $headername) {
- if (isset($this->_headers[$headername])) {
- $this->_headers[$headername] .= ',' . $headervalue;
- } else {
- $this->_headers[$headername] = $headervalue;
- }
- } else {
- $this->_parseCookie($headervalue);
- }
- }
-
-
- /**
- * Parse a Set-Cookie header to fill $_cookies array
- *
- * @access private
- * @param string value of Set-Cookie header
- */
- function _parseCookie($headervalue)
- {
- $cookie = array(
- 'expires' => null,
- 'domain' => null,
- 'path' => null,
- 'secure' => false
- );
-
- // Only a name=value pair
- if (!strpos($headervalue, ';')) {
- $pos = strpos($headervalue, '=');
- $cookie['name'] = trim(substr($headervalue, 0, $pos));
- $cookie['value'] = trim(substr($headervalue, $pos + 1));
-
- // Some optional parameters are supplied
- } else {
- $elements = explode(';', $headervalue);
- $pos = strpos($elements[0], '=');
- $cookie['name'] = trim(substr($elements[0], 0, $pos));
- $cookie['value'] = trim(substr($elements[0], $pos + 1));
-
- for ($i = 1; $i < count($elements); $i++) {
- if (false === strpos($elements[$i], '=')) {
- $elName = trim($elements[$i]);
- $elValue = null;
- } else {
- list ($elName, $elValue) = array_map('trim', explode('=', $elements[$i]));
- }
- $elName = strtolower($elName);
- if ('secure' == $elName) {
- $cookie['secure'] = true;
- } elseif ('expires' == $elName) {
- $cookie['expires'] = str_replace('"', '', $elValue);
- } elseif ('path' == $elName || 'domain' == $elName) {
- $cookie[$elName] = urldecode($elValue);
- } else {
- $cookie[$elName] = $elValue;
- }
- }
- }
- $this->_cookies[] = $cookie;
- }
-
-
- /**
- * Read a part of response body encoded with chunked Transfer-Encoding
- *
- * @access private
- * @return string
- */
- function _readChunked()
- {
- // at start of the next chunk?
- if (0 == $this->_chunkLength) {
- $line = $this->_sock->readLine();
- if (preg_match('/^([0-9a-f]+)/i', $line, $matches)) {
- $this->_chunkLength = hexdec($matches[1]);
- // Chunk with zero length indicates the end
- if (0 == $this->_chunkLength) {
- $this->_sock->readLine(); // make this an eof()
- return '';
- }
- } else {
- return '';
- }
- }
- $data = $this->_sock->read($this->_chunkLength);
- $this->_chunkLength -= HTTP_REQUEST_MBSTRING? mb_strlen($data, 'iso-8859-1'): strlen($data);
- if (0 == $this->_chunkLength) {
- $this->_sock->readLine(); // Trailing CRLF
- }
- return $data;
- }
-
-
- /**
- * Notifies all registered listeners of an event.
- *
- * @param string Event name
- * @param mixed Additional data
- * @access private
- * @see HTTP_Request::_notify()
- */
- function _notify($event, $data = null)
- {
- foreach (array_keys($this->_listeners) as $id) {
- $this->_listeners[$id]->update($this, $event, $data);
- }
- }
-
-
- /**
- * Decodes the message-body encoded by gzip
- *
- * The real decoding work is done by gzinflate() built-in function, this
- * method only parses the header and checks data for compliance with
- * RFC 1952
- *
- * @access private
- * @param string gzip-encoded data
- * @return string decoded data
- */
- function _decodeGzip($data)
- {
- if (HTTP_REQUEST_MBSTRING) {
- $oldEncoding = mb_internal_encoding();
- mb_internal_encoding('iso-8859-1');
- }
- $length = strlen($data);
- // If it doesn't look like gzip-encoded data, don't bother
- if (18 > $length || strcmp(substr($data, 0, 2), "\x1f\x8b")) {
- return $data;
- }
- $method = ord(substr($data, 2, 1));
- if (8 != $method) {
- return PEAR::raiseError('_decodeGzip(): unknown compression method', HTTP_REQUEST_ERROR_GZIP_METHOD);
- }
- $flags = ord(substr($data, 3, 1));
- if ($flags & 224) {
- return PEAR::raiseError('_decodeGzip(): reserved bits are set', HTTP_REQUEST_ERROR_GZIP_DATA);
- }
-
- // header is 10 bytes minimum. may be longer, though.
- $headerLength = 10;
- // extra fields, need to skip 'em
- if ($flags & 4) {
- if ($length - $headerLength - 2 < 8) {
- return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
- }
- $extraLength = unpack('v', substr($data, 10, 2));
- if ($length - $headerLength - 2 - $extraLength[1] < 8) {
- return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
- }
- $headerLength += $extraLength[1] + 2;
- }
- // file name, need to skip that
- if ($flags & 8) {
- if ($length - $headerLength - 1 < 8) {
- return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
- }
- $filenameLength = strpos(substr($data, $headerLength), chr(0));
- if (false === $filenameLength || $length - $headerLength - $filenameLength - 1 < 8) {
- return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
- }
- $headerLength += $filenameLength + 1;
- }
- // comment, need to skip that also
- if ($flags & 16) {
- if ($length - $headerLength - 1 < 8) {
- return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
- }
- $commentLength = strpos(substr($data, $headerLength), chr(0));
- if (false === $commentLength || $length - $headerLength - $commentLength - 1 < 8) {
- return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
- }
- $headerLength += $commentLength + 1;
- }
- // have a CRC for header. let's check
- if ($flags & 1) {
- if ($length - $headerLength - 2 < 8) {
- return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
- }
- $crcReal = 0xffff & crc32(substr($data, 0, $headerLength));
- $crcStored = unpack('v', substr($data, $headerLength, 2));
- if ($crcReal != $crcStored[1]) {
- return PEAR::raiseError('_decodeGzip(): header CRC check failed', HTTP_REQUEST_ERROR_GZIP_CRC);
- }
- $headerLength += 2;
- }
- // unpacked data CRC and size at the end of encoded data
- $tmp = unpack('V2', substr($data, -8));
- $dataCrc = $tmp[1];
- $dataSize = $tmp[2];
-
- // finally, call the gzinflate() function
- // don't pass $dataSize to gzinflate, see bugs #13135, #14370
- $unpacked = gzinflate(substr($data, $headerLength, -8));
- if (false === $unpacked) {
- return PEAR::raiseError('_decodeGzip(): gzinflate() call failed', HTTP_REQUEST_ERROR_GZIP_READ);
- } elseif ($dataSize != strlen($unpacked)) {
- return PEAR::raiseError('_decodeGzip(): data size check failed', HTTP_REQUEST_ERROR_GZIP_READ);
- } elseif ((0xffffffff & $dataCrc) != (0xffffffff & crc32($unpacked))) {
- return PEAR::raiseError('_decodeGzip(): data CRC check failed', HTTP_REQUEST_ERROR_GZIP_CRC);
- }
- if (HTTP_REQUEST_MBSTRING) {
- mb_internal_encoding($oldEncoding);
- }
- return $unpacked;
- }
-} // End class HTTP_Response
-?>
diff --git a/data/module/HTTP/Request/Listener.php b/data/module/HTTP/Request/Listener.php
deleted file mode 100644
index b4fe444b35d..00000000000
--- a/data/module/HTTP/Request/Listener.php
+++ /dev/null
@@ -1,106 +0,0 @@
-
- * @copyright 2002-2007 Richard Heyes
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Listener.php,v 1.3 2007/05/18 10:33:31 avb Exp $
- * @link http://pear.php.net/package/HTTP_Request/
- */
-
-/**
- * Listener for HTTP_Request and HTTP_Response objects
- *
- * This class implements the Observer part of a Subject-Observer
- * design pattern.
- *
- * @category HTTP
- * @package HTTP_Request
- * @author Alexey Borzov
- * @version Release: 1.4.4
- */
-class HTTP_Request_Listener
-{
- /**
- * A listener's identifier
- * @var string
- */
- var $_id;
-
- /**
- * Constructor, sets the object's identifier
- *
- * @access public
- */
- function HTTP_Request_Listener()
- {
- $this->_id = md5(uniqid('http_request_', 1));
- }
-
-
- /**
- * Returns the listener's identifier
- *
- * @access public
- * @return string
- */
- function getId()
- {
- return $this->_id;
- }
-
-
- /**
- * This method is called when Listener is notified of an event
- *
- * @access public
- * @param object an object the listener is attached to
- * @param string Event name
- * @param mixed Additional data
- * @abstract
- */
- function update(&$subject, $event, $data = null)
- {
- echo "Notified of event: '$event'\n";
- if (null !== $data) {
- echo "Additional data: ";
- var_dump($data);
- }
- }
-}
-?>
diff --git a/data/module/MDB2.php b/data/module/MDB2.php
deleted file mode 100644
index 45c0802dfb6..00000000000
--- a/data/module/MDB2.php
+++ /dev/null
@@ -1,4607 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: MDB2.php 328183 2012-10-29 15:10:42Z danielc $
-//
-
-/**
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-
-require_once 'PEAR.php';
-
-// {{{ Error constants
-
-/**
- * The method mapErrorCode in each MDB2_dbtype implementation maps
- * native error codes to one of these.
- *
- * If you add an error code here, make sure you also add a textual
- * version of it in MDB2::errorMessage().
- */
-
-define('MDB2_OK', true);
-define('MDB2_ERROR', -1);
-define('MDB2_ERROR_SYNTAX', -2);
-define('MDB2_ERROR_CONSTRAINT', -3);
-define('MDB2_ERROR_NOT_FOUND', -4);
-define('MDB2_ERROR_ALREADY_EXISTS', -5);
-define('MDB2_ERROR_UNSUPPORTED', -6);
-define('MDB2_ERROR_MISMATCH', -7);
-define('MDB2_ERROR_INVALID', -8);
-define('MDB2_ERROR_NOT_CAPABLE', -9);
-define('MDB2_ERROR_TRUNCATED', -10);
-define('MDB2_ERROR_INVALID_NUMBER', -11);
-define('MDB2_ERROR_INVALID_DATE', -12);
-define('MDB2_ERROR_DIVZERO', -13);
-define('MDB2_ERROR_NODBSELECTED', -14);
-define('MDB2_ERROR_CANNOT_CREATE', -15);
-define('MDB2_ERROR_CANNOT_DELETE', -16);
-define('MDB2_ERROR_CANNOT_DROP', -17);
-define('MDB2_ERROR_NOSUCHTABLE', -18);
-define('MDB2_ERROR_NOSUCHFIELD', -19);
-define('MDB2_ERROR_NEED_MORE_DATA', -20);
-define('MDB2_ERROR_NOT_LOCKED', -21);
-define('MDB2_ERROR_VALUE_COUNT_ON_ROW', -22);
-define('MDB2_ERROR_INVALID_DSN', -23);
-define('MDB2_ERROR_CONNECT_FAILED', -24);
-define('MDB2_ERROR_EXTENSION_NOT_FOUND',-25);
-define('MDB2_ERROR_NOSUCHDB', -26);
-define('MDB2_ERROR_ACCESS_VIOLATION', -27);
-define('MDB2_ERROR_CANNOT_REPLACE', -28);
-define('MDB2_ERROR_CONSTRAINT_NOT_NULL',-29);
-define('MDB2_ERROR_DEADLOCK', -30);
-define('MDB2_ERROR_CANNOT_ALTER', -31);
-define('MDB2_ERROR_MANAGER', -32);
-define('MDB2_ERROR_MANAGER_PARSE', -33);
-define('MDB2_ERROR_LOADMODULE', -34);
-define('MDB2_ERROR_INSUFFICIENT_DATA', -35);
-define('MDB2_ERROR_NO_PERMISSION', -36);
-define('MDB2_ERROR_DISCONNECT_FAILED', -37);
-
-// }}}
-// {{{ Verbose constants
-/**
- * These are just helper constants to more verbosely express parameters to prepare()
- */
-
-define('MDB2_PREPARE_MANIP', false);
-define('MDB2_PREPARE_RESULT', null);
-
-// }}}
-// {{{ Fetchmode constants
-
-/**
- * This is a special constant that tells MDB2 the user hasn't specified
- * any particular get mode, so the default should be used.
- */
-define('MDB2_FETCHMODE_DEFAULT', 0);
-
-/**
- * Column data indexed by numbers, ordered from 0 and up
- */
-define('MDB2_FETCHMODE_ORDERED', 1);
-
-/**
- * Column data indexed by column names
- */
-define('MDB2_FETCHMODE_ASSOC', 2);
-
-/**
- * Column data as object properties
- */
-define('MDB2_FETCHMODE_OBJECT', 3);
-
-/**
- * For multi-dimensional results: normally the first level of arrays
- * is the row number, and the second level indexed by column number or name.
- * MDB2_FETCHMODE_FLIPPED switches this order, so the first level of arrays
- * is the column name, and the second level the row number.
- */
-define('MDB2_FETCHMODE_FLIPPED', 4);
-
-// }}}
-// {{{ Portability mode constants
-
-/**
- * Portability: turn off all portability features.
- * @see MDB2_Driver_Common::setOption()
- */
-define('MDB2_PORTABILITY_NONE', 0);
-
-/**
- * Portability: convert names of tables and fields to case defined in the
- * "field_case" option when using the query*(), fetch*() and tableInfo() methods.
- * @see MDB2_Driver_Common::setOption()
- */
-define('MDB2_PORTABILITY_FIX_CASE', 1);
-
-/**
- * Portability: right trim the data output by query*() and fetch*().
- * @see MDB2_Driver_Common::setOption()
- */
-define('MDB2_PORTABILITY_RTRIM', 2);
-
-/**
- * Portability: force reporting the number of rows deleted.
- * @see MDB2_Driver_Common::setOption()
- */
-define('MDB2_PORTABILITY_DELETE_COUNT', 4);
-
-/**
- * Portability: not needed in MDB2 (just left here for compatibility to DB)
- * @see MDB2_Driver_Common::setOption()
- */
-define('MDB2_PORTABILITY_NUMROWS', 8);
-
-/**
- * Portability: makes certain error messages in certain drivers compatible
- * with those from other DBMS's.
- *
- * + mysql, mysqli: change unique/primary key constraints
- * MDB2_ERROR_ALREADY_EXISTS -> MDB2_ERROR_CONSTRAINT
- *
- * + odbc(access): MS's ODBC driver reports 'no such field' as code
- * 07001, which means 'too few parameters.' When this option is on
- * that code gets mapped to MDB2_ERROR_NOSUCHFIELD.
- *
- * @see MDB2_Driver_Common::setOption()
- */
-define('MDB2_PORTABILITY_ERRORS', 16);
-
-/**
- * Portability: convert empty values to null strings in data output by
- * query*() and fetch*().
- * @see MDB2_Driver_Common::setOption()
- */
-define('MDB2_PORTABILITY_EMPTY_TO_NULL', 32);
-
-/**
- * Portability: removes database/table qualifiers from associative indexes
- * @see MDB2_Driver_Common::setOption()
- */
-define('MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES', 64);
-
-/**
- * Portability: turn on all portability features.
- * @see MDB2_Driver_Common::setOption()
- */
-define('MDB2_PORTABILITY_ALL', 127);
-
-// }}}
-// {{{ Globals for class instance tracking
-
-/**
- * These are global variables that are used to track the various class instances
- */
-
-$GLOBALS['_MDB2_databases'] = array();
-$GLOBALS['_MDB2_dsninfo_default'] = array(
- 'phptype' => false,
- 'dbsyntax' => false,
- 'username' => false,
- 'password' => false,
- 'protocol' => false,
- 'hostspec' => false,
- 'port' => false,
- 'socket' => false,
- 'database' => false,
- 'mode' => false,
-);
-
-// }}}
-// {{{ class MDB2
-
-/**
- * The main 'MDB2' class is simply a container class with some static
- * methods for creating DB objects as well as some utility functions
- * common to all parts of DB.
- *
- * The object model of MDB2 is as follows (indentation means inheritance):
- *
- * MDB2 The main MDB2 class. This is simply a utility class
- * with some 'static' methods for creating MDB2 objects as
- * well as common utility functions for other MDB2 classes.
- *
- * MDB2_Driver_Common The base for each MDB2 implementation. Provides default
- * | implementations (in OO lingo virtual methods) for
- * | the actual DB implementations as well as a bunch of
- * | query utility functions.
- * |
- * +-MDB2_Driver_mysql The MDB2 implementation for MySQL. Inherits MDB2_Driver_Common.
- * When calling MDB2::factory or MDB2::connect for MySQL
- * connections, the object returned is an instance of this
- * class.
- * +-MDB2_Driver_pgsql The MDB2 implementation for PostGreSQL. Inherits MDB2_Driver_Common.
- * When calling MDB2::factory or MDB2::connect for PostGreSQL
- * connections, the object returned is an instance of this
- * class.
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2
-{
- // {{{ function setOptions($db, $options)
-
- /**
- * set option array in an exiting database object
- *
- * @param MDB2_Driver_Common MDB2 object
- * @param array An associative array of option names and their values.
- *
- * @return mixed MDB2_OK or a PEAR Error object
- *
- * @access public
- */
- static function setOptions($db, $options)
- {
- if (is_array($options)) {
- foreach ($options as $option => $value) {
- $test = $db->setOption($option, $value);
- if (MDB2::isError($test)) {
- return $test;
- }
- }
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ function classExists($classname)
-
- /**
- * Checks if a class exists without triggering __autoload
- *
- * @param string classname
- *
- * @return bool true success and false on error
- * @static
- * @access public
- */
- static function classExists($classname)
- {
- return class_exists($classname, false);
- }
-
- // }}}
- // {{{ function loadClass($class_name, $debug)
-
- /**
- * Loads a PEAR class.
- *
- * @param string classname to load
- * @param bool if errors should be suppressed
- *
- * @return mixed true success or PEAR_Error on failure
- *
- * @access public
- */
- static function loadClass($class_name, $debug)
- {
- if (!MDB2::classExists($class_name)) {
- $file_name = str_replace('_', DIRECTORY_SEPARATOR, $class_name).'.php';
- if ($debug) {
- $include = include_once($file_name);
- } else {
- $include = @include_once($file_name);
- }
- if (!$include) {
- if (!MDB2::fileExists($file_name)) {
- $msg = "unable to find package '$class_name' file '$file_name'";
- } else {
- $msg = "unable to load class '$class_name' from file '$file_name'";
- }
- $err = MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null, $msg);
- return $err;
- }
- if (!MDB2::classExists($class_name)) {
- $msg = "unable to load class '$class_name' from file '$file_name'";
- $err = MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null, $msg);
- return $err;
- }
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ function factory($dsn, $options = false)
-
- /**
- * Create a new MDB2 object for the specified database type
- *
- * @param mixed 'data source name', see the MDB2::parseDSN
- * method for a description of the dsn format.
- * Can also be specified as an array of the
- * format returned by MDB2::parseDSN.
- * @param array An associative array of option names and
- * their values.
- *
- * @return mixed a newly created MDB2 object, or false on error
- *
- * @access public
- */
- static function factory($dsn, $options = false)
- {
- $dsninfo = MDB2::parseDSN($dsn);
- if (empty($dsninfo['phptype'])) {
- $err = MDB2::raiseError(MDB2_ERROR_NOT_FOUND,
- null, null, 'no RDBMS driver specified');
- return $err;
- }
- $class_name = 'MDB2_Driver_'.$dsninfo['phptype'];
-
- $debug = (!empty($options['debug']));
- $err = MDB2::loadClass($class_name, $debug);
- if (MDB2::isError($err)) {
- return $err;
- }
-
- $db = new $class_name();
- $db->setDSN($dsninfo);
- $err = MDB2::setOptions($db, $options);
- if (MDB2::isError($err)) {
- return $err;
- }
-
- return $db;
- }
-
- // }}}
- // {{{ function connect($dsn, $options = false)
-
- /**
- * Create a new MDB2_Driver_* connection object and connect to the specified
- * database
- *
- * @param mixed $dsn 'data source name', see the MDB2::parseDSN
- * method for a description of the dsn format.
- * Can also be specified as an array of the
- * format returned by MDB2::parseDSN.
- * @param array $options An associative array of option names and
- * their values.
- *
- * @return mixed a newly created MDB2 connection object, or a MDB2
- * error object on error
- *
- * @access public
- * @see MDB2::parseDSN
- */
- static function connect($dsn, $options = false)
- {
- $db = MDB2::factory($dsn, $options);
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $err = $db->connect();
- if (MDB2::isError($err)) {
- $dsn = $db->getDSN('string', 'xxx');
- $db->disconnect();
- $err->addUserInfo($dsn);
- return $err;
- }
-
- return $db;
- }
-
- // }}}
- // {{{ function singleton($dsn = null, $options = false)
-
- /**
- * Returns a MDB2 connection with the requested DSN.
- * A new MDB2 connection object is only created if no object with the
- * requested DSN exists yet.
- *
- * @param mixed 'data source name', see the MDB2::parseDSN
- * method for a description of the dsn format.
- * Can also be specified as an array of the
- * format returned by MDB2::parseDSN.
- * @param array An associative array of option names and
- * their values.
- *
- * @return mixed a newly created MDB2 connection object, or a MDB2
- * error object on error
- *
- * @access public
- * @see MDB2::parseDSN
- */
- static function singleton($dsn = null, $options = false)
- {
- if ($dsn) {
- $dsninfo = MDB2::parseDSN($dsn);
- $dsninfo = array_merge($GLOBALS['_MDB2_dsninfo_default'], $dsninfo);
- $keys = array_keys($GLOBALS['_MDB2_databases']);
- for ($i=0, $j=count($keys); $i<$j; ++$i) {
- if (isset($GLOBALS['_MDB2_databases'][$keys[$i]])) {
- $tmp_dsn = $GLOBALS['_MDB2_databases'][$keys[$i]]->getDSN('array');
- if (count(array_diff_assoc($tmp_dsn, $dsninfo)) == 0) {
- MDB2::setOptions($GLOBALS['_MDB2_databases'][$keys[$i]], $options);
- return $GLOBALS['_MDB2_databases'][$keys[$i]];
- }
- }
- }
- } elseif (is_array($GLOBALS['_MDB2_databases']) && reset($GLOBALS['_MDB2_databases'])) {
- return $GLOBALS['_MDB2_databases'][key($GLOBALS['_MDB2_databases'])];
- }
- $db = MDB2::factory($dsn, $options);
- return $db;
- }
-
- // }}}
- // {{{ function areEquals()
-
- /**
- * It looks like there's a memory leak in array_diff() in PHP 5.1.x,
- * so use this method instead.
- * @see http://pear.php.net/bugs/bug.php?id=11790
- *
- * @param array $arr1
- * @param array $arr2
- * @return boolean
- */
- static function areEquals($arr1, $arr2)
- {
- if (count($arr1) != count($arr2)) {
- return false;
- }
- foreach (array_keys($arr1) as $k) {
- if (!array_key_exists($k, $arr2) || $arr1[$k] != $arr2[$k]) {
- return false;
- }
- }
- return true;
- }
-
- // }}}
- // {{{ function loadFile($file)
-
- /**
- * load a file (like 'Date')
- *
- * @param string $file name of the file in the MDB2 directory (without '.php')
- *
- * @return string name of the file that was included
- *
- * @access public
- */
- static function loadFile($file)
- {
- $file_name = 'MDB2'.DIRECTORY_SEPARATOR.$file.'.php';
- if (!MDB2::fileExists($file_name)) {
- return MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- 'unable to find: '.$file_name);
- }
- if (!include_once($file_name)) {
- return MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- 'unable to load driver class: '.$file_name);
- }
- return $file_name;
- }
-
- // }}}
- // {{{ function apiVersion()
-
- /**
- * Return the MDB2 API version
- *
- * @return string the MDB2 API version number
- *
- * @access public
- */
- static function apiVersion()
- {
- return '2.5.0b5';
- }
-
- // }}}
- // {{{ function &raiseError($code = null, $mode = null, $options = null, $userinfo = null)
-
- /**
- * This method is used to communicate an error and invoke error
- * callbacks etc. Basically a wrapper for PEAR::raiseError
- * without the message string.
- *
- * @param mixed int error code
- *
- * @param int error mode, see PEAR_Error docs
- *
- * @param mixed If error mode is PEAR_ERROR_TRIGGER, this is the
- * error level (E_USER_NOTICE etc). If error mode is
- * PEAR_ERROR_CALLBACK, this is the callback function,
- * either as a function name, or as an array of an
- * object and method name. For other error modes this
- * parameter is ignored.
- *
- * @param string Extra debug information. Defaults to the last
- * query and native error code.
- *
- * @return PEAR_Error instance of a PEAR Error object
- *
- * @access private
- * @see PEAR_Error
- */
- public static function &raiseError($code = null,
- $mode = null,
- $options = null,
- $userinfo = null,
- $dummy1 = null,
- $dummy2 = null,
- $dummy3 = false)
- {
- $pear = new PEAR;
- $err =& $pear->raiseError(null, $code, $mode, $options, $userinfo, 'MDB2_Error', true);
- return $err;
- }
-
- // }}}
- // {{{ function isError($data, $code = null)
-
- /**
- * Tell whether a value is a MDB2 error.
- *
- * @param mixed the value to test
- * @param int if is an error object, return true
- * only if $code is a string and
- * $db->getMessage() == $code or
- * $code is an integer and $db->getCode() == $code
- *
- * @return bool true if parameter is an error
- *
- * @access public
- */
- static function isError($data, $code = null)
- {
- if ($data instanceof MDB2_Error) {
- if (null === $code) {
- return true;
- }
- if (is_string($code)) {
- return $data->getMessage() === $code;
- }
- return in_array($data->getCode(), (array)$code);
- }
- return false;
- }
-
- // }}}
- // {{{ function isConnection($value)
-
- /**
- * Tell whether a value is a MDB2 connection
- *
- * @param mixed value to test
- *
- * @return bool whether $value is a MDB2 connection
- * @access public
- */
- static function isConnection($value)
- {
- return ($value instanceof MDB2_Driver_Common);
- }
-
- // }}}
- // {{{ function isResult($value)
-
- /**
- * Tell whether a value is a MDB2 result
- *
- * @param mixed $value value to test
- *
- * @return bool whether $value is a MDB2 result
- *
- * @access public
- */
- static function isResult($value)
- {
- return ($value instanceof MDB2_Result);
- }
-
- // }}}
- // {{{ function isResultCommon($value)
-
- /**
- * Tell whether a value is a MDB2 result implementing the common interface
- *
- * @param mixed $value value to test
- *
- * @return bool whether $value is a MDB2 result implementing the common interface
- *
- * @access public
- */
- static function isResultCommon($value)
- {
- return ($value instanceof MDB2_Result_Common);
- }
-
- // }}}
- // {{{ function isStatement($value)
-
- /**
- * Tell whether a value is a MDB2 statement interface
- *
- * @param mixed value to test
- *
- * @return bool whether $value is a MDB2 statement interface
- *
- * @access public
- */
- static function isStatement($value)
- {
- return ($value instanceof MDB2_Statement_Common);
- }
-
- // }}}
- // {{{ function errorMessage($value = null)
-
- /**
- * Return a textual error message for a MDB2 error code
- *
- * @param int|array integer error code,
- null to get the current error code-message map,
- or an array with a new error code-message map
- *
- * @return string error message, or false if the error code was
- * not recognized
- *
- * @access public
- */
- static function errorMessage($value = null)
- {
- static $errorMessages;
-
- if (is_array($value)) {
- $errorMessages = $value;
- return MDB2_OK;
- }
-
- if (!isset($errorMessages)) {
- $errorMessages = array(
- MDB2_OK => 'no error',
- MDB2_ERROR => 'unknown error',
- MDB2_ERROR_ALREADY_EXISTS => 'already exists',
- MDB2_ERROR_CANNOT_CREATE => 'can not create',
- MDB2_ERROR_CANNOT_ALTER => 'can not alter',
- MDB2_ERROR_CANNOT_REPLACE => 'can not replace',
- MDB2_ERROR_CANNOT_DELETE => 'can not delete',
- MDB2_ERROR_CANNOT_DROP => 'can not drop',
- MDB2_ERROR_CONSTRAINT => 'constraint violation',
- MDB2_ERROR_CONSTRAINT_NOT_NULL=> 'null value violates not-null constraint',
- MDB2_ERROR_DIVZERO => 'division by zero',
- MDB2_ERROR_INVALID => 'invalid',
- MDB2_ERROR_INVALID_DATE => 'invalid date or time',
- MDB2_ERROR_INVALID_NUMBER => 'invalid number',
- MDB2_ERROR_MISMATCH => 'mismatch',
- MDB2_ERROR_NODBSELECTED => 'no database selected',
- MDB2_ERROR_NOSUCHFIELD => 'no such field',
- MDB2_ERROR_NOSUCHTABLE => 'no such table',
- MDB2_ERROR_NOT_CAPABLE => 'MDB2 backend not capable',
- MDB2_ERROR_NOT_FOUND => 'not found',
- MDB2_ERROR_NOT_LOCKED => 'not locked',
- MDB2_ERROR_SYNTAX => 'syntax error',
- MDB2_ERROR_UNSUPPORTED => 'not supported',
- MDB2_ERROR_VALUE_COUNT_ON_ROW => 'value count on row',
- MDB2_ERROR_INVALID_DSN => 'invalid DSN',
- MDB2_ERROR_CONNECT_FAILED => 'connect failed',
- MDB2_ERROR_NEED_MORE_DATA => 'insufficient data supplied',
- MDB2_ERROR_EXTENSION_NOT_FOUND=> 'extension not found',
- MDB2_ERROR_NOSUCHDB => 'no such database',
- MDB2_ERROR_ACCESS_VIOLATION => 'insufficient permissions',
- MDB2_ERROR_LOADMODULE => 'error while including on demand module',
- MDB2_ERROR_TRUNCATED => 'truncated',
- MDB2_ERROR_DEADLOCK => 'deadlock detected',
- MDB2_ERROR_NO_PERMISSION => 'no permission',
- MDB2_ERROR_DISCONNECT_FAILED => 'disconnect failed',
- );
- }
-
- if (null === $value) {
- return $errorMessages;
- }
-
- if (MDB2::isError($value)) {
- $value = $value->getCode();
- }
-
- return isset($errorMessages[$value]) ?
- $errorMessages[$value] : $errorMessages[MDB2_ERROR];
- }
-
- // }}}
- // {{{ function parseDSN($dsn)
-
- /**
- * Parse a data source name.
- *
- * Additional keys can be added by appending a URI query string to the
- * end of the DSN.
- *
- * The format of the supplied DSN is in its fullest form:
- *
- * phptype(dbsyntax)://username:password@protocol+hostspec/database?option=8&another=true
- *
- *
- * Most variations are allowed:
- *
- * phptype://username:password@protocol+hostspec:110//usr/db_file.db?mode=0644
- * phptype://username:password@hostspec/database_name
- * phptype://username:password@hostspec
- * phptype://username@hostspec
- * phptype://hostspec/database
- * phptype://hostspec
- * phptype(dbsyntax)
- * phptype
- *
- *
- * @param string Data Source Name to be parsed
- *
- * @return array an associative array with the following keys:
- * + phptype: Database backend used in PHP (mysql, odbc etc.)
- * + dbsyntax: Database used with regards to SQL syntax etc.
- * + protocol: Communication protocol to use (tcp, unix etc.)
- * + hostspec: Host specification (hostname[:port])
- * + database: Database to use on the DBMS server
- * + username: User name for login
- * + password: Password for login
- *
- * @access public
- * @author Tomas V.V.Cox
- */
- static function parseDSN($dsn)
- {
- $parsed = $GLOBALS['_MDB2_dsninfo_default'];
-
- if (is_array($dsn)) {
- $dsn = array_merge($parsed, $dsn);
- if (!$dsn['dbsyntax']) {
- $dsn['dbsyntax'] = $dsn['phptype'];
- }
- return $dsn;
- }
-
- // Find phptype and dbsyntax
- if (($pos = strpos($dsn, '://')) !== false) {
- $str = substr($dsn, 0, $pos);
- $dsn = substr($dsn, $pos + 3);
- } else {
- $str = $dsn;
- $dsn = null;
- }
-
- // Get phptype and dbsyntax
- // $str => phptype(dbsyntax)
- if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) {
- $parsed['phptype'] = $arr[1];
- $parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2];
- } else {
- $parsed['phptype'] = $str;
- $parsed['dbsyntax'] = $str;
- }
-
- if (!count($dsn)) {
- return $parsed;
- }
-
- // Get (if found): username and password
- // $dsn => username:password@protocol+hostspec/database
- if (($at = strrpos($dsn,'@')) !== false) {
- $str = substr($dsn, 0, $at);
- $dsn = substr($dsn, $at + 1);
- if (($pos = strpos($str, ':')) !== false) {
- $parsed['username'] = rawurldecode(substr($str, 0, $pos));
- $parsed['password'] = rawurldecode(substr($str, $pos + 1));
- } else {
- $parsed['username'] = rawurldecode($str);
- }
- }
-
- // Find protocol and hostspec
-
- // $dsn => proto(proto_opts)/database
- if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) {
- $proto = $match[1];
- $proto_opts = $match[2] ? $match[2] : false;
- $dsn = $match[3];
-
- // $dsn => protocol+hostspec/database (old format)
- } else {
- if (strpos($dsn, '+') !== false) {
- list($proto, $dsn) = explode('+', $dsn, 2);
- }
- if ( strpos($dsn, '//') === 0
- && strpos($dsn, '/', 2) !== false
- && $parsed['phptype'] == 'oci8'
- ) {
- //oracle's "Easy Connect" syntax:
- //"username/password@[//]host[:port][/service_name]"
- //e.g. "scott/tiger@//mymachine:1521/oracle"
- $proto_opts = $dsn;
- $pos = strrpos($proto_opts, '/');
- $dsn = substr($proto_opts, $pos + 1);
- $proto_opts = substr($proto_opts, 0, $pos);
- } elseif (strpos($dsn, '/') !== false) {
- list($proto_opts, $dsn) = explode('/', $dsn, 2);
- } else {
- $proto_opts = $dsn;
- $dsn = null;
- }
- }
-
- // process the different protocol options
- $parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp';
- $proto_opts = rawurldecode($proto_opts);
- if (strpos($proto_opts, ':') !== false) {
- list($proto_opts, $parsed['port']) = explode(':', $proto_opts);
- }
- if ($parsed['protocol'] == 'tcp') {
- $parsed['hostspec'] = $proto_opts;
- } elseif ($parsed['protocol'] == 'unix') {
- $parsed['socket'] = $proto_opts;
- }
-
- // Get dabase if any
- // $dsn => database
- if ($dsn) {
- // /database
- if (($pos = strpos($dsn, '?')) === false) {
- $parsed['database'] = rawurldecode($dsn);
- // /database?param1=value1¶m2=value2
- } else {
- $parsed['database'] = rawurldecode(substr($dsn, 0, $pos));
- $dsn = substr($dsn, $pos + 1);
- if (strpos($dsn, '&') !== false) {
- $opts = explode('&', $dsn);
- } else { // database?param1=value1
- $opts = array($dsn);
- }
- foreach ($opts as $opt) {
- list($key, $value) = explode('=', $opt);
- if (!array_key_exists($key, $parsed) || false === $parsed[$key]) {
- // don't allow params overwrite
- $parsed[$key] = rawurldecode($value);
- }
- }
- }
- }
-
- return $parsed;
- }
-
- // }}}
- // {{{ function fileExists($file)
-
- /**
- * Checks if a file exists in the include path
- *
- * @param string filename
- *
- * @return bool true success and false on error
- *
- * @access public
- */
- static function fileExists($file)
- {
- // safe_mode does notwork with is_readable()
- if (!@ini_get('safe_mode')) {
- $dirs = explode(PATH_SEPARATOR, ini_get('include_path'));
- foreach ($dirs as $dir) {
- if (is_readable($dir . DIRECTORY_SEPARATOR . $file)) {
- return true;
- }
- }
- } else {
- $fp = @fopen($file, 'r', true);
- if (is_resource($fp)) {
- @fclose($fp);
- return true;
- }
- }
- return false;
- }
- // }}}
-}
-
-// }}}
-// {{{ class MDB2_Error extends PEAR_Error
-
-/**
- * MDB2_Error implements a class for reporting portable database error
- * messages.
- *
- * @package MDB2
- * @category Database
- * @author Stig Bakken
- */
-class MDB2_Error extends PEAR_Error
-{
- // {{{ constructor: function MDB2_Error($code = MDB2_ERROR, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE, $debuginfo = null)
-
- /**
- * MDB2_Error constructor.
- *
- * @param mixed MDB2 error code, or string with error message.
- * @param int what 'error mode' to operate in
- * @param int what error level to use for $mode & PEAR_ERROR_TRIGGER
- * @param mixed additional debug info, such as the last query
- */
- function __construct($code = MDB2_ERROR, $mode = PEAR_ERROR_RETURN,
- $level = E_USER_NOTICE, $debuginfo = null, $dummy = null)
- {
- if (null === $code) {
- $code = MDB2_ERROR;
- }
- $this->PEAR_Error('MDB2 Error: '.MDB2::errorMessage($code), $code,
- $mode, $level, $debuginfo);
- }
-
- // }}}
-}
-
-// }}}
-// {{{ class MDB2_Driver_Common extends PEAR
-
-/**
- * MDB2_Driver_Common: Base class that is extended by each MDB2 driver
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_Driver_Common
-{
- // {{{ Variables (Properties)
-
- /**
- * @var MDB2_Driver_Datatype_Common
- */
- public $datatype;
-
- /**
- * @var MDB2_Extended
- */
- public $extended;
-
- /**
- * @var MDB2_Driver_Function_Common
- */
- public $function;
-
- /**
- * @var MDB2_Driver_Manager_Common
- */
- public $manager;
-
- /**
- * @var MDB2_Driver_Native_Commonn
- */
- public $native;
-
- /**
- * @var MDB2_Driver_Reverse_Common
- */
- public $reverse;
-
- /**
- * index of the MDB2 object within the $GLOBALS['_MDB2_databases'] array
- * @var int
- * @access public
- */
- public $db_index = 0;
-
- /**
- * DSN used for the next query
- * @var array
- * @access protected
- */
- public $dsn = array();
-
- /**
- * DSN that was used to create the current connection
- * @var array
- * @access protected
- */
- public $connected_dsn = array();
-
- /**
- * connection resource
- * @var mixed
- * @access protected
- */
- public $connection = 0;
-
- /**
- * if the current opened connection is a persistent connection
- * @var bool
- * @access protected
- */
- public $opened_persistent;
-
- /**
- * the name of the database for the next query
- * @var string
- * @access public
- */
- public $database_name = '';
-
- /**
- * the name of the database currently selected
- * @var string
- * @access protected
- */
- public $connected_database_name = '';
-
- /**
- * server version information
- * @var string
- * @access protected
- */
- public $connected_server_info = '';
-
- /**
- * list of all supported features of the given driver
- * @var array
- * @access public
- */
- public $supported = array(
- 'sequences' => false,
- 'indexes' => false,
- 'affected_rows' => false,
- 'summary_functions' => false,
- 'order_by_text' => false,
- 'transactions' => false,
- 'savepoints' => false,
- 'current_id' => false,
- 'limit_queries' => false,
- 'LOBs' => false,
- 'replace' => false,
- 'sub_selects' => false,
- 'triggers' => false,
- 'auto_increment' => false,
- 'primary_key' => false,
- 'result_introspection' => false,
- 'prepared_statements' => false,
- 'identifier_quoting' => false,
- 'pattern_escaping' => false,
- 'new_link' => false,
- );
-
- /**
- * Array of supported options that can be passed to the MDB2 instance.
- *
- * The options can be set during object creation, using
- * MDB2::connect(), MDB2::factory() or MDB2::singleton(). The options can
- * also be set after the object is created, using MDB2::setOptions() or
- * MDB2_Driver_Common::setOption().
- * The list of available option includes:
- *
- * - $options['ssl'] -> boolean: determines if ssl should be used for connections
- * - $options['field_case'] -> CASE_LOWER|CASE_UPPER: determines what case to force on field/table names
- * - $options['disable_query'] -> boolean: determines if queries should be executed
- * - $options['result_class'] -> string: class used for result sets
- * - $options['buffered_result_class'] -> string: class used for buffered result sets
- * - $options['result_wrap_class'] -> string: class used to wrap result sets into
- * - $options['result_buffering'] -> boolean should results be buffered or not?
- * - $options['fetch_class'] -> string: class to use when fetch mode object is used
- * - $options['persistent'] -> boolean: persistent connection?
- * - $options['debug'] -> integer: numeric debug level
- * - $options['debug_handler'] -> string: function/method that captures debug messages
- * - $options['debug_expanded_output'] -> bool: BC option to determine if more context information should be send to the debug handler
- * - $options['default_text_field_length'] -> integer: default text field length to use
- * - $options['lob_buffer_length'] -> integer: LOB buffer length
- * - $options['log_line_break'] -> string: line-break format
- * - $options['idxname_format'] -> string: pattern for index name
- * - $options['seqname_format'] -> string: pattern for sequence name
- * - $options['savepoint_format'] -> string: pattern for auto generated savepoint names
- * - $options['statement_format'] -> string: pattern for prepared statement names
- * - $options['seqcol_name'] -> string: sequence column name
- * - $options['quote_identifier'] -> boolean: if identifier quoting should be done when check_option is used
- * - $options['use_transactions'] -> boolean: if transaction use should be enabled
- * - $options['decimal_places'] -> integer: number of decimal places to handle
- * - $options['portability'] -> integer: portability constant
- * - $options['modules'] -> array: short to long module name mapping for __call()
- * - $options['emulate_prepared'] -> boolean: force prepared statements to be emulated
- * - $options['datatype_map'] -> array: map user defined datatypes to other primitive datatypes
- * - $options['datatype_map_callback'] -> array: callback function/method that should be called
- * - $options['bindname_format'] -> string: regular expression pattern for named parameters
- * - $options['multi_query'] -> boolean: determines if queries returning multiple result sets should be executed
- * - $options['max_identifiers_length'] -> integer: max identifier length
- * - $options['default_fk_action_onupdate'] -> string: default FOREIGN KEY ON UPDATE action ['RESTRICT'|'NO ACTION'|'SET DEFAULT'|'SET NULL'|'CASCADE']
- * - $options['default_fk_action_ondelete'] -> string: default FOREIGN KEY ON DELETE action ['RESTRICT'|'NO ACTION'|'SET DEFAULT'|'SET NULL'|'CASCADE']
- *
- *
- * @var array
- * @access public
- * @see MDB2::connect()
- * @see MDB2::factory()
- * @see MDB2::singleton()
- * @see MDB2_Driver_Common::setOption()
- */
- public $options = array(
- 'ssl' => false,
- 'field_case' => CASE_LOWER,
- 'disable_query' => false,
- 'result_class' => 'MDB2_Result_%s',
- 'buffered_result_class' => 'MDB2_BufferedResult_%s',
- 'result_wrap_class' => false,
- 'result_buffering' => true,
- 'fetch_class' => 'stdClass',
- 'persistent' => false,
- 'debug' => 0,
- 'debug_handler' => 'MDB2_defaultDebugOutput',
- 'debug_expanded_output' => false,
- 'default_text_field_length' => 4096,
- 'lob_buffer_length' => 8192,
- 'log_line_break' => "\n",
- 'idxname_format' => '%s_idx',
- 'seqname_format' => '%s_seq',
- 'savepoint_format' => 'MDB2_SAVEPOINT_%s',
- 'statement_format' => 'MDB2_STATEMENT_%1$s_%2$s',
- 'seqcol_name' => 'sequence',
- 'quote_identifier' => false,
- 'use_transactions' => true,
- 'decimal_places' => 2,
- 'portability' => MDB2_PORTABILITY_ALL,
- 'modules' => array(
- 'ex' => 'Extended',
- 'dt' => 'Datatype',
- 'mg' => 'Manager',
- 'rv' => 'Reverse',
- 'na' => 'Native',
- 'fc' => 'Function',
- ),
- 'emulate_prepared' => false,
- 'datatype_map' => array(),
- 'datatype_map_callback' => array(),
- 'nativetype_map_callback' => array(),
- 'lob_allow_url_include' => false,
- 'bindname_format' => '(?:\d+)|(?:[a-zA-Z][a-zA-Z0-9_]*)',
- 'max_identifiers_length' => 30,
- 'default_fk_action_onupdate' => 'RESTRICT',
- 'default_fk_action_ondelete' => 'RESTRICT',
- );
-
- /**
- * string array
- * @var string
- * @access public
- */
- public $string_quoting = array(
- 'start' => "'",
- 'end' => "'",
- 'escape' => false,
- 'escape_pattern' => false,
- );
-
- /**
- * identifier quoting
- * @var array
- * @access public
- */
- public $identifier_quoting = array(
- 'start' => '"',
- 'end' => '"',
- 'escape' => '"',
- );
-
- /**
- * sql comments
- * @var array
- * @access protected
- */
- public $sql_comments = array(
- array('start' => '--', 'end' => "\n", 'escape' => false),
- array('start' => '/*', 'end' => '*/', 'escape' => false),
- );
-
- /**
- * comparision wildcards
- * @var array
- * @access protected
- */
- protected $wildcards = array('%', '_');
-
- /**
- * column alias keyword
- * @var string
- * @access protected
- */
- public $as_keyword = ' AS ';
-
- /**
- * warnings
- * @var array
- * @access protected
- */
- public $warnings = array();
-
- /**
- * string with the debugging information
- * @var string
- * @access public
- */
- public $debug_output = '';
-
- /**
- * determine if there is an open transaction
- * @var bool
- * @access protected
- */
- public $in_transaction = false;
-
- /**
- * the smart transaction nesting depth
- * @var int
- * @access protected
- */
- public $nested_transaction_counter = null;
-
- /**
- * the first error that occured inside a nested transaction
- * @var MDB2_Error|bool
- * @access protected
- */
- protected $has_transaction_error = false;
-
- /**
- * result offset used in the next query
- * @var int
- * @access public
- */
- public $offset = 0;
-
- /**
- * result limit used in the next query
- * @var int
- * @access public
- */
- public $limit = 0;
-
- /**
- * Database backend used in PHP (mysql, odbc etc.)
- * @var string
- * @access public
- */
- public $phptype;
-
- /**
- * Database used with regards to SQL syntax etc.
- * @var string
- * @access public
- */
- public $dbsyntax;
-
- /**
- * the last query sent to the driver
- * @var string
- * @access public
- */
- public $last_query;
-
- /**
- * the default fetchmode used
- * @var int
- * @access public
- */
- public $fetchmode = MDB2_FETCHMODE_ORDERED;
-
- /**
- * array of module instances
- * @var array
- * @access protected
- */
- protected $modules = array();
-
- /**
- * determines of the PHP4 destructor emulation has been enabled yet
- * @var array
- * @access protected
- */
- protected $destructor_registered = true;
-
- /**
- * @var PEAR
- */
- protected $pear;
-
- // }}}
- // {{{ constructor: function __construct()
-
- /**
- * Constructor
- */
- function __construct()
- {
- end($GLOBALS['_MDB2_databases']);
- $db_index = key($GLOBALS['_MDB2_databases']) + 1;
- $GLOBALS['_MDB2_databases'][$db_index] = &$this;
- $this->db_index = $db_index;
- $this->pear = new PEAR;
- }
-
- // }}}
- // {{{ destructor: function __destruct()
-
- /**
- * Destructor
- */
- function __destruct()
- {
- $this->disconnect(false);
- }
-
- // }}}
- // {{{ function free()
-
- /**
- * Free the internal references so that the instance can be destroyed
- *
- * @return bool true on success, false if result is invalid
- *
- * @access public
- */
- function free()
- {
- unset($GLOBALS['_MDB2_databases'][$this->db_index]);
- unset($this->db_index);
- return MDB2_OK;
- }
-
- // }}}
- // {{{ function __toString()
-
- /**
- * String conversation
- *
- * @return string representation of the object
- *
- * @access public
- */
- function __toString()
- {
- $info = get_class($this);
- $info.= ': (phptype = '.$this->phptype.', dbsyntax = '.$this->dbsyntax.')';
- if ($this->connection) {
- $info.= ' [connected]';
- }
- return $info;
- }
-
- // }}}
- // {{{ function errorInfo($error = null)
-
- /**
- * This method is used to collect information about an error
- *
- * @param mixed error code or resource
- *
- * @return array with MDB2 errorcode, native error code, native message
- *
- * @access public
- */
- function errorInfo($error = null)
- {
- return array($error, null, null);
- }
-
- // }}}
- // {{{ function &raiseError($code = null, $mode = null, $options = null, $userinfo = null)
-
- /**
- * This method is used to communicate an error and invoke error
- * callbacks etc. Basically a wrapper for PEAR::raiseError
- * without the message string.
- *
- * @param mixed $code integer error code, or a PEAR error object (all
- * other parameters are ignored if this parameter is
- * an object
- * @param int $mode error mode, see PEAR_Error docs
- * @param mixed $options If error mode is PEAR_ERROR_TRIGGER, this is the
- * error level (E_USER_NOTICE etc). If error mode is
- * PEAR_ERROR_CALLBACK, this is the callback function,
- * either as a function name, or as an array of an
- * object and method name. For other error modes this
- * parameter is ignored.
- * @param string $userinfo Extra debug information. Defaults to the last
- * query and native error code.
- * @param string $method name of the method that triggered the error
- * @param string $dummy1 not used
- * @param bool $dummy2 not used
- *
- * @return PEAR_Error instance of a PEAR Error object
- * @access public
- * @see PEAR_Error
- */
- function &raiseError($code = null,
- $mode = null,
- $options = null,
- $userinfo = null,
- $method = null,
- $dummy1 = null,
- $dummy2 = false
- ) {
- $userinfo = "[Error message: $userinfo]\n";
- // The error is yet a MDB2 error object
- if (MDB2::isError($code)) {
- // because we use the static PEAR::raiseError, our global
- // handler should be used if it is set
- if ((null === $mode) && !empty($this->_default_error_mode)) {
- $mode = $this->_default_error_mode;
- $options = $this->_default_error_options;
- }
- if (null === $userinfo) {
- $userinfo = $code->getUserinfo();
- }
- $code = $code->getCode();
- } elseif ($code == MDB2_ERROR_NOT_FOUND) {
- // extension not loaded: don't call $this->errorInfo() or the script
- // will die
- } elseif (isset($this->connection)) {
- if (!empty($this->last_query)) {
- $userinfo.= "[Last executed query: {$this->last_query}]\n";
- }
- $native_errno = $native_msg = null;
- list($code, $native_errno, $native_msg) = $this->errorInfo($code);
- if ((null !== $native_errno) && $native_errno !== '') {
- $userinfo.= "[Native code: $native_errno]\n";
- }
- if ((null !== $native_msg) && $native_msg !== '') {
- $userinfo.= "[Native message: ". strip_tags($native_msg) ."]\n";
- }
- if (null !== $method) {
- $userinfo = $method.': '.$userinfo;
- }
- }
-
- $err = $this->pear->raiseError(null, $code, $mode, $options, $userinfo, 'MDB2_Error', true);
- if ($err->getMode() !== PEAR_ERROR_RETURN
- && isset($this->nested_transaction_counter) && !$this->has_transaction_error) {
- $this->has_transaction_error = $err;
- }
- return $err;
- }
-
- // }}}
- // {{{ function resetWarnings()
-
- /**
- * reset the warning array
- *
- * @return void
- *
- * @access public
- */
- function resetWarnings()
- {
- $this->warnings = array();
- }
-
- // }}}
- // {{{ function getWarnings()
-
- /**
- * Get all warnings in reverse order.
- * This means that the last warning is the first element in the array
- *
- * @return array with warnings
- *
- * @access public
- * @see resetWarnings()
- */
- function getWarnings()
- {
- return array_reverse($this->warnings);
- }
-
- // }}}
- // {{{ function setFetchMode($fetchmode, $object_class = 'stdClass')
-
- /**
- * Sets which fetch mode should be used by default on queries
- * on this connection
- *
- * @param int MDB2_FETCHMODE_ORDERED, MDB2_FETCHMODE_ASSOC
- * or MDB2_FETCHMODE_OBJECT
- * @param string the class name of the object to be returned
- * by the fetch methods when the
- * MDB2_FETCHMODE_OBJECT mode is selected.
- * If no class is specified by default a cast
- * to object from the assoc array row will be
- * done. There is also the possibility to use
- * and extend the 'MDB2_row' class.
- *
- * @return mixed MDB2_OK or MDB2 Error Object
- *
- * @access public
- * @see MDB2_FETCHMODE_ORDERED, MDB2_FETCHMODE_ASSOC, MDB2_FETCHMODE_OBJECT
- */
- function setFetchMode($fetchmode, $object_class = 'stdClass')
- {
- switch ($fetchmode) {
- case MDB2_FETCHMODE_OBJECT:
- $this->options['fetch_class'] = $object_class;
- case MDB2_FETCHMODE_ORDERED:
- case MDB2_FETCHMODE_ASSOC:
- $this->fetchmode = $fetchmode;
- break;
- default:
- return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'invalid fetchmode mode', __FUNCTION__);
- }
-
- return MDB2_OK;
- }
-
- // }}}
- // {{{ function setOption($option, $value)
-
- /**
- * set the option for the db class
- *
- * @param string option name
- * @param mixed value for the option
- *
- * @return mixed MDB2_OK or MDB2 Error Object
- *
- * @access public
- */
- function setOption($option, $value)
- {
- if (array_key_exists($option, $this->options)) {
- $this->options[$option] = $value;
- return MDB2_OK;
- }
- return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- "unknown option $option", __FUNCTION__);
- }
-
- // }}}
- // {{{ function getOption($option)
-
- /**
- * Returns the value of an option
- *
- * @param string option name
- *
- * @return mixed the option value or error object
- *
- * @access public
- */
- function getOption($option)
- {
- if (array_key_exists($option, $this->options)) {
- return $this->options[$option];
- }
- return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- "unknown option $option", __FUNCTION__);
- }
-
- // }}}
- // {{{ function debug($message, $scope = '', $is_manip = null)
-
- /**
- * set a debug message
- *
- * @param string message that should be appended to the debug variable
- * @param string usually the method name that triggered the debug call:
- * for example 'query', 'prepare', 'execute', 'parameters',
- * 'beginTransaction', 'commit', 'rollback'
- * @param array contains context information about the debug() call
- * common keys are: is_manip, time, result etc.
- *
- * @return void
- *
- * @access public
- */
- function debug($message, $scope = '', $context = array())
- {
- if ($this->options['debug'] && $this->options['debug_handler']) {
- if (!$this->options['debug_expanded_output']) {
- if (!empty($context['when']) && $context['when'] !== 'pre') {
- return null;
- }
- $context = empty($context['is_manip']) ? false : $context['is_manip'];
- }
- return call_user_func_array($this->options['debug_handler'], array(&$this, $scope, $message, $context));
- }
- return null;
- }
-
- // }}}
- // {{{ function getDebugOutput()
-
- /**
- * output debug info
- *
- * @return string content of the debug_output class variable
- *
- * @access public
- */
- function getDebugOutput()
- {
- return $this->debug_output;
- }
-
- // }}}
- // {{{ function escape($text)
-
- /**
- * Quotes a string so it can be safely used in a query. It will quote
- * the text so it can safely be used within a query.
- *
- * @param string the input string to quote
- * @param bool escape wildcards
- *
- * @return string quoted string
- *
- * @access public
- */
- function escape($text, $escape_wildcards = false)
- {
- if ($escape_wildcards) {
- $text = $this->escapePattern($text);
- }
-
- $text = str_replace($this->string_quoting['end'], $this->string_quoting['escape'] . $this->string_quoting['end'], $text);
- return $text;
- }
-
- // }}}
- // {{{ function escapePattern($text)
-
- /**
- * Quotes pattern (% and _) characters in a string)
- *
- * @param string the input string to quote
- *
- * @return string quoted string
- *
- * @access public
- */
- function escapePattern($text)
- {
- if ($this->string_quoting['escape_pattern']) {
- $text = str_replace($this->string_quoting['escape_pattern'], $this->string_quoting['escape_pattern'] . $this->string_quoting['escape_pattern'], $text);
- foreach ($this->wildcards as $wildcard) {
- $text = str_replace($wildcard, $this->string_quoting['escape_pattern'] . $wildcard, $text);
- }
- }
- return $text;
- }
-
- // }}}
- // {{{ function quoteIdentifier($str, $check_option = false)
-
- /**
- * Quote a string so it can be safely used as a table or column name
- *
- * Delimiting style depends on which database driver is being used.
- *
- * NOTE: just because you CAN use delimited identifiers doesn't mean
- * you SHOULD use them. In general, they end up causing way more
- * problems than they solve.
- *
- * NOTE: if you have table names containing periods, don't use this method
- * (@see bug #11906)
- *
- * Portability is broken by using the following characters inside
- * delimited identifiers:
- * + backtick (`) -- due to MySQL
- * + double quote (") -- due to Oracle
- * + brackets ([ or ]) -- due to Access
- *
- * Delimited identifiers are known to generally work correctly under
- * the following drivers:
- * + mssql
- * + mysql
- * + mysqli
- * + oci8
- * + pgsql
- * + sqlite
- *
- * InterBase doesn't seem to be able to use delimited identifiers
- * via PHP 4. They work fine under PHP 5.
- *
- * @param string identifier name to be quoted
- * @param bool check the 'quote_identifier' option
- *
- * @return string quoted identifier string
- *
- * @access public
- */
- function quoteIdentifier($str, $check_option = false)
- {
- if ($check_option && !$this->options['quote_identifier']) {
- return $str;
- }
- $str = str_replace($this->identifier_quoting['end'], $this->identifier_quoting['escape'] . $this->identifier_quoting['end'], $str);
- $parts = explode('.', $str);
- foreach (array_keys($parts) as $k) {
- $parts[$k] = $this->identifier_quoting['start'] . $parts[$k] . $this->identifier_quoting['end'];
- }
- return implode('.', $parts);
- }
-
- // }}}
- // {{{ function getAsKeyword()
-
- /**
- * Gets the string to alias column
- *
- * @return string to use when aliasing a column
- */
- function getAsKeyword()
- {
- return $this->as_keyword;
- }
-
- // }}}
- // {{{ function getConnection()
-
- /**
- * Returns a native connection
- *
- * @return mixed a valid MDB2 connection object,
- * or a MDB2 error object on error
- *
- * @access public
- */
- function getConnection()
- {
- $result = $this->connect();
- if (MDB2::isError($result)) {
- return $result;
- }
- return $this->connection;
- }
-
- // }}}
- // {{{ function _fixResultArrayValues(&$row, $mode)
-
- /**
- * Do all necessary conversions on result arrays to fix DBMS quirks
- *
- * @param array the array to be fixed (passed by reference)
- * @param array bit-wise addition of the required portability modes
- *
- * @return void
- *
- * @access protected
- */
- function _fixResultArrayValues(&$row, $mode)
- {
- switch ($mode) {
- case MDB2_PORTABILITY_EMPTY_TO_NULL:
- foreach ($row as $key => $value) {
- if ($value === '') {
- $row[$key] = null;
- }
- }
- break;
- case MDB2_PORTABILITY_RTRIM:
- foreach ($row as $key => $value) {
- if (is_string($value)) {
- $row[$key] = rtrim($value);
- }
- }
- break;
- case MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES:
- $tmp_row = array();
- foreach ($row as $key => $value) {
- $tmp_row[preg_replace('/^(?:.*\.)?([^.]+)$/', '\\1', $key)] = $value;
- }
- $row = $tmp_row;
- break;
- case (MDB2_PORTABILITY_RTRIM + MDB2_PORTABILITY_EMPTY_TO_NULL):
- foreach ($row as $key => $value) {
- if ($value === '') {
- $row[$key] = null;
- } elseif (is_string($value)) {
- $row[$key] = rtrim($value);
- }
- }
- break;
- case (MDB2_PORTABILITY_RTRIM + MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES):
- $tmp_row = array();
- foreach ($row as $key => $value) {
- if (is_string($value)) {
- $value = rtrim($value);
- }
- $tmp_row[preg_replace('/^(?:.*\.)?([^.]+)$/', '\\1', $key)] = $value;
- }
- $row = $tmp_row;
- break;
- case (MDB2_PORTABILITY_EMPTY_TO_NULL + MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES):
- $tmp_row = array();
- foreach ($row as $key => $value) {
- if ($value === '') {
- $value = null;
- }
- $tmp_row[preg_replace('/^(?:.*\.)?([^.]+)$/', '\\1', $key)] = $value;
- }
- $row = $tmp_row;
- break;
- case (MDB2_PORTABILITY_RTRIM + MDB2_PORTABILITY_EMPTY_TO_NULL + MDB2_PORTABILITY_FIX_ASSOC_FIELD_NAMES):
- $tmp_row = array();
- foreach ($row as $key => $value) {
- if ($value === '') {
- $value = null;
- } elseif (is_string($value)) {
- $value = rtrim($value);
- }
- $tmp_row[preg_replace('/^(?:.*\.)?([^.]+)$/', '\\1', $key)] = $value;
- }
- $row = $tmp_row;
- break;
- }
- }
-
- // }}}
- // {{{ function loadModule($module, $property = null, $phptype_specific = null)
-
- /**
- * loads a module
- *
- * @param string name of the module that should be loaded
- * (only used for error messages)
- * @param string name of the property into which the class will be loaded
- * @param bool if the class to load for the module is specific to the
- * phptype
- *
- * @return object on success a reference to the given module is returned
- * and on failure a PEAR error
- *
- * @access public
- */
- function loadModule($module, $property = null, $phptype_specific = null)
- {
- if (!$property) {
- $property = strtolower($module);
- }
-
- if (!isset($this->{$property})) {
- $version = $phptype_specific;
- if ($phptype_specific !== false) {
- $version = true;
- $class_name = 'MDB2_Driver_'.$module.'_'.$this->phptype;
- $file_name = str_replace('_', DIRECTORY_SEPARATOR, $class_name).'.php';
- }
- if ($phptype_specific === false
- || (!MDB2::classExists($class_name) && !MDB2::fileExists($file_name))
- ) {
- $version = false;
- $class_name = 'MDB2_'.$module;
- $file_name = str_replace('_', DIRECTORY_SEPARATOR, $class_name).'.php';
- }
-
- $err = MDB2::loadClass($class_name, $this->getOption('debug'));
- if (MDB2::isError($err)) {
- return $err;
- }
-
- // load module in a specific version
- if ($version) {
- if (method_exists($class_name, 'getClassName')) {
- $class_name_new = call_user_func(array($class_name, 'getClassName'), $this->db_index);
- if ($class_name != $class_name_new) {
- $class_name = $class_name_new;
- $err = MDB2::loadClass($class_name, $this->getOption('debug'));
- if (MDB2::isError($err)) {
- return $err;
- }
- }
- }
- }
-
- if (!MDB2::classExists($class_name)) {
- $err = $this->raiseError(MDB2_ERROR_LOADMODULE, null, null,
- "unable to load module '$module' into property '$property'", __FUNCTION__);
- return $err;
- }
- $this->{$property} = new $class_name($this->db_index);
- $this->modules[$module] = $this->{$property};
- if ($version) {
- // this will be used in the connect method to determine if the module
- // needs to be loaded with a different version if the server
- // version changed in between connects
- $this->loaded_version_modules[] = $property;
- }
- }
-
- return $this->{$property};
- }
-
- // }}}
- // {{{ function __call($method, $params)
-
- /**
- * Calls a module method using the __call magic method
- *
- * @param string Method name.
- * @param array Arguments.
- *
- * @return mixed Returned value.
- */
- function __call($method, $params)
- {
- $module = null;
- if (preg_match('/^([a-z]+)([A-Z])(.*)$/', $method, $match)
- && isset($this->options['modules'][$match[1]])
- ) {
- $module = $this->options['modules'][$match[1]];
- $method = strtolower($match[2]).$match[3];
- if (!isset($this->modules[$module]) || !is_object($this->modules[$module])) {
- $result = $this->loadModule($module);
- if (MDB2::isError($result)) {
- return $result;
- }
- }
- } else {
- foreach ($this->modules as $key => $foo) {
- if (is_object($this->modules[$key])
- && method_exists($this->modules[$key], $method)
- ) {
- $module = $key;
- break;
- }
- }
- }
- if (null !== $module) {
- return call_user_func_array(array(&$this->modules[$module], $method), $params);
- }
-
- $class = get_class($this);
- $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
- $loc = 'in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'];
- if ($method == 'isError') {
- trigger_error("Deprecated: $class::isError() is deprecated, use MDB2::isError() $loc", E_USER_DEPRECATED);
- if (!array_key_exists(0, $params)) {
- trigger_error("Missing argument 1 for $class::$method, called $loc", E_USER_ERROR);
- }
- return MDB2::isError($params[0]);
- }
- trigger_error("Call to undefined function: $class::$method() $loc.", E_USER_ERROR);
- }
-
- // }}}
- // {{{ function __callStatic($method, $params)
-
- /**
- * Calls a module method using the __callStatic magic method
- *
- * @param string Method name.
- * @param array Arguments.
- *
- * @return mixed Returned value.
- */
- public static function __callStatic($method, $params)
- {
- $class = get_called_class();
- $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
- $loc = 'in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'];
- if ($method == 'isError') {
- trigger_error("Deprecated: $class::isError() is deprecated, use MDB2::isError() $loc", E_USER_DEPRECATED);
- if (!array_key_exists(0, $params)) {
- trigger_error("Missing argument 1 for $class::$method, called $loc", E_USER_ERROR);
- }
- return MDB2::isError($params[0]);
- }
- trigger_error("Call to undefined function: $class::$method() $loc.", E_USER_ERROR);
- }
-
- // }}}
- // {{{ function beginTransaction($savepoint = null)
-
- /**
- * Start a transaction or set a savepoint.
- *
- * @param string name of a savepoint to set
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- */
- function beginTransaction($savepoint = null)
- {
- $this->debug('Starting transaction', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
- return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'transactions are not supported', __FUNCTION__);
- }
-
- // }}}
- // {{{ function commit($savepoint = null)
-
- /**
- * Commit the database changes done during a transaction that is in
- * progress or release a savepoint. This function may only be called when
- * auto-committing is disabled, otherwise it will fail. Therefore, a new
- * transaction is implicitly started after committing the pending changes.
- *
- * @param string name of a savepoint to release
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- */
- function commit($savepoint = null)
- {
- $this->debug('Committing transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
- return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'commiting transactions is not supported', __FUNCTION__);
- }
-
- // }}}
- // {{{ function rollback($savepoint = null)
-
- /**
- * Cancel any database changes done during a transaction or since a specific
- * savepoint that is in progress. This function may only be called when
- * auto-committing is disabled, otherwise it will fail. Therefore, a new
- * transaction is implicitly started after canceling the pending changes.
- *
- * @param string name of a savepoint to rollback to
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- */
- function rollback($savepoint = null)
- {
- $this->debug('Rolling back transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
- return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'rolling back transactions is not supported', __FUNCTION__);
- }
-
- // }}}
- // {{{ function inTransaction($ignore_nested = false)
-
- /**
- * If a transaction is currently open.
- *
- * @param bool if the nested transaction count should be ignored
- * @return int|bool - an integer with the nesting depth is returned if a
- * nested transaction is open
- * - true is returned for a normal open transaction
- * - false is returned if no transaction is open
- *
- * @access public
- */
- function inTransaction($ignore_nested = false)
- {
- if (!$ignore_nested && isset($this->nested_transaction_counter)) {
- return $this->nested_transaction_counter;
- }
- return $this->in_transaction;
- }
-
- // }}}
- // {{{ function setTransactionIsolation($isolation)
-
- /**
- * Set the transacton isolation level.
- *
- * @param string standard isolation level
- * READ UNCOMMITTED (allows dirty reads)
- * READ COMMITTED (prevents dirty reads)
- * REPEATABLE READ (prevents nonrepeatable reads)
- * SERIALIZABLE (prevents phantom reads)
- * @param array some transaction options:
- * 'wait' => 'WAIT' | 'NO WAIT'
- * 'rw' => 'READ WRITE' | 'READ ONLY'
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- * @since 2.1.1
- */
- function setTransactionIsolation($isolation, $options = array())
- {
- $this->debug('Setting transaction isolation level', __FUNCTION__, array('is_manip' => true));
- return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'isolation level setting is not supported', __FUNCTION__);
- }
-
- // }}}
- // {{{ function beginNestedTransaction($savepoint = false)
-
- /**
- * Start a nested transaction.
- *
- * @return mixed MDB2_OK on success/savepoint name, a MDB2 error on failure
- *
- * @access public
- * @since 2.1.1
- */
- function beginNestedTransaction()
- {
- if ($this->in_transaction) {
- ++$this->nested_transaction_counter;
- $savepoint = sprintf($this->options['savepoint_format'], $this->nested_transaction_counter);
- if ($this->supports('savepoints') && $savepoint) {
- return $this->beginTransaction($savepoint);
- }
- return MDB2_OK;
- }
- $this->has_transaction_error = false;
- $result = $this->beginTransaction();
- $this->nested_transaction_counter = 1;
- return $result;
- }
-
- // }}}
- // {{{ function completeNestedTransaction($force_rollback = false, $release = false)
-
- /**
- * Finish a nested transaction by rolling back if an error occured or
- * committing otherwise.
- *
- * @param bool if the transaction should be rolled back regardless
- * even if no error was set within the nested transaction
- * @return mixed MDB_OK on commit/counter decrementing, false on rollback
- * and a MDB2 error on failure
- *
- * @access public
- * @since 2.1.1
- */
- function completeNestedTransaction($force_rollback = false)
- {
- if ($this->nested_transaction_counter > 1) {
- $savepoint = sprintf($this->options['savepoint_format'], $this->nested_transaction_counter);
- if ($this->supports('savepoints') && $savepoint) {
- if ($force_rollback || $this->has_transaction_error) {
- $result = $this->rollback($savepoint);
- if (!MDB2::isError($result)) {
- $result = false;
- $this->has_transaction_error = false;
- }
- } else {
- $result = $this->commit($savepoint);
- }
- } else {
- $result = MDB2_OK;
- }
- --$this->nested_transaction_counter;
- return $result;
- }
-
- $this->nested_transaction_counter = null;
- $result = MDB2_OK;
-
- // transaction has not yet been rolled back
- if ($this->in_transaction) {
- if ($force_rollback || $this->has_transaction_error) {
- $result = $this->rollback();
- if (!MDB2::isError($result)) {
- $result = false;
- }
- } else {
- $result = $this->commit();
- }
- }
- $this->has_transaction_error = false;
- return $result;
- }
-
- // }}}
- // {{{ function failNestedTransaction($error = null, $immediately = false)
-
- /**
- * Force setting nested transaction to failed.
- *
- * @param mixed value to return in getNestededTransactionError()
- * @param bool if the transaction should be rolled back immediately
- * @return bool MDB2_OK
- *
- * @access public
- * @since 2.1.1
- */
- function failNestedTransaction($error = null, $immediately = false)
- {
- if (null !== $error) {
- $error = $this->has_transaction_error ? $this->has_transaction_error : true;
- } elseif (!$error) {
- $error = true;
- }
- $this->has_transaction_error = $error;
- if (!$immediately) {
- return MDB2_OK;
- }
- return $this->rollback();
- }
-
- // }}}
- // {{{ function getNestedTransactionError()
-
- /**
- * The first error that occured since the transaction start.
- *
- * @return MDB2_Error|bool MDB2 error object if an error occured or false.
- *
- * @access public
- * @since 2.1.1
- */
- function getNestedTransactionError()
- {
- return $this->has_transaction_error;
- }
-
- // }}}
- // {{{ connect()
-
- /**
- * Connect to the database
- *
- * @return true on success, MDB2 Error Object on failure
- */
- function connect()
- {
- return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ databaseExists()
-
- /**
- * check if given database name is exists?
- *
- * @param string $name name of the database that should be checked
- *
- * @return mixed true/false on success, a MDB2 error on failure
- * @access public
- */
- function databaseExists($name)
- {
- return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ setCharset($charset, $connection = null)
-
- /**
- * Set the charset on the current connection
- *
- * @param string charset
- * @param resource connection handle
- *
- * @return true on success, MDB2 Error Object on failure
- */
- function setCharset($charset, $connection = null)
- {
- return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ function disconnect($force = true)
-
- /**
- * Log out and disconnect from the database.
- *
- * @param boolean $force whether the disconnect should be forced even if the
- * connection is opened persistently
- *
- * @return mixed true on success, false if not connected and error object on error
- *
- * @access public
- */
- function disconnect($force = true)
- {
- $this->connection = 0;
- $this->connected_dsn = array();
- $this->connected_database_name = '';
- $this->opened_persistent = null;
- $this->connected_server_info = '';
- $this->in_transaction = null;
- $this->nested_transaction_counter = null;
- return MDB2_OK;
- }
-
- // }}}
- // {{{ function setDatabase($name)
-
- /**
- * Select a different database
- *
- * @param string name of the database that should be selected
- *
- * @return string name of the database previously connected to
- *
- * @access public
- */
- function setDatabase($name)
- {
- $previous_database_name = (isset($this->database_name)) ? $this->database_name : '';
- $this->database_name = $name;
- if (!empty($this->connected_database_name) && ($this->connected_database_name != $this->database_name)) {
- $this->disconnect(false);
- }
- return $previous_database_name;
- }
-
- // }}}
- // {{{ function getDatabase()
-
- /**
- * Get the current database
- *
- * @return string name of the database
- *
- * @access public
- */
- function getDatabase()
- {
- return $this->database_name;
- }
-
- // }}}
- // {{{ function setDSN($dsn)
-
- /**
- * set the DSN
- *
- * @param mixed DSN string or array
- *
- * @return MDB2_OK
- *
- * @access public
- */
- function setDSN($dsn)
- {
- $dsn_default = $GLOBALS['_MDB2_dsninfo_default'];
- $dsn = MDB2::parseDSN($dsn);
- if (array_key_exists('database', $dsn)) {
- $this->database_name = $dsn['database'];
- unset($dsn['database']);
- }
- $this->dsn = array_merge($dsn_default, $dsn);
- return $this->disconnect(false);
- }
-
- // }}}
- // {{{ function getDSN($type = 'string', $hidepw = false)
-
- /**
- * return the DSN as a string
- *
- * @param string format to return ("array", "string")
- * @param string string to hide the password with
- *
- * @return mixed DSN in the chosen type
- *
- * @access public
- */
- function getDSN($type = 'string', $hidepw = false)
- {
- $dsn = array_merge($GLOBALS['_MDB2_dsninfo_default'], $this->dsn);
- $dsn['phptype'] = $this->phptype;
- $dsn['database'] = $this->database_name;
- if ($hidepw) {
- $dsn['password'] = $hidepw;
- }
- switch ($type) {
- // expand to include all possible options
- case 'string':
- $dsn = $dsn['phptype'].
- ($dsn['dbsyntax'] ? ('('.$dsn['dbsyntax'].')') : '').
- '://'.$dsn['username'].':'.
- $dsn['password'].'@'.$dsn['hostspec'].
- ($dsn['port'] ? (':'.$dsn['port']) : '').
- '/'.$dsn['database'];
- break;
- case 'array':
- default:
- break;
- }
- return $dsn;
- }
-
- // }}}
- // {{{ _isNewLinkSet()
-
- /**
- * Check if the 'new_link' option is set
- *
- * @return boolean
- *
- * @access protected
- */
- function _isNewLinkSet()
- {
- return (isset($this->dsn['new_link'])
- && ($this->dsn['new_link'] === true
- || (is_string($this->dsn['new_link']) && preg_match('/^true$/i', $this->dsn['new_link']))
- || (is_numeric($this->dsn['new_link']) && 0 != (int)$this->dsn['new_link'])
- )
- );
- }
-
- // }}}
- // {{{ function &standaloneQuery($query, $types = null, $is_manip = false)
-
- /**
- * execute a query as database administrator
- *
- * @param string the SQL query
- * @param mixed array that contains the types of the columns in
- * the result set
- * @param bool if the query is a manipulation query
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- */
- function standaloneQuery($query, $types = null, $is_manip = false)
- {
- $offset = $this->offset;
- $limit = $this->limit;
- $this->offset = $this->limit = 0;
- $query = $this->_modifyQuery($query, $is_manip, $limit, $offset);
-
- $connection = $this->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
-
- $result = $this->_doQuery($query, $is_manip, $connection, false);
- if (MDB2::isError($result)) {
- return $result;
- }
-
- if ($is_manip) {
- $affected_rows = $this->_affectedRows($connection, $result);
- return $affected_rows;
- }
- $result = $this->_wrapResult($result, $types, true, true, $limit, $offset);
- return $result;
- }
-
- // }}}
- // {{{ function _modifyQuery($query, $is_manip, $limit, $offset)
-
- /**
- * Changes a query string for various DBMS specific reasons
- *
- * @param string query to modify
- * @param bool if it is a DML query
- * @param int limit the number of rows
- * @param int start reading from given offset
- *
- * @return string modified query
- *
- * @access protected
- */
- function _modifyQuery($query, $is_manip, $limit, $offset)
- {
- return $query;
- }
-
- // }}}
- // {{{ function &_doQuery($query, $is_manip = false, $connection = null, $database_name = null)
-
- /**
- * Execute a query
- * @param string query
- * @param bool if the query is a manipulation query
- * @param resource connection handle
- * @param string database name
- *
- * @return result or error object
- *
- * @access protected
- */
- function _doQuery($query, $is_manip = false, $connection = null, $database_name = null)
- {
- $this->last_query = $query;
- $result = $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'pre'));
- if ($result) {
- if (MDB2::isError($result)) {
- return $result;
- }
- $query = $result;
- }
- $err = MDB2_Driver_Common::raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- return $err;
- }
-
- // }}}
- // {{{ function _affectedRows($connection, $result = null)
-
- /**
- * Returns the number of rows affected
- *
- * @param resource result handle
- * @param resource connection handle
- *
- * @return mixed MDB2 Error Object or the number of rows affected
- *
- * @access private
- */
- function _affectedRows($connection, $result = null)
- {
- return MDB2_Driver_Common::raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ function &exec($query)
-
- /**
- * Execute a manipulation query to the database and return the number of affected rows
- *
- * @param string the SQL query
- *
- * @return mixed number of affected rows on success, a MDB2 error on failure
- *
- * @access public
- */
- function exec($query)
- {
- $offset = $this->offset;
- $limit = $this->limit;
- $this->offset = $this->limit = 0;
- $query = $this->_modifyQuery($query, true, $limit, $offset);
-
- $connection = $this->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
-
- $result = $this->_doQuery($query, true, $connection, $this->database_name);
- if (MDB2::isError($result)) {
- return $result;
- }
-
- $affectedRows = $this->_affectedRows($connection, $result);
- return $affectedRows;
- }
-
- // }}}
- // {{{ function &query($query, $types = null, $result_class = true, $result_wrap_class = false)
-
- /**
- * Send a query to the database and return any results
- *
- * @param string the SQL query
- * @param mixed array that contains the types of the columns in
- * the result set
- * @param mixed string which specifies which result class to use
- * @param mixed string which specifies which class to wrap results in
- *
- * @return mixed an MDB2_Result handle on success, a MDB2 error on failure
- *
- * @access public
- */
- function query($query, $types = null, $result_class = true, $result_wrap_class = true)
- {
- $offset = $this->offset;
- $limit = $this->limit;
- $this->offset = $this->limit = 0;
- $query = $this->_modifyQuery($query, false, $limit, $offset);
-
- $connection = $this->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
-
- $result = $this->_doQuery($query, false, $connection, $this->database_name);
- if (MDB2::isError($result)) {
- return $result;
- }
-
- $result = $this->_wrapResult($result, $types, $result_class, $result_wrap_class, $limit, $offset);
- return $result;
- }
-
- // }}}
- // {{{ function _wrapResult($result_resource, $types = array(), $result_class = true, $result_wrap_class = false, $limit = null, $offset = null)
-
- /**
- * wrap a result set into the correct class
- *
- * @param resource result handle
- * @param mixed array that contains the types of the columns in
- * the result set
- * @param mixed string which specifies which result class to use
- * @param mixed string which specifies which class to wrap results in
- * @param string number of rows to select
- * @param string first row to select
- *
- * @return mixed an MDB2_Result, a MDB2 error on failure
- *
- * @access protected
- */
- function _wrapResult($result_resource, $types = array(), $result_class = true,
- $result_wrap_class = true, $limit = null, $offset = null)
- {
- if ($types === true) {
- if ($this->supports('result_introspection')) {
- $this->loadModule('Reverse', null, true);
- $tableInfo = $this->reverse->tableInfo($result_resource);
- if (MDB2::isError($tableInfo)) {
- return $tableInfo;
- }
- $types = array();
- $types_assoc = array();
- foreach ($tableInfo as $field) {
- $types[] = $field['mdb2type'];
- $types_assoc[$field['name']] = $field['mdb2type'];
- }
- } else {
- $types = null;
- }
- }
-
- if ($result_class === true) {
- $result_class = $this->options['result_buffering']
- ? $this->options['buffered_result_class'] : $this->options['result_class'];
- }
-
- if ($result_class) {
- $class_name = sprintf($result_class, $this->phptype);
- if (!MDB2::classExists($class_name)) {
- $err = MDB2_Driver_Common::raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- 'result class does not exist '.$class_name, __FUNCTION__);
- return $err;
- }
- $result = new $class_name($this, $result_resource, $limit, $offset);
- if (!MDB2::isResultCommon($result)) {
- $err = MDB2_Driver_Common::raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- 'result class is not extended from MDB2_Result_Common', __FUNCTION__);
- return $err;
- }
-
- if (!empty($types)) {
- $err = $result->setResultTypes($types);
- if (MDB2::isError($err)) {
- $result->free();
- return $err;
- }
- }
- if (!empty($types_assoc)) {
- $err = $result->setResultTypes($types_assoc);
- if (MDB2::isError($err)) {
- $result->free();
- return $err;
- }
- }
-
- if ($result_wrap_class === true) {
- $result_wrap_class = $this->options['result_wrap_class'];
- }
- if ($result_wrap_class) {
- if (!MDB2::classExists($result_wrap_class)) {
- $err = MDB2_Driver_Common::raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- 'result wrap class does not exist '.$result_wrap_class, __FUNCTION__);
- return $err;
- }
- $result = new $result_wrap_class($result, $this->fetchmode);
- }
-
- return $result;
- }
-
- return $result_resource;
- }
-
- // }}}
- // {{{ function getServerVersion($native = false)
-
- /**
- * return version information about the server
- *
- * @param bool determines if the raw version string should be returned
- *
- * @return mixed array with version information or row string
- *
- * @access public
- */
- function getServerVersion($native = false)
- {
- return MDB2_Driver_Common::raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ function setLimit($limit, $offset = null)
-
- /**
- * set the range of the next query
- *
- * @param string number of rows to select
- * @param string first row to select
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- */
- function setLimit($limit, $offset = null)
- {
- if (!$this->supports('limit_queries')) {
- return MDB2_Driver_Common::raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'limit is not supported by this driver', __FUNCTION__);
- }
- $limit = (int)$limit;
- if ($limit < 0) {
- return MDB2_Driver_Common::raiseError(MDB2_ERROR_SYNTAX, null, null,
- 'it was not specified a valid selected range row limit', __FUNCTION__);
- }
- $this->limit = $limit;
- if (null !== $offset) {
- $offset = (int)$offset;
- if ($offset < 0) {
- return MDB2_Driver_Common::raiseError(MDB2_ERROR_SYNTAX, null, null,
- 'it was not specified a valid first selected range row', __FUNCTION__);
- }
- $this->offset = $offset;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ function subSelect($query, $type = false)
-
- /**
- * simple subselect emulation: leaves the query untouched for all RDBMS
- * that support subselects
- *
- * @param string the SQL query for the subselect that may only
- * return a column
- * @param string determines type of the field
- *
- * @return string the query
- *
- * @access public
- */
- function subSelect($query, $type = false)
- {
- if ($this->supports('sub_selects') === true) {
- return $query;
- }
-
- if (!$this->supports('sub_selects')) {
- return MDB2_Driver_Common::raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- $col = $this->queryCol($query, $type);
- if (MDB2::isError($col)) {
- return $col;
- }
- if (!is_array($col) || count($col) == 0) {
- return 'NULL';
- }
- if ($type) {
- $this->loadModule('Datatype', null, true);
- return $this->datatype->implodeArray($col, $type);
- }
- return implode(', ', $col);
- }
-
- // }}}
- // {{{ function replace($table, $fields)
-
- /**
- * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
- * query, except that if there is already a row in the table with the same
- * key field values, the old row is deleted before the new row is inserted.
- *
- * The REPLACE type of query does not make part of the SQL standards. Since
- * practically only MySQL and SQLite implement it natively, this type of
- * query isemulated through this method for other DBMS using standard types
- * of queries inside a transaction to assure the atomicity of the operation.
- *
- * @param string name of the table on which the REPLACE query will
- * be executed.
- * @param array associative array that describes the fields and the
- * values that will be inserted or updated in the specified table. The
- * indexes of the array are the names of all the fields of the table.
- * The values of the array are also associative arrays that describe
- * the values and other properties of the table fields.
- *
- * Here follows a list of field properties that need to be specified:
- *
- * value
- * Value to be assigned to the specified field. This value may be
- * of specified in database independent type format as this
- * function can perform the necessary datatype conversions.
- *
- * Default: this property is required unless the Null property is
- * set to 1.
- *
- * type
- * Name of the type of the field. Currently, all types MDB2
- * are supported except for clob and blob.
- *
- * Default: no type conversion
- *
- * null
- * bool property that indicates that the value for this field
- * should be set to null.
- *
- * The default value for fields missing in INSERT queries may be
- * specified the definition of a table. Often, the default value
- * is already null, but since the REPLACE may be emulated using
- * an UPDATE query, make sure that all fields of the table are
- * listed in this function argument array.
- *
- * Default: 0
- *
- * key
- * bool property that indicates that this field should be
- * handled as a primary key or at least as part of the compound
- * unique index of the table that will determine the row that will
- * updated if it exists or inserted a new row otherwise.
- *
- * This function will fail if no key field is specified or if the
- * value of a key field is set to null because fields that are
- * part of unique index they may not be null.
- *
- * Default: 0
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- */
- function replace($table, $fields)
- {
- if (!$this->supports('replace')) {
- return MDB2_Driver_Common::raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'replace query is not supported', __FUNCTION__);
- }
- $count = count($fields);
- $condition = $values = array();
- for ($colnum = 0, reset($fields); $colnum < $count; next($fields), $colnum++) {
- $name = key($fields);
- if (isset($fields[$name]['null']) && $fields[$name]['null']) {
- $value = 'NULL';
- } else {
- $type = isset($fields[$name]['type']) ? $fields[$name]['type'] : null;
- $value = $this->quote($fields[$name]['value'], $type);
- }
- $values[$name] = $value;
- if (isset($fields[$name]['key']) && $fields[$name]['key']) {
- if ($value === 'NULL') {
- return MDB2_Driver_Common::raiseError(MDB2_ERROR_CANNOT_REPLACE, null, null,
- 'key value '.$name.' may not be NULL', __FUNCTION__);
- }
- $condition[] = $this->quoteIdentifier($name, true) . '=' . $value;
- }
- }
- if (empty($condition)) {
- return MDB2_Driver_Common::raiseError(MDB2_ERROR_CANNOT_REPLACE, null, null,
- 'not specified which fields are keys', __FUNCTION__);
- }
-
- $result = null;
- $in_transaction = $this->in_transaction;
- if (!$in_transaction && MDB2::isError($result = $this->beginTransaction())) {
- return $result;
- }
-
- $connection = $this->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
-
- $condition = ' WHERE '.implode(' AND ', $condition);
- $query = 'DELETE FROM ' . $this->quoteIdentifier($table, true) . $condition;
- $result = $this->_doQuery($query, true, $connection);
- if (!MDB2::isError($result)) {
- $affected_rows = $this->_affectedRows($connection, $result);
- $insert = '';
- foreach ($values as $key => $value) {
- $insert .= ($insert?', ':'') . $this->quoteIdentifier($key, true);
- }
- $values = implode(', ', $values);
- $query = 'INSERT INTO '. $this->quoteIdentifier($table, true) . "($insert) VALUES ($values)";
- $result = $this->_doQuery($query, true, $connection);
- if (!MDB2::isError($result)) {
- $affected_rows += $this->_affectedRows($connection, $result);;
- }
- }
-
- if (!$in_transaction) {
- if (MDB2::isError($result)) {
- $this->rollback();
- } else {
- $result = $this->commit();
- }
- }
-
- if (MDB2::isError($result)) {
- return $result;
- }
-
- return $affected_rows;
- }
-
- // }}}
- // {{{ function &prepare($query, $types = null, $result_types = null, $lobs = array())
-
- /**
- * Prepares a query for multiple execution with execute().
- * With some database backends, this is emulated.
- * prepare() requires a generic query as string like
- * 'INSERT INTO numbers VALUES(?,?)' or
- * 'INSERT INTO numbers VALUES(:foo,:bar)'.
- * The ? and :name and are placeholders which can be set using
- * bindParam() and the query can be sent off using the execute() method.
- * The allowed format for :name can be set with the 'bindname_format' option.
- *
- * @param string the query to prepare
- * @param mixed array that contains the types of the placeholders
- * @param mixed array that contains the types of the columns in
- * the result set or MDB2_PREPARE_RESULT, if set to
- * MDB2_PREPARE_MANIP the query is handled as a manipulation query
- * @param mixed key (field) value (parameter) pair for all lob placeholders
- *
- * @return mixed resource handle for the prepared query on success,
- * a MDB2 error on failure
- *
- * @access public
- * @see bindParam, execute
- */
- function prepare($query, $types = null, $result_types = null, $lobs = array())
- {
- $is_manip = ($result_types === MDB2_PREPARE_MANIP);
- $offset = $this->offset;
- $limit = $this->limit;
- $this->offset = $this->limit = 0;
- $result = $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'pre'));
- if ($result) {
- if (MDB2::isError($result)) {
- return $result;
- }
- $query = $result;
- }
- $placeholder_type_guess = $placeholder_type = null;
- $question = '?';
- $colon = ':';
- $positions = array();
- $position = 0;
- while ($position < strlen($query)) {
- $q_position = strpos($query, $question, $position);
- $c_position = strpos($query, $colon, $position);
- if ($q_position && $c_position) {
- $p_position = min($q_position, $c_position);
- } elseif ($q_position) {
- $p_position = $q_position;
- } elseif ($c_position) {
- $p_position = $c_position;
- } else {
- break;
- }
- if (null === $placeholder_type) {
- $placeholder_type_guess = $query[$p_position];
- }
-
- $new_pos = $this->_skipDelimitedStrings($query, $position, $p_position);
- if (MDB2::isError($new_pos)) {
- return $new_pos;
- }
- if ($new_pos != $position) {
- $position = $new_pos;
- continue; //evaluate again starting from the new position
- }
-
- if ($query[$position] == $placeholder_type_guess) {
- if (null === $placeholder_type) {
- $placeholder_type = $query[$p_position];
- $question = $colon = $placeholder_type;
- if (!empty($types) && is_array($types)) {
- if ($placeholder_type == ':') {
- if (is_int(key($types))) {
- $types_tmp = $types;
- $types = array();
- $count = -1;
- }
- } else {
- $types = array_values($types);
- }
- }
- }
- if ($placeholder_type == ':') {
- $regexp = '/^.{'.($position+1).'}('.$this->options['bindname_format'].').*$/s';
- $parameter = preg_replace($regexp, '\\1', $query);
- if ($parameter === '') {
- $err = MDB2_Driver_Common::raiseError(MDB2_ERROR_SYNTAX, null, null,
- 'named parameter name must match "bindname_format" option', __FUNCTION__);
- return $err;
- }
- $positions[$p_position] = $parameter;
- $query = substr_replace($query, '?', $position, strlen($parameter)+1);
- // use parameter name in type array
- if (isset($count) && isset($types_tmp[++$count])) {
- $types[$parameter] = $types_tmp[$count];
- }
- } else {
- $positions[$p_position] = count($positions);
- }
- $position = $p_position + 1;
- } else {
- $position = $p_position;
- }
- }
- $class_name = 'MDB2_Statement_'.$this->phptype;
- $statement = null;
- $obj = new $class_name($this, $statement, $positions, $query, $types, $result_types, $is_manip, $limit, $offset);
- $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'post', 'result' => $obj));
- return $obj;
- }
-
- // }}}
- // {{{ function _skipDelimitedStrings($query, $position, $p_position)
-
- /**
- * Utility method, used by prepare() to avoid replacing placeholders within delimited strings.
- * Check if the placeholder is contained within a delimited string.
- * If so, skip it and advance the position, otherwise return the current position,
- * which is valid
- *
- * @param string $query
- * @param integer $position current string cursor position
- * @param integer $p_position placeholder position
- *
- * @return mixed integer $new_position on success
- * MDB2_Error on failure
- *
- * @access protected
- */
- function _skipDelimitedStrings($query, $position, $p_position)
- {
- $ignores = array();
- $ignores[] = $this->string_quoting;
- $ignores[] = $this->identifier_quoting;
- $ignores = array_merge($ignores, $this->sql_comments);
-
- foreach ($ignores as $ignore) {
- if (!empty($ignore['start'])) {
- if (is_int($start_quote = strpos($query, $ignore['start'], $position)) && $start_quote < $p_position) {
- $end_quote = $start_quote;
- do {
- if (!is_int($end_quote = strpos($query, $ignore['end'], $end_quote + 1))) {
- if ($ignore['end'] === "\n") {
- $end_quote = strlen($query) - 1;
- } else {
- $err = MDB2_Driver_Common::raiseError(MDB2_ERROR_SYNTAX, null, null,
- 'query with an unterminated text string specified', __FUNCTION__);
- return $err;
- }
- }
- } while ($ignore['escape']
- && $end_quote-1 != $start_quote
- && $query[($end_quote - 1)] == $ignore['escape']
- && ( $ignore['escape_pattern'] !== $ignore['escape']
- || $query[($end_quote - 2)] != $ignore['escape'])
- );
-
- $position = $end_quote + 1;
- return $position;
- }
- }
- }
- return $position;
- }
-
- // }}}
- // {{{ function quote($value, $type = null, $quote = true)
-
- /**
- * Convert a text value into a DBMS specific format that is suitable to
- * compose query statements.
- *
- * @param string text string value that is intended to be converted.
- * @param string type to which the value should be converted to
- * @param bool quote
- * @param bool escape wildcards
- *
- * @return string text string that represents the given argument value in
- * a DBMS specific format.
- *
- * @access public
- */
- function quote($value, $type = null, $quote = true, $escape_wildcards = false)
- {
- $result = $this->loadModule('Datatype', null, true);
- if (MDB2::isError($result)) {
- return $result;
- }
-
- return $this->datatype->quote($value, $type, $quote, $escape_wildcards);
- }
-
- // }}}
- // {{{ function getDeclaration($type, $name, $field)
-
- /**
- * Obtain DBMS specific SQL code portion needed to declare
- * of the given type
- *
- * @param string type to which the value should be converted to
- * @param string name the field to be declared.
- * @param string definition of the field
- *
- * @return string DBMS specific SQL code portion that should be used to
- * declare the specified field.
- *
- * @access public
- */
- function getDeclaration($type, $name, $field)
- {
- $result = $this->loadModule('Datatype', null, true);
- if (MDB2::isError($result)) {
- return $result;
- }
- return $this->datatype->getDeclaration($type, $name, $field);
- }
-
- // }}}
- // {{{ function compareDefinition($current, $previous)
-
- /**
- * Obtain an array of changes that may need to applied
- *
- * @param array new definition
- * @param array old definition
- *
- * @return array containing all changes that will need to be applied
- *
- * @access public
- */
- function compareDefinition($current, $previous)
- {
- $result = $this->loadModule('Datatype', null, true);
- if (MDB2::isError($result)) {
- return $result;
- }
- return $this->datatype->compareDefinition($current, $previous);
- }
-
- // }}}
- // {{{ function supports($feature)
-
- /**
- * Tell whether a DB implementation or its backend extension
- * supports a given feature.
- *
- * @param string name of the feature (see the MDB2 class doc)
- *
- * @return bool|string if this DB implementation supports a given feature
- * false means no, true means native,
- * 'emulated' means emulated
- *
- * @access public
- */
- function supports($feature)
- {
- if (array_key_exists($feature, $this->supported)) {
- return $this->supported[$feature];
- }
- return MDB2_Driver_Common::raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- "unknown support feature $feature", __FUNCTION__);
- }
-
- // }}}
- // {{{ function getSequenceName($sqn)
-
- /**
- * adds sequence name formatting to a sequence name
- *
- * @param string name of the sequence
- *
- * @return string formatted sequence name
- *
- * @access public
- */
- function getSequenceName($sqn)
- {
- return sprintf($this->options['seqname_format'],
- preg_replace('/[^a-z0-9_\-\$.]/i', '_', $sqn));
- }
-
- // }}}
- // {{{ function getIndexName($idx)
-
- /**
- * adds index name formatting to a index name
- *
- * @param string name of the index
- *
- * @return string formatted index name
- *
- * @access public
- */
- function getIndexName($idx)
- {
- return sprintf($this->options['idxname_format'],
- preg_replace('/[^a-z0-9_\-\$.]/i', '_', $idx));
- }
-
- // }}}
- // {{{ function nextID($seq_name, $ondemand = true)
-
- /**
- * Returns the next free id of a sequence
- *
- * @param string name of the sequence
- * @param bool when true missing sequences are automatic created
- *
- * @return mixed MDB2 Error Object or id
- *
- * @access public
- */
- function nextID($seq_name, $ondemand = true)
- {
- return MDB2_Driver_Common::raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ function lastInsertID($table = null, $field = null)
-
- /**
- * Returns the autoincrement ID if supported or $id or fetches the current
- * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field)
- *
- * @param string name of the table into which a new row was inserted
- * @param string name of the field into which a new row was inserted
- *
- * @return mixed MDB2 Error Object or id
- *
- * @access public
- */
- function lastInsertID($table = null, $field = null)
- {
- return MDB2_Driver_Common::raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ function currID($seq_name)
-
- /**
- * Returns the current id of a sequence
- *
- * @param string name of the sequence
- *
- * @return mixed MDB2 Error Object or id
- *
- * @access public
- */
- function currID($seq_name)
- {
- $this->warnings[] = 'database does not support getting current
- sequence value, the sequence value was incremented';
- return $this->nextID($seq_name);
- }
-
- // }}}
- // {{{ function queryOne($query, $type = null, $colnum = 0)
-
- /**
- * Execute the specified query, fetch the value from the first column of
- * the first row of the result set and then frees
- * the result set.
- *
- * @param string $query the SELECT query statement to be executed.
- * @param string $type optional argument that specifies the expected
- * datatype of the result set field, so that an eventual
- * conversion may be performed. The default datatype is
- * text, meaning that no conversion is performed
- * @param mixed $colnum the column number (or name) to fetch
- *
- * @return mixed MDB2_OK or field value on success, a MDB2 error on failure
- *
- * @access public
- */
- function queryOne($query, $type = null, $colnum = 0)
- {
- $result = $this->query($query, $type);
- if (!MDB2::isResultCommon($result)) {
- return $result;
- }
-
- $one = $result->fetchOne($colnum);
- $result->free();
- return $one;
- }
-
- // }}}
- // {{{ function queryRow($query, $types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT)
-
- /**
- * Execute the specified query, fetch the values from the first
- * row of the result set into an array and then frees
- * the result set.
- *
- * @param string the SELECT query statement to be executed.
- * @param array optional array argument that specifies a list of
- * expected datatypes of the result set columns, so that the eventual
- * conversions may be performed. The default list of datatypes is
- * empty, meaning that no conversion is performed.
- * @param int how the array data should be indexed
- *
- * @return mixed MDB2_OK or data array on success, a MDB2 error on failure
- *
- * @access public
- */
- function queryRow($query, $types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT)
- {
- $result = $this->query($query, $types);
- if (!MDB2::isResultCommon($result)) {
- return $result;
- }
-
- $row = $result->fetchRow($fetchmode);
- $result->free();
- return $row;
- }
-
- // }}}
- // {{{ function queryCol($query, $type = null, $colnum = 0)
-
- /**
- * Execute the specified query, fetch the value from the first column of
- * each row of the result set into an array and then frees the result set.
- *
- * @param string $query the SELECT query statement to be executed.
- * @param string $type optional argument that specifies the expected
- * datatype of the result set field, so that an eventual
- * conversion may be performed. The default datatype is text,
- * meaning that no conversion is performed
- * @param mixed $colnum the column number (or name) to fetch
- *
- * @return mixed MDB2_OK or data array on success, a MDB2 error on failure
- * @access public
- */
- function queryCol($query, $type = null, $colnum = 0)
- {
- $result = $this->query($query, $type);
- if (!MDB2::isResultCommon($result)) {
- return $result;
- }
-
- $col = $result->fetchCol($colnum);
- $result->free();
- return $col;
- }
-
- // }}}
- // {{{ function queryAll($query, $types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT, $rekey = false, $force_array = false, $group = false)
-
- /**
- * Execute the specified query, fetch all the rows of the result set into
- * a two dimensional array and then frees the result set.
- *
- * @param string the SELECT query statement to be executed.
- * @param array optional array argument that specifies a list of
- * expected datatypes of the result set columns, so that the eventual
- * conversions may be performed. The default list of datatypes is
- * empty, meaning that no conversion is performed.
- * @param int how the array data should be indexed
- * @param bool if set to true, the $all will have the first
- * column as its first dimension
- * @param bool used only when the query returns exactly
- * two columns. If true, the values of the returned array will be
- * one-element arrays instead of scalars.
- * @param bool if true, the values of the returned array is
- * wrapped in another array. If the same key value (in the first
- * column) repeats itself, the values will be appended to this array
- * instead of overwriting the existing values.
- *
- * @return mixed MDB2_OK or data array on success, a MDB2 error on failure
- *
- * @access public
- */
- function queryAll($query, $types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT,
- $rekey = false, $force_array = false, $group = false)
- {
- $result = $this->query($query, $types);
- if (!MDB2::isResultCommon($result)) {
- return $result;
- }
-
- $all = $result->fetchAll($fetchmode, $rekey, $force_array, $group);
- $result->free();
- return $all;
- }
-
- // }}}
- // {{{ function delExpect($error_code)
-
- /**
- * This method deletes all occurences of the specified element from
- * the expected error codes stack.
- *
- * @param mixed $error_code error code that should be deleted
- * @return mixed list of error codes that were deleted or error
- *
- * @uses PEAR::delExpect()
- */
- public function delExpect($error_code)
- {
- return $this->pear->delExpect($error_code);
- }
-
- // }}}
- // {{{ function expectError($code)
-
- /**
- * This method is used to tell which errors you expect to get.
- * Expected errors are always returned with error mode
- * PEAR_ERROR_RETURN. Expected error codes are stored in a stack,
- * and this method pushes a new element onto it. The list of
- * expected errors are in effect until they are popped off the
- * stack with the popExpect() method.
- *
- * Note that this method can not be called statically
- *
- * @param mixed $code a single error code or an array of error codes to expect
- *
- * @return int the new depth of the "expected errors" stack
- *
- * @uses PEAR::expectError()
- */
- public function expectError($code = '*')
- {
- return $this->pear->expectError($code);
- }
-
- // }}}
- // {{{ function getStaticProperty($class, $var)
-
- /**
- * If you have a class that's mostly/entirely static, and you need static
- * properties, you can use this method to simulate them. Eg. in your method(s)
- * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
- * You MUST use a reference, or they will not persist!
- *
- * @param string $class The calling classname, to prevent clashes
- * @param string $var The variable to retrieve.
- * @return mixed A reference to the variable. If not set it will be
- * auto initialised to NULL.
- *
- * @uses PEAR::getStaticProperty()
- */
- public function &getStaticProperty($class, $var)
- {
- $tmp =& $this->pear->getStaticProperty($class, $var);
- return $tmp;
- }
-
- // }}}
- // {{{ function popErrorHandling()
-
- /**
- * Pop the last error handler used
- *
- * @return bool Always true
- *
- * @see PEAR::pushErrorHandling
- * @uses PEAR::popErrorHandling()
- */
- public function popErrorHandling()
- {
- return $this->pear->popErrorHandling();
- }
-
- // }}}
- // {{{ function popExpect()
-
- /**
- * This method pops one element off the expected error codes
- * stack.
- *
- * @return array the list of error codes that were popped
- *
- * @uses PEAR::popExpect()
- */
- public function popExpect()
- {
- return $this->pear->popExpect();
- }
-
- // }}}
- // {{{ function pushErrorHandling($mode, $options = null)
-
- /**
- * Push a new error handler on top of the error handler options stack. With this
- * you can easily override the actual error handler for some code and restore
- * it later with popErrorHandling.
- *
- * @param mixed $mode (same as setErrorHandling)
- * @param mixed $options (same as setErrorHandling)
- *
- * @return bool Always true
- *
- * @see PEAR::setErrorHandling
- * @uses PEAR::pushErrorHandling()
- */
- public function pushErrorHandling($mode, $options = null)
- {
- return $this->pear->pushErrorHandling($mode, $options);
- }
-
- // }}}
- // {{{ function registerShutdownFunc($func, $args = array())
-
- /**
- * Use this function to register a shutdown method for static
- * classes.
- *
- * @param mixed $func The function name (or array of class/method) to call
- * @param mixed $args The arguments to pass to the function
- * @return void
- *
- * @uses PEAR::registerShutdownFunc()
- */
- public function registerShutdownFunc($func, $args = array())
- {
- return $this->pear->registerShutdownFunc($func, $args);
- }
-
- // }}}
- // {{{ function setErrorHandling($mode = null, $options = null)
-
- /**
- * Sets how errors generated by this object should be handled.
- * Can be invoked both in objects and statically. If called
- * statically, setErrorHandling sets the default behaviour for all
- * PEAR objects. If called in an object, setErrorHandling sets
- * the default behaviour for that object.
- *
- * @param int $mode
- * One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
- * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
- * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
- *
- * @param mixed $options
- * When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
- * of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
- *
- * When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
- * to be the callback function or method. A callback
- * function is a string with the name of the function, a
- * callback method is an array of two elements: the element
- * at index 0 is the object, and the element at index 1 is
- * the name of the method to call in the object.
- *
- * When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
- * a printf format string used when printing the error
- * message.
- *
- * @access public
- * @return void
- * @see PEAR_ERROR_RETURN
- * @see PEAR_ERROR_PRINT
- * @see PEAR_ERROR_TRIGGER
- * @see PEAR_ERROR_DIE
- * @see PEAR_ERROR_CALLBACK
- * @see PEAR_ERROR_EXCEPTION
- *
- * @since PHP 4.0.5
- * @uses PEAR::setErrorHandling($mode, $options)
- */
- public function setErrorHandling($mode = null, $options = null)
- {
- return $this->pear->setErrorHandling($mode, $options);
- }
-
- /**
- * @uses PEAR::staticPopErrorHandling()
- */
- public function staticPopErrorHandling()
- {
- return $this->pear->staticPopErrorHandling();
- }
-
- // }}}
- // {{{ function staticPushErrorHandling($mode, $options = null)
-
- /**
- * @uses PEAR::staticPushErrorHandling($mode, $options)
- */
- public function staticPushErrorHandling($mode, $options = null)
- {
- return $this->pear->staticPushErrorHandling($mode, $options);
- }
-
- // }}}
- // {{{ function &throwError($message = null, $code = null, $userinfo = null)
-
- /**
- * Simpler form of raiseError with fewer options. In most cases
- * message, code and userinfo are enough.
- *
- * @param mixed $message a text error message or a PEAR error object
- *
- * @param int $code a numeric error code (it is up to your class
- * to define these if you want to use codes)
- *
- * @param string $userinfo If you need to pass along for example debug
- * information, this parameter is meant for that.
- *
- * @return object a PEAR error object
- * @see PEAR::raiseError
- * @uses PEAR::&throwError()
- */
- public function &throwError($message = null, $code = null, $userinfo = null)
- {
- $tmp =& $this->pear->throwError($message, $code, $userinfo);
- return $tmp;
- }
-
- // }}}
-}
-
-// }}}
-// {{{ class MDB2_Result
-
-/**
- * The dummy class that all user space result classes should extend from
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_Result
-{
-}
-
-// }}}
-// {{{ class MDB2_Result_Common extends MDB2_Result
-
-/**
- * The common result class for MDB2 result objects
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_Result_Common extends MDB2_Result
-{
- // {{{ Variables (Properties)
-
- public $db;
- public $result;
- public $rownum = -1;
- public $types = array();
- public $types_assoc = array();
- public $values = array();
- public $offset;
- public $offset_count = 0;
- public $limit;
- public $column_names;
-
- // }}}
- // {{{ constructor: function __construct($db, &$result, $limit = 0, $offset = 0)
-
- /**
- * Constructor
- */
- function __construct($db, &$result, $limit = 0, $offset = 0)
- {
- $this->db = $db;
- $this->result = $result;
- $this->offset = $offset;
- $this->limit = max(0, $limit - 1);
- }
-
- // }}}
- // {{{ function setResultTypes($types)
-
- /**
- * Define the list of types to be associated with the columns of a given
- * result set.
- *
- * This function may be called before invoking fetchRow(), fetchOne(),
- * fetchCol() and fetchAll() so that the necessary data type
- * conversions are performed on the data to be retrieved by them. If this
- * function is not called, the type of all result set columns is assumed
- * to be text, thus leading to not perform any conversions.
- *
- * @param array variable that lists the
- * data types to be expected in the result set columns. If this array
- * contains less types than the number of columns that are returned
- * in the result set, the remaining columns are assumed to be of the
- * type text. Currently, the types clob and blob are not fully
- * supported.
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- */
- function setResultTypes($types)
- {
- $load = $this->db->loadModule('Datatype', null, true);
- if (MDB2::isError($load)) {
- return $load;
- }
- $types = $this->db->datatype->checkResultTypes($types);
- if (MDB2::isError($types)) {
- return $types;
- }
- foreach ($types as $key => $value) {
- if (is_numeric($key)) {
- $this->types[$key] = $value;
- } else {
- $this->types_assoc[$key] = $value;
- }
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ function seek($rownum = 0)
-
- /**
- * Seek to a specific row in a result set
- *
- * @param int number of the row where the data can be found
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- */
- function seek($rownum = 0)
- {
- $target_rownum = $rownum - 1;
- if ($this->rownum > $target_rownum) {
- return MDB2::raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'seeking to previous rows not implemented', __FUNCTION__);
- }
- while ($this->rownum < $target_rownum) {
- $this->fetchRow();
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ function &fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null)
-
- /**
- * Fetch and return a row of data
- *
- * @param int how the array data should be indexed
- * @param int number of the row where the data can be found
- *
- * @return int data array on success, a MDB2 error on failure
- *
- * @access public
- */
- function fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null)
- {
- $err = MDB2::raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- return $err;
- }
-
- // }}}
- // {{{ function fetchOne($colnum = 0)
-
- /**
- * fetch single column from the next row from a result set
- *
- * @param int|string the column number (or name) to fetch
- * @param int number of the row where the data can be found
- *
- * @return string data on success, a MDB2 error on failure
- * @access public
- */
- function fetchOne($colnum = 0, $rownum = null)
- {
- $fetchmode = is_numeric($colnum) ? MDB2_FETCHMODE_ORDERED : MDB2_FETCHMODE_ASSOC;
- $row = $this->fetchRow($fetchmode, $rownum);
- if (!is_array($row) || MDB2::isError($row)) {
- return $row;
- }
- if (!array_key_exists($colnum, $row)) {
- return MDB2::raiseError(MDB2_ERROR_TRUNCATED, null, null,
- 'column is not defined in the result set: '.$colnum, __FUNCTION__);
- }
- return $row[$colnum];
- }
-
- // }}}
- // {{{ function fetchCol($colnum = 0)
-
- /**
- * Fetch and return a column from the current row pointer position
- *
- * @param int|string the column number (or name) to fetch
- *
- * @return mixed data array on success, a MDB2 error on failure
- * @access public
- */
- function fetchCol($colnum = 0)
- {
- $column = array();
- $fetchmode = is_numeric($colnum) ? MDB2_FETCHMODE_ORDERED : MDB2_FETCHMODE_ASSOC;
- $row = $this->fetchRow($fetchmode);
- if (is_array($row)) {
- if (!array_key_exists($colnum, $row)) {
- return MDB2::raiseError(MDB2_ERROR_TRUNCATED, null, null,
- 'column is not defined in the result set: '.$colnum, __FUNCTION__);
- }
- do {
- $column[] = $row[$colnum];
- } while (is_array($row = $this->fetchRow($fetchmode)));
- }
- if (MDB2::isError($row)) {
- return $row;
- }
- return $column;
- }
-
- // }}}
- // {{{ function fetchAll($fetchmode = MDB2_FETCHMODE_DEFAULT, $rekey = false, $force_array = false, $group = false)
-
- /**
- * Fetch and return all rows from the current row pointer position
- *
- * @param int $fetchmode the fetch mode to use:
- * + MDB2_FETCHMODE_ORDERED
- * + MDB2_FETCHMODE_ASSOC
- * + MDB2_FETCHMODE_ORDERED | MDB2_FETCHMODE_FLIPPED
- * + MDB2_FETCHMODE_ASSOC | MDB2_FETCHMODE_FLIPPED
- * @param bool if set to true, the $all will have the first
- * column as its first dimension
- * @param bool used only when the query returns exactly
- * two columns. If true, the values of the returned array will be
- * one-element arrays instead of scalars.
- * @param bool if true, the values of the returned array is
- * wrapped in another array. If the same key value (in the first
- * column) repeats itself, the values will be appended to this array
- * instead of overwriting the existing values.
- *
- * @return mixed data array on success, a MDB2 error on failure
- *
- * @access public
- * @see getAssoc()
- */
- function fetchAll($fetchmode = MDB2_FETCHMODE_DEFAULT, $rekey = false,
- $force_array = false, $group = false)
- {
- $all = array();
- $row = $this->fetchRow($fetchmode);
- if (MDB2::isError($row)) {
- return $row;
- } elseif (!$row) {
- return $all;
- }
-
- $shift_array = $rekey ? false : null;
- if (null !== $shift_array) {
- if (is_object($row)) {
- $colnum = count(get_object_vars($row));
- } else {
- $colnum = count($row);
- }
- if ($colnum < 2) {
- return MDB2::raiseError(MDB2_ERROR_TRUNCATED, null, null,
- 'rekey feature requires atleast 2 column', __FUNCTION__);
- }
- $shift_array = (!$force_array && $colnum == 2);
- }
-
- if ($rekey) {
- do {
- if (is_object($row)) {
- $arr = get_object_vars($row);
- $key = reset($arr);
- unset($row->{$key});
- } else {
- if ( $fetchmode == MDB2_FETCHMODE_ASSOC
- || $fetchmode == MDB2_FETCHMODE_OBJECT
- ) {
- $key = reset($row);
- unset($row[key($row)]);
- } else {
- $key = array_shift($row);
- }
- if ($shift_array) {
- $row = array_shift($row);
- }
- }
- if ($group) {
- $all[$key][] = $row;
- } else {
- $all[$key] = $row;
- }
- } while (($row = $this->fetchRow($fetchmode)));
- } elseif ($fetchmode == MDB2_FETCHMODE_FLIPPED) {
- do {
- foreach ($row as $key => $val) {
- $all[$key][] = $val;
- }
- } while (($row = $this->fetchRow($fetchmode)));
- } else {
- do {
- $all[] = $row;
- } while (($row = $this->fetchRow($fetchmode)));
- }
-
- return $all;
- }
-
- // }}}
- // {{{ function rowCount()
- /**
- * Returns the actual row number that was last fetched (count from 0)
- * @return int
- *
- * @access public
- */
- function rowCount()
- {
- return $this->rownum + 1;
- }
-
- // }}}
- // {{{ function numRows()
-
- /**
- * Returns the number of rows in a result object
- *
- * @return mixed MDB2 Error Object or the number of rows
- *
- * @access public
- */
- function numRows()
- {
- return MDB2::raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ function nextResult()
-
- /**
- * Move the internal result pointer to the next available result
- *
- * @return true on success, false if there is no more result set or an error object on failure
- *
- * @access public
- */
- function nextResult()
- {
- return MDB2::raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ function getColumnNames()
-
- /**
- * Retrieve the names of columns returned by the DBMS in a query result or
- * from the cache.
- *
- * @param bool If set to true the values are the column names,
- * otherwise the names of the columns are the keys.
- * @return mixed Array variable that holds the names of columns or an
- * MDB2 error on failure.
- * Some DBMS may not return any columns when the result set
- * does not contain any rows.
- *
- * @access public
- */
- function getColumnNames($flip = false)
- {
- if (!isset($this->column_names)) {
- $result = $this->_getColumnNames();
- if (MDB2::isError($result)) {
- return $result;
- }
- $this->column_names = $result;
- }
- if ($flip) {
- return array_flip($this->column_names);
- }
- return $this->column_names;
- }
-
- // }}}
- // {{{ function _getColumnNames()
-
- /**
- * Retrieve the names of columns returned by the DBMS in a query result.
- *
- * @return mixed Array variable that holds the names of columns as keys
- * or an MDB2 error on failure.
- * Some DBMS may not return any columns when the result set
- * does not contain any rows.
- *
- * @access private
- */
- function _getColumnNames()
- {
- return MDB2::raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ function numCols()
-
- /**
- * Count the number of columns returned by the DBMS in a query result.
- *
- * @return mixed integer value with the number of columns, a MDB2 error
- * on failure
- *
- * @access public
- */
- function numCols()
- {
- return MDB2::raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ function getResource()
-
- /**
- * return the resource associated with the result object
- *
- * @return resource
- *
- * @access public
- */
- function getResource()
- {
- return $this->result;
- }
-
- // }}}
- // {{{ function bindColumn($column, &$value, $type = null)
-
- /**
- * Set bind variable to a column.
- *
- * @param int column number or name
- * @param mixed variable reference
- * @param string specifies the type of the field
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- */
- function bindColumn($column, &$value, $type = null)
- {
- if (!is_numeric($column)) {
- $column_names = $this->getColumnNames();
- if ($this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- if ($this->db->options['field_case'] == CASE_LOWER) {
- $column = strtolower($column);
- } else {
- $column = strtoupper($column);
- }
- }
- $column = $column_names[$column];
- }
- $this->values[$column] =& $value;
- if (null !== $type) {
- $this->types[$column] = $type;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ function _assignBindColumns($row)
-
- /**
- * Bind a variable to a value in the result row.
- *
- * @param array row data
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access private
- */
- function _assignBindColumns($row)
- {
- $row = array_values($row);
- foreach ($row as $column => $value) {
- if (array_key_exists($column, $this->values)) {
- $this->values[$column] = $value;
- }
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ function free()
-
- /**
- * Free the internal resources associated with result.
- *
- * @return bool true on success, false if result is invalid
- *
- * @access public
- */
- function free()
- {
- $this->result = false;
- return MDB2_OK;
- }
-
- // }}}
-}
-
-// }}}
-// {{{ class MDB2_Row
-
-/**
- * The simple class that accepts row data as an array
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_Row
-{
- // {{{ constructor: function __construct(&$row)
-
- /**
- * constructor
- *
- * @param resource row data as array
- */
- function __construct(&$row)
- {
- foreach ($row as $key => $value) {
- $this->$key = &$row[$key];
- }
- }
-
- // }}}
-}
-
-// }}}
-// {{{ class MDB2_Statement_Common
-
-/**
- * The common statement class for MDB2 statement objects
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_Statement_Common
-{
- // {{{ Variables (Properties)
-
- var $db;
- var $statement;
- var $query;
- var $result_types;
- var $types;
- var $values = array();
- var $limit;
- var $offset;
- var $is_manip;
-
- // }}}
- // {{{ constructor: function __construct($db, $statement, $positions, $query, $types, $result_types, $is_manip = false, $limit = null, $offset = null)
-
- /**
- * Constructor
- */
- function __construct($db, $statement, $positions, $query, $types, $result_types, $is_manip = false, $limit = null, $offset = null)
- {
- $this->db = $db;
- $this->statement = $statement;
- $this->positions = $positions;
- $this->query = $query;
- $this->types = (array)$types;
- $this->result_types = (array)$result_types;
- $this->limit = $limit;
- $this->is_manip = $is_manip;
- $this->offset = $offset;
- }
-
- // }}}
- // {{{ function bindValue($parameter, &$value, $type = null)
-
- /**
- * Set the value of a parameter of a prepared query.
- *
- * @param int the order number of the parameter in the query
- * statement. The order number of the first parameter is 1.
- * @param mixed value that is meant to be assigned to specified
- * parameter. The type of the value depends on the $type argument.
- * @param string specifies the type of the field
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- */
- function bindValue($parameter, $value, $type = null)
- {
- if (!is_numeric($parameter)) {
- if (strpos($parameter, ':') === 0) {
- $parameter = substr($parameter, 1);
- }
- }
- if (!in_array($parameter, $this->positions)) {
- return MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- 'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__);
- }
- $this->values[$parameter] = $value;
- if (null !== $type) {
- $this->types[$parameter] = $type;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ function bindValueArray($values, $types = null)
-
- /**
- * Set the values of multiple a parameter of a prepared query in bulk.
- *
- * @param array specifies all necessary information
- * for bindValue() the array elements must use keys corresponding to
- * the number of the position of the parameter.
- * @param array specifies the types of the fields
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- * @see bindParam()
- */
- function bindValueArray($values, $types = null)
- {
- $types = is_array($types) ? array_values($types) : array_fill(0, count($values), null);
- $parameters = array_keys($values);
- $this->db->pushErrorHandling(PEAR_ERROR_RETURN);
- $this->db->expectError(MDB2_ERROR_NOT_FOUND);
- foreach ($parameters as $key => $parameter) {
- $err = $this->bindValue($parameter, $values[$parameter], $types[$key]);
- if (MDB2::isError($err)) {
- if ($err->getCode() == MDB2_ERROR_NOT_FOUND) {
- //ignore (extra value for missing placeholder)
- continue;
- }
- $this->db->popExpect();
- $this->db->popErrorHandling();
- return $err;
- }
- }
- $this->db->popExpect();
- $this->db->popErrorHandling();
- return MDB2_OK;
- }
-
- // }}}
- // {{{ function bindParam($parameter, &$value, $type = null)
-
- /**
- * Bind a variable to a parameter of a prepared query.
- *
- * @param int the order number of the parameter in the query
- * statement. The order number of the first parameter is 1.
- * @param mixed variable that is meant to be bound to specified
- * parameter. The type of the value depends on the $type argument.
- * @param string specifies the type of the field
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- */
- function bindParam($parameter, &$value, $type = null)
- {
- if (!is_numeric($parameter)) {
- if (strpos($parameter, ':') === 0) {
- $parameter = substr($parameter, 1);
- }
- }
- if (!in_array($parameter, $this->positions)) {
- return MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- 'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__);
- }
- $this->values[$parameter] =& $value;
- if (null !== $type) {
- $this->types[$parameter] = $type;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ function bindParamArray(&$values, $types = null)
-
- /**
- * Bind the variables of multiple a parameter of a prepared query in bulk.
- *
- * @param array specifies all necessary information
- * for bindParam() the array elements must use keys corresponding to
- * the number of the position of the parameter.
- * @param array specifies the types of the fields
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- * @see bindParam()
- */
- function bindParamArray(&$values, $types = null)
- {
- $types = is_array($types) ? array_values($types) : array_fill(0, count($values), null);
- $parameters = array_keys($values);
- foreach ($parameters as $key => $parameter) {
- $err = $this->bindParam($parameter, $values[$parameter], $types[$key]);
- if (MDB2::isError($err)) {
- return $err;
- }
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ function &execute($values = null, $result_class = true, $result_wrap_class = false)
-
- /**
- * Execute a prepared query statement.
- *
- * @param array specifies all necessary information
- * for bindParam() the array elements must use keys corresponding
- * to the number of the position of the parameter.
- * @param mixed specifies which result class to use
- * @param mixed specifies which class to wrap results in
- *
- * @return mixed MDB2_Result or integer (affected rows) on success,
- * a MDB2 error on failure
- * @access public
- */
- function execute($values = null, $result_class = true, $result_wrap_class = false)
- {
- if (null === $this->positions) {
- return MDB2::raiseError(MDB2_ERROR, null, null,
- 'Prepared statement has already been freed', __FUNCTION__);
- }
-
- $values = (array)$values;
- if (!empty($values)) {
- $err = $this->bindValueArray($values);
- if (MDB2::isError($err)) {
- return MDB2::raiseError(MDB2_ERROR, null, null,
- 'Binding Values failed with message: ' . $err->getMessage(), __FUNCTION__);
- }
- }
- $result = $this->_execute($result_class, $result_wrap_class);
- return $result;
- }
-
- // }}}
- // {{{ function _execute($result_class = true, $result_wrap_class = false)
-
- /**
- * Execute a prepared query statement helper method.
- *
- * @param mixed specifies which result class to use
- * @param mixed specifies which class to wrap results in
- *
- * @return mixed MDB2_Result or integer (affected rows) on success,
- * a MDB2 error on failure
- * @access private
- */
- function _execute($result_class = true, $result_wrap_class = false)
- {
- $this->last_query = $this->query;
- $query = '';
- $last_position = 0;
- foreach ($this->positions as $current_position => $parameter) {
- if (!array_key_exists($parameter, $this->values)) {
- return MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- 'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__);
- }
- $value = $this->values[$parameter];
- $query.= substr($this->query, $last_position, $current_position - $last_position);
- if (!isset($value)) {
- $value_quoted = 'NULL';
- } else {
- $type = !empty($this->types[$parameter]) ? $this->types[$parameter] : null;
- $value_quoted = $this->db->quote($value, $type);
- if (MDB2::isError($value_quoted)) {
- return $value_quoted;
- }
- }
- $query.= $value_quoted;
- $last_position = $current_position + 1;
- }
- $query.= substr($this->query, $last_position);
-
- $this->db->offset = $this->offset;
- $this->db->limit = $this->limit;
- if ($this->is_manip) {
- $result = $this->db->exec($query);
- } else {
- $result = $this->db->query($query, $this->result_types, $result_class, $result_wrap_class);
- }
- return $result;
- }
-
- // }}}
- // {{{ function free()
-
- /**
- * Release resources allocated for the specified prepared query.
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- */
- function free()
- {
- if (null === $this->positions) {
- return MDB2::raiseError(MDB2_ERROR, null, null,
- 'Prepared statement has already been freed', __FUNCTION__);
- }
-
- $this->statement = null;
- $this->positions = null;
- $this->query = null;
- $this->types = null;
- $this->result_types = null;
- $this->limit = null;
- $this->is_manip = null;
- $this->offset = null;
- $this->values = null;
-
- return MDB2_OK;
- }
-
- // }}}
-}
-
-// }}}
-// {{{ class MDB2_Module_Common
-
-/**
- * The common modules class for MDB2 module objects
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_Module_Common
-{
- // {{{ Variables (Properties)
-
- /**
- * contains the key to the global MDB2 instance array of the associated
- * MDB2 instance
- *
- * @var int
- * @access protected
- */
- protected $db_index;
-
- // }}}
- // {{{ constructor: function __construct($db_index)
-
- /**
- * Constructor
- */
- function __construct($db_index)
- {
- $this->db_index = $db_index;
- }
-
- // }}}
- // {{{ function getDBInstance()
-
- /**
- * Get the instance of MDB2 associated with the module instance
- *
- * @return object MDB2 instance or a MDB2 error on failure
- *
- * @access public
- */
- function getDBInstance()
- {
- if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
- $result = $GLOBALS['_MDB2_databases'][$this->db_index];
- } else {
- $result = MDB2::raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- 'could not find MDB2 instance');
- }
- return $result;
- }
-
- // }}}
-}
-
-// }}}
-// {{{ function MDB2_closeOpenTransactions()
-
-/**
- * Close any open transactions form persistent connections
- *
- * @return void
- *
- * @access public
- */
-
-function MDB2_closeOpenTransactions()
-{
- reset($GLOBALS['_MDB2_databases']);
- while (next($GLOBALS['_MDB2_databases'])) {
- $key = key($GLOBALS['_MDB2_databases']);
- if ($GLOBALS['_MDB2_databases'][$key]->opened_persistent
- && $GLOBALS['_MDB2_databases'][$key]->in_transaction
- ) {
- $GLOBALS['_MDB2_databases'][$key]->rollback();
- }
- }
-}
-
-// }}}
-// {{{ function MDB2_defaultDebugOutput(&$db, $scope, $message, $is_manip = null)
-
-/**
- * default debug output handler
- *
- * @param object reference to an MDB2 database object
- * @param string usually the method name that triggered the debug call:
- * for example 'query', 'prepare', 'execute', 'parameters',
- * 'beginTransaction', 'commit', 'rollback'
- * @param string message that should be appended to the debug variable
- * @param array contains context information about the debug() call
- * common keys are: is_manip, time, result etc.
- *
- * @return void|string optionally return a modified message, this allows
- * rewriting a query before being issued or prepared
- *
- * @access public
- */
-function MDB2_defaultDebugOutput(&$db, $scope, $message, $context = array())
-{
- $db->debug_output.= $scope.'('.$db->db_index.'): ';
- $db->debug_output.= $message.$db->getOption('log_line_break');
- return $message;
-}
-
-// }}}
-?>
diff --git a/data/module/MDB2/Date.php b/data/module/MDB2/Date.php
deleted file mode 100644
index e867e48e5bc..00000000000
--- a/data/module/MDB2/Date.php
+++ /dev/null
@@ -1,183 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: Date.php 327316 2012-08-27 15:17:02Z danielc $
-//
-
-/**
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-
-/**
- * Several methods to convert the MDB2 native timestamp format (ISO based)
- * to and from data structures that are convenient to worth with in side of php.
- * For more complex date arithmetic please take a look at the Date package in PEAR
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_Date
-{
- // {{{ mdbNow()
-
- /**
- * return the current datetime
- *
- * @return string current datetime in the MDB2 format
- * @access public
- */
- public static function mdbNow()
- {
- return date('Y-m-d H:i:s');
- }
- // }}}
-
- // {{{ mdbToday()
-
- /**
- * return the current date
- *
- * @return string current date in the MDB2 format
- * @access public
- */
- public static function mdbToday()
- {
- return date('Y-m-d');
- }
- // }}}
-
- // {{{ mdbTime()
-
- /**
- * return the current time
- *
- * @return string current time in the MDB2 format
- * @access public
- */
- public static function mdbTime()
- {
- return date('H:i:s');
- }
- // }}}
-
- // {{{ date2Mdbstamp()
-
- /**
- * convert a date into a MDB2 timestamp
- *
- * @param int hour of the date
- * @param int minute of the date
- * @param int second of the date
- * @param int month of the date
- * @param int day of the date
- * @param int year of the date
- *
- * @return string a valid MDB2 timestamp
- * @access public
- */
- public static function date2Mdbstamp($hour = null, $minute = null, $second = null,
- $month = null, $day = null, $year = null)
- {
- return MDB2_Date::unix2Mdbstamp(mktime($hour, $minute, $second, $month, $day, $year, -1));
- }
- // }}}
-
- // {{{ unix2Mdbstamp()
-
- /**
- * convert a unix timestamp into a MDB2 timestamp
- *
- * @param int a valid unix timestamp
- *
- * @return string a valid MDB2 timestamp
- * @access public
- */
- public static function unix2Mdbstamp($unix_timestamp)
- {
- return date('Y-m-d H:i:s', $unix_timestamp);
- }
- // }}}
-
- // {{{ mdbstamp2Unix()
-
- /**
- * convert a MDB2 timestamp into a unix timestamp
- *
- * @param int a valid MDB2 timestamp
- * @return string unix timestamp with the time stored in the MDB2 format
- *
- * @access public
- */
- public static function mdbstamp2Unix($mdb_timestamp)
- {
- $arr = MDB2_Date::mdbstamp2Date($mdb_timestamp);
-
- return mktime($arr['hour'], $arr['minute'], $arr['second'], $arr['month'], $arr['day'], $arr['year'], -1);
- }
- // }}}
-
- // {{{ mdbstamp2Date()
-
- /**
- * convert a MDB2 timestamp into an array containing all
- * values necessary to pass to php's date() function
- *
- * @param int a valid MDB2 timestamp
- *
- * @return array with the time split
- * @access public
- */
- public static function mdbstamp2Date($mdb_timestamp)
- {
- list($arr['year'], $arr['month'], $arr['day'], $arr['hour'], $arr['minute'], $arr['second']) =
- sscanf($mdb_timestamp, "%04u-%02u-%02u %02u:%02u:%02u");
- return $arr;
- }
- // }}}
-}
-
-?>
diff --git a/data/module/MDB2/Driver/Datatype/Common.php b/data/module/MDB2/Driver/Datatype/Common.php
deleted file mode 100644
index a06e37ceafb..00000000000
--- a/data/module/MDB2/Driver/Datatype/Common.php
+++ /dev/null
@@ -1,1847 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: Common.php 328137 2012-10-25 02:26:35Z danielc $
-
-require_once 'MDB2/LOB.php';
-
-/**
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-
-/**
- * MDB2_Driver_Common: Base class that is extended by each MDB2 driver
- *
- * To load this module in the MDB2 object:
- * $mdb->loadModule('Datatype');
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_Driver_Datatype_Common extends MDB2_Module_Common
-{
- var $valid_default_values = array(
- 'text' => '',
- 'boolean' => true,
- 'integer' => 0,
- 'decimal' => 0.0,
- 'float' => 0.0,
- 'timestamp' => '1970-01-01 00:00:00',
- 'time' => '00:00:00',
- 'date' => '1970-01-01',
- 'clob' => '',
- 'blob' => '',
- );
-
- /**
- * contains all LOB objects created with this MDB2 instance
- * @var array
- * @access protected
- */
- var $lobs = array();
-
- // }}}
- // {{{ getValidTypes()
-
- /**
- * Get the list of valid types
- *
- * This function returns an array of valid types as keys with the values
- * being possible default values for all native datatypes and mapped types
- * for custom datatypes.
- *
- * @return mixed array on success, a MDB2 error on failure
- * @access public
- */
- function getValidTypes()
- {
- $types = $this->valid_default_values;
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
- if (!empty($db->options['datatype_map'])) {
- foreach ($db->options['datatype_map'] as $type => $mapped_type) {
- if (array_key_exists($mapped_type, $types)) {
- $types[$type] = $types[$mapped_type];
- } elseif (!empty($db->options['datatype_map_callback'][$type])) {
- $parameter = array('type' => $type, 'mapped_type' => $mapped_type);
- $default = call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
- $types[$type] = $default;
- }
- }
- }
- return $types;
- }
-
- // }}}
- // {{{ checkResultTypes()
-
- /**
- * Define the list of types to be associated with the columns of a given
- * result set.
- *
- * This function may be called before invoking fetchRow(), fetchOne()
- * fetchCole() and fetchAll() so that the necessary data type
- * conversions are performed on the data to be retrieved by them. If this
- * function is not called, the type of all result set columns is assumed
- * to be text, thus leading to not perform any conversions.
- *
- * @param array $types array variable that lists the
- * data types to be expected in the result set columns. If this array
- * contains less types than the number of columns that are returned
- * in the result set, the remaining columns are assumed to be of the
- * type text. Currently, the types clob and blob are not fully
- * supported.
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function checkResultTypes($types)
- {
- $types = is_array($types) ? $types : array($types);
- foreach ($types as $key => $type) {
- if (!isset($this->valid_default_values[$type])) {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
- if (empty($db->options['datatype_map'][$type])) {
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- $type.' for '.$key.' is not a supported column type', __FUNCTION__);
- }
- }
- }
- return $types;
- }
-
- // }}}
- // {{{ _baseConvertResult()
-
- /**
- * General type conversion method
- *
- * @param mixed $value reference to a value to be converted
- * @param string $type specifies which type to convert to
- * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
- * @return object an MDB2 error on failure
- * @access protected
- */
- function _baseConvertResult($value, $type, $rtrim = true)
- {
- switch ($type) {
- case 'text':
- if ($rtrim) {
- $value = rtrim($value);
- }
- return $value;
- case 'integer':
- return intval($value);
- case 'boolean':
- return !empty($value);
- case 'decimal':
- return $value;
- case 'float':
- return doubleval($value);
- case 'date':
- return $value;
- case 'time':
- return $value;
- case 'timestamp':
- return $value;
- case 'clob':
- case 'blob':
- $this->lobs[] = array(
- 'buffer' => null,
- 'position' => 0,
- 'lob_index' => null,
- 'endOfLOB' => false,
- 'resource' => $value,
- 'value' => null,
- 'loaded' => false,
- );
- end($this->lobs);
- $lob_index = key($this->lobs);
- $this->lobs[$lob_index]['lob_index'] = $lob_index;
- return fopen('MDB2LOB://'.$lob_index.'@'.$this->db_index, 'r+');
- }
-
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_INVALID, null, null,
- 'attempt to convert result value to an unknown type :' . $type, __FUNCTION__);
- }
-
- // }}}
- // {{{ convertResult()
-
- /**
- * Convert a value to a RDBMS indipendent MDB2 type
- *
- * @param mixed $value value to be converted
- * @param string $type specifies which type to convert to
- * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
- * @return mixed converted value
- * @access public
- */
- function convertResult($value, $type, $rtrim = true)
- {
- if (null === $value) {
- return null;
- }
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
- if (!empty($db->options['datatype_map'][$type])) {
- $type = $db->options['datatype_map'][$type];
- if (!empty($db->options['datatype_map_callback'][$type])) {
- $parameter = array('type' => $type, 'value' => $value, 'rtrim' => $rtrim);
- return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
- }
- }
- return $this->_baseConvertResult($value, $type, $rtrim);
- }
-
- // }}}
- // {{{ convertResultRow()
-
- /**
- * Convert a result row
- *
- * @param array $types
- * @param array $row specifies the types to convert to
- * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
- * @return mixed MDB2_OK on success, an MDB2 error on failure
- * @access public
- */
- function convertResultRow($types, $row, $rtrim = true)
- {
- //$types = $this->_sortResultFieldTypes(array_keys($row), $types);
- $keys = array_keys($row);
- if (is_int($keys[0])) {
- $types = $this->_sortResultFieldTypes($keys, $types);
- }
- foreach ($row as $key => $value) {
- if (empty($types[$key])) {
- continue;
- }
- $value = $this->convertResult($row[$key], $types[$key], $rtrim);
- if (MDB2::isError($value)) {
- return $value;
- }
- $row[$key] = $value;
- }
- return $row;
- }
-
- // }}}
- // {{{ _sortResultFieldTypes()
-
- /**
- * convert a result row
- *
- * @param array $types
- * @param array $row specifies the types to convert to
- * @param bool $rtrim if to rtrim text values or not
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function _sortResultFieldTypes($columns, $types)
- {
- $n_cols = count($columns);
- $n_types = count($types);
- if ($n_cols > $n_types) {
- for ($i= $n_cols - $n_types; $i >= 0; $i--) {
- $types[] = null;
- }
- }
- $sorted_types = array();
- foreach ($columns as $col) {
- $sorted_types[$col] = null;
- }
- foreach ($types as $name => $type) {
- if (array_key_exists($name, $sorted_types)) {
- $sorted_types[$name] = $type;
- unset($types[$name]);
- }
- }
- // if there are left types in the array, fill the null values of the
- // sorted array with them, in order.
- if (count($types)) {
- reset($types);
- foreach (array_keys($sorted_types) as $k) {
- if (null === $sorted_types[$k]) {
- $sorted_types[$k] = current($types);
- next($types);
- }
- }
- }
- return $sorted_types;
- }
-
- // }}}
- // {{{ getDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to declare
- * of the given type
- *
- * @param string $type type to which the value should be converted to
- * @param string $name name the field to be declared.
- * @param string $field definition of the field
- * @return string DBMS specific SQL code portion that should be used to
- * declare the specified field.
- * @access public
- */
- function getDeclaration($type, $name, $field)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- if (!empty($db->options['datatype_map'][$type])) {
- $type = $db->options['datatype_map'][$type];
- if (!empty($db->options['datatype_map_callback'][$type])) {
- $parameter = array('type' => $type, 'name' => $name, 'field' => $field);
- return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
- }
- $field['type'] = $type;
- }
-
- if (!method_exists($this, "_get{$type}Declaration")) {
- return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- 'type not defined: '.$type, __FUNCTION__);
- }
- return $this->{"_get{$type}Declaration"}($name, $field);
- }
-
- // }}}
- // {{{ getTypeDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to declare an text type
- * field to be used in statements like CREATE TABLE.
- *
- * @param array $field associative array with the name of the properties
- * of the field being declared as array indexes. Currently, the types
- * of supported field properties are as follows:
- *
- * length
- * Integer value that determines the maximum length of the text
- * field. If this argument is missing the field should be
- * declared to have the longest length allowed by the DBMS.
- *
- * default
- * Text value to be used as default for this field.
- *
- * notnull
- * Boolean flag that indicates whether this field is constrained
- * to not be set to null.
- * @return string DBMS specific SQL code portion that should be used to
- * declare the specified field.
- * @access public
- */
- function getTypeDeclaration($field)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- switch ($field['type']) {
- case 'text':
- $length = !empty($field['length']) ? $field['length'] : $db->options['default_text_field_length'];
- $fixed = !empty($field['fixed']) ? $field['fixed'] : false;
- return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')')
- : ($length ? 'VARCHAR('.$length.')' : 'TEXT');
- case 'clob':
- return 'TEXT';
- case 'blob':
- return 'TEXT';
- case 'integer':
- return 'INT';
- case 'boolean':
- return 'INT';
- case 'date':
- return 'CHAR ('.strlen('YYYY-MM-DD').')';
- case 'time':
- return 'CHAR ('.strlen('HH:MM:SS').')';
- case 'timestamp':
- return 'CHAR ('.strlen('YYYY-MM-DD HH:MM:SS').')';
- case 'float':
- return 'TEXT';
- case 'decimal':
- return 'TEXT';
- }
- return '';
- }
-
- // }}}
- // {{{ _getDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to declare a generic type
- * field to be used in statements like CREATE TABLE.
- *
- * @param string $name name the field to be declared.
- * @param array $field associative array with the name of the properties
- * of the field being declared as array indexes. Currently, the types
- * of supported field properties are as follows:
- *
- * length
- * Integer value that determines the maximum length of the text
- * field. If this argument is missing the field should be
- * declared to have the longest length allowed by the DBMS.
- *
- * default
- * Text value to be used as default for this field.
- *
- * notnull
- * Boolean flag that indicates whether this field is constrained
- * to not be set to null.
- * charset
- * Text value with the default CHARACTER SET for this field.
- * collation
- * Text value with the default COLLATION for this field.
- * @return string DBMS specific SQL code portion that should be used to
- * declare the specified field, or a MDB2_Error on failure
- * @access protected
- */
- function _getDeclaration($name, $field)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $name = $db->quoteIdentifier($name, true);
- $declaration_options = $db->datatype->_getDeclarationOptions($field);
- if (MDB2::isError($declaration_options)) {
- return $declaration_options;
- }
- return $name.' '.$this->getTypeDeclaration($field).$declaration_options;
- }
-
- // }}}
- // {{{ _getDeclarationOptions()
-
- /**
- * Obtain DBMS specific SQL code portion needed to declare a generic type
- * field to be used in statement like CREATE TABLE, without the field name
- * and type values (ie. just the character set, default value, if the
- * field is permitted to be NULL or not, and the collation options).
- *
- * @param array $field associative array with the name of the properties
- * of the field being declared as array indexes. Currently, the types
- * of supported field properties are as follows:
- *
- * default
- * Text value to be used as default for this field.
- * notnull
- * Boolean flag that indicates whether this field is constrained
- * to not be set to null.
- * charset
- * Text value with the default CHARACTER SET for this field.
- * collation
- * Text value with the default COLLATION for this field.
- * @return string DBMS specific SQL code portion that should be used to
- * declare the specified field's options.
- * @access protected
- */
- function _getDeclarationOptions($field)
- {
- $charset = empty($field['charset']) ? '' :
- ' '.$this->_getCharsetFieldDeclaration($field['charset']);
-
- $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
- $default = '';
- if (array_key_exists('default', $field)) {
- if ($field['default'] === '') {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
- $valid_default_values = $this->getValidTypes();
- $field['default'] = $valid_default_values[$field['type']];
- if ($field['default'] === '' && ($db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL)) {
- $field['default'] = ' ';
- }
- }
- if (null !== $field['default']) {
- $default = ' DEFAULT ' . $this->quote($field['default'], $field['type']);
- }
- }
-
- $collation = empty($field['collation']) ? '' :
- ' '.$this->_getCollationFieldDeclaration($field['collation']);
-
- return $charset.$default.$notnull.$collation;
- }
-
- // }}}
- // {{{ _getCharsetFieldDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET
- * of a field declaration to be used in statements like CREATE TABLE.
- *
- * @param string $charset name of the charset
- * @return string DBMS specific SQL code portion needed to set the CHARACTER SET
- * of a field declaration.
- */
- function _getCharsetFieldDeclaration($charset)
- {
- return '';
- }
-
- // }}}
- // {{{ _getCollationFieldDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to set the COLLATION
- * of a field declaration to be used in statements like CREATE TABLE.
- *
- * @param string $collation name of the collation
- * @return string DBMS specific SQL code portion needed to set the COLLATION
- * of a field declaration.
- */
- function _getCollationFieldDeclaration($collation)
- {
- return '';
- }
-
- // }}}
- // {{{ _getIntegerDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to declare an integer type
- * field to be used in statements like CREATE TABLE.
- *
- * @param string $name name the field to be declared.
- * @param array $field associative array with the name of the properties
- * of the field being declared as array indexes. Currently, the types
- * of supported field properties are as follows:
- *
- * unsigned
- * Boolean flag that indicates whether the field should be
- * declared as unsigned integer if possible.
- *
- * default
- * Integer value to be used as default for this field.
- *
- * notnull
- * Boolean flag that indicates whether this field is constrained
- * to not be set to null.
- * @return string DBMS specific SQL code portion that should be used to
- * declare the specified field.
- * @access protected
- */
- function _getIntegerDeclaration($name, $field)
- {
- if (!empty($field['unsigned'])) {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer";
- }
- return $this->_getDeclaration($name, $field);
- }
-
- // }}}
- // {{{ _getTextDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to declare an text type
- * field to be used in statements like CREATE TABLE.
- *
- * @param string $name name the field to be declared.
- * @param array $field associative array with the name of the properties
- * of the field being declared as array indexes. Currently, the types
- * of supported field properties are as follows:
- *
- * length
- * Integer value that determines the maximum length of the text
- * field. If this argument is missing the field should be
- * declared to have the longest length allowed by the DBMS.
- *
- * default
- * Text value to be used as default for this field.
- *
- * notnull
- * Boolean flag that indicates whether this field is constrained
- * to not be set to null.
- * @return string DBMS specific SQL code portion that should be used to
- * declare the specified field.
- * @access protected
- */
- function _getTextDeclaration($name, $field)
- {
- return $this->_getDeclaration($name, $field);
- }
-
- // }}}
- // {{{ _getCLOBDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to declare an character
- * large object type field to be used in statements like CREATE TABLE.
- *
- * @param string $name name the field to be declared.
- * @param array $field associative array with the name of the properties
- * of the field being declared as array indexes. Currently, the types
- * of supported field properties are as follows:
- *
- * length
- * Integer value that determines the maximum length of the large
- * object field. If this argument is missing the field should be
- * declared to have the longest length allowed by the DBMS.
- *
- * notnull
- * Boolean flag that indicates whether this field is constrained
- * to not be set to null.
- * @return string DBMS specific SQL code portion that should be used to
- * declare the specified field.
- * @access public
- */
- function _getCLOBDeclaration($name, $field)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
- $name = $db->quoteIdentifier($name, true);
- return $name.' '.$this->getTypeDeclaration($field).$notnull;
- }
-
- // }}}
- // {{{ _getBLOBDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to declare an binary large
- * object type field to be used in statements like CREATE TABLE.
- *
- * @param string $name name the field to be declared.
- * @param array $field associative array with the name of the properties
- * of the field being declared as array indexes. Currently, the types
- * of supported field properties are as follows:
- *
- * length
- * Integer value that determines the maximum length of the large
- * object field. If this argument is missing the field should be
- * declared to have the longest length allowed by the DBMS.
- *
- * notnull
- * Boolean flag that indicates whether this field is constrained
- * to not be set to null.
- * @return string DBMS specific SQL code portion that should be used to
- * declare the specified field.
- * @access protected
- */
- function _getBLOBDeclaration($name, $field)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
- $name = $db->quoteIdentifier($name, true);
- return $name.' '.$this->getTypeDeclaration($field).$notnull;
- }
-
- // }}}
- // {{{ _getBooleanDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to declare a boolean type
- * field to be used in statements like CREATE TABLE.
- *
- * @param string $name name the field to be declared.
- * @param array $field associative array with the name of the properties
- * of the field being declared as array indexes. Currently, the types
- * of supported field properties are as follows:
- *
- * default
- * Boolean value to be used as default for this field.
- *
- * notnullL
- * Boolean flag that indicates whether this field is constrained
- * to not be set to null.
- * @return string DBMS specific SQL code portion that should be used to
- * declare the specified field.
- * @access protected
- */
- function _getBooleanDeclaration($name, $field)
- {
- return $this->_getDeclaration($name, $field);
- }
-
- // }}}
- // {{{ _getDateDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to declare a date type
- * field to be used in statements like CREATE TABLE.
- *
- * @param string $name name the field to be declared.
- * @param array $field associative array with the name of the properties
- * of the field being declared as array indexes. Currently, the types
- * of supported field properties are as follows:
- *
- * default
- * Date value to be used as default for this field.
- *
- * notnull
- * Boolean flag that indicates whether this field is constrained
- * to not be set to null.
- * @return string DBMS specific SQL code portion that should be used to
- * declare the specified field.
- * @access protected
- */
- function _getDateDeclaration($name, $field)
- {
- return $this->_getDeclaration($name, $field);
- }
-
- // }}}
- // {{{ _getTimestampDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to declare a timestamp
- * field to be used in statements like CREATE TABLE.
- *
- * @param string $name name the field to be declared.
- * @param array $field associative array with the name of the properties
- * of the field being declared as array indexes. Currently, the types
- * of supported field properties are as follows:
- *
- * default
- * Timestamp value to be used as default for this field.
- *
- * notnull
- * Boolean flag that indicates whether this field is constrained
- * to not be set to null.
- * @return string DBMS specific SQL code portion that should be used to
- * declare the specified field.
- * @access protected
- */
- function _getTimestampDeclaration($name, $field)
- {
- return $this->_getDeclaration($name, $field);
- }
-
- // }}}
- // {{{ _getTimeDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to declare a time
- * field to be used in statements like CREATE TABLE.
- *
- * @param string $name name the field to be declared.
- * @param array $field associative array with the name of the properties
- * of the field being declared as array indexes. Currently, the types
- * of supported field properties are as follows:
- *
- * default
- * Time value to be used as default for this field.
- *
- * notnull
- * Boolean flag that indicates whether this field is constrained
- * to not be set to null.
- * @return string DBMS specific SQL code portion that should be used to
- * declare the specified field.
- * @access protected
- */
- function _getTimeDeclaration($name, $field)
- {
- return $this->_getDeclaration($name, $field);
- }
-
- // }}}
- // {{{ _getFloatDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to declare a float type
- * field to be used in statements like CREATE TABLE.
- *
- * @param string $name name the field to be declared.
- * @param array $field associative array with the name of the properties
- * of the field being declared as array indexes. Currently, the types
- * of supported field properties are as follows:
- *
- * default
- * Float value to be used as default for this field.
- *
- * notnull
- * Boolean flag that indicates whether this field is constrained
- * to not be set to null.
- * @return string DBMS specific SQL code portion that should be used to
- * declare the specified field.
- * @access protected
- */
- function _getFloatDeclaration($name, $field)
- {
- return $this->_getDeclaration($name, $field);
- }
-
- // }}}
- // {{{ _getDecimalDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to declare a decimal type
- * field to be used in statements like CREATE TABLE.
- *
- * @param string $name name the field to be declared.
- * @param array $field associative array with the name of the properties
- * of the field being declared as array indexes. Currently, the types
- * of supported field properties are as follows:
- *
- * default
- * Decimal value to be used as default for this field.
- *
- * notnull
- * Boolean flag that indicates whether this field is constrained
- * to not be set to null.
- * @return string DBMS specific SQL code portion that should be used to
- * declare the specified field.
- * @access protected
- */
- function _getDecimalDeclaration($name, $field)
- {
- return $this->_getDeclaration($name, $field);
- }
-
- // }}}
- // {{{ compareDefinition()
-
- /**
- * Obtain an array of changes that may need to applied
- *
- * @param array $current new definition
- * @param array $previous old definition
- * @return array containing all changes that will need to be applied
- * @access public
- */
- function compareDefinition($current, $previous)
- {
- $type = !empty($current['type']) ? $current['type'] : null;
-
- if (!method_exists($this, "_compare{$type}Definition")) {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
- if (!empty($db->options['datatype_map_callback'][$type])) {
- $parameter = array('current' => $current, 'previous' => $previous);
- $change = call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
- return $change;
- }
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'type "'.$current['type'].'" is not yet supported', __FUNCTION__);
- }
-
- if (empty($previous['type']) || $previous['type'] != $type) {
- return $current;
- }
-
- $change = $this->{"_compare{$type}Definition"}($current, $previous);
-
- if ($previous['type'] != $type) {
- $change['type'] = true;
- }
-
- $previous_notnull = !empty($previous['notnull']) ? $previous['notnull'] : false;
- $notnull = !empty($current['notnull']) ? $current['notnull'] : false;
- if ($previous_notnull != $notnull) {
- $change['notnull'] = true;
- }
-
- $previous_default = array_key_exists('default', $previous) ? $previous['default'] :
- null;
- $default = array_key_exists('default', $current) ? $current['default'] :
- null;
- if ($previous_default !== $default) {
- $change['default'] = true;
- }
-
- return $change;
- }
-
- // }}}
- // {{{ _compareIntegerDefinition()
-
- /**
- * Obtain an array of changes that may need to applied to an integer field
- *
- * @param array $current new definition
- * @param array $previous old definition
- * @return array containing all changes that will need to be applied
- * @access protected
- */
- function _compareIntegerDefinition($current, $previous)
- {
- $change = array();
- $previous_length = !empty($previous['length']) ? $previous['length'] : 4;
- $length = !empty($current['length']) ? $current['length'] : 4;
- if ($previous_length != $length) {
- $change['length'] = $length;
- }
- $previous_unsigned = !empty($previous['unsigned']) ? $previous['unsigned'] : false;
- $unsigned = !empty($current['unsigned']) ? $current['unsigned'] : false;
- if ($previous_unsigned != $unsigned) {
- $change['unsigned'] = true;
- }
- $previous_autoincrement = !empty($previous['autoincrement']) ? $previous['autoincrement'] : false;
- $autoincrement = !empty($current['autoincrement']) ? $current['autoincrement'] : false;
- if ($previous_autoincrement != $autoincrement) {
- $change['autoincrement'] = true;
- }
- return $change;
- }
-
- // }}}
- // {{{ _compareTextDefinition()
-
- /**
- * Obtain an array of changes that may need to applied to an text field
- *
- * @param array $current new definition
- * @param array $previous old definition
- * @return array containing all changes that will need to be applied
- * @access protected
- */
- function _compareTextDefinition($current, $previous)
- {
- $change = array();
- $previous_length = !empty($previous['length']) ? $previous['length'] : 0;
- $length = !empty($current['length']) ? $current['length'] : 0;
- if ($previous_length != $length) {
- $change['length'] = true;
- }
- $previous_fixed = !empty($previous['fixed']) ? $previous['fixed'] : 0;
- $fixed = !empty($current['fixed']) ? $current['fixed'] : 0;
- if ($previous_fixed != $fixed) {
- $change['fixed'] = true;
- }
- return $change;
- }
-
- // }}}
- // {{{ _compareCLOBDefinition()
-
- /**
- * Obtain an array of changes that may need to applied to an CLOB field
- *
- * @param array $current new definition
- * @param array $previous old definition
- * @return array containing all changes that will need to be applied
- * @access protected
- */
- function _compareCLOBDefinition($current, $previous)
- {
- return $this->_compareTextDefinition($current, $previous);
- }
-
- // }}}
- // {{{ _compareBLOBDefinition()
-
- /**
- * Obtain an array of changes that may need to applied to an BLOB field
- *
- * @param array $current new definition
- * @param array $previous old definition
- * @return array containing all changes that will need to be applied
- * @access protected
- */
- function _compareBLOBDefinition($current, $previous)
- {
- return $this->_compareTextDefinition($current, $previous);
- }
-
- // }}}
- // {{{ _compareDateDefinition()
-
- /**
- * Obtain an array of changes that may need to applied to an date field
- *
- * @param array $current new definition
- * @param array $previous old definition
- * @return array containing all changes that will need to be applied
- * @access protected
- */
- function _compareDateDefinition($current, $previous)
- {
- return array();
- }
-
- // }}}
- // {{{ _compareTimeDefinition()
-
- /**
- * Obtain an array of changes that may need to applied to an time field
- *
- * @param array $current new definition
- * @param array $previous old definition
- * @return array containing all changes that will need to be applied
- * @access protected
- */
- function _compareTimeDefinition($current, $previous)
- {
- return array();
- }
-
- // }}}
- // {{{ _compareTimestampDefinition()
-
- /**
- * Obtain an array of changes that may need to applied to an timestamp field
- *
- * @param array $current new definition
- * @param array $previous old definition
- * @return array containing all changes that will need to be applied
- * @access protected
- */
- function _compareTimestampDefinition($current, $previous)
- {
- return array();
- }
-
- // }}}
- // {{{ _compareBooleanDefinition()
-
- /**
- * Obtain an array of changes that may need to applied to an boolean field
- *
- * @param array $current new definition
- * @param array $previous old definition
- * @return array containing all changes that will need to be applied
- * @access protected
- */
- function _compareBooleanDefinition($current, $previous)
- {
- return array();
- }
-
- // }}}
- // {{{ _compareFloatDefinition()
-
- /**
- * Obtain an array of changes that may need to applied to an float field
- *
- * @param array $current new definition
- * @param array $previous old definition
- * @return array containing all changes that will need to be applied
- * @access protected
- */
- function _compareFloatDefinition($current, $previous)
- {
- return array();
- }
-
- // }}}
- // {{{ _compareDecimalDefinition()
-
- /**
- * Obtain an array of changes that may need to applied to an decimal field
- *
- * @param array $current new definition
- * @param array $previous old definition
- * @return array containing all changes that will need to be applied
- * @access protected
- */
- function _compareDecimalDefinition($current, $previous)
- {
- return array();
- }
-
- // }}}
- // {{{ quote()
-
- /**
- * Convert a text value into a DBMS specific format that is suitable to
- * compose query statements.
- *
- * @param string $value text string value that is intended to be converted.
- * @param string $type type to which the value should be converted to
- * @param bool $quote determines if the value should be quoted and escaped
- * @param bool $escape_wildcards if to escape escape wildcards
- * @return string text string that represents the given argument value in
- * a DBMS specific format.
- * @access public
- */
- function quote($value, $type = null, $quote = true, $escape_wildcards = false)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- if ((null === $value)
- || ($value === '' && $db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL)
- ) {
- if (!$quote) {
- return null;
- }
- return 'NULL';
- }
-
- if (null === $type) {
- switch (gettype($value)) {
- case 'integer':
- $type = 'integer';
- break;
- case 'double':
- // todo: default to decimal as float is quite unusual
- // $type = 'float';
- $type = 'decimal';
- break;
- case 'boolean':
- $type = 'boolean';
- break;
- case 'array':
- $value = serialize($value);
- case 'object':
- $type = 'text';
- break;
- default:
- if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/', $value)) {
- $type = 'timestamp';
- } elseif (preg_match('/^\d{2}:\d{2}$/', $value)) {
- $type = 'time';
- } elseif (preg_match('/^\d{4}-\d{2}-\d{2}$/', $value)) {
- $type = 'date';
- } else {
- $type = 'text';
- }
- break;
- }
- } elseif (!empty($db->options['datatype_map'][$type])) {
- $type = $db->options['datatype_map'][$type];
- if (!empty($db->options['datatype_map_callback'][$type])) {
- $parameter = array('type' => $type, 'value' => $value, 'quote' => $quote, 'escape_wildcards' => $escape_wildcards);
- return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
- }
- }
-
- if (!method_exists($this, "_quote{$type}")) {
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'type not defined: '.$type, __FUNCTION__);
- }
- $value = $this->{"_quote{$type}"}($value, $quote, $escape_wildcards);
- if ($quote && $escape_wildcards && $db->string_quoting['escape_pattern']
- && $db->string_quoting['escape'] !== $db->string_quoting['escape_pattern']
- ) {
- $value.= $this->patternEscapeString();
- }
- return $value;
- }
-
- // }}}
- // {{{ _quoteInteger()
-
- /**
- * Convert a text value into a DBMS specific format that is suitable to
- * compose query statements.
- *
- * @param string $value text string value that is intended to be converted.
- * @param bool $quote determines if the value should be quoted and escaped
- * @param bool $escape_wildcards if to escape escape wildcards
- * @return string text string that represents the given argument value in
- * a DBMS specific format.
- * @access protected
- */
- function _quoteInteger($value, $quote, $escape_wildcards)
- {
- return (int)$value;
- }
-
- // }}}
- // {{{ _quoteText()
-
- /**
- * Convert a text value into a DBMS specific format that is suitable to
- * compose query statements.
- *
- * @param string $value text string value that is intended to be converted.
- * @param bool $quote determines if the value should be quoted and escaped
- * @param bool $escape_wildcards if to escape escape wildcards
- * @return string text string that already contains any DBMS specific
- * escaped character sequences.
- * @access protected
- */
- function _quoteText($value, $quote, $escape_wildcards)
- {
- if (!$quote) {
- return $value;
- }
-
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $value = $db->escape($value, $escape_wildcards);
- if (MDB2::isError($value)) {
- return $value;
- }
- return "'".$value."'";
- }
-
- // }}}
- // {{{ _readFile()
-
- /**
- * Convert a text value into a DBMS specific format that is suitable to
- * compose query statements.
- *
- * @param string $value text string value that is intended to be converted.
- * @return string text string that represents the given argument value in
- * a DBMS specific format.
- * @access protected
- */
- function _readFile($value)
- {
- $close = false;
- if (preg_match('/^(\w+:\/\/)(.*)$/', $value, $match)) {
- $close = true;
- if (strtolower($match[1]) == 'file://') {
- $value = $match[2];
- }
- $value = @fopen($value, 'r');
- }
-
- if (is_resource($value)) {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $fp = $value;
- $value = '';
- while (!@feof($fp)) {
- $value.= @fread($fp, $db->options['lob_buffer_length']);
- }
- if ($close) {
- @fclose($fp);
- }
- }
-
- return $value;
- }
-
- // }}}
- // {{{ _quoteLOB()
-
- /**
- * Convert a text value into a DBMS specific format that is suitable to
- * compose query statements.
- *
- * @param string $value text string value that is intended to be converted.
- * @param bool $quote determines if the value should be quoted and escaped
- * @param bool $escape_wildcards if to escape escape wildcards
- * @return string text string that represents the given argument value in
- * a DBMS specific format.
- * @access protected
- */
- function _quoteLOB($value, $quote, $escape_wildcards)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
- if ($db->options['lob_allow_url_include']) {
- $value = $this->_readFile($value);
- if (MDB2::isError($value)) {
- return $value;
- }
- }
- return $this->_quoteText($value, $quote, $escape_wildcards);
- }
-
- // }}}
- // {{{ _quoteCLOB()
-
- /**
- * Convert a text value into a DBMS specific format that is suitable to
- * compose query statements.
- *
- * @param string $value text string value that is intended to be converted.
- * @param bool $quote determines if the value should be quoted and escaped
- * @param bool $escape_wildcards if to escape escape wildcards
- * @return string text string that represents the given argument value in
- * a DBMS specific format.
- * @access protected
- */
- function _quoteCLOB($value, $quote, $escape_wildcards)
- {
- return $this->_quoteLOB($value, $quote, $escape_wildcards);
- }
-
- // }}}
- // {{{ _quoteBLOB()
-
- /**
- * Convert a text value into a DBMS specific format that is suitable to
- * compose query statements.
- *
- * @param string $value text string value that is intended to be converted.
- * @param bool $quote determines if the value should be quoted and escaped
- * @param bool $escape_wildcards if to escape escape wildcards
- * @return string text string that represents the given argument value in
- * a DBMS specific format.
- * @access protected
- */
- function _quoteBLOB($value, $quote, $escape_wildcards)
- {
- return $this->_quoteLOB($value, $quote, $escape_wildcards);
- }
-
- // }}}
- // {{{ _quoteBoolean()
-
- /**
- * Convert a text value into a DBMS specific format that is suitable to
- * compose query statements.
- *
- * @param string $value text string value that is intended to be converted.
- * @param bool $quote determines if the value should be quoted and escaped
- * @param bool $escape_wildcards if to escape escape wildcards
- * @return string text string that represents the given argument value in
- * a DBMS specific format.
- * @access protected
- */
- function _quoteBoolean($value, $quote, $escape_wildcards)
- {
- return ($value ? 1 : 0);
- }
-
- // }}}
- // {{{ _quoteDate()
-
- /**
- * Convert a text value into a DBMS specific format that is suitable to
- * compose query statements.
- *
- * @param string $value text string value that is intended to be converted.
- * @param bool $quote determines if the value should be quoted and escaped
- * @param bool $escape_wildcards if to escape escape wildcards
- * @return string text string that represents the given argument value in
- * a DBMS specific format.
- * @access protected
- */
- function _quoteDate($value, $quote, $escape_wildcards)
- {
- if ($value === 'CURRENT_DATE') {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
- if (isset($db->function) && is_object($this->function) && is_a($db->function, 'MDB2_Driver_Function_Common')) {
- return $db->function->now('date');
- }
- return 'CURRENT_DATE';
- }
- return $this->_quoteText($value, $quote, $escape_wildcards);
- }
-
- // }}}
- // {{{ _quoteTimestamp()
-
- /**
- * Convert a text value into a DBMS specific format that is suitable to
- * compose query statements.
- *
- * @param string $value text string value that is intended to be converted.
- * @param bool $quote determines if the value should be quoted and escaped
- * @param bool $escape_wildcards if to escape escape wildcards
- * @return string text string that represents the given argument value in
- * a DBMS specific format.
- * @access protected
- */
- function _quoteTimestamp($value, $quote, $escape_wildcards)
- {
- if ($value === 'CURRENT_TIMESTAMP') {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
- if (isset($db->function) && is_object($db->function) && is_a($db->function, 'MDB2_Driver_Function_Common')) {
- return $db->function->now('timestamp');
- }
- return 'CURRENT_TIMESTAMP';
- }
- return $this->_quoteText($value, $quote, $escape_wildcards);
- }
-
- // }}}
- // {{{ _quoteTime()
-
- /**
- * Convert a text value into a DBMS specific format that is suitable to
- * compose query statements.
- *
- * @param string $value text string value that is intended to be converted.
- * @param bool $quote determines if the value should be quoted and escaped
- * @param bool $escape_wildcards if to escape escape wildcards
- * @return string text string that represents the given argument value in
- * a DBMS specific format.
- * @access protected
- */
- function _quoteTime($value, $quote, $escape_wildcards)
- {
- if ($value === 'CURRENT_TIME') {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
- if (isset($db->function) && is_object($this->function) && is_a($db->function, 'MDB2_Driver_Function_Common')) {
- return $db->function->now('time');
- }
- return 'CURRENT_TIME';
- }
- return $this->_quoteText($value, $quote, $escape_wildcards);
- }
-
- // }}}
- // {{{ _quoteFloat()
-
- /**
- * Convert a text value into a DBMS specific format that is suitable to
- * compose query statements.
- *
- * @param string $value text string value that is intended to be converted.
- * @param bool $quote determines if the value should be quoted and escaped
- * @param bool $escape_wildcards if to escape escape wildcards
- * @return string text string that represents the given argument value in
- * a DBMS specific format.
- * @access protected
- */
- function _quoteFloat($value, $quote, $escape_wildcards)
- {
- if (preg_match('/^(.*)e([-+])(\d+)$/i', $value, $matches)) {
- $decimal = $this->_quoteDecimal($matches[1], $quote, $escape_wildcards);
- $sign = $matches[2];
- $exponent = str_pad($matches[3], 2, '0', STR_PAD_LEFT);
- $value = $decimal.'E'.$sign.$exponent;
- } else {
- $value = $this->_quoteDecimal($value, $quote, $escape_wildcards);
- }
- return $value;
- }
-
- // }}}
- // {{{ _quoteDecimal()
-
- /**
- * Convert a text value into a DBMS specific format that is suitable to
- * compose query statements.
- *
- * @param string $value text string value that is intended to be converted.
- * @param bool $quote determines if the value should be quoted and escaped
- * @param bool $escape_wildcards if to escape escape wildcards
- * @return string text string that represents the given argument value in
- * a DBMS specific format.
- * @access protected
- */
- function _quoteDecimal($value, $quote, $escape_wildcards)
- {
- $value = (string)$value;
- $value = preg_replace('/[^\d\.,\-+eE]/', '', $value);
- if (preg_match('/[^\.\d]/', $value)) {
- if (strpos($value, ',')) {
- // 1000,00
- if (!strpos($value, '.')) {
- // convert the last "," to a "."
- $value = strrev(str_replace(',', '.', strrev($value)));
- // 1.000,00
- } elseif (strpos($value, '.') && strpos($value, '.') < strpos($value, ',')) {
- $value = str_replace('.', '', $value);
- // convert the last "," to a "."
- $value = strrev(str_replace(',', '.', strrev($value)));
- // 1,000.00
- } else {
- $value = str_replace(',', '', $value);
- }
- }
- }
- return $value;
- }
-
- // }}}
- // {{{ writeLOBToFile()
-
- /**
- * retrieve LOB from the database
- *
- * @param resource $lob stream handle
- * @param string $file name of the file into which the LOb should be fetched
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access protected
- */
- function writeLOBToFile($lob, $file)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- if (preg_match('/^(\w+:\/\/)(.*)$/', $file, $match)) {
- if ($match[1] == 'file://') {
- $file = $match[2];
- }
- }
-
- $fp = @fopen($file, 'wb');
- while (!@feof($lob)) {
- $result = @fread($lob, $db->options['lob_buffer_length']);
- $read = strlen($result);
- if (@fwrite($fp, $result, $read) != $read) {
- @fclose($fp);
- return $db->raiseError(MDB2_ERROR, null, null,
- 'could not write to the output file', __FUNCTION__);
- }
- }
- @fclose($fp);
- return MDB2_OK;
- }
-
- // }}}
- // {{{ _retrieveLOB()
-
- /**
- * retrieve LOB from the database
- *
- * @param array $lob array
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access protected
- */
- function _retrieveLOB(&$lob)
- {
- if (null === $lob['value']) {
- $lob['value'] = $lob['resource'];
- }
- $lob['loaded'] = true;
- return MDB2_OK;
- }
-
- // }}}
- // {{{ readLOB()
-
- /**
- * Read data from large object input stream.
- *
- * @param resource $lob stream handle
- * @param string $data reference to a variable that will hold data
- * to be read from the large object input stream
- * @param integer $length value that indicates the largest ammount ofdata
- * to be read from the large object input stream.
- * @return mixed the effective number of bytes read from the large object
- * input stream on sucess or an MDB2 error object.
- * @access public
- * @see endOfLOB()
- */
- function _readLOB($lob, $length)
- {
- return substr($lob['value'], $lob['position'], $length);
- }
-
- // }}}
- // {{{ _endOfLOB()
-
- /**
- * Determine whether it was reached the end of the large object and
- * therefore there is no more data to be read for the its input stream.
- *
- * @param array $lob array
- * @return mixed true or false on success, a MDB2 error on failure
- * @access protected
- */
- function _endOfLOB($lob)
- {
- return $lob['endOfLOB'];
- }
-
- // }}}
- // {{{ destroyLOB()
-
- /**
- * Free any resources allocated during the lifetime of the large object
- * handler object.
- *
- * @param resource $lob stream handle
- * @access public
- */
- function destroyLOB($lob)
- {
- $lob_data = stream_get_meta_data($lob);
- $lob_index = $lob_data['wrapper_data']->lob_index;
- fclose($lob);
- if (isset($this->lobs[$lob_index])) {
- $this->_destroyLOB($this->lobs[$lob_index]);
- unset($this->lobs[$lob_index]);
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ _destroyLOB()
-
- /**
- * Free any resources allocated during the lifetime of the large object
- * handler object.
- *
- * @param array $lob array
- * @access private
- */
- function _destroyLOB(&$lob)
- {
- return MDB2_OK;
- }
-
- // }}}
- // {{{ implodeArray()
-
- /**
- * apply a type to all values of an array and return as a comma seperated string
- * useful for generating IN statements
- *
- * @access public
- *
- * @param array $array data array
- * @param string $type determines type of the field
- *
- * @return string comma seperated values
- */
- function implodeArray($array, $type = false)
- {
- if (!is_array($array) || empty($array)) {
- return 'NULL';
- }
- if ($type) {
- foreach ($array as $value) {
- $return[] = $this->quote($value, $type);
- }
- } else {
- $return = $array;
- }
- return implode(', ', $return);
- }
-
- // }}}
- // {{{ matchPattern()
-
- /**
- * build a pattern matching string
- *
- * @access public
- *
- * @param array $pattern even keys are strings, odd are patterns (% and _)
- * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
- * @param string $field optional field name that is being matched against
- * (might be required when emulating ILIKE)
- *
- * @return string SQL pattern
- */
- function matchPattern($pattern, $operator = null, $field = null)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $match = '';
- if (null !== $operator) {
- $operator = strtoupper($operator);
- switch ($operator) {
- // case insensitive
- case 'ILIKE':
- if (null === $field) {
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'case insensitive LIKE matching requires passing the field name', __FUNCTION__);
- }
- $db->loadModule('Function', null, true);
- $match = $db->function->lower($field).' LIKE ';
- break;
- case 'NOT ILIKE':
- if (null === $field) {
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'case insensitive NOT ILIKE matching requires passing the field name', __FUNCTION__);
- }
- $db->loadModule('Function', null, true);
- $match = $db->function->lower($field).' NOT LIKE ';
- break;
- // case sensitive
- case 'LIKE':
- $match = (null === $field) ? 'LIKE ' : ($field.' LIKE ');
- break;
- case 'NOT LIKE':
- $match = (null === $field) ? 'NOT LIKE ' : ($field.' NOT LIKE ');
- break;
- default:
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'not a supported operator type:'. $operator, __FUNCTION__);
- }
- }
- $match.= "'";
- foreach ($pattern as $key => $value) {
- if ($key % 2) {
- $match.= $value;
- } else {
- $escaped = $db->escape($value);
- if (MDB2::isError($escaped)) {
- return $escaped;
- }
- $match.= $db->escapePattern($escaped);
- }
- }
- $match.= "'";
- $match.= $this->patternEscapeString();
- return $match;
- }
-
- // }}}
- // {{{ patternEscapeString()
-
- /**
- * build string to define pattern escape character
- *
- * @access public
- *
- * @return string define pattern escape character
- */
- function patternEscapeString()
- {
- return '';
- }
-
- // }}}
- // {{{ mapNativeDatatype()
-
- /**
- * Maps a native array description of a field to a MDB2 datatype and length
- *
- * @param array $field native field description
- * @return array containing the various possible types, length, sign, fixed
- * @access public
- */
- function mapNativeDatatype($field)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- // If the user has specified an option to map the native field
- // type to a custom MDB2 datatype...
- $db_type = strtok($field['type'], '(), ');
- if (!empty($db->options['nativetype_map_callback'][$db_type])) {
- return call_user_func_array($db->options['nativetype_map_callback'][$db_type], array($db, $field));
- }
-
- // Otherwise perform the built-in (i.e. normal) MDB2 native type to
- // MDB2 datatype conversion
- return $this->_mapNativeDatatype($field);
- }
-
- // }}}
- // {{{ _mapNativeDatatype()
-
- /**
- * Maps a native array description of a field to a MDB2 datatype and length
- *
- * @param array $field native field description
- * @return array containing the various possible types, length, sign, fixed
- * @access public
- */
- function _mapNativeDatatype($field)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ mapPrepareDatatype()
-
- /**
- * Maps an mdb2 datatype to mysqli prepare type
- *
- * @param string $type
- * @return string
- * @access public
- */
- function mapPrepareDatatype($type)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- if (!empty($db->options['datatype_map'][$type])) {
- $type = $db->options['datatype_map'][$type];
- if (!empty($db->options['datatype_map_callback'][$type])) {
- $parameter = array('type' => $type);
- return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
- }
- }
-
- return $type;
- }
-}
-?>
diff --git a/data/module/MDB2/Driver/Datatype/mysql.php b/data/module/MDB2/Driver/Datatype/mysql.php
deleted file mode 100644
index 5d2385ddb8e..00000000000
--- a/data/module/MDB2/Driver/Datatype/mysql.php
+++ /dev/null
@@ -1,602 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: mysql.php 327310 2012-08-27 15:16:18Z danielc $
-//
-
-require_once 'MDB2/Driver/Datatype/Common.php';
-
-/**
- * MDB2 MySQL driver
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_Driver_Datatype_mysql extends MDB2_Driver_Datatype_Common
-{
- // {{{ _getCharsetFieldDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET
- * of a field declaration to be used in statements like CREATE TABLE.
- *
- * @param string $charset name of the charset
- * @return string DBMS specific SQL code portion needed to set the CHARACTER SET
- * of a field declaration.
- */
- function _getCharsetFieldDeclaration($charset)
- {
- return 'CHARACTER SET '.$charset;
- }
-
- // }}}
- // {{{ _getCollationFieldDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to set the COLLATION
- * of a field declaration to be used in statements like CREATE TABLE.
- *
- * @param string $collation name of the collation
- * @return string DBMS specific SQL code portion needed to set the COLLATION
- * of a field declaration.
- */
- function _getCollationFieldDeclaration($collation)
- {
- return 'COLLATE '.$collation;
- }
-
- // }}}
- // {{{ getDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to declare
- * of the given type
- *
- * @param string $type type to which the value should be converted to
- * @param string $name name the field to be declared.
- * @param string $field definition of the field
- *
- * @return string DBMS-specific SQL code portion that should be used to
- * declare the specified field.
- * @access public
- */
- function getDeclaration($type, $name, $field)
- {
- // MySQL DDL syntax forbids combining NOT NULL with DEFAULT NULL.
- // To get a default of NULL for NOT NULL columns, omit it.
- if ( isset($field['notnull'])
- && !empty($field['notnull'])
- && array_key_exists('default', $field) // do not use isset() here!
- && null === $field['default']
- ) {
- unset($field['default']);
- }
- return parent::getDeclaration($type, $name, $field);
- }
-
- // }}}
- // {{{ getTypeDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to declare an text type
- * field to be used in statements like CREATE TABLE.
- *
- * @param array $field associative array with the name of the properties
- * of the field being declared as array indexes. Currently, the types
- * of supported field properties are as follows:
- *
- * length
- * Integer value that determines the maximum length of the text
- * field. If this argument is missing the field should be
- * declared to have the longest length allowed by the DBMS.
- *
- * default
- * Text value to be used as default for this field.
- *
- * notnull
- * Boolean flag that indicates whether this field is constrained
- * to not be set to null.
- * @return string DBMS specific SQL code portion that should be used to
- * declare the specified field.
- * @access public
- */
- function getTypeDeclaration($field)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- switch ($field['type']) {
- case 'text':
- if (empty($field['length']) && array_key_exists('default', $field)) {
- $field['length'] = $db->varchar_max_length;
- }
- $length = !empty($field['length']) ? $field['length'] : false;
- $fixed = !empty($field['fixed']) ? $field['fixed'] : false;
- return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR(255)')
- : ($length ? 'VARCHAR('.$length.')' : 'TEXT');
- case 'clob':
- if (!empty($field['length'])) {
- $length = $field['length'];
- if ($length <= 255) {
- return 'TINYTEXT';
- } elseif ($length <= 65532) {
- return 'TEXT';
- } elseif ($length <= 16777215) {
- return 'MEDIUMTEXT';
- }
- }
- return 'LONGTEXT';
- case 'blob':
- if (!empty($field['length'])) {
- $length = $field['length'];
- if ($length <= 255) {
- return 'TINYBLOB';
- } elseif ($length <= 65532) {
- return 'BLOB';
- } elseif ($length <= 16777215) {
- return 'MEDIUMBLOB';
- }
- }
- return 'LONGBLOB';
- case 'integer':
- if (!empty($field['length'])) {
- $length = $field['length'];
- if ($length <= 1) {
- return 'TINYINT';
- } elseif ($length == 2) {
- return 'SMALLINT';
- } elseif ($length == 3) {
- return 'MEDIUMINT';
- } elseif ($length == 4) {
- return 'INT';
- } elseif ($length > 4) {
- return 'BIGINT';
- }
- }
- return 'INT';
- case 'boolean':
- return 'TINYINT(1)';
- case 'date':
- return 'DATE';
- case 'time':
- return 'TIME';
- case 'timestamp':
- return 'DATETIME';
- case 'float':
- $l = '';
- if (!empty($field['length'])) {
- $l = '(' . $field['length'];
- if (!empty($field['scale'])) {
- $l .= ',' . $field['scale'];
- }
- $l .= ')';
- }
- return 'DOUBLE' . $l;
- case 'decimal':
- $length = !empty($field['length']) ? $field['length'] : 18;
- $scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
- return 'DECIMAL('.$length.','.$scale.')';
- }
- return '';
- }
-
- // }}}
- // {{{ _getIntegerDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to declare an integer type
- * field to be used in statements like CREATE TABLE.
- *
- * @param string $name name the field to be declared.
- * @param string $field associative array with the name of the properties
- * of the field being declared as array indexes.
- * Currently, the types of supported field
- * properties are as follows:
- *
- * unsigned
- * Boolean flag that indicates whether the field
- * should be declared as unsigned integer if
- * possible.
- *
- * default
- * Integer value to be used as default for this
- * field.
- *
- * notnull
- * Boolean flag that indicates whether this field is
- * constrained to not be set to null.
- * @return string DBMS specific SQL code portion that should be used to
- * declare the specified field.
- * @access protected
- */
- function _getIntegerDeclaration($name, $field)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $default = $autoinc = '';
- if (!empty($field['autoincrement'])) {
- $autoinc = ' AUTO_INCREMENT PRIMARY KEY';
- } elseif (array_key_exists('default', $field)) {
- if ($field['default'] === '') {
- $field['default'] = empty($field['notnull']) ? null : 0;
- }
- $default = ' DEFAULT '.$this->quote($field['default'], 'integer');
- }
-
- $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
- $unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED';
- if (empty($default) && empty($notnull)) {
- $default = ' DEFAULT NULL';
- }
- $name = $db->quoteIdentifier($name, true);
- return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull.$autoinc;
- }
-
- // }}}
- // {{{ _getFloatDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to declare an float type
- * field to be used in statements like CREATE TABLE.
- *
- * @param string $name name the field to be declared.
- * @param string $field associative array with the name of the properties
- * of the field being declared as array indexes.
- * Currently, the types of supported field
- * properties are as follows:
- *
- * unsigned
- * Boolean flag that indicates whether the field
- * should be declared as unsigned float if
- * possible.
- *
- * default
- * float value to be used as default for this
- * field.
- *
- * notnull
- * Boolean flag that indicates whether this field is
- * constrained to not be set to null.
- * @return string DBMS specific SQL code portion that should be used to
- * declare the specified field.
- * @access protected
- */
- function _getFloatDeclaration($name, $field)
- {
- // Since AUTO_INCREMENT can be used for integer or floating-point types,
- // reuse the INTEGER declaration
- // @see http://bugs.mysql.com/bug.php?id=31032
- return $this->_getIntegerDeclaration($name, $field);
- }
-
- // }}}
- // {{{ _getDecimalDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to declare an decimal type
- * field to be used in statements like CREATE TABLE.
- *
- * @param string $name name the field to be declared.
- * @param string $field associative array with the name of the properties
- * of the field being declared as array indexes.
- * Currently, the types of supported field
- * properties are as follows:
- *
- * unsigned
- * Boolean flag that indicates whether the field
- * should be declared as unsigned integer if
- * possible.
- *
- * default
- * Decimal value to be used as default for this
- * field.
- *
- * notnull
- * Boolean flag that indicates whether this field is
- * constrained to not be set to null.
- * @return string DBMS specific SQL code portion that should be used to
- * declare the specified field.
- * @access protected
- */
- function _getDecimalDeclaration($name, $field)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $default = '';
- if (array_key_exists('default', $field)) {
- if ($field['default'] === '') {
- $field['default'] = empty($field['notnull']) ? null : 0;
- }
- $default = ' DEFAULT '.$this->quote($field['default'], 'integer');
- } elseif (empty($field['notnull'])) {
- $default = ' DEFAULT NULL';
- }
-
- $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
- $unsigned = empty($field['unsigned']) ? '' : ' UNSIGNED';
- $name = $db->quoteIdentifier($name, true);
- return $name.' '.$this->getTypeDeclaration($field).$unsigned.$default.$notnull;
- }
-
- // }}}
- // {{{ matchPattern()
-
- /**
- * build a pattern matching string
- *
- * @access public
- *
- * @param array $pattern even keys are strings, odd are patterns (% and _)
- * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
- * @param string $field optional field name that is being matched against
- * (might be required when emulating ILIKE)
- *
- * @return string SQL pattern
- */
- function matchPattern($pattern, $operator = null, $field = null)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $match = '';
- if (null !== $operator) {
- $field = (null === $field) ? '' : $field.' ';
- $operator = strtoupper($operator);
- switch ($operator) {
- // case insensitive
- case 'ILIKE':
- $match = $field.'LIKE ';
- break;
- case 'NOT ILIKE':
- $match = $field.'NOT LIKE ';
- break;
- // case sensitive
- case 'LIKE':
- $match = $field.'LIKE BINARY ';
- break;
- case 'NOT LIKE':
- $match = $field.'NOT LIKE BINARY ';
- break;
- default:
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'not a supported operator type:'. $operator, __FUNCTION__);
- }
- }
- $match.= "'";
- foreach ($pattern as $key => $value) {
- if ($key % 2) {
- $match.= $value;
- } else {
- $match.= $db->escapePattern($db->escape($value));
- }
- }
- $match.= "'";
- $match.= $this->patternEscapeString();
- return $match;
- }
-
- // }}}
- // {{{ _mapNativeDatatype()
-
- /**
- * Maps a native array description of a field to a MDB2 datatype and length
- *
- * @param array $field native field description
- * @return array containing the various possible types, length, sign, fixed
- * @access public
- */
- function _mapNativeDatatype($field)
- {
- $db_type = strtolower($field['type']);
- $db_type = strtok($db_type, '(), ');
- if ($db_type == 'national') {
- $db_type = strtok('(), ');
- }
- if (!empty($field['length'])) {
- $length = strtok($field['length'], ', ');
- $decimal = strtok(', ');
- } else {
- $length = strtok('(), ');
- $decimal = strtok('(), ');
- }
- $type = array();
- $unsigned = $fixed = null;
- switch ($db_type) {
- case 'tinyint':
- $type[] = 'integer';
- $type[] = 'boolean';
- if (preg_match('/^(is|has)/', $field['name'])) {
- $type = array_reverse($type);
- }
- $unsigned = preg_match('/ unsigned/i', $field['type']);
- $length = 1;
- break;
- case 'smallint':
- $type[] = 'integer';
- $unsigned = preg_match('/ unsigned/i', $field['type']);
- $length = 2;
- break;
- case 'mediumint':
- $type[] = 'integer';
- $unsigned = preg_match('/ unsigned/i', $field['type']);
- $length = 3;
- break;
- case 'int':
- case 'integer':
- $type[] = 'integer';
- $unsigned = preg_match('/ unsigned/i', $field['type']);
- $length = 4;
- break;
- case 'bigint':
- $type[] = 'integer';
- $unsigned = preg_match('/ unsigned/i', $field['type']);
- $length = 8;
- break;
- case 'tinytext':
- case 'mediumtext':
- case 'longtext':
- case 'text':
- case 'varchar':
- $fixed = false;
- case 'string':
- case 'char':
- $type[] = 'text';
- if ($length == '1') {
- $type[] = 'boolean';
- if (preg_match('/^(is|has)/', $field['name'])) {
- $type = array_reverse($type);
- }
- } elseif (strstr($db_type, 'text')) {
- $type[] = 'clob';
- if ($decimal == 'binary') {
- $type[] = 'blob';
- }
- $type = array_reverse($type);
- }
- if ($fixed !== false) {
- $fixed = true;
- }
- break;
- case 'enum':
- $type[] = 'text';
- preg_match_all('/\'.+\'/U', $field['type'], $matches);
- $length = 0;
- $fixed = false;
- if (is_array($matches)) {
- foreach ($matches[0] as $value) {
- $length = max($length, strlen($value)-2);
- }
- if ($length == '1' && count($matches[0]) == 2) {
- $type[] = 'boolean';
- if (preg_match('/^(is|has)/', $field['name'])) {
- $type = array_reverse($type);
- }
- }
- }
- $type[] = 'integer';
- case 'set':
- $fixed = false;
- $type[] = 'text';
- $type[] = 'integer';
- break;
- case 'date':
- $type[] = 'date';
- $length = null;
- break;
- case 'datetime':
- case 'timestamp':
- $type[] = 'timestamp';
- $length = null;
- break;
- case 'time':
- $type[] = 'time';
- $length = null;
- break;
- case 'float':
- case 'double':
- case 'real':
- $type[] = 'float';
- $unsigned = preg_match('/ unsigned/i', $field['type']);
- if ($decimal !== false) {
- $length = $length.','.$decimal;
- }
- break;
- case 'unknown':
- case 'decimal':
- case 'numeric':
- $type[] = 'decimal';
- $unsigned = preg_match('/ unsigned/i', $field['type']);
- if ($decimal !== false) {
- $length = $length.','.$decimal;
- }
- break;
- case 'tinyblob':
- case 'mediumblob':
- case 'longblob':
- case 'blob':
- $type[] = 'blob';
- $length = null;
- break;
- case 'binary':
- case 'varbinary':
- $type[] = 'blob';
- break;
- case 'year':
- $type[] = 'integer';
- $type[] = 'date';
- $length = null;
- break;
- default:
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'unknown database attribute type: '.$db_type, __FUNCTION__);
- }
-
- if ((int)$length <= 0) {
- $length = null;
- }
-
- return array($type, $length, $unsigned, $fixed);
- }
-
- // }}}
-}
-
-?>
diff --git a/data/module/MDB2/Driver/Datatype/pgsql.php b/data/module/MDB2/Driver/Datatype/pgsql.php
deleted file mode 100644
index 7b9ef8da712..00000000000
--- a/data/module/MDB2/Driver/Datatype/pgsql.php
+++ /dev/null
@@ -1,579 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: pgsql.php 327310 2012-08-27 15:16:18Z danielc $
-
-require_once 'MDB2/Driver/Datatype/Common.php';
-
-/**
- * MDB2 PostGreSQL driver
- *
- * @package MDB2
- * @category Database
- * @author Paul Cooper
- */
-class MDB2_Driver_Datatype_pgsql extends MDB2_Driver_Datatype_Common
-{
- // {{{ _baseConvertResult()
-
- /**
- * General type conversion method
- *
- * @param mixed $value refernce to a value to be converted
- * @param string $type specifies which type to convert to
- * @param boolean $rtrim [optional] when TRUE [default], apply rtrim() to text
- * @return object a MDB2 error on failure
- * @access protected
- */
- function _baseConvertResult($value, $type, $rtrim = true)
- {
- if (null === $value) {
- return null;
- }
- switch ($type) {
- case 'boolean':
- return ($value == 'f')? false : !empty($value);
- case 'float':
- return doubleval($value);
- case 'date':
- return $value;
- case 'time':
- return substr($value, 0, strlen('HH:MM:SS'));
- case 'timestamp':
- return substr($value, 0, strlen('YYYY-MM-DD HH:MM:SS'));
- case 'blob':
- $value = pg_unescape_bytea($value);
- return parent::_baseConvertResult($value, $type, $rtrim);
- }
- return parent::_baseConvertResult($value, $type, $rtrim);
- }
-
- // }}}
- // {{{ getTypeDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to declare an text type
- * field to be used in statements like CREATE TABLE.
- *
- * @param array $field associative array with the name of the properties
- * of the field being declared as array indexes. Currently, the types
- * of supported field properties are as follows:
- *
- * length
- * Integer value that determines the maximum length of the text
- * field. If this argument is missing the field should be
- * declared to have the longest length allowed by the DBMS.
- *
- * default
- * Text value to be used as default for this field.
- *
- * notnull
- * Boolean flag that indicates whether this field is constrained
- * to not be set to null.
- * @return string DBMS specific SQL code portion that should be used to
- * declare the specified field.
- * @access public
- */
- function getTypeDeclaration($field)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- switch ($field['type']) {
- case 'text':
- $length = !empty($field['length']) ? $field['length'] : false;
- $fixed = !empty($field['fixed']) ? $field['fixed'] : false;
- return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')')
- : ($length ? 'VARCHAR('.$length.')' : 'TEXT');
- case 'clob':
- return 'TEXT';
- case 'blob':
- return 'BYTEA';
- case 'integer':
- if (!empty($field['autoincrement'])) {
- if (!empty($field['length'])) {
- $length = $field['length'];
- if ($length > 4) {
- return 'BIGSERIAL PRIMARY KEY';
- }
- }
- return 'SERIAL PRIMARY KEY';
- }
- if (!empty($field['length'])) {
- $length = $field['length'];
- if ($length <= 2) {
- return 'SMALLINT';
- } elseif ($length == 3 || $length == 4) {
- return 'INT';
- } elseif ($length > 4) {
- return 'BIGINT';
- }
- }
- return 'INT';
- case 'boolean':
- return 'BOOLEAN';
- case 'date':
- return 'DATE';
- case 'time':
- return 'TIME without time zone';
- case 'timestamp':
- return 'TIMESTAMP without time zone';
- case 'float':
- return 'FLOAT8';
- case 'decimal':
- $length = !empty($field['length']) ? $field['length'] : 18;
- $scale = !empty($field['scale']) ? $field['scale'] : $db->options['decimal_places'];
- return 'NUMERIC('.$length.','.$scale.')';
- }
- }
-
- // }}}
- // {{{ _getIntegerDeclaration()
-
- /**
- * Obtain DBMS specific SQL code portion needed to declare an integer type
- * field to be used in statements like CREATE TABLE.
- *
- * @param string $name name the field to be declared.
- * @param array $field associative array with the name of the properties
- * of the field being declared as array indexes. Currently, the types
- * of supported field properties are as follows:
- *
- * unsigned
- * Boolean flag that indicates whether the field should be
- * declared as unsigned integer if possible.
- *
- * default
- * Integer value to be used as default for this field.
- *
- * notnull
- * Boolean flag that indicates whether this field is constrained
- * to not be set to null.
- * @return string DBMS specific SQL code portion that should be used to
- * declare the specified field.
- * @access protected
- */
- function _getIntegerDeclaration($name, $field)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- if (!empty($field['unsigned'])) {
- $db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer";
- }
- if (!empty($field['autoincrement'])) {
- $name = $db->quoteIdentifier($name, true);
- return $name.' '.$this->getTypeDeclaration($field);
- }
- $default = '';
- if (array_key_exists('default', $field)) {
- if ($field['default'] === '') {
- $field['default'] = empty($field['notnull']) ? null : 0;
- }
- $default = ' DEFAULT '.$this->quote($field['default'], 'integer');
- }
-
- $notnull = empty($field['notnull']) ? '' : ' NOT NULL';
- if (empty($default) && empty($notnull)) {
- $default = ' DEFAULT NULL';
- }
- $name = $db->quoteIdentifier($name, true);
- return $name.' '.$this->getTypeDeclaration($field).$default.$notnull;
- }
-
- // }}}
- // {{{ _quoteCLOB()
-
- /**
- * Convert a text value into a DBMS specific format that is suitable to
- * compose query statements.
- *
- * @param string $value text string value that is intended to be converted.
- * @param bool $quote determines if the value should be quoted and escaped
- * @param bool $escape_wildcards if to escape escape wildcards
- * @return string text string that represents the given argument value in
- * a DBMS specific format.
- * @access protected
- */
- function _quoteCLOB($value, $quote, $escape_wildcards)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
- if ($db->options['lob_allow_url_include']) {
- $value = $this->_readFile($value);
- if (MDB2::isError($value)) {
- return $value;
- }
- }
- return $this->_quoteText($value, $quote, $escape_wildcards);
- }
-
- // }}}
- // {{{ _quoteBLOB()
-
- /**
- * Convert a text value into a DBMS specific format that is suitable to
- * compose query statements.
- *
- * @param string $value text string value that is intended to be converted.
- * @param bool $quote determines if the value should be quoted and escaped
- * @param bool $escape_wildcards if to escape escape wildcards
- * @return string text string that represents the given argument value in
- * a DBMS specific format.
- * @access protected
- */
- function _quoteBLOB($value, $quote, $escape_wildcards)
- {
- if (!$quote) {
- return $value;
- }
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
- if ($db->options['lob_allow_url_include']) {
- $value = $this->_readFile($value);
- if (MDB2::isError($value)) {
- return $value;
- }
- }
- if (version_compare(PHP_VERSION, '5.2.0RC6', '>=')) {
- $connection = $db->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
- $value = @pg_escape_bytea($connection, $value);
- } else {
- $value = @pg_escape_bytea($value);
- }
- return "'".$value."'";
- }
-
- // }}}
- // {{{ _quoteBoolean()
-
- /**
- * Convert a text value into a DBMS specific format that is suitable to
- * compose query statements.
- *
- * @param string $value text string value that is intended to be converted.
- * @param bool $quote determines if the value should be quoted and escaped
- * @param bool $escape_wildcards if to escape escape wildcards
- * @return string text string that represents the given argument value in
- * a DBMS specific format.
- * @access protected
- */
- function _quoteBoolean($value, $quote, $escape_wildcards)
- {
- $value = $value ? 't' : 'f';
- if (!$quote) {
- return $value;
- }
- return "'".$value."'";
- }
-
- // }}}
- // {{{ matchPattern()
-
- /**
- * build a pattern matching string
- *
- * @access public
- *
- * @param array $pattern even keys are strings, odd are patterns (% and _)
- * @param string $operator optional pattern operator (LIKE, ILIKE and maybe others in the future)
- * @param string $field optional field name that is being matched against
- * (might be required when emulating ILIKE)
- *
- * @return string SQL pattern
- */
- function matchPattern($pattern, $operator = null, $field = null)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $match = '';
- if (null !== $operator) {
- $field = (null === $field) ? '' : $field.' ';
- $operator = strtoupper($operator);
- switch ($operator) {
- // case insensitive
- case 'ILIKE':
- $match = $field.'ILIKE ';
- break;
- case 'NOT ILIKE':
- $match = $field.'NOT ILIKE ';
- break;
- // case sensitive
- case 'LIKE':
- $match = $field.'LIKE ';
- break;
- case 'NOT LIKE':
- $match = $field.'NOT LIKE ';
- break;
- default:
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'not a supported operator type:'. $operator, __FUNCTION__);
- }
- }
- $match.= "'";
- foreach ($pattern as $key => $value) {
- if ($key % 2) {
- $match.= $value;
- } else {
- $match.= $db->escapePattern($db->escape($value));
- }
- }
- $match.= "'";
- $match.= $this->patternEscapeString();
- return $match;
- }
-
- // }}}
- // {{{ patternEscapeString()
-
- /**
- * build string to define escape pattern string
- *
- * @access public
- *
- *
- * @return string define escape pattern
- */
- function patternEscapeString()
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
- return ' ESCAPE '.$this->quote($db->string_quoting['escape_pattern']);
- }
-
- // }}}
- // {{{ _mapNativeDatatype()
-
- /**
- * Maps a native array description of a field to a MDB2 datatype and length
- *
- * @param array $field native field description
- * @return array containing the various possible types, length, sign, fixed
- * @access public
- */
- function _mapNativeDatatype($field)
- {
- $db_type = strtolower($field['type']);
- $length = $field['length'];
- $type = array();
- $unsigned = $fixed = null;
- switch ($db_type) {
- case 'smallint':
- case 'int2':
- $type[] = 'integer';
- $unsigned = false;
- $length = 2;
- if ($length == '2') {
- $type[] = 'boolean';
- if (preg_match('/^(is|has)/', $field['name'])) {
- $type = array_reverse($type);
- }
- }
- break;
- case 'int':
- case 'int4':
- case 'integer':
- case 'serial':
- case 'serial4':
- $type[] = 'integer';
- $unsigned = false;
- $length = 4;
- break;
- case 'bigint':
- case 'int8':
- case 'bigserial':
- case 'serial8':
- $type[] = 'integer';
- $unsigned = false;
- $length = 8;
- break;
- case 'bool':
- case 'boolean':
- $type[] = 'boolean';
- $length = null;
- break;
- case 'text':
- case 'varchar':
- $fixed = false;
- case 'unknown':
- case 'char':
- case 'bpchar':
- $type[] = 'text';
- if ($length == '1') {
- $type[] = 'boolean';
- if (preg_match('/^(is|has)/', $field['name'])) {
- $type = array_reverse($type);
- }
- } elseif (strstr($db_type, 'text')) {
- $type[] = 'clob';
- $type = array_reverse($type);
- }
- if ($fixed !== false) {
- $fixed = true;
- }
- break;
- case 'date':
- $type[] = 'date';
- $length = null;
- break;
- case 'datetime':
- case 'timestamp':
- case 'timestamptz':
- $type[] = 'timestamp';
- $length = null;
- break;
- case 'time':
- $type[] = 'time';
- $length = null;
- break;
- case 'float':
- case 'float4':
- case 'float8':
- case 'double':
- case 'real':
- $type[] = 'float';
- break;
- case 'decimal':
- case 'money':
- case 'numeric':
- $type[] = 'decimal';
- if (isset($field['scale'])) {
- $length = $length.','.$field['scale'];
- }
- break;
- case 'tinyblob':
- case 'mediumblob':
- case 'longblob':
- case 'blob':
- case 'bytea':
- $type[] = 'blob';
- $length = null;
- break;
- case 'oid':
- $type[] = 'blob';
- $type[] = 'clob';
- $length = null;
- break;
- case 'year':
- $type[] = 'integer';
- $type[] = 'date';
- $length = null;
- break;
- default:
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'unknown database attribute type: '.$db_type, __FUNCTION__);
- }
-
- if ((int)$length <= 0) {
- $length = null;
- }
-
- return array($type, $length, $unsigned, $fixed);
- }
-
- // }}}
- // {{{ mapPrepareDatatype()
-
- /**
- * Maps an mdb2 datatype to native prepare type
- *
- * @param string $type
- * @return string
- * @access public
- */
- function mapPrepareDatatype($type)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- if (!empty($db->options['datatype_map'][$type])) {
- $type = $db->options['datatype_map'][$type];
- if (!empty($db->options['datatype_map_callback'][$type])) {
- $parameter = array('type' => $type);
- return call_user_func_array($db->options['datatype_map_callback'][$type], array(&$db, __FUNCTION__, $parameter));
- }
- }
-
- switch ($type) {
- case 'integer':
- return 'int';
- case 'boolean':
- return 'bool';
- case 'decimal':
- case 'float':
- return 'numeric';
- case 'clob':
- return 'text';
- case 'blob':
- return 'bytea';
- default:
- break;
- }
- return $type;
- }
- // }}}
-}
-?>
diff --git a/data/module/MDB2/Driver/Function/Common.php b/data/module/MDB2/Driver/Function/Common.php
deleted file mode 100644
index d62dc26e91c..00000000000
--- a/data/module/MDB2/Driver/Function/Common.php
+++ /dev/null
@@ -1,293 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: Common.php 327310 2012-08-27 15:16:18Z danielc $
-//
-
-/**
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-
-/**
- * Base class for the function modules that is extended by each MDB2 driver
- *
- * To load this module in the MDB2 object:
- * $mdb->loadModule('Function');
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_Driver_Function_Common extends MDB2_Module_Common
-{
- // {{{ executeStoredProc()
-
- /**
- * Execute a stored procedure and return any results
- *
- * @param string $name string that identifies the function to execute
- * @param mixed $params array that contains the paramaters to pass the stored proc
- * @param mixed $types array that contains the types of the columns in
- * the result set
- * @param mixed $result_class string which specifies which result class to use
- * @param mixed $result_wrap_class string which specifies which class to wrap results in
- *
- * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $error = $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- return $error;
- }
-
- // }}}
- // {{{ functionTable()
-
- /**
- * return string for internal table used when calling only a function
- *
- * @return string for internal table used when calling only a function
- * @access public
- */
- function functionTable()
- {
- return '';
- }
-
- // }}}
- // {{{ now()
-
- /**
- * Return string to call a variable with the current timestamp inside an SQL statement
- * There are three special variables for current date and time:
- * - CURRENT_TIMESTAMP (date and time, TIMESTAMP type)
- * - CURRENT_DATE (date, DATE type)
- * - CURRENT_TIME (time, TIME type)
- *
- * @param string $type 'timestamp' | 'time' | 'date'
- *
- * @return string to call a variable with the current timestamp
- * @access public
- */
- function now($type = 'timestamp')
- {
- switch ($type) {
- case 'time':
- return 'CURRENT_TIME';
- case 'date':
- return 'CURRENT_DATE';
- case 'timestamp':
- default:
- return 'CURRENT_TIMESTAMP';
- }
- }
-
- // }}}
- // {{{ unixtimestamp()
-
- /**
- * return string to call a function to get the unix timestamp from a iso timestamp
- *
- * @param string $expression
- *
- * @return string to call a variable with the timestamp
- * @access public
- */
- function unixtimestamp($expression)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $error = $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- return $error;
- }
-
- // }}}
- // {{{ substring()
-
- /**
- * return string to call a function to get a substring inside an SQL statement
- *
- * @return string to call a function to get a substring
- * @access public
- */
- function substring($value, $position = 1, $length = null)
- {
- if (null !== $length) {
- return "SUBSTRING($value FROM $position FOR $length)";
- }
- return "SUBSTRING($value FROM $position)";
- }
-
- // }}}
- // {{{ replace()
-
- /**
- * return string to call a function to get replace inside an SQL statement.
- *
- * @return string to call a function to get a replace
- * @access public
- */
- function replace($str, $from_str, $to_str)
- {
- return "REPLACE($str, $from_str , $to_str)";
- }
-
- // }}}
- // {{{ concat()
-
- /**
- * Returns string to concatenate two or more string parameters
- *
- * @param string $value1
- * @param string $value2
- * @param string $values...
- *
- * @return string to concatenate two strings
- * @access public
- */
- function concat($value1, $value2)
- {
- $args = func_get_args();
- return "(".implode(' || ', $args).")";
- }
-
- // }}}
- // {{{ random()
-
- /**
- * return string to call a function to get random value inside an SQL statement
- *
- * @return return string to generate float between 0 and 1
- * @access public
- */
- function random()
- {
- return 'RAND()';
- }
-
- // }}}
- // {{{ lower()
-
- /**
- * return string to call a function to lower the case of an expression
- *
- * @param string $expression
- *
- * @return return string to lower case of an expression
- * @access public
- */
- function lower($expression)
- {
- return "LOWER($expression)";
- }
-
- // }}}
- // {{{ upper()
-
- /**
- * return string to call a function to upper the case of an expression
- *
- * @param string $expression
- *
- * @return return string to upper case of an expression
- * @access public
- */
- function upper($expression)
- {
- return "UPPER($expression)";
- }
-
- // }}}
- // {{{ length()
-
- /**
- * return string to call a function to get the length of a string expression
- *
- * @param string $expression
- *
- * @return return string to get the string expression length
- * @access public
- */
- function length($expression)
- {
- return "LENGTH($expression)";
- }
-
- // }}}
- // {{{ guid()
-
- /**
- * Returns global unique identifier
- *
- * @return string to get global unique identifier
- * @access public
- */
- function guid()
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $error = $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- return $error;
- }
-
- // }}}
-}
-?>
diff --git a/data/module/MDB2/Driver/Function/mysql.php b/data/module/MDB2/Driver/Function/mysql.php
deleted file mode 100644
index 6ac2441dcdf..00000000000
--- a/data/module/MDB2/Driver/Function/mysql.php
+++ /dev/null
@@ -1,136 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: mysql.php 327310 2012-08-27 15:16:18Z danielc $
-//
-
-require_once 'MDB2/Driver/Function/Common.php';
-
-/**
- * MDB2 MySQL driver for the function modules
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_Driver_Function_mysql extends MDB2_Driver_Function_Common
-{
- // }}}
- // {{{ executeStoredProc()
-
- /**
- * Execute a stored procedure and return any results
- *
- * @param string $name string that identifies the function to execute
- * @param mixed $params array that contains the paramaters to pass the stored proc
- * @param mixed $types array that contains the types of the columns in
- * the result set
- * @param mixed $result_class string which specifies which result class to use
- * @param mixed $result_wrap_class string which specifies which class to wrap results in
- * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $query = 'CALL '.$name;
- $query .= $params ? '('.implode(', ', $params).')' : '()';
- return $db->query($query, $types, $result_class, $result_wrap_class);
- }
-
- // }}}
- // {{{ unixtimestamp()
-
- /**
- * return string to call a function to get the unix timestamp from a iso timestamp
- *
- * @param string $expression
- *
- * @return string to call a variable with the timestamp
- * @access public
- */
- function unixtimestamp($expression)
- {
- return 'UNIX_TIMESTAMP('. $expression.')';
- }
-
- // }}}
- // {{{ concat()
-
- /**
- * Returns string to concatenate two or more string parameters
- *
- * @param string $value1
- * @param string $value2
- * @param string $values...
- * @return string to concatenate two strings
- * @access public
- **/
- function concat($value1, $value2)
- {
- $args = func_get_args();
- return "CONCAT(".implode(', ', $args).")";
- }
-
- // }}}
- // {{{ guid()
-
- /**
- * Returns global unique identifier
- *
- * @return string to get global unique identifier
- * @access public
- */
- function guid()
- {
- return 'UUID()';
- }
-
- // }}}
-}
-?>
diff --git a/data/module/MDB2/Driver/Function/pgsql.php b/data/module/MDB2/Driver/Function/pgsql.php
deleted file mode 100644
index a346c52bec1..00000000000
--- a/data/module/MDB2/Driver/Function/pgsql.php
+++ /dev/null
@@ -1,132 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: pgsql.php 327310 2012-08-27 15:16:18Z danielc $
-
-require_once 'MDB2/Driver/Function/Common.php';
-
-/**
- * MDB2 MySQL driver for the function modules
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_Driver_Function_pgsql extends MDB2_Driver_Function_Common
-{
- // {{{ executeStoredProc()
-
- /**
- * Execute a stored procedure and return any results
- *
- * @param string $name string that identifies the function to execute
- * @param mixed $params array that contains the paramaters to pass the stored proc
- * @param mixed $types array that contains the types of the columns in
- * the result set
- * @param mixed $result_class string which specifies which result class to use
- * @param mixed $result_wrap_class string which specifies which class to wrap results in
- * @return mixed a result handle or MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function executeStoredProc($name, $params = null, $types = null, $result_class = true, $result_wrap_class = false)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $query = 'SELECT * FROM '.$name;
- $query .= $params ? '('.implode(', ', $params).')' : '()';
- return $db->query($query, $types, $result_class, $result_wrap_class);
- }
- // }}}
- // {{{ unixtimestamp()
-
- /**
- * return string to call a function to get the unix timestamp from a iso timestamp
- *
- * @param string $expression
- *
- * @return string to call a variable with the timestamp
- * @access public
- */
- function unixtimestamp($expression)
- {
- return 'EXTRACT(EPOCH FROM DATE_TRUNC(\'seconds\', CAST ((' . $expression . ') AS TIMESTAMP)))';
- }
-
- // }}}
- // {{{ substring()
-
- /**
- * return string to call a function to get a substring inside an SQL statement
- *
- * @return string to call a function to get a substring
- * @access public
- */
- function substring($value, $position = 1, $length = null)
- {
- if (null !== $length) {
- return "SUBSTRING(CAST($value AS VARCHAR) FROM $position FOR $length)";
- }
- return "SUBSTRING(CAST($value AS VARCHAR) FROM $position)";
- }
-
- // }}}
- // {{{ random()
-
- /**
- * return string to call a function to get random value inside an SQL statement
- *
- * @return return string to generate float between 0 and 1
- * @access public
- */
- function random()
- {
- return 'RANDOM()';
- }
-
- // }}}
-}
-?>
diff --git a/data/module/MDB2/Driver/Manager/Common.php b/data/module/MDB2/Driver/Manager/Common.php
deleted file mode 100644
index c9d95524d1f..00000000000
--- a/data/module/MDB2/Driver/Manager/Common.php
+++ /dev/null
@@ -1,1038 +0,0 @@
- |
-// | Lorenzo Alberton |
-// +----------------------------------------------------------------------+
-//
-// $Id: Common.php 327310 2012-08-27 15:16:18Z danielc $
-//
-
-/**
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- * @author Lorenzo Alberton
- */
-
-/**
- * Base class for the management modules that is extended by each MDB2 driver
- *
- * To load this module in the MDB2 object:
- * $mdb->loadModule('Manager');
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_Driver_Manager_Common extends MDB2_Module_Common
-{
- // {{{ splitTableSchema()
-
- /**
- * Split the "[owner|schema].table" notation into an array
- *
- * @param string $table [schema and] table name
- *
- * @return array array(schema, table)
- * @access private
- */
- function splitTableSchema($table)
- {
- $ret = array();
- if (strpos($table, '.') !== false) {
- return explode('.', $table);
- }
- return array(null, $table);
- }
-
- // }}}
- // {{{ getFieldDeclarationList()
-
- /**
- * Get declaration of a number of field in bulk
- *
- * @param array $fields a multidimensional associative array.
- * The first dimension determines the field name, while the second
- * dimension is keyed with the name of the properties
- * of the field being declared as array indexes. Currently, the types
- * of supported field properties are as follows:
- *
- * default
- * Boolean value to be used as default for this field.
- *
- * notnull
- * Boolean flag that indicates whether this field is constrained
- * to not be set to null.
- *
- * @return mixed string on success, a MDB2 error on failure
- * @access public
- */
- function getFieldDeclarationList($fields)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- if (!is_array($fields) || empty($fields)) {
- return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
- 'missing any fields', __FUNCTION__);
- }
- foreach ($fields as $field_name => $field) {
- $query = $db->getDeclaration($field['type'], $field_name, $field);
- if (MDB2::isError($query)) {
- return $query;
- }
- $query_fields[] = $query;
- }
- return implode(', ', $query_fields);
- }
-
- // }}}
- // {{{ _fixSequenceName()
-
- /**
- * Removes any formatting in an sequence name using the 'seqname_format' option
- *
- * @param string $sqn string that containts name of a potential sequence
- * @param bool $check if only formatted sequences should be returned
- * @return string name of the sequence with possible formatting removed
- * @access protected
- */
- function _fixSequenceName($sqn, $check = false)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $seq_pattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $db->options['seqname_format']).'$/i';
- $seq_name = preg_replace($seq_pattern, '\\1', $sqn);
- if ($seq_name && !strcasecmp($sqn, $db->getSequenceName($seq_name))) {
- return $seq_name;
- }
- if ($check) {
- return false;
- }
- return $sqn;
- }
-
- // }}}
- // {{{ _fixIndexName()
-
- /**
- * Removes any formatting in an index name using the 'idxname_format' option
- *
- * @param string $idx string that containts name of anl index
- * @return string name of the index with eventual formatting removed
- * @access protected
- */
- function _fixIndexName($idx)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $idx_pattern = '/^'.preg_replace('/%s/', '([a-z0-9_]+)', $db->options['idxname_format']).'$/i';
- $idx_name = preg_replace($idx_pattern, '\\1', $idx);
- if ($idx_name && !strcasecmp($idx, $db->getIndexName($idx_name))) {
- return $idx_name;
- }
- return $idx;
- }
-
- // }}}
- // {{{ createDatabase()
-
- /**
- * create a new database
- *
- * @param string $name name of the database that should be created
- * @param array $options array with charset, collation info
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function createDatabase($database, $options = array())
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ alterDatabase()
-
- /**
- * alter an existing database
- *
- * @param string $name name of the database that should be created
- * @param array $options array with charset, collation info
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function alterDatabase($database, $options = array())
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ dropDatabase()
-
- /**
- * drop an existing database
- *
- * @param string $name name of the database that should be dropped
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function dropDatabase($database)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ _getCreateTableQuery()
-
- /**
- * Create a basic SQL query for a new table creation
- *
- * @param string $name Name of the database that should be created
- * @param array $fields Associative array that contains the definition of each field of the new table
- * @param array $options An associative array of table options
- *
- * @return mixed string (the SQL query) on success, a MDB2 error on failure
- * @see createTable()
- */
- function _getCreateTableQuery($name, $fields, $options = array())
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- if (!$name) {
- return $db->raiseError(MDB2_ERROR_CANNOT_CREATE, null, null,
- 'no valid table name specified', __FUNCTION__);
- }
- if (empty($fields)) {
- return $db->raiseError(MDB2_ERROR_CANNOT_CREATE, null, null,
- 'no fields specified for table "'.$name.'"', __FUNCTION__);
- }
- $query_fields = $this->getFieldDeclarationList($fields);
- if (MDB2::isError($query_fields)) {
- return $query_fields;
- }
- if (!empty($options['primary'])) {
- $query_fields.= ', PRIMARY KEY ('.implode(', ', array_keys($options['primary'])).')';
- }
-
- $name = $db->quoteIdentifier($name, true);
- $result = 'CREATE ';
- if (!empty($options['temporary'])) {
- $result .= $this->_getTemporaryTableQuery();
- }
- $result .= " TABLE $name ($query_fields)";
- return $result;
- }
-
- // }}}
- // {{{ _getTemporaryTableQuery()
-
- /**
- * A method to return the required SQL string that fits between CREATE ... TABLE
- * to create the table as a temporary table.
- *
- * Should be overridden in driver classes to return the correct string for the
- * specific database type.
- *
- * The default is to return the string "TEMPORARY" - this will result in a
- * SQL error for any database that does not support temporary tables, or that
- * requires a different SQL command from "CREATE TEMPORARY TABLE".
- *
- * @return string The string required to be placed between "CREATE" and "TABLE"
- * to generate a temporary table, if possible.
- */
- function _getTemporaryTableQuery()
- {
- return 'TEMPORARY';
- }
-
- // }}}
- // {{{ createTable()
-
- /**
- * create a new table
- *
- * @param string $name Name of the database that should be created
- * @param array $fields Associative array that contains the definition of each field of the new table
- * The indexes of the array entries are the names of the fields of the table an
- * the array entry values are associative arrays like those that are meant to be
- * passed with the field definitions to get[Type]Declaration() functions.
- * array(
- * 'id' => array(
- * 'type' => 'integer',
- * 'unsigned' => 1
- * 'notnull' => 1
- * 'default' => 0
- * ),
- * 'name' => array(
- * 'type' => 'text',
- * 'length' => 12
- * ),
- * 'password' => array(
- * 'type' => 'text',
- * 'length' => 12
- * )
- * );
- * @param array $options An associative array of table options:
- * array(
- * 'comment' => 'Foo',
- * 'temporary' => true|false,
- * );
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function createTable($name, $fields, $options = array())
- {
- $query = $this->_getCreateTableQuery($name, $fields, $options);
- if (MDB2::isError($query)) {
- return $query;
- }
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
- $result = $db->exec($query);
- if (MDB2::isError($result)) {
- return $result;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ dropTable()
-
- /**
- * drop an existing table
- *
- * @param string $name name of the table that should be dropped
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function dropTable($name)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $name = $db->quoteIdentifier($name, true);
- $result = $db->exec("DROP TABLE $name");
- if (MDB2::isError($result)) {
- return $result;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ truncateTable()
-
- /**
- * Truncate an existing table (if the TRUNCATE TABLE syntax is not supported,
- * it falls back to a DELETE FROM TABLE query)
- *
- * @param string $name name of the table that should be truncated
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function truncateTable($name)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $name = $db->quoteIdentifier($name, true);
- $result = $db->exec("DELETE FROM $name");
- if (MDB2::isError($result)) {
- return $result;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ vacuum()
-
- /**
- * Optimize (vacuum) all the tables in the db (or only the specified table)
- * and optionally run ANALYZE.
- *
- * @param string $table table name (all the tables if empty)
- * @param array $options an array with driver-specific options:
- * - timeout [int] (in seconds) [mssql-only]
- * - analyze [boolean] [pgsql and mysql]
- * - full [boolean] [pgsql-only]
- * - freeze [boolean] [pgsql-only]
- *
- * @return mixed MDB2_OK success, a MDB2 error on failure
- * @access public
- */
- function vacuum($table = null, $options = array())
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ alterTable()
-
- /**
- * alter an existing table
- *
- * @param string $name name of the table that is intended to be changed.
- * @param array $changes associative array that contains the details of each type
- * of change that is intended to be performed. The types of
- * changes that are currently supported are defined as follows:
- *
- * name
- *
- * New name for the table.
- *
- * add
- *
- * Associative array with the names of fields to be added as
- * indexes of the array. The value of each entry of the array
- * should be set to another associative array with the properties
- * of the fields to be added. The properties of the fields should
- * be the same as defined by the MDB2 parser.
- *
- *
- * remove
- *
- * Associative array with the names of fields to be removed as indexes
- * of the array. Currently the values assigned to each entry are ignored.
- * An empty array should be used for future compatibility.
- *
- * rename
- *
- * Associative array with the names of fields to be renamed as indexes
- * of the array. The value of each entry of the array should be set to
- * another associative array with the entry named name with the new
- * field name and the entry named Declaration that is expected to contain
- * the portion of the field declaration already in DBMS specific SQL code
- * as it is used in the CREATE TABLE statement.
- *
- * change
- *
- * Associative array with the names of the fields to be changed as indexes
- * of the array. Keep in mind that if it is intended to change either the
- * name of a field and any other properties, the change array entries
- * should have the new names of the fields as array indexes.
- *
- * The value of each entry of the array should be set to another associative
- * array with the properties of the fields to that are meant to be changed as
- * array entries. These entries should be assigned to the new values of the
- * respective properties. The properties of the fields should be the same
- * as defined by the MDB2 parser.
- *
- * Example
- * array(
- * 'name' => 'userlist',
- * 'add' => array(
- * 'quota' => array(
- * 'type' => 'integer',
- * 'unsigned' => 1
- * )
- * ),
- * 'remove' => array(
- * 'file_limit' => array(),
- * 'time_limit' => array()
- * ),
- * 'change' => array(
- * 'name' => array(
- * 'length' => '20',
- * 'definition' => array(
- * 'type' => 'text',
- * 'length' => 20,
- * ),
- * )
- * ),
- * 'rename' => array(
- * 'sex' => array(
- * 'name' => 'gender',
- * 'definition' => array(
- * 'type' => 'text',
- * 'length' => 1,
- * 'default' => 'M',
- * ),
- * )
- * )
- * )
- *
- * @param boolean $check indicates whether the function should just check if the DBMS driver
- * can perform the requested table alterations if the value is true or
- * actually perform them otherwise.
- * @access public
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- */
- function alterTable($name, $changes, $check)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ listDatabases()
-
- /**
- * list all databases
- *
- * @return mixed array of database names on success, a MDB2 error on failure
- * @access public
- */
- function listDatabases()
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implementedd', __FUNCTION__);
- }
-
- // }}}
- // {{{ listUsers()
-
- /**
- * list all users
- *
- * @return mixed array of user names on success, a MDB2 error on failure
- * @access public
- */
- function listUsers()
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ listViews()
-
- /**
- * list all views in the current database
- *
- * @param string database, the current is default
- * NB: not all the drivers can get the view names from
- * a database other than the current one
- * @return mixed array of view names on success, a MDB2 error on failure
- * @access public
- */
- function listViews($database = null)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ listTableViews()
-
- /**
- * list the views in the database that reference a given table
- *
- * @param string table for which all referenced views should be found
- * @return mixed array of view names on success, a MDB2 error on failure
- * @access public
- */
- function listTableViews($table)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ listTableTriggers()
-
- /**
- * list all triggers in the database that reference a given table
- *
- * @param string table for which all referenced triggers should be found
- * @return mixed array of trigger names on success, a MDB2 error on failure
- * @access public
- */
- function listTableTriggers($table = null)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ listFunctions()
-
- /**
- * list all functions in the current database
- *
- * @return mixed array of function names on success, a MDB2 error on failure
- * @access public
- */
- function listFunctions()
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ listTables()
-
- /**
- * list all tables in the current database
- *
- * @param string database, the current is default.
- * NB: not all the drivers can get the table names from
- * a database other than the current one
- * @return mixed array of table names on success, a MDB2 error on failure
- * @access public
- */
- function listTables($database = null)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ listTableFields()
-
- /**
- * list all fields in a table in the current database
- *
- * @param string $table name of table that should be used in method
- * @return mixed array of field names on success, a MDB2 error on failure
- * @access public
- */
- function listTableFields($table)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ createIndex()
-
- /**
- * Get the stucture of a field into an array
- *
- * @param string $table name of the table on which the index is to be created
- * @param string $name name of the index to be created
- * @param array $definition associative array that defines properties of the index to be created.
- * Currently, only one property named FIELDS is supported. This property
- * is also an associative with the names of the index fields as array
- * indexes. Each entry of this array is set to another type of associative
- * array that specifies properties of the index that are specific to
- * each field.
- *
- * Currently, only the sorting property is supported. It should be used
- * to define the sorting direction of the index. It may be set to either
- * ascending or descending.
- *
- * Not all DBMS support index sorting direction configuration. The DBMS
- * drivers of those that do not support it ignore this property. Use the
- * function supports() to determine whether the DBMS driver can manage indexes.
- *
- * Example
- * array(
- * 'fields' => array(
- * 'user_name' => array(
- * 'sorting' => 'ascending'
- * ),
- * 'last_login' => array()
- * )
- * )
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function createIndex($table, $name, $definition)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $table = $db->quoteIdentifier($table, true);
- $name = $db->quoteIdentifier($db->getIndexName($name), true);
- $query = "CREATE INDEX $name ON $table";
- $fields = array();
- foreach (array_keys($definition['fields']) as $field) {
- $fields[] = $db->quoteIdentifier($field, true);
- }
- $query .= ' ('. implode(', ', $fields) . ')';
- $result = $db->exec($query);
- if (MDB2::isError($result)) {
- return $result;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ dropIndex()
-
- /**
- * drop existing index
- *
- * @param string $table name of table that should be used in method
- * @param string $name name of the index to be dropped
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function dropIndex($table, $name)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $name = $db->quoteIdentifier($db->getIndexName($name), true);
- $result = $db->exec("DROP INDEX $name");
- if (MDB2::isError($result)) {
- return $result;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ listTableIndexes()
-
- /**
- * list all indexes in a table
- *
- * @param string $table name of table that should be used in method
- * @return mixed array of index names on success, a MDB2 error on failure
- * @access public
- */
- function listTableIndexes($table)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ _getAdvancedFKOptions()
-
- /**
- * Return the FOREIGN KEY query section dealing with non-standard options
- * as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
- *
- * @param array $definition
- * @return string
- * @access protected
- */
- function _getAdvancedFKOptions($definition)
- {
- return '';
- }
-
- // }}}
- // {{{ createConstraint()
-
- /**
- * create a constraint on a table
- *
- * @param string $table name of the table on which the constraint is to be created
- * @param string $name name of the constraint to be created
- * @param array $definition associative array that defines properties of the constraint to be created.
- * The full structure of the array looks like this:
- *
- * array (
- * [primary] => 0
- * [unique] => 0
- * [foreign] => 1
- * [check] => 0
- * [fields] => array (
- * [field1name] => array() // one entry per each field covered
- * [field2name] => array() // by the index
- * [field3name] => array(
- * [sorting] => ascending
- * [position] => 3
- * )
- * )
- * [references] => array(
- * [table] => name
- * [fields] => array(
- * [field1name] => array( //one entry per each referenced field
- * [position] => 1
- * )
- * )
- * )
- * [deferrable] => 0
- * [initiallydeferred] => 0
- * [onupdate] => CASCADE|RESTRICT|SET NULL|SET DEFAULT|NO ACTION
- * [ondelete] => CASCADE|RESTRICT|SET NULL|SET DEFAULT|NO ACTION
- * [match] => SIMPLE|PARTIAL|FULL
- * );
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function createConstraint($table, $name, $definition)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
- $table = $db->quoteIdentifier($table, true);
- $name = $db->quoteIdentifier($db->getIndexName($name), true);
- $query = "ALTER TABLE $table ADD CONSTRAINT $name";
- if (!empty($definition['primary'])) {
- $query.= ' PRIMARY KEY';
- } elseif (!empty($definition['unique'])) {
- $query.= ' UNIQUE';
- } elseif (!empty($definition['foreign'])) {
- $query.= ' FOREIGN KEY';
- }
- $fields = array();
- foreach (array_keys($definition['fields']) as $field) {
- $fields[] = $db->quoteIdentifier($field, true);
- }
- $query .= ' ('. implode(', ', $fields) . ')';
- if (!empty($definition['foreign'])) {
- $query.= ' REFERENCES ' . $db->quoteIdentifier($definition['references']['table'], true);
- $referenced_fields = array();
- foreach (array_keys($definition['references']['fields']) as $field) {
- $referenced_fields[] = $db->quoteIdentifier($field, true);
- }
- $query .= ' ('. implode(', ', $referenced_fields) . ')';
- $query .= $this->_getAdvancedFKOptions($definition);
- }
- $result = $db->exec($query);
- if (MDB2::isError($result)) {
- return $result;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ dropConstraint()
-
- /**
- * drop existing constraint
- *
- * @param string $table name of table that should be used in method
- * @param string $name name of the constraint to be dropped
- * @param string $primary hint if the constraint is primary
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function dropConstraint($table, $name, $primary = false)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $table = $db->quoteIdentifier($table, true);
- $name = $db->quoteIdentifier($db->getIndexName($name), true);
- $result = $db->exec("ALTER TABLE $table DROP CONSTRAINT $name");
- if (MDB2::isError($result)) {
- return $result;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ listTableConstraints()
-
- /**
- * list all constraints in a table
- *
- * @param string $table name of table that should be used in method
- * @return mixed array of constraint names on success, a MDB2 error on failure
- * @access public
- */
- function listTableConstraints($table)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ createSequence()
-
- /**
- * create sequence
- *
- * @param string $seq_name name of the sequence to be created
- * @param string $start start value of the sequence; default is 1
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function createSequence($seq_name, $start = 1)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ dropSequence()
-
- /**
- * drop existing sequence
- *
- * @param string $seq_name name of the sequence to be dropped
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function dropSequence($name)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ listSequences()
-
- /**
- * list all sequences in the current database
- *
- * @param string database, the current is default
- * NB: not all the drivers can get the sequence names from
- * a database other than the current one
- * @return mixed array of sequence names on success, a MDB2 error on failure
- * @access public
- */
- function listSequences($database = null)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
-}
-?>
diff --git a/data/module/MDB2/Driver/Manager/mysql.php b/data/module/MDB2/Driver/Manager/mysql.php
deleted file mode 100644
index 2f33c559e98..00000000000
--- a/data/module/MDB2/Driver/Manager/mysql.php
+++ /dev/null
@@ -1,1471 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: mysql.php 327310 2012-08-27 15:16:18Z danielc $
-//
-
-require_once 'MDB2/Driver/Manager/Common.php';
-
-/**
- * MDB2 MySQL driver for the management modules
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_Driver_Manager_mysql extends MDB2_Driver_Manager_Common
-{
-
- // }}}
- // {{{ createDatabase()
-
- /**
- * create a new database
- *
- * @param string $name name of the database that should be created
- * @param array $options array with charset, collation info
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function createDatabase($name, $options = array())
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $name = $db->quoteIdentifier($name, true);
- $query = 'CREATE DATABASE ' . $name;
- if (!empty($options['charset'])) {
- $query .= ' DEFAULT CHARACTER SET ' . $db->quote($options['charset'], 'text');
- }
- if (!empty($options['collation'])) {
- $query .= ' COLLATE ' . $db->quote($options['collation'], 'text');
- }
- return $db->standaloneQuery($query, null, true);
- }
-
- // }}}
- // {{{ alterDatabase()
-
- /**
- * alter an existing database
- *
- * @param string $name name of the database that is intended to be changed
- * @param array $options array with charset, collation info
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function alterDatabase($name, $options = array())
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $query = 'ALTER DATABASE '. $db->quoteIdentifier($name, true);
- if (!empty($options['charset'])) {
- $query .= ' DEFAULT CHARACTER SET ' . $db->quote($options['charset'], 'text');
- }
- if (!empty($options['collation'])) {
- $query .= ' COLLATE ' . $db->quote($options['collation'], 'text');
- }
- return $db->standaloneQuery($query, null, true);
- }
-
- // }}}
- // {{{ dropDatabase()
-
- /**
- * drop an existing database
- *
- * @param string $name name of the database that should be dropped
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function dropDatabase($name)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $name = $db->quoteIdentifier($name, true);
- $query = "DROP DATABASE $name";
- return $db->standaloneQuery($query, null, true);
- }
-
- // }}}
- // {{{ _getAdvancedFKOptions()
-
- /**
- * Return the FOREIGN KEY query section dealing with non-standard options
- * as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
- *
- * @param array $definition
- * @return string
- * @access protected
- */
- function _getAdvancedFKOptions($definition)
- {
- $query = '';
- if (!empty($definition['match'])) {
- $query .= ' MATCH '.$definition['match'];
- }
- if (!empty($definition['onupdate'])) {
- $query .= ' ON UPDATE '.$definition['onupdate'];
- }
- if (!empty($definition['ondelete'])) {
- $query .= ' ON DELETE '.$definition['ondelete'];
- }
- return $query;
- }
-
- // }}}
- // {{{ createTable()
-
- /**
- * create a new table
- *
- * @param string $name Name of the database that should be created
- * @param array $fields Associative array that contains the definition of each field of the new table
- * The indexes of the array entries are the names of the fields of the table an
- * the array entry values are associative arrays like those that are meant to be
- * passed with the field definitions to get[Type]Declaration() functions.
- * array(
- * 'id' => array(
- * 'type' => 'integer',
- * 'unsigned' => 1
- * 'notnull' => 1
- * 'default' => 0
- * ),
- * 'name' => array(
- * 'type' => 'text',
- * 'length' => 12
- * ),
- * 'password' => array(
- * 'type' => 'text',
- * 'length' => 12
- * )
- * );
- * @param array $options An associative array of table options:
- * array(
- * 'comment' => 'Foo',
- * 'charset' => 'utf8',
- * 'collate' => 'utf8_unicode_ci',
- * 'type' => 'innodb',
- * );
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function createTable($name, $fields, $options = array())
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- // if we have an AUTO_INCREMENT column and a PK on more than one field,
- // we have to handle it differently...
- $autoincrement = null;
- if (empty($options['primary'])) {
- $pk_fields = array();
- foreach ($fields as $fieldname => $def) {
- if (!empty($def['primary'])) {
- $pk_fields[$fieldname] = true;
- }
- if (!empty($def['autoincrement'])) {
- $autoincrement = $fieldname;
- }
- }
- if ((null !== $autoincrement) && count($pk_fields) > 1) {
- $options['primary'] = $pk_fields;
- } else {
- // the PK constraint is on max one field => OK
- $autoincrement = null;
- }
- }
-
- $query = $this->_getCreateTableQuery($name, $fields, $options);
- if (MDB2::isError($query)) {
- return $query;
- }
-
- if (null !== $autoincrement) {
- // we have to remove the PK clause added by _getIntegerDeclaration()
- $query = str_replace('AUTO_INCREMENT PRIMARY KEY', 'AUTO_INCREMENT', $query);
- }
-
- $options_strings = array();
-
- if (!empty($options['comment'])) {
- $options_strings['comment'] = 'COMMENT = '.$db->quote($options['comment'], 'text');
- }
-
- if (!empty($options['charset'])) {
- $options_strings['charset'] = 'DEFAULT CHARACTER SET '.$options['charset'];
- if (!empty($options['collate'])) {
- $options_strings['charset'].= ' COLLATE '.$options['collate'];
- }
- }
-
- $type = false;
- if (!empty($options['type'])) {
- $type = $options['type'];
- } elseif ($db->options['default_table_type']) {
- $type = $db->options['default_table_type'];
- }
- if ($type) {
- $options_strings[] = "ENGINE = $type";
- }
-
- if (!empty($options_strings)) {
- $query .= ' '.implode(' ', $options_strings);
- }
- $result = $db->exec($query);
- if (MDB2::isError($result)) {
- return $result;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ dropTable()
-
- /**
- * drop an existing table
- *
- * @param string $name name of the table that should be dropped
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function dropTable($name)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- //delete the triggers associated to existing FK constraints
- $constraints = $this->listTableConstraints($name);
- if (!MDB2::isError($constraints) && !empty($constraints)) {
- $db->loadModule('Reverse', null, true);
- foreach ($constraints as $constraint) {
- $definition = $db->reverse->getTableConstraintDefinition($name, $constraint);
- if (!MDB2::isError($definition) && !empty($definition['foreign'])) {
- $result = $this->_dropFKTriggers($name, $constraint, $definition['references']['table']);
- if (MDB2::isError($result)) {
- return $result;
- }
- }
- }
- }
-
- return parent::dropTable($name);
- }
-
- // }}}
- // {{{ truncateTable()
-
- /**
- * Truncate an existing table (if the TRUNCATE TABLE syntax is not supported,
- * it falls back to a DELETE FROM TABLE query)
- *
- * @param string $name name of the table that should be truncated
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function truncateTable($name)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $name = $db->quoteIdentifier($name, true);
- $result = $db->exec("TRUNCATE TABLE $name");
- if (MDB2::isError($result)) {
- return $result;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ vacuum()
-
- /**
- * Optimize (vacuum) all the tables in the db (or only the specified table)
- * and optionally run ANALYZE.
- *
- * @param string $table table name (all the tables if empty)
- * @param array $options an array with driver-specific options:
- * - timeout [int] (in seconds) [mssql-only]
- * - analyze [boolean] [pgsql and mysql]
- * - full [boolean] [pgsql-only]
- * - freeze [boolean] [pgsql-only]
- *
- * @return mixed MDB2_OK success, a MDB2 error on failure
- * @access public
- */
- function vacuum($table = null, $options = array())
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- if (empty($table)) {
- $table = $this->listTables();
- if (MDB2::isError($table)) {
- return $table;
- }
- }
- if (is_array($table)) {
- foreach (array_keys($table) as $k) {
- $table[$k] = $db->quoteIdentifier($table[$k], true);
- }
- $table = implode(', ', $table);
- } else {
- $table = $db->quoteIdentifier($table, true);
- }
-
- $result = $db->exec('OPTIMIZE TABLE '.$table);
- if (MDB2::isError($result)) {
- return $result;
- }
- if (!empty($options['analyze'])) {
- $result = $db->exec('ANALYZE TABLE '.$table);
- if (MDB2::isError($result)) {
- return $result;
- }
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ alterTable()
-
- /**
- * alter an existing table
- *
- * @param string $name name of the table that is intended to be changed.
- * @param array $changes associative array that contains the details of each type
- * of change that is intended to be performed. The types of
- * changes that are currently supported are defined as follows:
- *
- * name
- *
- * New name for the table.
- *
- * add
- *
- * Associative array with the names of fields to be added as
- * indexes of the array. The value of each entry of the array
- * should be set to another associative array with the properties
- * of the fields to be added. The properties of the fields should
- * be the same as defined by the MDB2 parser.
- *
- *
- * remove
- *
- * Associative array with the names of fields to be removed as indexes
- * of the array. Currently the values assigned to each entry are ignored.
- * An empty array should be used for future compatibility.
- *
- * rename
- *
- * Associative array with the names of fields to be renamed as indexes
- * of the array. The value of each entry of the array should be set to
- * another associative array with the entry named name with the new
- * field name and the entry named Declaration that is expected to contain
- * the portion of the field declaration already in DBMS specific SQL code
- * as it is used in the CREATE TABLE statement.
- *
- * change
- *
- * Associative array with the names of the fields to be changed as indexes
- * of the array. Keep in mind that if it is intended to change either the
- * name of a field and any other properties, the change array entries
- * should have the new names of the fields as array indexes.
- *
- * The value of each entry of the array should be set to another associative
- * array with the properties of the fields to that are meant to be changed as
- * array entries. These entries should be assigned to the new values of the
- * respective properties. The properties of the fields should be the same
- * as defined by the MDB2 parser.
- *
- * Example
- * array(
- * 'name' => 'userlist',
- * 'add' => array(
- * 'quota' => array(
- * 'type' => 'integer',
- * 'unsigned' => 1
- * )
- * ),
- * 'remove' => array(
- * 'file_limit' => array(),
- * 'time_limit' => array()
- * ),
- * 'change' => array(
- * 'name' => array(
- * 'length' => '20',
- * 'definition' => array(
- * 'type' => 'text',
- * 'length' => 20,
- * ),
- * )
- * ),
- * 'rename' => array(
- * 'sex' => array(
- * 'name' => 'gender',
- * 'definition' => array(
- * 'type' => 'text',
- * 'length' => 1,
- * 'default' => 'M',
- * ),
- * )
- * )
- * )
- *
- * @param boolean $check indicates whether the function should just check if the DBMS driver
- * can perform the requested table alterations if the value is true or
- * actually perform them otherwise.
- * @access public
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- */
- function alterTable($name, $changes, $check)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- foreach ($changes as $change_name => $change) {
- switch ($change_name) {
- case 'add':
- case 'remove':
- case 'change':
- case 'rename':
- case 'name':
- break;
- default:
- return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null,
- 'change type "'.$change_name.'" not yet supported', __FUNCTION__);
- }
- }
-
- if ($check) {
- return MDB2_OK;
- }
-
- $query = '';
- if (!empty($changes['name'])) {
- $change_name = $db->quoteIdentifier($changes['name'], true);
- $query .= 'RENAME TO ' . $change_name;
- }
-
- if (!empty($changes['add']) && is_array($changes['add'])) {
- foreach ($changes['add'] as $field_name => $field) {
- if ($query) {
- $query.= ', ';
- }
- $query.= 'ADD ' . $db->getDeclaration($field['type'], $field_name, $field);
- }
- }
-
- if (!empty($changes['remove']) && is_array($changes['remove'])) {
- foreach ($changes['remove'] as $field_name => $field) {
- if ($query) {
- $query.= ', ';
- }
- $field_name = $db->quoteIdentifier($field_name, true);
- $query.= 'DROP ' . $field_name;
- }
- }
-
- $rename = array();
- if (!empty($changes['rename']) && is_array($changes['rename'])) {
- foreach ($changes['rename'] as $field_name => $field) {
- $rename[$field['name']] = $field_name;
- }
- }
-
- if (!empty($changes['change']) && is_array($changes['change'])) {
- foreach ($changes['change'] as $field_name => $field) {
- if ($query) {
- $query.= ', ';
- }
- if (isset($rename[$field_name])) {
- $old_field_name = $rename[$field_name];
- unset($rename[$field_name]);
- } else {
- $old_field_name = $field_name;
- }
- $old_field_name = $db->quoteIdentifier($old_field_name, true);
- $query.= "CHANGE $old_field_name " . $db->getDeclaration($field['definition']['type'], $field_name, $field['definition']);
- }
- }
-
- if (!empty($rename) && is_array($rename)) {
- foreach ($rename as $rename_name => $renamed_field) {
- if ($query) {
- $query.= ', ';
- }
- $field = $changes['rename'][$renamed_field];
- $renamed_field = $db->quoteIdentifier($renamed_field, true);
- $query.= 'CHANGE ' . $renamed_field . ' ' . $db->getDeclaration($field['definition']['type'], $field['name'], $field['definition']);
- }
- }
-
- if (!$query) {
- return MDB2_OK;
- }
-
- $name = $db->quoteIdentifier($name, true);
- $result = $db->exec("ALTER TABLE $name $query");
- if (MDB2::isError($result)) {
- return $result;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ listDatabases()
-
- /**
- * list all databases
- *
- * @return mixed array of database names on success, a MDB2 error on failure
- * @access public
- */
- function listDatabases()
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $result = $db->queryCol('SHOW DATABASES');
- if (MDB2::isError($result)) {
- return $result;
- }
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
- }
- return $result;
- }
-
- // }}}
- // {{{ listUsers()
-
- /**
- * list all users
- *
- * @return mixed array of user names on success, a MDB2 error on failure
- * @access public
- */
- function listUsers()
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->queryCol('SELECT DISTINCT USER FROM mysql.USER');
- }
-
- // }}}
- // {{{ listFunctions()
-
- /**
- * list all functions in the current database
- *
- * @return mixed array of function names on success, a MDB2 error on failure
- * @access public
- */
- function listFunctions()
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $query = "SELECT name FROM mysql.proc";
- /*
- SELECT ROUTINE_NAME
- FROM INFORMATION_SCHEMA.ROUTINES
- WHERE ROUTINE_TYPE = 'FUNCTION'
- */
- $result = $db->queryCol($query);
- if (MDB2::isError($result)) {
- return $result;
- }
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
- }
- return $result;
- }
-
- // }}}
- // {{{ listTableTriggers()
-
- /**
- * list all triggers in the database that reference a given table
- *
- * @param string table for which all referenced triggers should be found
- * @return mixed array of trigger names on success, a MDB2 error on failure
- * @access public
- */
- function listTableTriggers($table = null)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $query = 'SHOW TRIGGERS';
- if (null !== $table) {
- $table = $db->quote($table, 'text');
- $query .= " LIKE $table";
- }
- $result = $db->queryCol($query);
- if (MDB2::isError($result)) {
- return $result;
- }
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
- }
- return $result;
- }
-
- // }}}
- // {{{ listTables()
-
- /**
- * list all tables in the current database
- *
- * @param string database, the current is default
- * @return mixed array of table names on success, a MDB2 error on failure
- * @access public
- */
- function listTables($database = null)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $query = "SHOW /*!50002 FULL*/ TABLES";
- if (null !== $database) {
- $query .= " FROM $database";
- }
- $query.= "/*!50002 WHERE Table_type = 'BASE TABLE'*/";
-
- $table_names = $db->queryAll($query, null, MDB2_FETCHMODE_ORDERED);
- if (MDB2::isError($table_names)) {
- return $table_names;
- }
-
- $result = array();
- foreach ($table_names as $table) {
- if (!$this->_fixSequenceName($table[0], true)) {
- $result[] = $table[0];
- }
- }
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
- }
- return $result;
- }
-
- // }}}
- // {{{ listViews()
-
- /**
- * list all views in the current database
- *
- * @param string database, the current is default
- * @return mixed array of view names on success, a MDB2 error on failure
- * @access public
- */
- function listViews($database = null)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $query = 'SHOW FULL TABLES';
- if (null !== $database) {
- $query.= " FROM $database";
- }
- $query.= " WHERE Table_type = 'VIEW'";
-
- $result = $db->queryCol($query);
- if (MDB2::isError($result)) {
- return $result;
- }
-
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
- }
- return $result;
- }
-
- // }}}
- // {{{ listTableFields()
-
- /**
- * list all fields in a table in the current database
- *
- * @param string $table name of table that should be used in method
- * @return mixed array of field names on success, a MDB2 error on failure
- * @access public
- */
- function listTableFields($table)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $table = $db->quoteIdentifier($table, true);
- $result = $db->queryCol("SHOW COLUMNS FROM $table");
- if (MDB2::isError($result)) {
- return $result;
- }
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
- }
- return $result;
- }
-
- // }}}
- // {{{ createIndex()
-
- /**
- * Get the stucture of a field into an array
- *
- * @author Leoncx
- * @param string $table name of the table on which the index is to be created
- * @param string $name name of the index to be created
- * @param array $definition associative array that defines properties of the index to be created.
- * Currently, only one property named FIELDS is supported. This property
- * is also an associative with the names of the index fields as array
- * indexes. Each entry of this array is set to another type of associative
- * array that specifies properties of the index that are specific to
- * each field.
- *
- * Currently, only the sorting property is supported. It should be used
- * to define the sorting direction of the index. It may be set to either
- * ascending or descending.
- *
- * Not all DBMS support index sorting direction configuration. The DBMS
- * drivers of those that do not support it ignore this property. Use the
- * function supports() to determine whether the DBMS driver can manage indexes.
- *
- * Example
- * array(
- * 'fields' => array(
- * 'user_name' => array(
- * 'sorting' => 'ascending'
- * 'length' => 10
- * ),
- * 'last_login' => array()
- * )
- * )
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function createIndex($table, $name, $definition)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $table = $db->quoteIdentifier($table, true);
- $name = $db->quoteIdentifier($db->getIndexName($name), true);
- $query = "CREATE INDEX $name ON $table";
- $fields = array();
- foreach ($definition['fields'] as $field => $fieldinfo) {
- if (!empty($fieldinfo['length'])) {
- $fields[] = $db->quoteIdentifier($field, true) . '(' . $fieldinfo['length'] . ')';
- } else {
- $fields[] = $db->quoteIdentifier($field, true);
- }
- }
- $query .= ' ('. implode(', ', $fields) . ')';
- $result = $db->exec($query);
- if (MDB2::isError($result)) {
- return $result;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ dropIndex()
-
- /**
- * drop existing index
- *
- * @param string $table name of table that should be used in method
- * @param string $name name of the index to be dropped
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function dropIndex($table, $name)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $table = $db->quoteIdentifier($table, true);
- $name = $db->quoteIdentifier($db->getIndexName($name), true);
- $result = $db->exec("DROP INDEX $name ON $table");
- if (MDB2::isError($result)) {
- return $result;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ listTableIndexes()
-
- /**
- * list all indexes in a table
- *
- * @param string $table name of table that should be used in method
- * @return mixed array of index names on success, a MDB2 error on failure
- * @access public
- */
- function listTableIndexes($table)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $key_name = 'Key_name';
- $non_unique = 'Non_unique';
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- if ($db->options['field_case'] == CASE_LOWER) {
- $key_name = strtolower($key_name);
- $non_unique = strtolower($non_unique);
- } else {
- $key_name = strtoupper($key_name);
- $non_unique = strtoupper($non_unique);
- }
- }
-
- $table = $db->quoteIdentifier($table, true);
- $query = "SHOW INDEX FROM $table";
- $indexes = $db->queryAll($query, null, MDB2_FETCHMODE_ASSOC);
- if (MDB2::isError($indexes)) {
- return $indexes;
- }
-
- $result = array();
- foreach ($indexes as $index_data) {
- if ($index_data[$non_unique] && ($index = $this->_fixIndexName($index_data[$key_name]))) {
- $result[$index] = true;
- }
- }
-
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- $result = array_change_key_case($result, $db->options['field_case']);
- }
- return array_keys($result);
- }
-
- // }}}
- // {{{ createConstraint()
-
- /**
- * create a constraint on a table
- *
- * @param string $table name of the table on which the constraint is to be created
- * @param string $name name of the constraint to be created
- * @param array $definition associative array that defines properties of the constraint to be created.
- * Currently, only one property named FIELDS is supported. This property
- * is also an associative with the names of the constraint fields as array
- * constraints. Each entry of this array is set to another type of associative
- * array that specifies properties of the constraint that are specific to
- * each field.
- *
- * Example
- * array(
- * 'fields' => array(
- * 'user_name' => array(),
- * 'last_login' => array()
- * )
- * )
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function createConstraint($table, $name, $definition)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $type = '';
- $idx_name = $db->quoteIdentifier($db->getIndexName($name), true);
- if (!empty($definition['primary'])) {
- $type = 'PRIMARY';
- $idx_name = 'KEY';
- } elseif (!empty($definition['unique'])) {
- $type = 'UNIQUE';
- } elseif (!empty($definition['foreign'])) {
- $type = 'CONSTRAINT';
- }
- if (empty($type)) {
- return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
- 'invalid definition, could not create constraint', __FUNCTION__);
- }
-
- $table_quoted = $db->quoteIdentifier($table, true);
- $query = "ALTER TABLE $table_quoted ADD $type $idx_name";
- if (!empty($definition['foreign'])) {
- $query .= ' FOREIGN KEY';
- }
- $fields = array();
- foreach ($definition['fields'] as $field => $fieldinfo) {
- $quoted = $db->quoteIdentifier($field, true);
- if (!empty($fieldinfo['length'])) {
- $quoted .= '(' . $fieldinfo['length'] . ')';
- }
- $fields[] = $quoted;
- }
- $query .= ' ('. implode(', ', $fields) . ')';
- if (!empty($definition['foreign'])) {
- $query.= ' REFERENCES ' . $db->quoteIdentifier($definition['references']['table'], true);
- $referenced_fields = array();
- foreach (array_keys($definition['references']['fields']) as $field) {
- $referenced_fields[] = $db->quoteIdentifier($field, true);
- }
- $query .= ' ('. implode(', ', $referenced_fields) . ')';
- $query .= $this->_getAdvancedFKOptions($definition);
-
- // add index on FK column(s) or we can't add a FK constraint
- // @see http://forums.mysql.com/read.php?22,19755,226009
- $result = $this->createIndex($table, $name.'_fkidx', $definition);
- if (MDB2::isError($result)) {
- return $result;
- }
- }
- $res = $db->exec($query);
- if (MDB2::isError($res)) {
- return $res;
- }
- if (!empty($definition['foreign'])) {
- return $this->_createFKTriggers($table, array($name => $definition));
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ dropConstraint()
-
- /**
- * drop existing constraint
- *
- * @param string $table name of table that should be used in method
- * @param string $name name of the constraint to be dropped
- * @param string $primary hint if the constraint is primary
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function dropConstraint($table, $name, $primary = false)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- if ($primary || strtolower($name) == 'primary') {
- $query = 'ALTER TABLE '. $db->quoteIdentifier($table, true) .' DROP PRIMARY KEY';
- $result = $db->exec($query);
- if (MDB2::isError($result)) {
- return $result;
- }
- return MDB2_OK;
- }
-
- //is it a FK constraint? If so, also delete the associated triggers
- $db->loadModule('Reverse', null, true);
- $definition = $db->reverse->getTableConstraintDefinition($table, $name);
- if (!MDB2::isError($definition) && !empty($definition['foreign'])) {
- //first drop the FK enforcing triggers
- $result = $this->_dropFKTriggers($table, $name, $definition['references']['table']);
- if (MDB2::isError($result)) {
- return $result;
- }
- //then drop the constraint itself
- $table = $db->quoteIdentifier($table, true);
- $name = $db->quoteIdentifier($db->getIndexName($name), true);
- $query = "ALTER TABLE $table DROP FOREIGN KEY $name";
- $result = $db->exec($query);
- if (MDB2::isError($result)) {
- return $result;
- }
- return MDB2_OK;
- }
-
- $table = $db->quoteIdentifier($table, true);
- $name = $db->quoteIdentifier($db->getIndexName($name), true);
- $query = "ALTER TABLE $table DROP INDEX $name";
- $result = $db->exec($query);
- if (MDB2::isError($result)) {
- return $result;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ _createFKTriggers()
-
- /**
- * Create triggers to enforce the FOREIGN KEY constraint on the table
- *
- * NB: since there's no RAISE_APPLICATION_ERROR facility in mysql,
- * we call a non-existent procedure to raise the FK violation message.
- * @see http://forums.mysql.com/read.php?99,55108,71877#msg-71877
- *
- * @param string $table table name
- * @param array $foreign_keys FOREIGN KEY definitions
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access private
- */
- function _createFKTriggers($table, $foreign_keys)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
- // create triggers to enforce FOREIGN KEY constraints
- if ($db->supports('triggers') && !empty($foreign_keys)) {
- $table_quoted = $db->quoteIdentifier($table, true);
- foreach ($foreign_keys as $fkname => $fkdef) {
- if (empty($fkdef)) {
- continue;
- }
- //set actions to default if not set
- $fkdef['onupdate'] = empty($fkdef['onupdate']) ? $db->options['default_fk_action_onupdate'] : strtoupper($fkdef['onupdate']);
- $fkdef['ondelete'] = empty($fkdef['ondelete']) ? $db->options['default_fk_action_ondelete'] : strtoupper($fkdef['ondelete']);
-
- $trigger_names = array(
- 'insert' => $fkname.'_insert_trg',
- 'update' => $fkname.'_update_trg',
- 'pk_update' => $fkname.'_pk_update_trg',
- 'pk_delete' => $fkname.'_pk_delete_trg',
- );
- $table_fields = array_keys($fkdef['fields']);
- $referenced_fields = array_keys($fkdef['references']['fields']);
-
- //create the ON [UPDATE|DELETE] triggers on the primary table
- $restrict_action = ' IF (SELECT ';
- $aliased_fields = array();
- foreach ($table_fields as $field) {
- $aliased_fields[] = $table_quoted .'.'.$field .' AS '.$field;
- }
- $restrict_action .= implode(',', $aliased_fields)
- .' FROM '.$table_quoted
- .' WHERE ';
- $conditions = array();
- $new_values = array();
- $null_values = array();
- for ($i=0; $i OLD.'.$referenced_fields[$i];
- }
-
- $restrict_action .= implode(' AND ', $conditions).') IS NOT NULL';
- $restrict_action2 = empty($conditions2) ? '' : ' AND (' .implode(' OR ', $conditions2) .')';
- $restrict_action3 = ' THEN CALL %s_ON_TABLE_'.$table.'_VIOLATES_FOREIGN_KEY_CONSTRAINT();'
- .' END IF;';
-
- $restrict_action_update = $restrict_action . $restrict_action2 . $restrict_action3;
- $restrict_action_delete = $restrict_action . $restrict_action3; // There is no NEW row in on DELETE trigger
-
- $cascade_action_update = 'UPDATE '.$table_quoted.' SET '.implode(', ', $new_values) .' WHERE '.implode(' AND ', $conditions). ';';
- $cascade_action_delete = 'DELETE FROM '.$table_quoted.' WHERE '.implode(' AND ', $conditions). ';';
- $setnull_action = 'UPDATE '.$table_quoted.' SET '.implode(', ', $null_values).' WHERE '.implode(' AND ', $conditions). ';';
-
- if ('SET DEFAULT' == $fkdef['onupdate'] || 'SET DEFAULT' == $fkdef['ondelete']) {
- $db->loadModule('Reverse', null, true);
- $default_values = array();
- foreach ($table_fields as $table_field) {
- $field_definition = $db->reverse->getTableFieldDefinition($table, $field);
- if (MDB2::isError($field_definition)) {
- return $field_definition;
- }
- $default_values[] = $table_field .' = '. $field_definition[0]['default'];
- }
- $setdefault_action = 'UPDATE '.$table_quoted.' SET '.implode(', ', $default_values).' WHERE '.implode(' AND ', $conditions). ';';
- }
-
- $query = 'CREATE TRIGGER %s'
- .' %s ON '.$fkdef['references']['table']
- .' FOR EACH ROW BEGIN '
- .' SET FOREIGN_KEY_CHECKS = 0; '; //only really needed for ON UPDATE CASCADE
-
- if ('CASCADE' == $fkdef['onupdate']) {
- $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $cascade_action_update;
- } elseif ('SET NULL' == $fkdef['onupdate']) {
- $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $setnull_action;
- } elseif ('SET DEFAULT' == $fkdef['onupdate']) {
- $sql_update = sprintf($query, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update') . $setdefault_action;
- } elseif ('NO ACTION' == $fkdef['onupdate']) {
- $sql_update = sprintf($query.$restrict_action_update, $trigger_names['pk_update'], 'AFTER UPDATE', 'update');
- } elseif ('RESTRICT' == $fkdef['onupdate']) {
- $sql_update = sprintf($query.$restrict_action_update, $trigger_names['pk_update'], 'BEFORE UPDATE', 'update');
- }
- if ('CASCADE' == $fkdef['ondelete']) {
- $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $cascade_action_delete;
- } elseif ('SET NULL' == $fkdef['ondelete']) {
- $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $setnull_action;
- } elseif ('SET DEFAULT' == $fkdef['ondelete']) {
- $sql_delete = sprintf($query, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete') . $setdefault_action;
- } elseif ('NO ACTION' == $fkdef['ondelete']) {
- $sql_delete = sprintf($query.$restrict_action_delete, $trigger_names['pk_delete'], 'AFTER DELETE', 'delete');
- } elseif ('RESTRICT' == $fkdef['ondelete']) {
- $sql_delete = sprintf($query.$restrict_action_delete, $trigger_names['pk_delete'], 'BEFORE DELETE', 'delete');
- }
- $sql_update .= ' SET FOREIGN_KEY_CHECKS = 1; END;';
- $sql_delete .= ' SET FOREIGN_KEY_CHECKS = 1; END;';
-
- $db->pushErrorHandling(PEAR_ERROR_RETURN);
- $db->expectError(MDB2_ERROR_CANNOT_CREATE);
- $result = $db->exec($sql_delete);
- $expected_errmsg = 'This MySQL version doesn\'t support multiple triggers with the same action time and event for one table';
- $db->popExpect();
- $db->popErrorHandling();
- if (MDB2::isError($result)) {
- if ($result->getCode() != MDB2_ERROR_CANNOT_CREATE) {
- return $result;
- }
- $db->warnings[] = $expected_errmsg;
- }
- $db->pushErrorHandling(PEAR_ERROR_RETURN);
- $db->expectError(MDB2_ERROR_CANNOT_CREATE);
- $result = $db->exec($sql_update);
- $db->popExpect();
- $db->popErrorHandling();
- if (MDB2::isError($result) && $result->getCode() != MDB2_ERROR_CANNOT_CREATE) {
- if ($result->getCode() != MDB2_ERROR_CANNOT_CREATE) {
- return $result;
- }
- $db->warnings[] = $expected_errmsg;
- }
- }
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ _dropFKTriggers()
-
- /**
- * Drop the triggers created to enforce the FOREIGN KEY constraint on the table
- *
- * @param string $table table name
- * @param string $fkname FOREIGN KEY constraint name
- * @param string $referenced_table referenced table name
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access private
- */
- function _dropFKTriggers($table, $fkname, $referenced_table)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $triggers = $this->listTableTriggers($table);
- $triggers2 = $this->listTableTriggers($referenced_table);
- if (!MDB2::isError($triggers2) && !MDB2::isError($triggers)) {
- $triggers = array_merge($triggers, $triggers2);
- $pattern = '/^'.$fkname.'(_pk)?_(insert|update|delete)_trg$/i';
- foreach ($triggers as $trigger) {
- if (preg_match($pattern, $trigger)) {
- $result = $db->exec('DROP TRIGGER '.$trigger);
- if (MDB2::isError($result)) {
- return $result;
- }
- }
- }
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ listTableConstraints()
-
- /**
- * list all constraints in a table
- *
- * @param string $table name of table that should be used in method
- * @return mixed array of constraint names on success, a MDB2 error on failure
- * @access public
- */
- function listTableConstraints($table)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $key_name = 'Key_name';
- $non_unique = 'Non_unique';
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- if ($db->options['field_case'] == CASE_LOWER) {
- $key_name = strtolower($key_name);
- $non_unique = strtolower($non_unique);
- } else {
- $key_name = strtoupper($key_name);
- $non_unique = strtoupper($non_unique);
- }
- }
-
- $query = 'SHOW INDEX FROM ' . $db->quoteIdentifier($table, true);
- $indexes = $db->queryAll($query, null, MDB2_FETCHMODE_ASSOC);
- if (MDB2::isError($indexes)) {
- return $indexes;
- }
-
- $result = array();
- foreach ($indexes as $index_data) {
- if (!$index_data[$non_unique]) {
- if ($index_data[$key_name] !== 'PRIMARY') {
- $index = $this->_fixIndexName($index_data[$key_name]);
- } else {
- $index = 'PRIMARY';
- }
- if (!empty($index)) {
- $result[$index] = true;
- }
- }
- }
-
- //list FOREIGN KEY constraints...
- $query = 'SHOW CREATE TABLE '. $db->escape($table);
- $definition = $db->queryOne($query, 'text', 1);
- if (!MDB2::isError($definition) && !empty($definition)) {
- $pattern = '/\bCONSTRAINT\b\s+([^\s]+)\s+\bFOREIGN KEY\b/Uims';
- if (preg_match_all($pattern, str_replace('`', '', $definition), $matches) > 0) {
- foreach ($matches[1] as $constraint) {
- $result[$constraint] = true;
- }
- }
- }
-
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- $result = array_change_key_case($result, $db->options['field_case']);
- }
- return array_keys($result);
- }
-
- // }}}
- // {{{ createSequence()
-
- /**
- * create sequence
- *
- * @param string $seq_name name of the sequence to be created
- * @param string $start start value of the sequence; default is 1
- * @param array $options An associative array of table options:
- * array(
- * 'comment' => 'Foo',
- * 'charset' => 'utf8',
- * 'collate' => 'utf8_unicode_ci',
- * 'type' => 'innodb',
- * );
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function createSequence($seq_name, $start = 1, $options = array())
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
- $seqcol_name = $db->quoteIdentifier($db->options['seqcol_name'], true);
-
- $options_strings = array();
-
- if (!empty($options['comment'])) {
- $options_strings['comment'] = 'COMMENT = '.$db->quote($options['comment'], 'text');
- }
-
- if (!empty($options['charset'])) {
- $options_strings['charset'] = 'DEFAULT CHARACTER SET '.$options['charset'];
- if (!empty($options['collate'])) {
- $options_strings['charset'].= ' COLLATE '.$options['collate'];
- }
- }
-
- $type = false;
- if (!empty($options['type'])) {
- $type = $options['type'];
- } elseif ($db->options['default_table_type']) {
- $type = $db->options['default_table_type'];
- }
- if ($type) {
- $options_strings[] = "ENGINE = $type";
- }
-
- $query = "CREATE TABLE $sequence_name ($seqcol_name INT NOT NULL AUTO_INCREMENT, PRIMARY KEY ($seqcol_name))";
- if (!empty($options_strings)) {
- $query .= ' '.implode(' ', $options_strings);
- }
- $res = $db->exec($query);
- if (MDB2::isError($res)) {
- return $res;
- }
-
- if ($start == 1) {
- return MDB2_OK;
- }
-
- $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (".($start-1).')';
- $res = $db->exec($query);
- if (!MDB2::isError($res)) {
- return MDB2_OK;
- }
-
- // Handle error
- $result = $db->exec("DROP TABLE $sequence_name");
- if (MDB2::isError($result)) {
- return $db->raiseError($result, null, null,
- 'could not drop inconsistent sequence table', __FUNCTION__);
- }
-
- return $db->raiseError($res, null, null,
- 'could not create sequence table', __FUNCTION__);
- }
-
- // }}}
- // {{{ dropSequence()
-
- /**
- * drop existing sequence
- *
- * @param string $seq_name name of the sequence to be dropped
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function dropSequence($seq_name)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
- $result = $db->exec("DROP TABLE $sequence_name");
- if (MDB2::isError($result)) {
- return $result;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ listSequences()
-
- /**
- * list all sequences in the current database
- *
- * @param string database, the current is default
- * @return mixed array of sequence names on success, a MDB2 error on failure
- * @access public
- */
- function listSequences($database = null)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $query = "SHOW TABLES";
- if (null !== $database) {
- $query .= " FROM $database";
- }
- $table_names = $db->queryCol($query);
- if (MDB2::isError($table_names)) {
- return $table_names;
- }
-
- $result = array();
- foreach ($table_names as $table_name) {
- if ($sqn = $this->_fixSequenceName($table_name, true)) {
- $result[] = $sqn;
- }
- }
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
- }
- return $result;
- }
-
- // }}}
-}
-?>
diff --git a/data/module/MDB2/Driver/Manager/pgsql.php b/data/module/MDB2/Driver/Manager/pgsql.php
deleted file mode 100644
index 75c4e757e15..00000000000
--- a/data/module/MDB2/Driver/Manager/pgsql.php
+++ /dev/null
@@ -1,978 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: pgsql.php 327310 2012-08-27 15:16:18Z danielc $
-
-require_once 'MDB2/Driver/Manager/Common.php';
-
-/**
- * MDB2 MySQL driver for the management modules
- *
- * @package MDB2
- * @category Database
- * @author Paul Cooper
- */
-class MDB2_Driver_Manager_pgsql extends MDB2_Driver_Manager_Common
-{
- // {{{ createDatabase()
-
- /**
- * create a new database
- *
- * @param string $name name of the database that should be created
- * @param array $options array with charset info
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function createDatabase($name, $options = array())
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $name = $db->quoteIdentifier($name, true);
- $query = 'CREATE DATABASE ' . $name;
- if (!empty($options['charset'])) {
- $query .= ' WITH ENCODING ' . $db->quote($options['charset'], 'text');
- }
- return $db->standaloneQuery($query, null, true);
- }
-
- // }}}
- // {{{ alterDatabase()
-
- /**
- * alter an existing database
- *
- * @param string $name name of the database that is intended to be changed
- * @param array $options array with name, owner info
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function alterDatabase($name, $options = array())
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $query = '';
- if (!empty($options['name'])) {
- $query .= ' RENAME TO ' . $options['name'];
- }
- if (!empty($options['owner'])) {
- $query .= ' OWNER TO ' . $options['owner'];
- }
-
- if (empty($query)) {
- return MDB2_OK;
- }
-
- $query = 'ALTER DATABASE '. $db->quoteIdentifier($name, true) . $query;
- return $db->standaloneQuery($query, null, true);
- }
-
- // }}}
- // {{{ dropDatabase()
-
- /**
- * drop an existing database
- *
- * @param string $name name of the database that should be dropped
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function dropDatabase($name)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $name = $db->quoteIdentifier($name, true);
- $query = "DROP DATABASE $name";
- return $db->standaloneQuery($query, null, true);
- }
-
- // }}}
- // {{{ _getAdvancedFKOptions()
-
- /**
- * Return the FOREIGN KEY query section dealing with non-standard options
- * as MATCH, INITIALLY DEFERRED, ON UPDATE, ...
- *
- * @param array $definition
- * @return string
- * @access protected
- */
- function _getAdvancedFKOptions($definition)
- {
- $query = '';
- if (!empty($definition['match'])) {
- $query .= ' MATCH '.$definition['match'];
- }
- if (!empty($definition['onupdate'])) {
- $query .= ' ON UPDATE '.$definition['onupdate'];
- }
- if (!empty($definition['ondelete'])) {
- $query .= ' ON DELETE '.$definition['ondelete'];
- }
- if (!empty($definition['deferrable'])) {
- $query .= ' DEFERRABLE';
- } else {
- $query .= ' NOT DEFERRABLE';
- }
- if (!empty($definition['initiallydeferred'])) {
- $query .= ' INITIALLY DEFERRED';
- } else {
- $query .= ' INITIALLY IMMEDIATE';
- }
- return $query;
- }
-
- // }}}
- // {{{ truncateTable()
-
- /**
- * Truncate an existing table (if the TRUNCATE TABLE syntax is not supported,
- * it falls back to a DELETE FROM TABLE query)
- *
- * @param string $name name of the table that should be truncated
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function truncateTable($name)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $name = $db->quoteIdentifier($name, true);
- $result = $db->exec("TRUNCATE TABLE $name");
- if (MDB2::isError($result)) {
- return $result;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ vacuum()
-
- /**
- * Optimize (vacuum) all the tables in the db (or only the specified table)
- * and optionally run ANALYZE.
- *
- * @param string $table table name (all the tables if empty)
- * @param array $options an array with driver-specific options:
- * - timeout [int] (in seconds) [mssql-only]
- * - analyze [boolean] [pgsql and mysql]
- * - full [boolean] [pgsql-only]
- * - freeze [boolean] [pgsql-only]
- *
- * @return mixed MDB2_OK success, a MDB2 error on failure
- * @access public
- */
- function vacuum($table = null, $options = array())
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
- $query = 'VACUUM';
-
- if (!empty($options['full'])) {
- $query .= ' FULL';
- }
- if (!empty($options['freeze'])) {
- $query .= ' FREEZE';
- }
- if (!empty($options['analyze'])) {
- $query .= ' ANALYZE';
- }
-
- if (!empty($table)) {
- $query .= ' '.$db->quoteIdentifier($table, true);
- }
- $result = $db->exec($query);
- if (MDB2::isError($result)) {
- return $result;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ alterTable()
-
- /**
- * alter an existing table
- *
- * @param string $name name of the table that is intended to be changed.
- * @param array $changes associative array that contains the details of each type
- * of change that is intended to be performed. The types of
- * changes that are currently supported are defined as follows:
- *
- * name
- *
- * New name for the table.
- *
- * add
- *
- * Associative array with the names of fields to be added as
- * indexes of the array. The value of each entry of the array
- * should be set to another associative array with the properties
- * of the fields to be added. The properties of the fields should
- * be the same as defined by the MDB2 parser.
- *
- *
- * remove
- *
- * Associative array with the names of fields to be removed as indexes
- * of the array. Currently the values assigned to each entry are ignored.
- * An empty array should be used for future compatibility.
- *
- * rename
- *
- * Associative array with the names of fields to be renamed as indexes
- * of the array. The value of each entry of the array should be set to
- * another associative array with the entry named name with the new
- * field name and the entry named Declaration that is expected to contain
- * the portion of the field declaration already in DBMS specific SQL code
- * as it is used in the CREATE TABLE statement.
- *
- * change
- *
- * Associative array with the names of the fields to be changed as indexes
- * of the array. Keep in mind that if it is intended to change either the
- * name of a field and any other properties, the change array entries
- * should have the new names of the fields as array indexes.
- *
- * The value of each entry of the array should be set to another associative
- * array with the properties of the fields to that are meant to be changed as
- * array entries. These entries should be assigned to the new values of the
- * respective properties. The properties of the fields should be the same
- * as defined by the MDB2 parser.
- *
- * Example
- * array(
- * 'name' => 'userlist',
- * 'add' => array(
- * 'quota' => array(
- * 'type' => 'integer',
- * 'unsigned' => 1
- * )
- * ),
- * 'remove' => array(
- * 'file_limit' => array(),
- * 'time_limit' => array()
- * ),
- * 'change' => array(
- * 'name' => array(
- * 'length' => '20',
- * 'definition' => array(
- * 'type' => 'text',
- * 'length' => 20,
- * ),
- * )
- * ),
- * 'rename' => array(
- * 'sex' => array(
- * 'name' => 'gender',
- * 'definition' => array(
- * 'type' => 'text',
- * 'length' => 1,
- * 'default' => 'M',
- * ),
- * )
- * )
- * )
- *
- * @param boolean $check indicates whether the function should just check if the DBMS driver
- * can perform the requested table alterations if the value is true or
- * actually perform them otherwise.
- * @access public
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- */
- function alterTable($name, $changes, $check)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- foreach ($changes as $change_name => $change) {
- switch ($change_name) {
- case 'add':
- case 'remove':
- case 'change':
- case 'name':
- case 'rename':
- break;
- default:
- return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null,
- 'change type "'.$change_name.'\" not yet supported', __FUNCTION__);
- }
- }
-
- if ($check) {
- return MDB2_OK;
- }
-
- $name = $db->quoteIdentifier($name, true);
-
- if (!empty($changes['remove']) && is_array($changes['remove'])) {
- foreach ($changes['remove'] as $field_name => $field) {
- $field_name = $db->quoteIdentifier($field_name, true);
- $query = 'DROP ' . $field_name;
- $result = $db->exec("ALTER TABLE $name $query");
- if (MDB2::isError($result)) {
- return $result;
- }
- }
- }
-
- if (!empty($changes['rename']) && is_array($changes['rename'])) {
- foreach ($changes['rename'] as $field_name => $field) {
- $field_name = $db->quoteIdentifier($field_name, true);
- $result = $db->exec("ALTER TABLE $name RENAME COLUMN $field_name TO ".$db->quoteIdentifier($field['name'], true));
- if (MDB2::isError($result)) {
- return $result;
- }
- }
- }
-
- if (!empty($changes['add']) && is_array($changes['add'])) {
- foreach ($changes['add'] as $field_name => $field) {
- $query = 'ADD ' . $db->getDeclaration($field['type'], $field_name, $field);
- $result = $db->exec("ALTER TABLE $name $query");
- if (MDB2::isError($result)) {
- return $result;
- }
- }
- }
-
- if (!empty($changes['change']) && is_array($changes['change'])) {
- foreach ($changes['change'] as $field_name => $field) {
- $field_name = $db->quoteIdentifier($field_name, true);
- if (!empty($field['definition']['type'])) {
- $server_info = $db->getServerVersion();
- if (MDB2::isError($server_info)) {
- return $server_info;
- }
- if (is_array($server_info) && $server_info['major'] < 8) {
- return $db->raiseError(MDB2_ERROR_CANNOT_ALTER, null, null,
- 'changing column type for "'.$change_name.'\" requires PostgreSQL 8.0 or above', __FUNCTION__);
- }
- $db->loadModule('Datatype', null, true);
- $type = $db->datatype->getTypeDeclaration($field['definition']);
- $query = "ALTER $field_name TYPE $type USING CAST($field_name AS $type)";
- $result = $db->exec("ALTER TABLE $name $query");
- if (MDB2::isError($result)) {
- return $result;
- }
- }
- if (array_key_exists('default', $field['definition'])) {
- $query = "ALTER $field_name SET DEFAULT ".$db->quote($field['definition']['default'], $field['definition']['type']);
- $result = $db->exec("ALTER TABLE $name $query");
- if (MDB2::isError($result)) {
- return $result;
- }
- }
- if (array_key_exists('notnull', $field['definition'])) {
- $query = "ALTER $field_name ".($field['definition']['notnull'] ? 'SET' : 'DROP').' NOT NULL';
- $result = $db->exec("ALTER TABLE $name $query");
- if (MDB2::isError($result)) {
- return $result;
- }
- }
- }
- }
-
- if (!empty($changes['name'])) {
- $change_name = $db->quoteIdentifier($changes['name'], true);
- $result = $db->exec("ALTER TABLE $name RENAME TO ".$change_name);
- if (MDB2::isError($result)) {
- return $result;
- }
- }
-
- return MDB2_OK;
- }
-
- // }}}
- // {{{ listDatabases()
-
- /**
- * list all databases
- *
- * @return mixed array of database names on success, a MDB2 error on failure
- * @access public
- */
- function listDatabases()
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $query = 'SELECT datname FROM pg_database';
- $result2 = $db->standaloneQuery($query, array('text'), false);
- if (!MDB2::isResultCommon($result2)) {
- return $result2;
- }
-
- $result = $result2->fetchCol();
- $result2->free();
- if (MDB2::isError($result)) {
- return $result;
- }
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
- }
- return $result;
- }
-
- // }}}
- // {{{ listUsers()
-
- /**
- * list all users
- *
- * @return mixed array of user names on success, a MDB2 error on failure
- * @access public
- */
- function listUsers()
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $query = 'SELECT usename FROM pg_user';
- $result2 = $db->standaloneQuery($query, array('text'), false);
- if (!MDB2::isResultCommon($result2)) {
- return $result2;
- }
-
- $result = $result2->fetchCol();
- $result2->free();
- return $result;
- }
-
- // }}}
- // {{{ listViews()
-
- /**
- * list all views in the current database
- *
- * @return mixed array of view names on success, a MDB2 error on failure
- * @access public
- */
- function listViews()
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $query = "SELECT viewname
- FROM pg_views
- WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
- AND viewname !~ '^pg_'";
- $result = $db->queryCol($query);
- if (MDB2::isError($result)) {
- return $result;
- }
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
- }
- return $result;
- }
-
- // }}}
- // {{{ listTableViews()
-
- /**
- * list the views in the database that reference a given table
- *
- * @param string table for which all referenced views should be found
- * @return mixed array of view names on success, a MDB2 error on failure
- * @access public
- */
- function listTableViews($table)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $query = 'SELECT viewname FROM pg_views NATURAL JOIN pg_tables';
- $query.= ' WHERE tablename ='.$db->quote($table, 'text');
- $result = $db->queryCol($query);
- if (MDB2::isError($result)) {
- return $result;
- }
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
- }
- return $result;
- }
-
- // }}}
- // {{{ listFunctions()
-
- /**
- * list all functions in the current database
- *
- * @return mixed array of function names on success, a MDB2 error on failure
- * @access public
- */
- function listFunctions()
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $query = "
- SELECT
- proname
- FROM
- pg_proc pr,
- pg_type tp
- WHERE
- tp.oid = pr.prorettype
- AND pr.proisagg = FALSE
- AND tp.typname <> 'trigger'
- AND pr.pronamespace IN
- (SELECT oid FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema')";
- $result = $db->queryCol($query);
- if (MDB2::isError($result)) {
- return $result;
- }
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
- }
- return $result;
- }
-
- // }}}
- // {{{ listTableTriggers()
-
- /**
- * list all triggers in the database that reference a given table
- *
- * @param string table for which all referenced triggers should be found
- * @return mixed array of trigger names on success, a MDB2 error on failure
- * @access public
- */
- function listTableTriggers($table = null)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $query = 'SELECT trg.tgname AS trigger_name
- FROM pg_trigger trg,
- pg_class tbl
- WHERE trg.tgrelid = tbl.oid';
- if (null !== $table) {
- $table = $db->quote(strtoupper($table), 'text');
- $query .= " AND UPPER(tbl.relname) = $table";
- }
- $result = $db->queryCol($query);
- if (MDB2::isError($result)) {
- return $result;
- }
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
- }
- return $result;
- }
-
- // }}}
- // {{{ listTables()
-
- /**
- * list all tables in the current database
- *
- * @return mixed array of table names on success, a MDB2 error on failure
- * @access public
- */
- function listTables()
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- // gratuitously stolen from PEAR DB _getSpecialQuery in pgsql.php
- $query = 'SELECT c.relname AS "Name"'
- . ' FROM pg_class c, pg_user u'
- . ' WHERE c.relowner = u.usesysid'
- . " AND c.relkind = 'r'"
- . ' AND NOT EXISTS'
- . ' (SELECT 1 FROM pg_views'
- . ' WHERE viewname = c.relname)'
- . " AND c.relname !~ '^(pg_|sql_)'"
- . ' UNION'
- . ' SELECT c.relname AS "Name"'
- . ' FROM pg_class c'
- . " WHERE c.relkind = 'r'"
- . ' AND NOT EXISTS'
- . ' (SELECT 1 FROM pg_views'
- . ' WHERE viewname = c.relname)'
- . ' AND NOT EXISTS'
- . ' (SELECT 1 FROM pg_user'
- . ' WHERE usesysid = c.relowner)'
- . " AND c.relname !~ '^pg_'";
- $result = $db->queryCol($query);
- if (MDB2::isError($result)) {
- return $result;
- }
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
- }
- return $result;
- }
-
- // }}}
- // {{{ listTableFields()
-
- /**
- * list all fields in a table in the current database
- *
- * @param string $table name of table that should be used in method
- * @return mixed array of field names on success, a MDB2 error on failure
- * @access public
- */
- function listTableFields($table)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- list($schema, $table) = $this->splitTableSchema($table);
-
- $table = $db->quoteIdentifier($table, true);
- if (!empty($schema)) {
- $table = $db->quoteIdentifier($schema, true) . '.' .$table;
- }
- $db->setLimit(1);
- $result2 = $db->query("SELECT * FROM $table");
- if (MDB2::isError($result2)) {
- return $result2;
- }
- $result = $result2->getColumnNames();
- $result2->free();
- if (MDB2::isError($result)) {
- return $result;
- }
- return array_flip($result);
- }
-
- // }}}
- // {{{ listTableIndexes()
-
- /**
- * list all indexes in a table
- *
- * @param string $table name of table that should be used in method
- * @return mixed array of index names on success, a MDB2 error on failure
- * @access public
- */
- function listTableIndexes($table)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- list($schema, $table) = $this->splitTableSchema($table);
-
- $table = $db->quote($table, 'text');
- $subquery = "SELECT indexrelid
- FROM pg_index
- LEFT JOIN pg_class ON pg_class.oid = pg_index.indrelid
- LEFT JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
- WHERE pg_class.relname = $table
- AND indisunique != 't'
- AND indisprimary != 't'";
- if (!empty($schema)) {
- $subquery .= ' AND pg_namespace.nspname = '.$db->quote($schema, 'text');
- }
- $query = "SELECT relname FROM pg_class WHERE oid IN ($subquery)";
- $indexes = $db->queryCol($query, 'text');
- if (MDB2::isError($indexes)) {
- return $indexes;
- }
-
- $result = array();
- foreach ($indexes as $index) {
- $index = $this->_fixIndexName($index);
- if (!empty($index)) {
- $result[$index] = true;
- }
- }
-
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- $result = array_change_key_case($result, $db->options['field_case']);
- }
- return array_keys($result);
- }
-
- // }}}
- // {{{ dropConstraint()
-
- /**
- * drop existing constraint
- *
- * @param string $table name of table that should be used in method
- * @param string $name name of the constraint to be dropped
- * @param string $primary hint if the constraint is primary
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function dropConstraint($table, $name, $primary = false)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- // is it an UNIQUE index?
- $query = 'SELECT relname
- FROM pg_class
- WHERE oid IN (
- SELECT indexrelid
- FROM pg_index, pg_class
- WHERE pg_class.relname = '.$db->quote($table, 'text').'
- AND pg_class.oid = pg_index.indrelid
- AND indisunique = \'t\')
- EXCEPT
- SELECT conname
- FROM pg_constraint, pg_class
- WHERE pg_constraint.conrelid = pg_class.oid
- AND relname = '. $db->quote($table, 'text');
- $unique = $db->queryCol($query, 'text');
- if (MDB2::isError($unique) || empty($unique)) {
- // not an UNIQUE index, maybe a CONSTRAINT
- return parent::dropConstraint($table, $name, $primary);
- }
-
- if (in_array($name, $unique)) {
- $result = $db->exec('DROP INDEX '.$db->quoteIdentifier($name, true));
- if (MDB2::isError($result)) {
- return $result;
- }
- return MDB2_OK;
- }
- $idxname = $db->getIndexName($name);
- if (in_array($idxname, $unique)) {
- $result = $db->exec('DROP INDEX '.$db->quoteIdentifier($idxname, true));
- if (MDB2::isError($result)) {
- return $result;
- }
- return MDB2_OK;
- }
- return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- $name . ' is not an existing constraint for table ' . $table, __FUNCTION__);
- }
-
- // }}}
- // {{{ listTableConstraints()
-
- /**
- * list all constraints in a table
- *
- * @param string $table name of table that should be used in method
- * @return mixed array of constraint names on success, a MDB2 error on failure
- * @access public
- */
- function listTableConstraints($table)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- list($schema, $table) = $this->splitTableSchema($table);
-
- $table = $db->quote($table, 'text');
- $query = 'SELECT conname
- FROM pg_constraint
- LEFT JOIN pg_class ON pg_constraint.conrelid = pg_class.oid
- LEFT JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
- WHERE relname = ' .$table;
- if (!empty($schema)) {
- $query .= ' AND pg_namespace.nspname = ' . $db->quote($schema, 'text');
- }
- $query .= '
- UNION DISTINCT
- SELECT relname
- FROM pg_class
- WHERE oid IN (
- SELECT indexrelid
- FROM pg_index
- LEFT JOIN pg_class ON pg_class.oid = pg_index.indrelid
- LEFT JOIN pg_namespace ON pg_class.relnamespace = pg_namespace.oid
- WHERE pg_class.relname = '.$table.'
- AND indisunique = \'t\'';
- if (!empty($schema)) {
- $query .= ' AND pg_namespace.nspname = ' . $db->quote($schema, 'text');
- }
- $query .= ')';
- $constraints = $db->queryCol($query);
- if (MDB2::isError($constraints)) {
- return $constraints;
- }
-
- $result = array();
- foreach ($constraints as $constraint) {
- $constraint = $this->_fixIndexName($constraint);
- if (!empty($constraint)) {
- $result[$constraint] = true;
- }
- }
-
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE
- && $db->options['field_case'] == CASE_LOWER
- ) {
- $result = array_change_key_case($result, $db->options['field_case']);
- }
- return array_keys($result);
- }
-
- // }}}
- // {{{ createSequence()
-
- /**
- * create sequence
- *
- * @param string $seq_name name of the sequence to be created
- * @param string $start start value of the sequence; default is 1
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function createSequence($seq_name, $start = 1)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
- $result = $db->exec("CREATE SEQUENCE $sequence_name INCREMENT 1".
- ($start < 1 ? " MINVALUE $start" : '')." START $start");
- if (MDB2::isError($result)) {
- return $result;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ dropSequence()
-
- /**
- * drop existing sequence
- *
- * @param string $seq_name name of the sequence to be dropped
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function dropSequence($seq_name)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $sequence_name = $db->quoteIdentifier($db->getSequenceName($seq_name), true);
- $result = $db->exec("DROP SEQUENCE $sequence_name");
- if (MDB2::isError($result)) {
- return $result;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ listSequences()
-
- /**
- * list all sequences in the current database
- *
- * @return mixed array of sequence names on success, a MDB2 error on failure
- * @access public
- */
- function listSequences()
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $query = "SELECT relname FROM pg_class WHERE relkind = 'S' AND relnamespace IN";
- $query.= "(SELECT oid FROM pg_namespace WHERE nspname NOT LIKE 'pg_%' AND nspname != 'information_schema')";
- $table_names = $db->queryCol($query);
- if (MDB2::isError($table_names)) {
- return $table_names;
- }
- $result = array();
- foreach ($table_names as $table_name) {
- $result[] = $this->_fixSequenceName($table_name);
- }
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- $result = array_map(($db->options['field_case'] == CASE_LOWER ? 'strtolower' : 'strtoupper'), $result);
- }
- return $result;
- }
-}
-?>
diff --git a/data/module/MDB2/Driver/Native/Common.php b/data/module/MDB2/Driver/Native/Common.php
deleted file mode 100644
index 20e652e3e17..00000000000
--- a/data/module/MDB2/Driver/Native/Common.php
+++ /dev/null
@@ -1,61 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: Common.php 242348 2007-09-09 13:47:36Z quipo $
-//
-
-/**
- * Base class for the natuve modules that is extended by each MDB2 driver
- *
- * To load this module in the MDB2 object:
- * $mdb->loadModule('Native');
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_Driver_Native_Common extends MDB2_Module_Common
-{
-}
-?>
\ No newline at end of file
diff --git a/data/module/MDB2/Driver/Native/mysql.php b/data/module/MDB2/Driver/Native/mysql.php
deleted file mode 100644
index 2d4ffe09d4c..00000000000
--- a/data/module/MDB2/Driver/Native/mysql.php
+++ /dev/null
@@ -1,60 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: mysql.php 215004 2006-06-18 21:59:05Z lsmith $
-//
-
-require_once 'MDB2/Driver/Native/Common.php';
-
-/**
- * MDB2 MySQL driver for the native module
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_Driver_Native_mysql extends MDB2_Driver_Native_Common
-{
-}
-?>
\ No newline at end of file
diff --git a/data/module/MDB2/Driver/Native/pgsql.php b/data/module/MDB2/Driver/Native/pgsql.php
deleted file mode 100644
index a20b6d04f10..00000000000
--- a/data/module/MDB2/Driver/Native/pgsql.php
+++ /dev/null
@@ -1,88 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: pgsql.php 327310 2012-08-27 15:16:18Z danielc $
-
-require_once 'MDB2/Driver/Native/Common.php';
-
-/**
- * MDB2 PostGreSQL driver for the native module
- *
- * @package MDB2
- * @category Database
- * @author Paul Cooper
- */
-class MDB2_Driver_Native_pgsql extends MDB2_Driver_Native_Common
-{
- // }}}
- // {{{ deleteOID()
-
- /**
- * delete an OID
- *
- * @param integer $OID
- * @return mixed MDB2_OK on success or MDB2 Error Object on failure
- * @access public
- */
- function deleteOID($OID)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $connection = $db->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
-
- if (!@pg_lo_unlink($connection, $OID)) {
- return $db->raiseError(null, null, null,
- 'Unable to unlink OID: '.$OID, __FUNCTION__);
- }
- return MDB2_OK;
- }
-
-}
-?>
diff --git a/data/module/MDB2/Driver/Reverse/Common.php b/data/module/MDB2/Driver/Reverse/Common.php
deleted file mode 100644
index e31cb5a4595..00000000000
--- a/data/module/MDB2/Driver/Reverse/Common.php
+++ /dev/null
@@ -1,517 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: Common.php 327310 2012-08-27 15:16:18Z danielc $
-//
-
-/**
- * @package MDB2
- * @category Database
- */
-
-/**
- * These are constants for the tableInfo-function
- * they are bitwised or'ed. so if there are more constants to be defined
- * in the future, adjust MDB2_TABLEINFO_FULL accordingly
- */
-
-define('MDB2_TABLEINFO_ORDER', 1);
-define('MDB2_TABLEINFO_ORDERTABLE', 2);
-define('MDB2_TABLEINFO_FULL', 3);
-
-/**
- * Base class for the schema reverse engineering module that is extended by each MDB2 driver
- *
- * To load this module in the MDB2 object:
- * $mdb->loadModule('Reverse');
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_Driver_Reverse_Common extends MDB2_Module_Common
-{
- // {{{ splitTableSchema()
-
- /**
- * Split the "[owner|schema].table" notation into an array
- *
- * @param string $table [schema and] table name
- *
- * @return array array(schema, table)
- * @access private
- */
- function splitTableSchema($table)
- {
- $ret = array();
- if (strpos($table, '.') !== false) {
- return explode('.', $table);
- }
- return array(null, $table);
- }
-
- // }}}
- // {{{ getTableFieldDefinition()
-
- /**
- * Get the structure of a field into an array
- *
- * @param string $table name of table that should be used in method
- * @param string $field name of field that should be used in method
- * @return mixed data array on success, a MDB2 error on failure.
- * The returned array contains an array for each field definition,
- * with all or some of these indices, depending on the field data type:
- * [notnull] [nativetype] [length] [fixed] [default] [type] [mdb2type]
- * @access public
- */
- function getTableFieldDefinition($table, $field)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ getTableIndexDefinition()
-
- /**
- * Get the structure of an index into an array
- *
- * @param string $table name of table that should be used in method
- * @param string $index name of index that should be used in method
- * @return mixed data array on success, a MDB2 error on failure
- * The returned array has this structure:
- *
- * array (
- * [fields] => array (
- * [field1name] => array() // one entry per each field covered
- * [field2name] => array() // by the index
- * [field3name] => array(
- * [sorting] => ascending
- * )
- * )
- * );
- *
- * @access public
- */
- function getTableIndexDefinition($table, $index)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ getTableConstraintDefinition()
-
- /**
- * Get the structure of an constraints into an array
- *
- * @param string $table name of table that should be used in method
- * @param string $index name of index that should be used in method
- * @return mixed data array on success, a MDB2 error on failure
- * The returned array has this structure:
- *
- * array (
- * [primary] => 0
- * [unique] => 0
- * [foreign] => 1
- * [check] => 0
- * [fields] => array (
- * [field1name] => array() // one entry per each field covered
- * [field2name] => array() // by the index
- * [field3name] => array(
- * [sorting] => ascending
- * [position] => 3
- * )
- * )
- * [references] => array(
- * [table] => name
- * [fields] => array(
- * [field1name] => array( //one entry per each referenced field
- * [position] => 1
- * )
- * )
- * )
- * [deferrable] => 0
- * [initiallydeferred] => 0
- * [onupdate] => CASCADE|RESTRICT|SET NULL|SET DEFAULT|NO ACTION
- * [ondelete] => CASCADE|RESTRICT|SET NULL|SET DEFAULT|NO ACTION
- * [match] => SIMPLE|PARTIAL|FULL
- * );
- *
- * @access public
- */
- function getTableConstraintDefinition($table, $index)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ getSequenceDefinition()
-
- /**
- * Get the structure of a sequence into an array
- *
- * @param string $sequence name of sequence that should be used in method
- * @return mixed data array on success, a MDB2 error on failure
- * The returned array has this structure:
- *
- * array (
- * [start] => n
- * );
- *
- * @access public
- */
- function getSequenceDefinition($sequence)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $start = $db->currId($sequence);
- if (MDB2::isError($start)) {
- return $start;
- }
- if ($db->supports('current_id')) {
- $start++;
- } else {
- $db->warnings[] = 'database does not support getting current
- sequence value, the sequence value was incremented';
- }
- $definition = array();
- if ($start != 1) {
- $definition = array('start' => $start);
- }
- return $definition;
- }
-
- // }}}
- // {{{ getTriggerDefinition()
-
- /**
- * Get the structure of a trigger into an array
- *
- * EXPERIMENTAL
- *
- * WARNING: this function is experimental and may change the returned value
- * at any time until labelled as non-experimental
- *
- * @param string $trigger name of trigger that should be used in method
- * @return mixed data array on success, a MDB2 error on failure
- * The returned array has this structure:
- *
- * array (
- * [trigger_name] => 'trigger name',
- * [table_name] => 'table name',
- * [trigger_body] => 'trigger body definition',
- * [trigger_type] => 'BEFORE' | 'AFTER',
- * [trigger_event] => 'INSERT' | 'UPDATE' | 'DELETE'
- * //or comma separated list of multiple events, when supported
- * [trigger_enabled] => true|false
- * [trigger_comment] => 'trigger comment',
- * );
- *
- * The oci8 driver also returns a [when_clause] index.
- * @access public
- */
- function getTriggerDefinition($trigger)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- // }}}
- // {{{ tableInfo()
-
- /**
- * Returns information about a table or a result set
- *
- * The format of the resulting array depends on which $mode
- * you select. The sample output below is based on this query:
- *
- * SELECT tblFoo.fldID, tblFoo.fldPhone, tblBar.fldId
- * FROM tblFoo
- * JOIN tblBar ON tblFoo.fldId = tblBar.fldId
- *
- *
- *
- * -
- *
- * null (default)
- *
- * [0] => Array (
- * [table] => tblFoo
- * [name] => fldId
- * [type] => int
- * [len] => 11
- * [flags] => primary_key not_null
- * )
- * [1] => Array (
- * [table] => tblFoo
- * [name] => fldPhone
- * [type] => string
- * [len] => 20
- * [flags] =>
- * )
- * [2] => Array (
- * [table] => tblBar
- * [name] => fldId
- * [type] => int
- * [len] => 11
- * [flags] => primary_key not_null
- * )
- *
- *
- * -
- *
- * MDB2_TABLEINFO_ORDER
- *
- *
In addition to the information found in the default output,
- * a notation of the number of columns is provided by the
- * num_fields element while the order
- * element provides an array with the column names as the keys and
- * their location index number (corresponding to the keys in the
- * the default output) as the values.
- *
- * If a result set has identical field names, the last one is
- * used.
- *
- *
- * [num_fields] => 3
- * [order] => Array (
- * [fldId] => 2
- * [fldTrans] => 1
- * )
- *
- *
- * -
- *
- * MDB2_TABLEINFO_ORDERTABLE
- *
- *
Similar to MDB2_TABLEINFO_ORDER but adds more
- * dimensions to the array in which the table names are keys and
- * the field names are sub-keys. This is helpful for queries that
- * join tables which have identical field names.
- *
- *
- * [num_fields] => 3
- * [ordertable] => Array (
- * [tblFoo] => Array (
- * [fldId] => 0
- * [fldPhone] => 1
- * )
- * [tblBar] => Array (
- * [fldId] => 2
- * )
- * )
- *
- *
- *
- *
- *
- * The flags element contains a space separated list
- * of extra information about the field. This data is inconsistent
- * between DBMS's due to the way each DBMS works.
- * + primary_key
- * + unique_key
- * + multiple_key
- * + not_null
- *
- * Most DBMS's only provide the table and flags
- * elements if $result is a table name. The following DBMS's
- * provide full information from queries:
- * + fbsql
- * + mysql
- *
- * If the 'portability' option has MDB2_PORTABILITY_FIX_CASE
- * turned on, the names of tables and fields will be lower or upper cased.
- *
- * @param object|string $result MDB2_result object from a query or a
- * string containing the name of a table.
- * While this also accepts a query result
- * resource identifier, this behavior is
- * deprecated.
- * @param int $mode either unused or one of the tableInfo modes:
- * MDB2_TABLEINFO_ORDERTABLE,
- * MDB2_TABLEINFO_ORDER or
- * MDB2_TABLEINFO_FULL (which does both).
- * These are bitwise, so the first two can be
- * combined using |.
- *
- * @return array an associative array with the information requested.
- * A MDB2_Error object on failure.
- *
- * @see MDB2_Driver_Common::setOption()
- */
- function tableInfo($result, $mode = null)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- if (!is_string($result)) {
- return $db->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'method not implemented', __FUNCTION__);
- }
-
- $db->loadModule('Manager', null, true);
- $fields = $db->manager->listTableFields($result);
- if (MDB2::isError($fields)) {
- return $fields;
- }
-
- $flags = array();
-
- $idxname_format = $db->getOption('idxname_format');
- $db->setOption('idxname_format', '%s');
-
- $indexes = $db->manager->listTableIndexes($result);
- if (MDB2::isError($indexes)) {
- $db->setOption('idxname_format', $idxname_format);
- return $indexes;
- }
-
- foreach ($indexes as $index) {
- $definition = $this->getTableIndexDefinition($result, $index);
- if (MDB2::isError($definition)) {
- $db->setOption('idxname_format', $idxname_format);
- return $definition;
- }
- if (count($definition['fields']) > 1) {
- foreach ($definition['fields'] as $field => $sort) {
- $flags[$field] = 'multiple_key';
- }
- }
- }
-
- $constraints = $db->manager->listTableConstraints($result);
- if (MDB2::isError($constraints)) {
- return $constraints;
- }
-
- foreach ($constraints as $constraint) {
- $definition = $this->getTableConstraintDefinition($result, $constraint);
- if (MDB2::isError($definition)) {
- $db->setOption('idxname_format', $idxname_format);
- return $definition;
- }
- $flag = !empty($definition['primary'])
- ? 'primary_key' : (!empty($definition['unique'])
- ? 'unique_key' : false);
- if ($flag) {
- foreach ($definition['fields'] as $field => $sort) {
- if (empty($flags[$field]) || $flags[$field] != 'primary_key') {
- $flags[$field] = $flag;
- }
- }
- }
- }
-
- $res = array();
-
- if ($mode) {
- $res['num_fields'] = count($fields);
- }
-
- foreach ($fields as $i => $field) {
- $definition = $this->getTableFieldDefinition($result, $field);
- if (MDB2::isError($definition)) {
- $db->setOption('idxname_format', $idxname_format);
- return $definition;
- }
- $res[$i] = $definition[0];
- $res[$i]['name'] = $field;
- $res[$i]['table'] = $result;
- $res[$i]['type'] = preg_replace('/^([a-z]+).*$/i', '\\1', trim($definition[0]['nativetype']));
- // 'primary_key', 'unique_key', 'multiple_key'
- $res[$i]['flags'] = empty($flags[$field]) ? '' : $flags[$field];
- // not_null', 'unsigned', 'auto_increment', 'default_[rawencodedvalue]'
- if (!empty($res[$i]['notnull'])) {
- $res[$i]['flags'].= ' not_null';
- }
- if (!empty($res[$i]['unsigned'])) {
- $res[$i]['flags'].= ' unsigned';
- }
- if (!empty($res[$i]['auto_increment'])) {
- $res[$i]['flags'].= ' autoincrement';
- }
- if (!empty($res[$i]['default'])) {
- $res[$i]['flags'].= ' default_'.rawurlencode($res[$i]['default']);
- }
-
- if ($mode & MDB2_TABLEINFO_ORDER) {
- $res['order'][$res[$i]['name']] = $i;
- }
- if ($mode & MDB2_TABLEINFO_ORDERTABLE) {
- $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
- }
- }
-
- $db->setOption('idxname_format', $idxname_format);
- return $res;
- }
-}
-?>
diff --git a/data/module/MDB2/Driver/Reverse/mysql.php b/data/module/MDB2/Driver/Reverse/mysql.php
deleted file mode 100644
index 3aea5a7aa92..00000000000
--- a/data/module/MDB2/Driver/Reverse/mysql.php
+++ /dev/null
@@ -1,546 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: mysql.php 327310 2012-08-27 15:16:18Z danielc $
-//
-
-require_once 'MDB2/Driver/Reverse/Common.php';
-
-/**
- * MDB2 MySQL driver for the schema reverse engineering module
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- * @author Lorenzo Alberton
- */
-class MDB2_Driver_Reverse_mysql extends MDB2_Driver_Reverse_Common
-{
- // {{{ getTableFieldDefinition()
-
- /**
- * Get the structure of a field into an array
- *
- * @param string $table_name name of table that should be used in method
- * @param string $field_name name of field that should be used in method
- * @return mixed data array on success, a MDB2 error on failure
- * @access public
- */
- function getTableFieldDefinition($table_name, $field_name)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $result = $db->loadModule('Datatype', null, true);
- if (MDB2::isError($result)) {
- return $result;
- }
-
- list($schema, $table) = $this->splitTableSchema($table_name);
-
- $table = $db->quoteIdentifier($table, true);
- $query = "SHOW FULL COLUMNS FROM $table LIKE ".$db->quote($field_name);
- $columns = $db->queryAll($query, null, MDB2_FETCHMODE_ASSOC);
- if (MDB2::isError($columns)) {
- return $columns;
- }
- foreach ($columns as $column) {
- $column = array_change_key_case($column, CASE_LOWER);
- $column['name'] = $column['field'];
- unset($column['field']);
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- if ($db->options['field_case'] == CASE_LOWER) {
- $column['name'] = strtolower($column['name']);
- } else {
- $column['name'] = strtoupper($column['name']);
- }
- } else {
- $column = array_change_key_case($column, $db->options['field_case']);
- }
- if ($field_name == $column['name']) {
- $mapped_datatype = $db->datatype->mapNativeDatatype($column);
- if (MDB2::isError($mapped_datatype)) {
- return $mapped_datatype;
- }
- list($types, $length, $unsigned, $fixed) = $mapped_datatype;
- $notnull = false;
- if (empty($column['null']) || $column['null'] !== 'YES') {
- $notnull = true;
- }
- $default = false;
- if (array_key_exists('default', $column)) {
- $default = $column['default'];
- if ((null === $default) && $notnull) {
- $default = '';
- }
- }
- $definition[0] = array(
- 'notnull' => $notnull,
- 'nativetype' => preg_replace('/^([a-z]+)[^a-z].*/i', '\\1', $column['type'])
- );
- $autoincrement = false;
- if (!empty($column['extra'])) {
- if ($column['extra'] == 'auto_increment') {
- $autoincrement = true;
- } else {
- $definition[0]['extra'] = $column['extra'];
- }
- }
- $collate = null;
- if (!empty($column['collation'])) {
- $collate = $column['collation'];
- $charset = preg_replace('/(.+?)(_.+)?/', '$1', $collate);
- }
-
- if (null !== $length) {
- $definition[0]['length'] = $length;
- }
- if (null !== $unsigned) {
- $definition[0]['unsigned'] = $unsigned;
- }
- if (null !== $fixed) {
- $definition[0]['fixed'] = $fixed;
- }
- if ($default !== false) {
- $definition[0]['default'] = $default;
- }
- if ($autoincrement !== false) {
- $definition[0]['autoincrement'] = $autoincrement;
- }
- if (null !== $collate) {
- $definition[0]['collate'] = $collate;
- $definition[0]['charset'] = $charset;
- }
- foreach ($types as $key => $type) {
- $definition[$key] = $definition[0];
- if ($type == 'clob' || $type == 'blob') {
- unset($definition[$key]['default']);
- } elseif ($type == 'timestamp' && $notnull && empty($definition[$key]['default'])) {
- $definition[$key]['default'] = '0000-00-00 00:00:00';
- }
- $definition[$key]['type'] = $type;
- $definition[$key]['mdb2type'] = $type;
- }
- return $definition;
- }
- }
-
- return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- 'it was not specified an existing table column', __FUNCTION__);
- }
-
- // }}}
- // {{{ getTableIndexDefinition()
-
- /**
- * Get the structure of an index into an array
- *
- * @param string $table_name name of table that should be used in method
- * @param string $index_name name of index that should be used in method
- * @return mixed data array on success, a MDB2 error on failure
- * @access public
- */
- function getTableIndexDefinition($table_name, $index_name)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- list($schema, $table) = $this->splitTableSchema($table_name);
-
- $table = $db->quoteIdentifier($table, true);
- $query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = %s */";
- $index_name_mdb2 = $db->getIndexName($index_name);
- $result = $db->queryRow(sprintf($query, $db->quote($index_name_mdb2)));
- if (!MDB2::isError($result) && (null !== $result)) {
- // apply 'idxname_format' only if the query succeeded, otherwise
- // fallback to the given $index_name, without transformation
- $index_name = $index_name_mdb2;
- }
- $result = $db->query(sprintf($query, $db->quote($index_name)));
- if (MDB2::isError($result)) {
- return $result;
- }
- $colpos = 1;
- $definition = array();
- while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) {
- $row = array_change_key_case($row, CASE_LOWER);
- $key_name = $row['key_name'];
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- if ($db->options['field_case'] == CASE_LOWER) {
- $key_name = strtolower($key_name);
- } else {
- $key_name = strtoupper($key_name);
- }
- }
- if ($index_name == $key_name) {
- if (!$row['non_unique']) {
- return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- $index_name . ' is not an existing table index', __FUNCTION__);
- }
- $column_name = $row['column_name'];
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- if ($db->options['field_case'] == CASE_LOWER) {
- $column_name = strtolower($column_name);
- } else {
- $column_name = strtoupper($column_name);
- }
- }
- $definition['fields'][$column_name] = array(
- 'position' => $colpos++
- );
- if (!empty($row['collation'])) {
- $definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A'
- ? 'ascending' : 'descending');
- }
- }
- }
- $result->free();
- if (empty($definition['fields'])) {
- return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- $index_name . ' is not an existing table index', __FUNCTION__);
- }
- return $definition;
- }
-
- // }}}
- // {{{ getTableConstraintDefinition()
-
- /**
- * Get the structure of a constraint into an array
- *
- * @param string $table_name name of table that should be used in method
- * @param string $constraint_name name of constraint that should be used in method
- * @return mixed data array on success, a MDB2 error on failure
- * @access public
- */
- function getTableConstraintDefinition($table_name, $constraint_name)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- list($schema, $table) = $this->splitTableSchema($table_name);
- $constraint_name_original = $constraint_name;
-
- $table = $db->quoteIdentifier($table, true);
- $query = "SHOW INDEX FROM $table /*!50002 WHERE Key_name = %s */";
- if (strtolower($constraint_name) != 'primary') {
- $constraint_name_mdb2 = $db->getIndexName($constraint_name);
- $result = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2)));
- if (!MDB2::isError($result) && (null !== $result)) {
- // apply 'idxname_format' only if the query succeeded, otherwise
- // fallback to the given $index_name, without transformation
- $constraint_name = $constraint_name_mdb2;
- }
- }
- $result = $db->query(sprintf($query, $db->quote($constraint_name)));
- if (MDB2::isError($result)) {
- return $result;
- }
- $colpos = 1;
- //default values, eventually overridden
- $definition = array(
- 'primary' => false,
- 'unique' => false,
- 'foreign' => false,
- 'check' => false,
- 'fields' => array(),
- 'references' => array(
- 'table' => '',
- 'fields' => array(),
- ),
- 'onupdate' => '',
- 'ondelete' => '',
- 'match' => '',
- 'deferrable' => false,
- 'initiallydeferred' => false,
- );
- while (is_array($row = $result->fetchRow(MDB2_FETCHMODE_ASSOC))) {
- $row = array_change_key_case($row, CASE_LOWER);
- $key_name = $row['key_name'];
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- if ($db->options['field_case'] == CASE_LOWER) {
- $key_name = strtolower($key_name);
- } else {
- $key_name = strtoupper($key_name);
- }
- }
- if ($constraint_name == $key_name) {
- if ($row['non_unique']) {
- //FOREIGN KEY?
- return $this->_getTableFKConstraintDefinition($table, $constraint_name_original, $definition);
- }
- if ($row['key_name'] == 'PRIMARY') {
- $definition['primary'] = true;
- } elseif (!$row['non_unique']) {
- $definition['unique'] = true;
- }
- $column_name = $row['column_name'];
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- if ($db->options['field_case'] == CASE_LOWER) {
- $column_name = strtolower($column_name);
- } else {
- $column_name = strtoupper($column_name);
- }
- }
- $definition['fields'][$column_name] = array(
- 'position' => $colpos++
- );
- if (!empty($row['collation'])) {
- $definition['fields'][$column_name]['sorting'] = ($row['collation'] == 'A'
- ? 'ascending' : 'descending');
- }
- }
- }
- $result->free();
- if (empty($definition['fields'])) {
- return $this->_getTableFKConstraintDefinition($table, $constraint_name_original, $definition);
- }
- return $definition;
- }
-
- // }}}
- // {{{ _getTableFKConstraintDefinition()
-
- /**
- * Get the FK definition from the CREATE TABLE statement
- *
- * @param string $table table name
- * @param string $constraint_name constraint name
- * @param array $definition default values for constraint definition
- *
- * @return array|PEAR_Error
- * @access private
- */
- function _getTableFKConstraintDefinition($table, $constraint_name, $definition)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
- //Use INFORMATION_SCHEMA instead?
- //SELECT *
- // FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
- // WHERE CONSTRAINT_SCHEMA = '$dbname'
- // AND TABLE_NAME = '$table'
- // AND CONSTRAINT_NAME = '$constraint_name';
- $query = 'SHOW CREATE TABLE '. $db->escape($table);
- $constraint = $db->queryOne($query, 'text', 1);
- if (!MDB2::isError($constraint) && !empty($constraint)) {
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- if ($db->options['field_case'] == CASE_LOWER) {
- $constraint = strtolower($constraint);
- } else {
- $constraint = strtoupper($constraint);
- }
- }
- $constraint_name_original = $constraint_name;
- $constraint_name = $db->getIndexName($constraint_name);
- $pattern = '/\bCONSTRAINT\s+'.$constraint_name.'\s+FOREIGN KEY\s+\(([^\)]+)\) \bREFERENCES\b ([^\s]+) \(([^\)]+)\)(?: ON DELETE ([^\s]+))?(?: ON UPDATE ([^\s]+))?/i';
- if (!preg_match($pattern, str_replace('`', '', $constraint), $matches)) {
- //fallback to original constraint name
- $pattern = '/\bCONSTRAINT\s+'.$constraint_name_original.'\s+FOREIGN KEY\s+\(([^\)]+)\) \bREFERENCES\b ([^\s]+) \(([^\)]+)\)(?: ON DELETE ([^\s]+))?(?: ON UPDATE ([^\s]+))?/i';
- }
- if (preg_match($pattern, str_replace('`', '', $constraint), $matches)) {
- $definition['foreign'] = true;
- $column_names = explode(',', $matches[1]);
- $referenced_cols = explode(',', $matches[3]);
- $definition['references'] = array(
- 'table' => $matches[2],
- 'fields' => array(),
- );
- $colpos = 1;
- foreach ($column_names as $column_name) {
- $definition['fields'][trim($column_name)] = array(
- 'position' => $colpos++
- );
- }
- $colpos = 1;
- foreach ($referenced_cols as $column_name) {
- $definition['references']['fields'][trim($column_name)] = array(
- 'position' => $colpos++
- );
- }
- $definition['ondelete'] = empty($matches[4]) ? 'RESTRICT' : strtoupper($matches[4]);
- $definition['onupdate'] = empty($matches[5]) ? 'RESTRICT' : strtoupper($matches[5]);
- $definition['match'] = 'SIMPLE';
- return $definition;
- }
- }
- return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- $constraint_name . ' is not an existing table constraint', __FUNCTION__);
- }
-
- // }}}
- // {{{ getTriggerDefinition()
-
- /**
- * Get the structure of a trigger into an array
- *
- * EXPERIMENTAL
- *
- * WARNING: this function is experimental and may change the returned value
- * at any time until labelled as non-experimental
- *
- * @param string $trigger name of trigger that should be used in method
- * @return mixed data array on success, a MDB2 error on failure
- * @access public
- */
- function getTriggerDefinition($trigger)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $query = 'SELECT trigger_name,
- event_object_table AS table_name,
- action_statement AS trigger_body,
- action_timing AS trigger_type,
- event_manipulation AS trigger_event
- FROM information_schema.triggers
- WHERE trigger_name = '. $db->quote($trigger, 'text');
- $types = array(
- 'trigger_name' => 'text',
- 'table_name' => 'text',
- 'trigger_body' => 'text',
- 'trigger_type' => 'text',
- 'trigger_event' => 'text',
- );
- $def = $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC);
- if (MDB2::isError($def)) {
- return $def;
- }
- $def['trigger_comment'] = '';
- $def['trigger_enabled'] = true;
- return $def;
- }
-
- // }}}
- // {{{ tableInfo()
-
- /**
- * Returns information about a table or a result set
- *
- * @param object|string $result MDB2_result object from a query or a
- * string containing the name of a table.
- * While this also accepts a query result
- * resource identifier, this behavior is
- * deprecated.
- * @param int $mode a valid tableInfo mode
- *
- * @return array an associative array with the information requested.
- * A MDB2_Error object on failure.
- *
- * @see MDB2_Driver_Common::setOption()
- */
- function tableInfo($result, $mode = null)
- {
- if (is_string($result)) {
- return parent::tableInfo($result, $mode);
- }
-
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $resource = MDB2::isResultCommon($result) ? $result->getResource() : $result;
- if (!is_resource($resource)) {
- return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
- 'Could not generate result resource', __FUNCTION__);
- }
-
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- if ($db->options['field_case'] == CASE_LOWER) {
- $case_func = 'strtolower';
- } else {
- $case_func = 'strtoupper';
- }
- } else {
- $case_func = 'strval';
- }
-
- $count = @mysql_num_fields($resource);
- $res = array();
- if ($mode) {
- $res['num_fields'] = $count;
- }
-
- $db->loadModule('Datatype', null, true);
- for ($i = 0; $i < $count; $i++) {
- $res[$i] = array(
- 'table' => $case_func(@mysql_field_table($resource, $i)),
- 'name' => $case_func(@mysql_field_name($resource, $i)),
- 'type' => @mysql_field_type($resource, $i),
- 'length' => @mysql_field_len($resource, $i),
- 'flags' => @mysql_field_flags($resource, $i),
- );
- if ($res[$i]['type'] == 'string') {
- $res[$i]['type'] = 'char';
- } elseif ($res[$i]['type'] == 'unknown') {
- $res[$i]['type'] = 'decimal';
- }
- $mdb2type_info = $db->datatype->mapNativeDatatype($res[$i]);
- if (MDB2::isError($mdb2type_info)) {
- return $mdb2type_info;
- }
- $res[$i]['mdb2type'] = $mdb2type_info[0][0];
- if ($mode & MDB2_TABLEINFO_ORDER) {
- $res['order'][$res[$i]['name']] = $i;
- }
- if ($mode & MDB2_TABLEINFO_ORDERTABLE) {
- $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
- }
- }
-
- return $res;
- }
-}
-?>
diff --git a/data/module/MDB2/Driver/Reverse/pgsql.php b/data/module/MDB2/Driver/Reverse/pgsql.php
deleted file mode 100644
index dd3596a67a8..00000000000
--- a/data/module/MDB2/Driver/Reverse/pgsql.php
+++ /dev/null
@@ -1,574 +0,0 @@
- |
-// | Lorenzo Alberton |
-// +----------------------------------------------------------------------+
-//
-// $Id: pgsql.php 327310 2012-08-27 15:16:18Z danielc $
-
-require_once 'MDB2/Driver/Reverse/Common.php';
-
-/**
- * MDB2 PostGreSQL driver for the schema reverse engineering module
- *
- * @package MDB2
- * @category Database
- * @author Paul Cooper
- * @author Lorenzo Alberton
- */
-class MDB2_Driver_Reverse_pgsql extends MDB2_Driver_Reverse_Common
-{
- // {{{ getTableFieldDefinition()
-
- /**
- * Get the structure of a field into an array
- *
- * @param string $table_name name of table that should be used in method
- * @param string $field_name name of field that should be used in method
- * @return mixed data array on success, a MDB2 error on failure
- * @access public
- */
- function getTableFieldDefinition($table_name, $field_name)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $result = $db->loadModule('Datatype', null, true);
- if (MDB2::isError($result)) {
- return $result;
- }
-
- list($schema, $table) = $this->splitTableSchema($table_name);
-
- $query = "SELECT a.attname AS name,
- t.typname AS type,
- CASE a.attlen
- WHEN -1 THEN
- CASE t.typname
- WHEN 'numeric' THEN (a.atttypmod / 65536)
- WHEN 'decimal' THEN (a.atttypmod / 65536)
- WHEN 'money' THEN (a.atttypmod / 65536)
- ELSE CASE a.atttypmod
- WHEN -1 THEN NULL
- ELSE a.atttypmod - 4
- END
- END
- ELSE a.attlen
- END AS length,
- CASE t.typname
- WHEN 'numeric' THEN (a.atttypmod % 65536) - 4
- WHEN 'decimal' THEN (a.atttypmod % 65536) - 4
- WHEN 'money' THEN (a.atttypmod % 65536) - 4
- ELSE 0
- END AS scale,
- a.attnotnull,
- a.atttypmod,
- a.atthasdef,
- (SELECT substring(pg_get_expr(d.adbin, d.adrelid) for 128)
- FROM pg_attrdef d
- WHERE d.adrelid = a.attrelid
- AND d.adnum = a.attnum
- AND a.atthasdef
- ) as default
- FROM pg_attribute a,
- pg_class c,
- pg_type t
- WHERE c.relname = ".$db->quote($table, 'text')."
- AND a.atttypid = t.oid
- AND c.oid = a.attrelid
- AND NOT a.attisdropped
- AND a.attnum > 0
- AND a.attname = ".$db->quote($field_name, 'text')."
- ORDER BY a.attnum";
- $column = $db->queryRow($query, null, MDB2_FETCHMODE_ASSOC);
- if (MDB2::isError($column)) {
- return $column;
- }
-
- if (empty($column)) {
- return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- 'it was not specified an existing table column', __FUNCTION__);
- }
-
- $column = array_change_key_case($column, CASE_LOWER);
- $mapped_datatype = $db->datatype->mapNativeDatatype($column);
- if (MDB2::isError($mapped_datatype)) {
- return $mapped_datatype;
- }
- list($types, $length, $unsigned, $fixed) = $mapped_datatype;
- $notnull = false;
- if (!empty($column['attnotnull']) && $column['attnotnull'] == 't') {
- $notnull = true;
- }
- $default = null;
- if ($column['atthasdef'] === 't'
- && strpos($column['default'], 'NULL') !== 0
- && !preg_match("/nextval\('([^']+)'/", $column['default'])
- ) {
- $pattern = '/^\'(.*)\'::[\w ]+$/i';
- $default = $column['default'];#substr($column['adsrc'], 1, -1);
- if ((null === $default) && $notnull) {
- $default = '';
- } elseif (!empty($default) && preg_match($pattern, $default)) {
- //remove data type cast
- $default = preg_replace ($pattern, '\\1', $default);
- }
- }
- $autoincrement = false;
- if (preg_match("/nextval\('([^']+)'/", $column['default'], $nextvals)) {
- $autoincrement = true;
- }
- $definition[0] = array('notnull' => $notnull, 'nativetype' => $column['type']);
- if (null !== $length) {
- $definition[0]['length'] = $length;
- }
- if (null !== $unsigned) {
- $definition[0]['unsigned'] = $unsigned;
- }
- if (null !== $fixed) {
- $definition[0]['fixed'] = $fixed;
- }
- if ($default !== false) {
- $definition[0]['default'] = $default;
- }
- if ($autoincrement !== false) {
- $definition[0]['autoincrement'] = $autoincrement;
- }
- foreach ($types as $key => $type) {
- $definition[$key] = $definition[0];
- if ($type == 'clob' || $type == 'blob') {
- unset($definition[$key]['default']);
- }
- $definition[$key]['type'] = $type;
- $definition[$key]['mdb2type'] = $type;
- }
- return $definition;
- }
-
- // }}}
- // {{{ getTableIndexDefinition()
-
- /**
- * Get the structure of an index into an array
- *
- * @param string $table_name name of table that should be used in method
- * @param string $index_name name of index that should be used in method
- * @return mixed data array on success, a MDB2 error on failure
- * @access public
- */
- function getTableIndexDefinition($table_name, $index_name)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- list($schema, $table) = $this->splitTableSchema($table_name);
-
- $query = 'SELECT relname, indkey FROM pg_index, pg_class';
- $query.= ' WHERE pg_class.oid = pg_index.indexrelid';
- $query.= " AND indisunique != 't' AND indisprimary != 't'";
- $query.= ' AND pg_class.relname = %s';
- $index_name_mdb2 = $db->getIndexName($index_name);
- $row = $db->queryRow(sprintf($query, $db->quote($index_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC);
- if (MDB2::isError($row) || empty($row)) {
- // fallback to the given $index_name, without transformation
- $row = $db->queryRow(sprintf($query, $db->quote($index_name, 'text')), null, MDB2_FETCHMODE_ASSOC);
- }
- if (MDB2::isError($row)) {
- return $row;
- }
-
- if (empty($row)) {
- return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- 'it was not specified an existing table index', __FUNCTION__);
- }
-
- $row = array_change_key_case($row, CASE_LOWER);
-
- $db->loadModule('Manager', null, true);
- $columns = $db->manager->listTableFields($table_name);
-
- $definition = array();
-
- $index_column_numbers = explode(' ', $row['indkey']);
-
- $colpos = 1;
- foreach ($index_column_numbers as $number) {
- $definition['fields'][$columns[($number - 1)]] = array(
- 'position' => $colpos++,
- 'sorting' => 'ascending',
- );
- }
- return $definition;
- }
-
- // }}}
- // {{{ getTableConstraintDefinition()
-
- /**
- * Get the structure of a constraint into an array
- *
- * @param string $table_name name of table that should be used in method
- * @param string $constraint_name name of constraint that should be used in method
- * @return mixed data array on success, a MDB2 error on failure
- * @access public
- */
- function getTableConstraintDefinition($table_name, $constraint_name)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- list($schema, $table) = $this->splitTableSchema($table_name);
-
- $query = "SELECT c.oid,
- c.conname AS constraint_name,
- CASE WHEN c.contype = 'c' THEN 1 ELSE 0 END AS \"check\",
- CASE WHEN c.contype = 'f' THEN 1 ELSE 0 END AS \"foreign\",
- CASE WHEN c.contype = 'p' THEN 1 ELSE 0 END AS \"primary\",
- CASE WHEN c.contype = 'u' THEN 1 ELSE 0 END AS \"unique\",
- CASE WHEN c.condeferrable = 'f' THEN 0 ELSE 1 END AS deferrable,
- CASE WHEN c.condeferred = 'f' THEN 0 ELSE 1 END AS initiallydeferred,
- --array_to_string(c.conkey, ' ') AS constraint_key,
- t.relname AS table_name,
- t2.relname AS references_table,
- CASE confupdtype
- WHEN 'a' THEN 'NO ACTION'
- WHEN 'r' THEN 'RESTRICT'
- WHEN 'c' THEN 'CASCADE'
- WHEN 'n' THEN 'SET NULL'
- WHEN 'd' THEN 'SET DEFAULT'
- END AS onupdate,
- CASE confdeltype
- WHEN 'a' THEN 'NO ACTION'
- WHEN 'r' THEN 'RESTRICT'
- WHEN 'c' THEN 'CASCADE'
- WHEN 'n' THEN 'SET NULL'
- WHEN 'd' THEN 'SET DEFAULT'
- END AS ondelete,
- CASE confmatchtype
- WHEN 'u' THEN 'UNSPECIFIED'
- WHEN 'f' THEN 'FULL'
- WHEN 'p' THEN 'PARTIAL'
- END AS match,
- --array_to_string(c.confkey, ' ') AS fk_constraint_key,
- consrc
- FROM pg_constraint c
- LEFT JOIN pg_class t ON c.conrelid = t.oid
- LEFT JOIN pg_class t2 ON c.confrelid = t2.oid
- WHERE c.conname = %s
- AND t.relname = " . $db->quote($table, 'text');
- $constraint_name_mdb2 = $db->getIndexName($constraint_name);
- $row = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC);
- if (MDB2::isError($row) || empty($row)) {
- // fallback to the given $index_name, without transformation
- $constraint_name_mdb2 = $constraint_name;
- $row = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC);
- }
- if (MDB2::isError($row)) {
- return $row;
- }
- $uniqueIndex = false;
- if (empty($row)) {
- // We might be looking for a UNIQUE index that was not created
- // as a constraint but should be treated as such.
- $query = 'SELECT relname AS constraint_name,
- indkey,
- 0 AS "check",
- 0 AS "foreign",
- 0 AS "primary",
- 1 AS "unique",
- 0 AS deferrable,
- 0 AS initiallydeferred,
- NULL AS references_table,
- NULL AS onupdate,
- NULL AS ondelete,
- NULL AS match
- FROM pg_index, pg_class
- WHERE pg_class.oid = pg_index.indexrelid
- AND indisunique = \'t\'
- AND pg_class.relname = %s';
- $constraint_name_mdb2 = $db->getIndexName($constraint_name);
- $row = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC);
- if (MDB2::isError($row) || empty($row)) {
- // fallback to the given $index_name, without transformation
- $constraint_name_mdb2 = $constraint_name;
- $row = $db->queryRow(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null, MDB2_FETCHMODE_ASSOC);
- }
- if (MDB2::isError($row)) {
- return $row;
- }
- if (empty($row)) {
- return $db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- $constraint_name . ' is not an existing table constraint', __FUNCTION__);
- }
- $uniqueIndex = true;
- }
-
- $row = array_change_key_case($row, CASE_LOWER);
-
- $definition = array(
- 'primary' => (boolean)$row['primary'],
- 'unique' => (boolean)$row['unique'],
- 'foreign' => (boolean)$row['foreign'],
- 'check' => (boolean)$row['check'],
- 'fields' => array(),
- 'references' => array(
- 'table' => $row['references_table'],
- 'fields' => array(),
- ),
- 'deferrable' => (boolean)$row['deferrable'],
- 'initiallydeferred' => (boolean)$row['initiallydeferred'],
- 'onupdate' => $row['onupdate'],
- 'ondelete' => $row['ondelete'],
- 'match' => $row['match'],
- );
-
- if ($uniqueIndex) {
- $db->loadModule('Manager', null, true);
- $columns = $db->manager->listTableFields($table_name);
- $index_column_numbers = explode(' ', $row['indkey']);
- $colpos = 1;
- foreach ($index_column_numbers as $number) {
- $definition['fields'][$columns[($number - 1)]] = array(
- 'position' => $colpos++,
- 'sorting' => 'ascending',
- );
- }
- return $definition;
- }
-
- $query = 'SELECT a.attname
- FROM pg_constraint c
- LEFT JOIN pg_class t ON c.conrelid = t.oid
- LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.conkey)
- WHERE c.conname = %s
- AND t.relname = ' . $db->quote($table, 'text');
- $fields = $db->queryCol(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null);
- if (MDB2::isError($fields)) {
- return $fields;
- }
- $colpos = 1;
- foreach ($fields as $field) {
- $definition['fields'][$field] = array(
- 'position' => $colpos++,
- 'sorting' => 'ascending',
- );
- }
-
- if ($definition['foreign']) {
- $query = 'SELECT a.attname
- FROM pg_constraint c
- LEFT JOIN pg_class t ON c.confrelid = t.oid
- LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(c.confkey)
- WHERE c.conname = %s
- AND t.relname = ' . $db->quote($definition['references']['table'], 'text');
- $foreign_fields = $db->queryCol(sprintf($query, $db->quote($constraint_name_mdb2, 'text')), null);
- if (MDB2::isError($foreign_fields)) {
- return $foreign_fields;
- }
- $colpos = 1;
- foreach ($foreign_fields as $foreign_field) {
- $definition['references']['fields'][$foreign_field] = array(
- 'position' => $colpos++,
- );
- }
- }
-
- if ($definition['check']) {
- $check_def = $db->queryOne("SELECT pg_get_constraintdef(" . $row['oid'] . ", 't')");
- // ...
- }
- return $definition;
- }
-
- // }}}
- // {{{ getTriggerDefinition()
-
- /**
- * Get the structure of a trigger into an array
- *
- * EXPERIMENTAL
- *
- * WARNING: this function is experimental and may change the returned value
- * at any time until labelled as non-experimental
- *
- * @param string $trigger name of trigger that should be used in method
- * @return mixed data array on success, a MDB2 error on failure
- * @access public
- *
- * @TODO: add support for plsql functions and functions with args
- */
- function getTriggerDefinition($trigger)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $query = "SELECT trg.tgname AS trigger_name,
- tbl.relname AS table_name,
- CASE
- WHEN p.proname IS NOT NULL THEN 'EXECUTE PROCEDURE ' || p.proname || '();'
- ELSE ''
- END AS trigger_body,
- CASE trg.tgtype & cast(2 as int2)
- WHEN 0 THEN 'AFTER'
- ELSE 'BEFORE'
- END AS trigger_type,
- CASE trg.tgtype & cast(28 as int2)
- WHEN 16 THEN 'UPDATE'
- WHEN 8 THEN 'DELETE'
- WHEN 4 THEN 'INSERT'
- WHEN 20 THEN 'INSERT, UPDATE'
- WHEN 28 THEN 'INSERT, UPDATE, DELETE'
- WHEN 24 THEN 'UPDATE, DELETE'
- WHEN 12 THEN 'INSERT, DELETE'
- END AS trigger_event,
- CASE trg.tgenabled
- WHEN 'O' THEN 't'
- ELSE trg.tgenabled
- END AS trigger_enabled,
- obj_description(trg.oid, 'pg_trigger') AS trigger_comment
- FROM pg_trigger trg,
- pg_class tbl,
- pg_proc p
- WHERE trg.tgrelid = tbl.oid
- AND trg.tgfoid = p.oid
- AND trg.tgname = ". $db->quote($trigger, 'text');
- $types = array(
- 'trigger_name' => 'text',
- 'table_name' => 'text',
- 'trigger_body' => 'text',
- 'trigger_type' => 'text',
- 'trigger_event' => 'text',
- 'trigger_comment' => 'text',
- 'trigger_enabled' => 'boolean',
- );
- return $db->queryRow($query, $types, MDB2_FETCHMODE_ASSOC);
- }
-
- // }}}
- // {{{ tableInfo()
-
- /**
- * Returns information about a table or a result set
- *
- * NOTE: only supports 'table' and 'flags' if $result
- * is a table name.
- *
- * @param object|string $result MDB2_result object from a query or a
- * string containing the name of a table.
- * While this also accepts a query result
- * resource identifier, this behavior is
- * deprecated.
- * @param int $mode a valid tableInfo mode
- *
- * @return array an associative array with the information requested.
- * A MDB2_Error object on failure.
- *
- * @see MDB2_Driver_Common::tableInfo()
- */
- function tableInfo($result, $mode = null)
- {
- if (is_string($result)) {
- return parent::tableInfo($result, $mode);
- }
-
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $resource = MDB2::isResultCommon($result) ? $result->getResource() : $result;
- if (!is_resource($resource)) {
- return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
- 'Could not generate result resource', __FUNCTION__);
- }
-
- if ($db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- if ($db->options['field_case'] == CASE_LOWER) {
- $case_func = 'strtolower';
- } else {
- $case_func = 'strtoupper';
- }
- } else {
- $case_func = 'strval';
- }
-
- $count = @pg_num_fields($resource);
- $res = array();
-
- if ($mode) {
- $res['num_fields'] = $count;
- }
-
- $db->loadModule('Datatype', null, true);
- for ($i = 0; $i < $count; $i++) {
- $res[$i] = array(
- 'table' => function_exists('pg_field_table') ? @pg_field_table($resource, $i) : '',
- 'name' => $case_func(@pg_field_name($resource, $i)),
- 'type' => @pg_field_type($resource, $i),
- 'length' => @pg_field_size($resource, $i),
- 'flags' => '',
- );
- $mdb2type_info = $db->datatype->mapNativeDatatype($res[$i]);
- if (MDB2::isError($mdb2type_info)) {
- return $mdb2type_info;
- }
- $res[$i]['mdb2type'] = $mdb2type_info[0][0];
- if ($mode & MDB2_TABLEINFO_ORDER) {
- $res['order'][$res[$i]['name']] = $i;
- }
- if ($mode & MDB2_TABLEINFO_ORDERTABLE) {
- $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
- }
- }
-
- return $res;
- }
-}
-?>
diff --git a/data/module/MDB2/Driver/mysql.php b/data/module/MDB2/Driver/mysql.php
deleted file mode 100644
index 2dc51b12b52..00000000000
--- a/data/module/MDB2/Driver/mysql.php
+++ /dev/null
@@ -1,1729 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: mysql.php 327320 2012-08-27 15:52:50Z danielc $
-//
-
-/**
- * MDB2 MySQL driver
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_Driver_mysql extends MDB2_Driver_Common
-{
- // {{{ properties
-
- public $string_quoting = array(
- 'start' => "'",
- 'end' => "'",
- 'escape' => '\\',
- 'escape_pattern' => '\\',
- );
-
- public $identifier_quoting = array(
- 'start' => '`',
- 'end' => '`',
- 'escape' => '`',
- );
-
- public $sql_comments = array(
- array('start' => '-- ', 'end' => "\n", 'escape' => false),
- array('start' => '#', 'end' => "\n", 'escape' => false),
- array('start' => '/*', 'end' => '*/', 'escape' => false),
- );
-
- protected $server_capabilities_checked = false;
-
- protected $start_transaction = false;
-
- public $varchar_max_length = 255;
-
- // }}}
- // {{{ constructor
-
- /**
- * Constructor
- */
- function __construct()
- {
- parent::__construct();
-
- $this->phptype = 'mysql';
- $this->dbsyntax = 'mysql';
-
- $this->supported['sequences'] = 'emulated';
- $this->supported['indexes'] = true;
- $this->supported['affected_rows'] = true;
- $this->supported['transactions'] = false;
- $this->supported['savepoints'] = false;
- $this->supported['summary_functions'] = true;
- $this->supported['order_by_text'] = true;
- $this->supported['current_id'] = 'emulated';
- $this->supported['limit_queries'] = true;
- $this->supported['LOBs'] = true;
- $this->supported['replace'] = true;
- $this->supported['sub_selects'] = 'emulated';
- $this->supported['triggers'] = false;
- $this->supported['auto_increment'] = true;
- $this->supported['primary_key'] = true;
- $this->supported['result_introspection'] = true;
- $this->supported['prepared_statements'] = 'emulated';
- $this->supported['identifier_quoting'] = true;
- $this->supported['pattern_escaping'] = true;
- $this->supported['new_link'] = true;
-
- $this->options['DBA_username'] = false;
- $this->options['DBA_password'] = false;
- $this->options['default_table_type'] = '';
- $this->options['max_identifiers_length'] = 64;
-
- $this->_reCheckSupportedOptions();
- }
-
- // }}}
- // {{{ _reCheckSupportedOptions()
-
- /**
- * If the user changes certain options, other capabilities may depend
- * on the new settings, so we need to check them (again).
- *
- * @access private
- */
- function _reCheckSupportedOptions()
- {
- $this->supported['transactions'] = $this->options['use_transactions'];
- $this->supported['savepoints'] = $this->options['use_transactions'];
- if ($this->options['default_table_type']) {
- switch (strtoupper($this->options['default_table_type'])) {
- case 'BLACKHOLE':
- case 'MEMORY':
- case 'ARCHIVE':
- case 'CSV':
- case 'HEAP':
- case 'ISAM':
- case 'MERGE':
- case 'MRG_ISAM':
- case 'ISAM':
- case 'MRG_MYISAM':
- case 'MYISAM':
- $this->supported['savepoints'] = false;
- $this->supported['transactions'] = false;
- $this->warnings[] = $this->options['default_table_type'] .
- ' is not a supported default table type';
- break;
- }
- }
- }
-
- // }}}
- // {{{ function setOption($option, $value)
-
- /**
- * set the option for the db class
- *
- * @param string option name
- * @param mixed value for the option
- *
- * @return mixed MDB2_OK or MDB2 Error Object
- *
- * @access public
- */
- function setOption($option, $value)
- {
- $res = parent::setOption($option, $value);
- $this->_reCheckSupportedOptions();
- }
-
- // }}}
- // {{{ errorInfo()
-
- /**
- * This method is used to collect information about an error
- *
- * @param integer $error
- * @return array
- * @access public
- */
- function errorInfo($error = null)
- {
- if ($this->connection) {
- $native_code = @mysql_errno($this->connection);
- $native_msg = @mysql_error($this->connection);
- } else {
- $native_code = @mysql_errno();
- $native_msg = @mysql_error();
- }
- if (is_null($error)) {
- static $ecode_map;
- if (empty($ecode_map)) {
- $ecode_map = array(
- 1000 => MDB2_ERROR_INVALID, //hashchk
- 1001 => MDB2_ERROR_INVALID, //isamchk
- 1004 => MDB2_ERROR_CANNOT_CREATE,
- 1005 => MDB2_ERROR_CANNOT_CREATE,
- 1006 => MDB2_ERROR_CANNOT_CREATE,
- 1007 => MDB2_ERROR_ALREADY_EXISTS,
- 1008 => MDB2_ERROR_CANNOT_DROP,
- 1009 => MDB2_ERROR_CANNOT_DROP,
- 1010 => MDB2_ERROR_CANNOT_DROP,
- 1011 => MDB2_ERROR_CANNOT_DELETE,
- 1022 => MDB2_ERROR_ALREADY_EXISTS,
- 1029 => MDB2_ERROR_NOT_FOUND,
- 1032 => MDB2_ERROR_NOT_FOUND,
- 1044 => MDB2_ERROR_ACCESS_VIOLATION,
- 1045 => MDB2_ERROR_ACCESS_VIOLATION,
- 1046 => MDB2_ERROR_NODBSELECTED,
- 1048 => MDB2_ERROR_CONSTRAINT,
- 1049 => MDB2_ERROR_NOSUCHDB,
- 1050 => MDB2_ERROR_ALREADY_EXISTS,
- 1051 => MDB2_ERROR_NOSUCHTABLE,
- 1054 => MDB2_ERROR_NOSUCHFIELD,
- 1060 => MDB2_ERROR_ALREADY_EXISTS,
- 1061 => MDB2_ERROR_ALREADY_EXISTS,
- 1062 => MDB2_ERROR_ALREADY_EXISTS,
- 1064 => MDB2_ERROR_SYNTAX,
- 1067 => MDB2_ERROR_INVALID,
- 1072 => MDB2_ERROR_NOT_FOUND,
- 1086 => MDB2_ERROR_ALREADY_EXISTS,
- 1091 => MDB2_ERROR_NOT_FOUND,
- 1100 => MDB2_ERROR_NOT_LOCKED,
- 1109 => MDB2_ERROR_NOT_FOUND,
- 1125 => MDB2_ERROR_ALREADY_EXISTS,
- 1136 => MDB2_ERROR_VALUE_COUNT_ON_ROW,
- 1138 => MDB2_ERROR_INVALID,
- 1142 => MDB2_ERROR_ACCESS_VIOLATION,
- 1143 => MDB2_ERROR_ACCESS_VIOLATION,
- 1146 => MDB2_ERROR_NOSUCHTABLE,
- 1149 => MDB2_ERROR_SYNTAX,
- 1169 => MDB2_ERROR_CONSTRAINT,
- 1176 => MDB2_ERROR_NOT_FOUND,
- 1177 => MDB2_ERROR_NOSUCHTABLE,
- 1213 => MDB2_ERROR_DEADLOCK,
- 1216 => MDB2_ERROR_CONSTRAINT,
- 1217 => MDB2_ERROR_CONSTRAINT,
- 1227 => MDB2_ERROR_ACCESS_VIOLATION,
- 1235 => MDB2_ERROR_CANNOT_CREATE,
- 1299 => MDB2_ERROR_INVALID_DATE,
- 1300 => MDB2_ERROR_INVALID,
- 1304 => MDB2_ERROR_ALREADY_EXISTS,
- 1305 => MDB2_ERROR_NOT_FOUND,
- 1306 => MDB2_ERROR_CANNOT_DROP,
- 1307 => MDB2_ERROR_CANNOT_CREATE,
- 1334 => MDB2_ERROR_CANNOT_ALTER,
- 1339 => MDB2_ERROR_NOT_FOUND,
- 1356 => MDB2_ERROR_INVALID,
- 1359 => MDB2_ERROR_ALREADY_EXISTS,
- 1360 => MDB2_ERROR_NOT_FOUND,
- 1363 => MDB2_ERROR_NOT_FOUND,
- 1365 => MDB2_ERROR_DIVZERO,
- 1451 => MDB2_ERROR_CONSTRAINT,
- 1452 => MDB2_ERROR_CONSTRAINT,
- 1542 => MDB2_ERROR_CANNOT_DROP,
- 1546 => MDB2_ERROR_CONSTRAINT,
- 1582 => MDB2_ERROR_CONSTRAINT,
- 2003 => MDB2_ERROR_CONNECT_FAILED,
- 2019 => MDB2_ERROR_INVALID,
- );
- }
- if ($this->options['portability'] & MDB2_PORTABILITY_ERRORS) {
- $ecode_map[1022] = MDB2_ERROR_CONSTRAINT;
- $ecode_map[1048] = MDB2_ERROR_CONSTRAINT_NOT_NULL;
- $ecode_map[1062] = MDB2_ERROR_CONSTRAINT;
- } else {
- // Doing this in case mode changes during runtime.
- $ecode_map[1022] = MDB2_ERROR_ALREADY_EXISTS;
- $ecode_map[1048] = MDB2_ERROR_CONSTRAINT;
- $ecode_map[1062] = MDB2_ERROR_ALREADY_EXISTS;
- }
- if (isset($ecode_map[$native_code])) {
- $error = $ecode_map[$native_code];
- }
- }
- return array($error, $native_code, $native_msg);
- }
-
- // }}}
- // {{{ escape()
-
- /**
- * Quotes a string so it can be safely used in a query. It will quote
- * the text so it can safely be used within a query.
- *
- * @param string the input string to quote
- * @param bool escape wildcards
- *
- * @return string quoted string
- *
- * @access public
- */
- function escape($text, $escape_wildcards = false)
- {
- if ($escape_wildcards) {
- $text = $this->escapePattern($text);
- }
- $connection = $this->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
- $text = @mysql_real_escape_string($text, $connection);
- return $text;
- }
-
- // }}}
- // {{{ beginTransaction()
-
- /**
- * Start a transaction or set a savepoint.
- *
- * @param string name of a savepoint to set
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- */
- function beginTransaction($savepoint = null)
- {
- $this->debug('Starting transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
- $this->_getServerCapabilities();
- if (!is_null($savepoint)) {
- if (!$this->supports('savepoints')) {
- return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'savepoints are not supported', __FUNCTION__);
- }
- if (!$this->in_transaction) {
- return $this->raiseError(MDB2_ERROR_INVALID, null, null,
- 'savepoint cannot be released when changes are auto committed', __FUNCTION__);
- }
- $query = 'SAVEPOINT '.$savepoint;
- return $this->_doQuery($query, true);
- } elseif ($this->in_transaction) {
- return MDB2_OK; //nothing to do
- }
- if (!$this->destructor_registered && $this->opened_persistent) {
- $this->destructor_registered = true;
- register_shutdown_function('MDB2_closeOpenTransactions');
- }
- $query = $this->start_transaction ? 'START TRANSACTION' : 'SET AUTOCOMMIT = 0';
- $result = $this->_doQuery($query, true);
- if (MDB2::isError($result)) {
- return $result;
- }
- $this->in_transaction = true;
- return MDB2_OK;
- }
-
- // }}}
- // {{{ commit()
-
- /**
- * Commit the database changes done during a transaction that is in
- * progress or release a savepoint. This function may only be called when
- * auto-committing is disabled, otherwise it will fail. Therefore, a new
- * transaction is implicitly started after committing the pending changes.
- *
- * @param string name of a savepoint to release
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- */
- function commit($savepoint = null)
- {
- $this->debug('Committing transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
- if (!$this->in_transaction) {
- return $this->raiseError(MDB2_ERROR_INVALID, null, null,
- 'commit/release savepoint cannot be done changes are auto committed', __FUNCTION__);
- }
- if (!is_null($savepoint)) {
- if (!$this->supports('savepoints')) {
- return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'savepoints are not supported', __FUNCTION__);
- }
- $server_info = $this->getServerVersion();
- if (version_compare($server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'], '5.0.3', '<')) {
- return MDB2_OK;
- }
- $query = 'RELEASE SAVEPOINT '.$savepoint;
- return $this->_doQuery($query, true);
- }
-
- if (!$this->supports('transactions')) {
- return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'transactions are not supported', __FUNCTION__);
- }
-
- $result = $this->_doQuery('COMMIT', true);
- if (MDB2::isError($result)) {
- return $result;
- }
- if (!$this->start_transaction) {
- $query = 'SET AUTOCOMMIT = 1';
- $result = $this->_doQuery($query, true);
- if (MDB2::isError($result)) {
- return $result;
- }
- }
- $this->in_transaction = false;
- return MDB2_OK;
- }
-
- // }}}
- // {{{ rollback()
-
- /**
- * Cancel any database changes done during a transaction or since a specific
- * savepoint that is in progress. This function may only be called when
- * auto-committing is disabled, otherwise it will fail. Therefore, a new
- * transaction is implicitly started after canceling the pending changes.
- *
- * @param string name of a savepoint to rollback to
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- */
- function rollback($savepoint = null)
- {
- $this->debug('Rolling back transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
- if (!$this->in_transaction) {
- return $this->raiseError(MDB2_ERROR_INVALID, null, null,
- 'rollback cannot be done changes are auto committed', __FUNCTION__);
- }
- if (!is_null($savepoint)) {
- if (!$this->supports('savepoints')) {
- return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'savepoints are not supported', __FUNCTION__);
- }
- $query = 'ROLLBACK TO SAVEPOINT '.$savepoint;
- return $this->_doQuery($query, true);
- }
-
- $query = 'ROLLBACK';
- $result = $this->_doQuery($query, true);
- if (MDB2::isError($result)) {
- return $result;
- }
- if (!$this->start_transaction) {
- $query = 'SET AUTOCOMMIT = 1';
- $result = $this->_doQuery($query, true);
- if (MDB2::isError($result)) {
- return $result;
- }
- }
- $this->in_transaction = false;
- return MDB2_OK;
- }
-
- // }}}
- // {{{ function setTransactionIsolation()
-
- /**
- * Set the transacton isolation level.
- *
- * @param string standard isolation level
- * READ UNCOMMITTED (allows dirty reads)
- * READ COMMITTED (prevents dirty reads)
- * REPEATABLE READ (prevents nonrepeatable reads)
- * SERIALIZABLE (prevents phantom reads)
- * @param array some transaction options:
- * 'wait' => 'WAIT' | 'NO WAIT'
- * 'rw' => 'READ WRITE' | 'READ ONLY'
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- * @since 2.1.1
- */
- function setTransactionIsolation($isolation, $options = array())
- {
- $this->debug('Setting transaction isolation level', __FUNCTION__, array('is_manip' => true));
- if (!$this->supports('transactions')) {
- return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'transactions are not supported', __FUNCTION__);
- }
- switch ($isolation) {
- case 'READ UNCOMMITTED':
- case 'READ COMMITTED':
- case 'REPEATABLE READ':
- case 'SERIALIZABLE':
- break;
- default:
- return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'isolation level is not supported: '.$isolation, __FUNCTION__);
- }
-
- $query = "SET SESSION TRANSACTION ISOLATION LEVEL $isolation";
- return $this->_doQuery($query, true);
- }
-
- // }}}
- // {{{ _doConnect()
-
- /**
- * do the grunt work of the connect
- *
- * @return connection on success or MDB2 Error Object on failure
- * @access protected
- */
- function _doConnect($username, $password, $persistent = false)
- {
- if (!extension_loaded($this->phptype)) {
- return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- 'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__);
- }
-
- $params = array();
- $unix = ($this->dsn['protocol'] && $this->dsn['protocol'] == 'unix');
- if (empty($this->dsn['hostspec'])) {
- $this->dsn['hostspec'] = $unix ? '' : 'localhost';
- }
- if ($this->dsn['hostspec']) {
- $params[0] = $this->dsn['hostspec'] . ($this->dsn['port'] ? ':' . $this->dsn['port'] : '');
- } else {
- $params[0] = ':' . $this->dsn['socket'];
- }
- $params[] = $username ? $username : null;
- $params[] = $password ? $password : null;
- if (!$persistent) {
- if ($this->_isNewLinkSet()) {
- $params[] = true;
- } else {
- $params[] = false;
- }
- }
- if (version_compare(phpversion(), '4.3.0', '>=')) {
- $params[] = isset($this->dsn['client_flags'])
- ? $this->dsn['client_flags'] : null;
- }
- $connect_function = $persistent ? 'mysql_pconnect' : 'mysql_connect';
-
- $connection = @call_user_func_array($connect_function, $params);
- if (!$connection) {
- if (($err = @mysql_error()) != '') {
- return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null,
- $err, __FUNCTION__);
- } else {
- return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null,
- 'unable to establish a connection', __FUNCTION__);
- }
- }
-
- if (!empty($this->dsn['charset'])) {
- $result = $this->setCharset($this->dsn['charset'], $connection);
- if (MDB2::isError($result)) {
- $this->disconnect(false);
- return $result;
- }
- }
-
- return $connection;
- }
-
- // }}}
- // {{{ connect()
-
- /**
- * Connect to the database
- *
- * @return MDB2_OK on success, MDB2 Error Object on failure
- * @access public
- */
- function connect()
- {
- if (is_resource($this->connection)) {
- //if (count(array_diff($this->connected_dsn, $this->dsn)) == 0
- if (MDB2::areEquals($this->connected_dsn, $this->dsn)
- && $this->opened_persistent == $this->options['persistent']
- ) {
- return MDB2_OK;
- }
- $this->disconnect(false);
- }
-
- $connection = $this->_doConnect(
- $this->dsn['username'],
- $this->dsn['password'],
- $this->options['persistent']
- );
- if (MDB2::isError($connection)) {
- return $connection;
- }
-
- $this->connection = $connection;
- $this->connected_dsn = $this->dsn;
- $this->connected_database_name = '';
- $this->opened_persistent = $this->options['persistent'];
- $this->dbsyntax = $this->dsn['dbsyntax'] ? $this->dsn['dbsyntax'] : $this->phptype;
-
- if ($this->database_name) {
- if ($this->database_name != $this->connected_database_name) {
- if (!@mysql_select_db($this->database_name, $connection)) {
- $err = $this->raiseError(null, null, null,
- 'Could not select the database: '.$this->database_name, __FUNCTION__);
- return $err;
- }
- $this->connected_database_name = $this->database_name;
- }
- }
-
- $this->_getServerCapabilities();
-
- return MDB2_OK;
- }
-
- // }}}
- // {{{ setCharset()
-
- /**
- * Set the charset on the current connection
- *
- * @param string charset (or array(charset, collation))
- * @param resource connection handle
- *
- * @return true on success, MDB2 Error Object on failure
- */
- function setCharset($charset, $connection = null)
- {
- if (is_null($connection)) {
- $connection = $this->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
- }
- $collation = null;
- if (is_array($charset) && 2 == count($charset)) {
- $collation = array_pop($charset);
- $charset = array_pop($charset);
- }
- $client_info = mysql_get_client_info();
- if (function_exists('mysql_set_charset') && version_compare($client_info, '5.0.6')) {
- if (!$result = mysql_set_charset($charset, $connection)) {
- $err = $this->raiseError(null, null, null,
- 'Could not set client character set', __FUNCTION__);
- return $err;
- }
- return $result;
- }
- $query = "SET NAMES '".mysql_real_escape_string($charset, $connection)."'";
- if (!is_null($collation)) {
- $query .= " COLLATE '".mysql_real_escape_string($collation, $connection)."'";
- }
- return $this->_doQuery($query, true, $connection);
- }
-
- // }}}
- // {{{ databaseExists()
-
- /**
- * check if given database name is exists?
- *
- * @param string $name name of the database that should be checked
- *
- * @return mixed true/false on success, a MDB2 error on failure
- * @access public
- */
- function databaseExists($name)
- {
- $connection = $this->_doConnect($this->dsn['username'],
- $this->dsn['password'],
- $this->options['persistent']);
- if (MDB2::isError($connection)) {
- return $connection;
- }
-
- $result = @mysql_select_db($name, $connection);
- @mysql_close($connection);
-
- return $result;
- }
-
- // }}}
- // {{{ disconnect()
-
- /**
- * Log out and disconnect from the database.
- *
- * @param boolean $force if the disconnect should be forced even if the
- * connection is opened persistently
- * @return mixed true on success, false if not connected and error
- * object on error
- * @access public
- */
- function disconnect($force = true)
- {
- if (is_resource($this->connection)) {
- if ($this->in_transaction) {
- $dsn = $this->dsn;
- $database_name = $this->database_name;
- $persistent = $this->options['persistent'];
- $this->dsn = $this->connected_dsn;
- $this->database_name = $this->connected_database_name;
- $this->options['persistent'] = $this->opened_persistent;
- $this->rollback();
- $this->dsn = $dsn;
- $this->database_name = $database_name;
- $this->options['persistent'] = $persistent;
- }
-
- if (!$this->opened_persistent || $force) {
- $ok = @mysql_close($this->connection);
- if (!$ok) {
- return $this->raiseError(MDB2_ERROR_DISCONNECT_FAILED,
- null, null, null, __FUNCTION__);
- }
- }
- } else {
- return false;
- }
- return parent::disconnect($force);
- }
-
- // }}}
- // {{{ standaloneQuery()
-
- /**
- * execute a query as DBA
- *
- * @param string $query the SQL query
- * @param mixed $types array that contains the types of the columns in
- * the result set
- * @param boolean $is_manip if the query is a manipulation query
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function standaloneQuery($query, $types = null, $is_manip = false)
- {
- $user = $this->options['DBA_username']? $this->options['DBA_username'] : $this->dsn['username'];
- $pass = $this->options['DBA_password']? $this->options['DBA_password'] : $this->dsn['password'];
- $connection = $this->_doConnect($user, $pass, $this->options['persistent']);
- if (MDB2::isError($connection)) {
- return $connection;
- }
-
- $offset = $this->offset;
- $limit = $this->limit;
- $this->offset = $this->limit = 0;
- $query = $this->_modifyQuery($query, $is_manip, $limit, $offset);
-
- $result = $this->_doQuery($query, $is_manip, $connection, $this->database_name);
- if (!MDB2::isError($result)) {
- $result = $this->_affectedRows($connection, $result);
- }
-
- @mysql_close($connection);
- return $result;
- }
-
- // }}}
- // {{{ _doQuery()
-
- /**
- * Execute a query
- * @param string $query query
- * @param boolean $is_manip if the query is a manipulation query
- * @param resource $connection
- * @param string $database_name
- * @return result or error object
- * @access protected
- */
- function _doQuery($query, $is_manip = false, $connection = null, $database_name = null)
- {
- $this->last_query = $query;
- $result = $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'pre'));
- if ($result) {
- if (MDB2::isError($result)) {
- return $result;
- }
- $query = $result;
- }
- if ($this->options['disable_query']) {
- $result = $is_manip ? 0 : null;
- return $result;
- }
-
- if (is_null($connection)) {
- $connection = $this->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
- }
- if (is_null($database_name)) {
- $database_name = $this->database_name;
- }
-
- if ($database_name) {
- if ($database_name != $this->connected_database_name) {
- if (!@mysql_select_db($database_name, $connection)) {
- $err = $this->raiseError(null, null, null,
- 'Could not select the database: '.$database_name, __FUNCTION__);
- return $err;
- }
- $this->connected_database_name = $database_name;
- }
- }
-
- $function = $this->options['result_buffering']
- ? 'mysql_query' : 'mysql_unbuffered_query';
- $result = @$function($query, $connection);
- if (!$result && 0 !== mysql_errno($connection)) {
- $err = $this->raiseError(null, null, null,
- 'Could not execute statement', __FUNCTION__);
- return $err;
- }
-
- $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'post', 'result' => $result));
- return $result;
- }
-
- // }}}
- // {{{ _affectedRows()
-
- /**
- * Returns the number of rows affected
- *
- * @param resource $result
- * @param resource $connection
- * @return mixed MDB2 Error Object or the number of rows affected
- * @access private
- */
- function _affectedRows($connection, $result = null)
- {
- if (is_null($connection)) {
- $connection = $this->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
- }
- return @mysql_affected_rows($connection);
- }
-
- // }}}
- // {{{ _modifyQuery()
-
- /**
- * Changes a query string for various DBMS specific reasons
- *
- * @param string $query query to modify
- * @param boolean $is_manip if it is a DML query
- * @param integer $limit limit the number of rows
- * @param integer $offset start reading from given offset
- * @return string modified query
- * @access protected
- */
- function _modifyQuery($query, $is_manip, $limit, $offset)
- {
- if ($this->options['portability'] & MDB2_PORTABILITY_DELETE_COUNT) {
- // "DELETE FROM table" gives 0 affected rows in MySQL.
- // This little hack lets you know how many rows were deleted.
- if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) {
- $query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/',
- 'DELETE FROM \1 WHERE 1=1', $query);
- }
- }
- if ($limit > 0
- && !preg_match('/LIMIT\s*\d(?:\s*(?:,|OFFSET)\s*\d+)?(?:[^\)]*)?$/i', $query)
- ) {
- $query = rtrim($query);
- if (substr($query, -1) == ';') {
- $query = substr($query, 0, -1);
- }
-
- // LIMIT doesn't always come last in the query
- // @see http://dev.mysql.com/doc/refman/5.0/en/select.html
- $after = '';
- if (preg_match('/(\s+INTO\s+(?:OUT|DUMP)FILE\s.*)$/ims', $query, $matches)) {
- $after = $matches[0];
- $query = preg_replace('/(\s+INTO\s+(?:OUT|DUMP)FILE\s.*)$/ims', '', $query);
- } elseif (preg_match('/(\s+FOR\s+UPDATE\s*)$/i', $query, $matches)) {
- $after = $matches[0];
- $query = preg_replace('/(\s+FOR\s+UPDATE\s*)$/im', '', $query);
- } elseif (preg_match('/(\s+LOCK\s+IN\s+SHARE\s+MODE\s*)$/im', $query, $matches)) {
- $after = $matches[0];
- $query = preg_replace('/(\s+LOCK\s+IN\s+SHARE\s+MODE\s*)$/im', '', $query);
- }
-
- if ($is_manip) {
- return $query . " LIMIT $limit" . $after;
- } else {
- return $query . " LIMIT $offset, $limit" . $after;
- }
- }
- return $query;
- }
-
- // }}}
- // {{{ getServerVersion()
-
- /**
- * return version information about the server
- *
- * @param bool $native determines if the raw version string should be returned
- * @return mixed array/string with version information or MDB2 error object
- * @access public
- */
- function getServerVersion($native = false)
- {
- $connection = $this->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
- if ($this->connected_server_info) {
- $server_info = $this->connected_server_info;
- } else {
- $server_info = @mysql_get_server_info($connection);
- }
- if (!$server_info) {
- return $this->raiseError(null, null, null,
- 'Could not get server information', __FUNCTION__);
- }
- // cache server_info
- $this->connected_server_info = $server_info;
- if (!$native) {
- $tmp = explode('.', $server_info, 3);
- if (isset($tmp[2]) && strpos($tmp[2], '-')) {
- $tmp2 = explode('-', @$tmp[2], 2);
- } else {
- $tmp2[0] = isset($tmp[2]) ? $tmp[2] : null;
- $tmp2[1] = null;
- }
- $server_info = array(
- 'major' => isset($tmp[0]) ? $tmp[0] : null,
- 'minor' => isset($tmp[1]) ? $tmp[1] : null,
- 'patch' => $tmp2[0],
- 'extra' => $tmp2[1],
- 'native' => $server_info,
- );
- }
- return $server_info;
- }
-
- // }}}
- // {{{ _getServerCapabilities()
-
- /**
- * Fetch some information about the server capabilities
- * (transactions, subselects, prepared statements, etc).
- *
- * @access private
- */
- function _getServerCapabilities()
- {
- if (!$this->server_capabilities_checked) {
- $this->server_capabilities_checked = true;
-
- //set defaults
- $this->supported['sub_selects'] = 'emulated';
- $this->supported['prepared_statements'] = 'emulated';
- $this->supported['triggers'] = false;
- $this->start_transaction = false;
- $this->varchar_max_length = 255;
-
- $server_info = $this->getServerVersion();
- if (is_array($server_info)) {
- $server_version = $server_info['major'].'.'.$server_info['minor'].'.'.$server_info['patch'];
-
- if (!version_compare($server_version, '4.1.0', '<')) {
- $this->supported['sub_selects'] = true;
- $this->supported['prepared_statements'] = true;
- }
-
- // SAVEPOINTs were introduced in MySQL 4.0.14 and 4.1.1 (InnoDB)
- if (version_compare($server_version, '4.1.0', '>=')) {
- if (version_compare($server_version, '4.1.1', '<')) {
- $this->supported['savepoints'] = false;
- }
- } elseif (version_compare($server_version, '4.0.14', '<')) {
- $this->supported['savepoints'] = false;
- }
-
- if (!version_compare($server_version, '4.0.11', '<')) {
- $this->start_transaction = true;
- }
-
- if (!version_compare($server_version, '5.0.3', '<')) {
- $this->varchar_max_length = 65532;
- }
-
- if (!version_compare($server_version, '5.0.2', '<')) {
- $this->supported['triggers'] = true;
- }
- }
- }
- }
-
- // }}}
- // {{{ function _skipUserDefinedVariable($query, $position)
-
- /**
- * Utility method, used by prepare() to avoid misinterpreting MySQL user
- * defined variables (SELECT @x:=5) for placeholders.
- * Check if the placeholder is a false positive, i.e. if it is an user defined
- * variable instead. If so, skip it and advance the position, otherwise
- * return the current position, which is valid
- *
- * @param string $query
- * @param integer $position current string cursor position
- * @return integer $new_position
- * @access protected
- */
- function _skipUserDefinedVariable($query, $position)
- {
- $found = strpos(strrev(substr($query, 0, $position)), '@');
- if ($found === false) {
- return $position;
- }
- $pos = strlen($query) - strlen(substr($query, $position)) - $found - 1;
- $substring = substr($query, $pos, $position - $pos + 2);
- if (preg_match('/^@\w+\s*:=$/', $substring)) {
- return $position + 1; //found an user defined variable: skip it
- }
- return $position;
- }
-
- // }}}
- // {{{ prepare()
-
- /**
- * Prepares a query for multiple execution with execute().
- * With some database backends, this is emulated.
- * prepare() requires a generic query as string like
- * 'INSERT INTO numbers VALUES(?,?)' or
- * 'INSERT INTO numbers VALUES(:foo,:bar)'.
- * The ? and :name and are placeholders which can be set using
- * bindParam() and the query can be sent off using the execute() method.
- * The allowed format for :name can be set with the 'bindname_format' option.
- *
- * @param string $query the query to prepare
- * @param mixed $types array that contains the types of the placeholders
- * @param mixed $result_types array that contains the types of the columns in
- * the result set or MDB2_PREPARE_RESULT, if set to
- * MDB2_PREPARE_MANIP the query is handled as a manipulation query
- * @param mixed $lobs key (field) value (parameter) pair for all lob placeholders
- * @return mixed resource handle for the prepared query on success, a MDB2
- * error on failure
- * @access public
- * @see bindParam, execute
- */
- function prepare($query, $types = null, $result_types = null, $lobs = array())
- {
- // connect to get server capabilities (http://pear.php.net/bugs/16147)
- $connection = $this->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
-
- if ($this->options['emulate_prepared']
- || $this->supported['prepared_statements'] !== true
- ) {
- return parent::prepare($query, $types, $result_types, $lobs);
- }
- $is_manip = ($result_types === MDB2_PREPARE_MANIP);
- $offset = $this->offset;
- $limit = $this->limit;
- $this->offset = $this->limit = 0;
- $query = $this->_modifyQuery($query, $is_manip, $limit, $offset);
- $result = $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'pre'));
- if ($result) {
- if (MDB2::isError($result)) {
- return $result;
- }
- $query = $result;
- }
- $placeholder_type_guess = $placeholder_type = null;
- $question = '?';
- $colon = ':';
- $positions = array();
- $position = 0;
- while ($position < strlen($query)) {
- $q_position = strpos($query, $question, $position);
- $c_position = strpos($query, $colon, $position);
- if ($q_position && $c_position) {
- $p_position = min($q_position, $c_position);
- } elseif ($q_position) {
- $p_position = $q_position;
- } elseif ($c_position) {
- $p_position = $c_position;
- } else {
- break;
- }
- if (is_null($placeholder_type)) {
- $placeholder_type_guess = $query[$p_position];
- }
-
- $new_pos = $this->_skipDelimitedStrings($query, $position, $p_position);
- if (MDB2::isError($new_pos)) {
- return $new_pos;
- }
- if ($new_pos != $position) {
- $position = $new_pos;
- continue; //evaluate again starting from the new position
- }
-
- //make sure this is not part of an user defined variable
- $new_pos = $this->_skipUserDefinedVariable($query, $position);
- if ($new_pos != $position) {
- $position = $new_pos;
- continue; //evaluate again starting from the new position
- }
-
- if ($query[$position] == $placeholder_type_guess) {
- if (is_null($placeholder_type)) {
- $placeholder_type = $query[$p_position];
- $question = $colon = $placeholder_type;
- }
- if ($placeholder_type == ':') {
- $regexp = '/^.{'.($position+1).'}('.$this->options['bindname_format'].').*$/s';
- $parameter = preg_replace($regexp, '\\1', $query);
- if ($parameter === '') {
- $err = $this->raiseError(MDB2_ERROR_SYNTAX, null, null,
- 'named parameter name must match "bindname_format" option', __FUNCTION__);
- return $err;
- }
- $positions[$p_position] = $parameter;
- $query = substr_replace($query, '?', $position, strlen($parameter)+1);
- } else {
- $positions[$p_position] = count($positions);
- }
- $position = $p_position + 1;
- } else {
- $position = $p_position;
- }
- }
-
- static $prep_statement_counter = 1;
- $statement_name = sprintf($this->options['statement_format'], $this->phptype, $prep_statement_counter++ . sha1(microtime() + mt_rand()));
- $statement_name = substr(strtolower($statement_name), 0, $this->options['max_identifiers_length']);
- $query = "PREPARE $statement_name FROM ".$this->quote($query, 'text');
- $statement = $this->_doQuery($query, true, $connection);
- if (MDB2::isError($statement)) {
- return $statement;
- }
-
- $class_name = 'MDB2_Statement_'.$this->phptype;
- $obj = new $class_name($this, $statement_name, $positions, $query, $types, $result_types, $is_manip, $limit, $offset);
- $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'post', 'result' => $obj));
- return $obj;
- }
-
- // }}}
- // {{{ replace()
-
- /**
- * Execute a SQL REPLACE query. A REPLACE query is identical to a INSERT
- * query, except that if there is already a row in the table with the same
- * key field values, the old row is deleted before the new row is inserted.
- *
- * The REPLACE type of query does not make part of the SQL standards. Since
- * practically only MySQL implements it natively, this type of query is
- * emulated through this method for other DBMS using standard types of
- * queries inside a transaction to assure the atomicity of the operation.
- *
- * @access public
- *
- * @param string $table name of the table on which the REPLACE query will
- * be executed.
- * @param array $fields associative array that describes the fields and the
- * values that will be inserted or updated in the specified table. The
- * indexes of the array are the names of all the fields of the table. The
- * values of the array are also associative arrays that describe the
- * values and other properties of the table fields.
- *
- * Here follows a list of field properties that need to be specified:
- *
- * value:
- * Value to be assigned to the specified field. This value may be
- * of specified in database independent type format as this
- * function can perform the necessary datatype conversions.
- *
- * Default:
- * this property is required unless the Null property
- * is set to 1.
- *
- * type
- * Name of the type of the field. Currently, all types Metabase
- * are supported except for clob and blob.
- *
- * Default: no type conversion
- *
- * null
- * Boolean property that indicates that the value for this field
- * should be set to null.
- *
- * The default value for fields missing in INSERT queries may be
- * specified the definition of a table. Often, the default value
- * is already null, but since the REPLACE may be emulated using
- * an UPDATE query, make sure that all fields of the table are
- * listed in this function argument array.
- *
- * Default: 0
- *
- * key
- * Boolean property that indicates that this field should be
- * handled as a primary key or at least as part of the compound
- * unique index of the table that will determine the row that will
- * updated if it exists or inserted a new row otherwise.
- *
- * This function will fail if no key field is specified or if the
- * value of a key field is set to null because fields that are
- * part of unique index they may not be null.
- *
- * Default: 0
- *
- * @see http://dev.mysql.com/doc/refman/5.0/en/replace.html
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- */
- function replace($table, $fields)
- {
- $count = count($fields);
- $query = $values = '';
- $keys = $colnum = 0;
- for (reset($fields); $colnum < $count; next($fields), $colnum++) {
- $name = key($fields);
- if ($colnum > 0) {
- $query .= ',';
- $values.= ',';
- }
- $query.= $this->quoteIdentifier($name, true);
- if (isset($fields[$name]['null']) && $fields[$name]['null']) {
- $value = 'NULL';
- } else {
- $type = isset($fields[$name]['type']) ? $fields[$name]['type'] : null;
- $value = $this->quote($fields[$name]['value'], $type);
- if (MDB2::isError($value)) {
- return $value;
- }
- }
- $values.= $value;
- if (isset($fields[$name]['key']) && $fields[$name]['key']) {
- if ($value === 'NULL') {
- return $this->raiseError(MDB2_ERROR_CANNOT_REPLACE, null, null,
- 'key value '.$name.' may not be NULL', __FUNCTION__);
- }
- $keys++;
- }
- }
- if ($keys == 0) {
- return $this->raiseError(MDB2_ERROR_CANNOT_REPLACE, null, null,
- 'not specified which fields are keys', __FUNCTION__);
- }
-
- $connection = $this->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
-
- $table = $this->quoteIdentifier($table, true);
- $query = "REPLACE INTO $table ($query) VALUES ($values)";
- $result = $this->_doQuery($query, true, $connection);
- if (MDB2::isError($result)) {
- return $result;
- }
- return $this->_affectedRows($connection, $result);
- }
-
- // }}}
- // {{{ nextID()
-
- /**
- * Returns the next free id of a sequence
- *
- * @param string $seq_name name of the sequence
- * @param boolean $ondemand when true the sequence is
- * automatic created, if it
- * not exists
- *
- * @return mixed MDB2 Error Object or id
- * @access public
- */
- function nextID($seq_name, $ondemand = true)
- {
- $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true);
- $seqcol_name = $this->quoteIdentifier($this->options['seqcol_name'], true);
- $query = "INSERT INTO $sequence_name ($seqcol_name) VALUES (NULL)";
- $this->pushErrorHandling(PEAR_ERROR_RETURN);
- $this->expectError(MDB2_ERROR_NOSUCHTABLE);
- $result = $this->_doQuery($query, true);
- $this->popExpect();
- $this->popErrorHandling();
- if (MDB2::isError($result)) {
- if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) {
- $this->loadModule('Manager', null, true);
- $result = $this->manager->createSequence($seq_name);
- if (MDB2::isError($result)) {
- return $this->raiseError($result, null, null,
- 'on demand sequence '.$seq_name.' could not be created', __FUNCTION__);
- } else {
- return $this->nextID($seq_name, false);
- }
- }
- return $result;
- }
- $value = $this->lastInsertID();
- if (is_numeric($value)) {
- $query = "DELETE FROM $sequence_name WHERE $seqcol_name < $value";
- $result = $this->_doQuery($query, true);
- if (MDB2::isError($result)) {
- $this->warnings[] = 'nextID: could not delete previous sequence table values from '.$seq_name;
- }
- }
- return $value;
- }
-
- // }}}
- // {{{ lastInsertID()
-
- /**
- * Returns the autoincrement ID if supported or $id or fetches the current
- * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field)
- *
- * @param string $table name of the table into which a new row was inserted
- * @param string $field name of the field into which a new row was inserted
- * @return mixed MDB2 Error Object or id
- * @access public
- */
- function lastInsertID($table = null, $field = null)
- {
- // not using mysql_insert_id() due to http://pear.php.net/bugs/bug.php?id=8051
- // not casting to integer to handle BIGINT http://pear.php.net/bugs/bug.php?id=17650
- return $this->queryOne('SELECT LAST_INSERT_ID()');
- }
-
- // }}}
- // {{{ currID()
-
- /**
- * Returns the current id of a sequence
- *
- * @param string $seq_name name of the sequence
- * @return mixed MDB2 Error Object or id
- * @access public
- */
- function currID($seq_name)
- {
- $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true);
- $seqcol_name = $this->quoteIdentifier($this->options['seqcol_name'], true);
- $query = "SELECT MAX($seqcol_name) FROM $sequence_name";
- return $this->queryOne($query, 'integer');
- }
-}
-
-/**
- * MDB2 MySQL result driver
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_Result_mysql extends MDB2_Result_Common
-{
- // }}}
- // {{{ fetchRow()
-
- /**
- * Fetch a row and insert the data into an existing array.
- *
- * @param int $fetchmode how the array data should be indexed
- * @param int $rownum number of the row where the data can be found
- * @return int data array on success, a MDB2 error on failure
- * @access public
- */
- function fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null)
- {
- if (!is_null($rownum)) {
- $seek = $this->seek($rownum);
- if (MDB2::isError($seek)) {
- return $seek;
- }
- }
- if ($fetchmode == MDB2_FETCHMODE_DEFAULT) {
- $fetchmode = $this->db->fetchmode;
- }
- if ( $fetchmode == MDB2_FETCHMODE_ASSOC
- || $fetchmode == MDB2_FETCHMODE_OBJECT
- ) {
- $row = @mysql_fetch_assoc($this->result);
- if (is_array($row)
- && $this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE
- ) {
- $row = array_change_key_case($row, $this->db->options['field_case']);
- }
- } else {
- $row = @mysql_fetch_row($this->result);
- }
-
- if (!$row) {
- if ($this->result === false) {
- $err = $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
- 'resultset has already been freed', __FUNCTION__);
- return $err;
- }
- return null;
- }
- $mode = $this->db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL;
- $rtrim = false;
- if ($this->db->options['portability'] & MDB2_PORTABILITY_RTRIM) {
- if (empty($this->types)) {
- $mode += MDB2_PORTABILITY_RTRIM;
- } else {
- $rtrim = true;
- }
- }
- if ($mode) {
- $this->db->_fixResultArrayValues($row, $mode);
- }
- if ( ( $fetchmode != MDB2_FETCHMODE_ASSOC
- && $fetchmode != MDB2_FETCHMODE_OBJECT)
- && !empty($this->types)
- ) {
- $row = $this->db->datatype->convertResultRow($this->types, $row, $rtrim);
- } elseif (($fetchmode == MDB2_FETCHMODE_ASSOC
- || $fetchmode == MDB2_FETCHMODE_OBJECT)
- && !empty($this->types_assoc)
- ) {
- $row = $this->db->datatype->convertResultRow($this->types_assoc, $row, $rtrim);
- }
- if (!empty($this->values)) {
- $this->_assignBindColumns($row);
- }
- if ($fetchmode === MDB2_FETCHMODE_OBJECT) {
- $object_class = $this->db->options['fetch_class'];
- if ($object_class == 'stdClass') {
- $row = (object) $row;
- } else {
- $rowObj = new $object_class($row);
- $row = $rowObj;
- }
- }
- ++$this->rownum;
- return $row;
- }
-
- // }}}
- // {{{ _getColumnNames()
-
- /**
- * Retrieve the names of columns returned by the DBMS in a query result.
- *
- * @return mixed Array variable that holds the names of columns as keys
- * or an MDB2 error on failure.
- * Some DBMS may not return any columns when the result set
- * does not contain any rows.
- * @access private
- */
- function _getColumnNames()
- {
- $columns = array();
- $numcols = $this->numCols();
- if (MDB2::isError($numcols)) {
- return $numcols;
- }
- for ($column = 0; $column < $numcols; $column++) {
- $column_name = @mysql_field_name($this->result, $column);
- $columns[$column_name] = $column;
- }
- if ($this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- $columns = array_change_key_case($columns, $this->db->options['field_case']);
- }
- return $columns;
- }
-
- // }}}
- // {{{ numCols()
-
- /**
- * Count the number of columns returned by the DBMS in a query result.
- *
- * @return mixed integer value with the number of columns, a MDB2 error
- * on failure
- * @access public
- */
- function numCols()
- {
- $cols = @mysql_num_fields($this->result);
- if (is_null($cols)) {
- if ($this->result === false) {
- return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
- 'resultset has already been freed', __FUNCTION__);
- } elseif (is_null($this->result)) {
- return count($this->types);
- }
- return $this->db->raiseError(null, null, null,
- 'Could not get column count', __FUNCTION__);
- }
- return $cols;
- }
-
- // }}}
- // {{{ free()
-
- /**
- * Free the internal resources associated with result.
- *
- * @return boolean true on success, false if result is invalid
- * @access public
- */
- function free()
- {
- if (is_resource($this->result) && $this->db->connection) {
- $free = @mysql_free_result($this->result);
- if ($free === false) {
- return $this->db->raiseError(null, null, null,
- 'Could not free result', __FUNCTION__);
- }
- }
- $this->result = false;
- return MDB2_OK;
- }
-}
-
-/**
- * MDB2 MySQL buffered result driver
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_BufferedResult_mysql extends MDB2_Result_mysql
-{
- // }}}
- // {{{ seek()
-
- /**
- * Seek to a specific row in a result set
- *
- * @param int $rownum number of the row where the data can be found
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function seek($rownum = 0)
- {
- if ($this->rownum != ($rownum - 1) && !@mysql_data_seek($this->result, $rownum)) {
- if ($this->result === false) {
- return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
- 'resultset has already been freed', __FUNCTION__);
- } elseif (is_null($this->result)) {
- return MDB2_OK;
- }
- return $this->db->raiseError(MDB2_ERROR_INVALID, null, null,
- 'tried to seek to an invalid row number ('.$rownum.')', __FUNCTION__);
- }
- $this->rownum = $rownum - 1;
- return MDB2_OK;
- }
-
- // }}}
- // {{{ valid()
-
- /**
- * Check if the end of the result set has been reached
- *
- * @return mixed true or false on sucess, a MDB2 error on failure
- * @access public
- */
- function valid()
- {
- $numrows = $this->numRows();
- if (MDB2::isError($numrows)) {
- return $numrows;
- }
- return $this->rownum < ($numrows - 1);
- }
-
- // }}}
- // {{{ numRows()
-
- /**
- * Returns the number of rows in a result object
- *
- * @return mixed MDB2 Error Object or the number of rows
- * @access public
- */
- function numRows()
- {
- $rows = @mysql_num_rows($this->result);
- if (false === $rows) {
- if (false === $this->result) {
- return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
- 'resultset has already been freed', __FUNCTION__);
- } elseif (is_null($this->result)) {
- return 0;
- }
- return $this->db->raiseError(null, null, null,
- 'Could not get row count', __FUNCTION__);
- }
- return $rows;
- }
-
- // }}}
-}
-
-/**
- * MDB2 MySQL statement driver
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_Statement_mysql extends MDB2_Statement_Common
-{
- // {{{ _execute()
-
- /**
- * Execute a prepared query statement helper method.
- *
- * @param mixed $result_class string which specifies which result class to use
- * @param mixed $result_wrap_class string which specifies which class to wrap results in
- *
- * @return mixed MDB2_Result or integer (affected rows) on success,
- * a MDB2 error on failure
- * @access private
- */
- function _execute($result_class = true, $result_wrap_class = true)
- {
- if (is_null($this->statement)) {
- $result = parent::_execute($result_class, $result_wrap_class);
- return $result;
- }
- $this->db->last_query = $this->query;
- $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'pre', 'parameters' => $this->values));
- if ($this->db->getOption('disable_query')) {
- $result = $this->is_manip ? 0 : null;
- return $result;
- }
-
- $connection = $this->db->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
-
- $query = 'EXECUTE '.$this->statement;
- if (!empty($this->positions)) {
- $parameters = array();
- foreach ($this->positions as $parameter) {
- if (!array_key_exists($parameter, $this->values)) {
- return $this->db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- 'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__);
- }
- $close = false;
- $value = $this->values[$parameter];
- $type = array_key_exists($parameter, $this->types) ? $this->types[$parameter] : null;
- if (is_resource($value) || $type == 'clob' || $type == 'blob' && $this->db->options['lob_allow_url_include']) {
- if (!is_resource($value) && preg_match('/^(\w+:\/\/)(.*)$/', $value, $match)) {
- if ($match[1] == 'file://') {
- $value = $match[2];
- }
- $value = @fopen($value, 'r');
- $close = true;
- }
- if (is_resource($value)) {
- $data = '';
- while (!@feof($value)) {
- $data.= @fread($value, $this->db->options['lob_buffer_length']);
- }
- if ($close) {
- @fclose($value);
- }
- $value = $data;
- }
- }
- $quoted = $this->db->quote($value, $type);
- if (MDB2::isError($quoted)) {
- return $quoted;
- }
- $param_query = 'SET @'.$parameter.' = '.$quoted;
- $result = $this->db->_doQuery($param_query, true, $connection);
- if (MDB2::isError($result)) {
- return $result;
- }
- }
- $query.= ' USING @'.implode(', @', array_values($this->positions));
- }
-
- $result = $this->db->_doQuery($query, $this->is_manip, $connection);
- if (MDB2::isError($result)) {
- return $result;
- }
-
- if ($this->is_manip) {
- $affected_rows = $this->db->_affectedRows($connection, $result);
- return $affected_rows;
- }
-
- $result = $this->db->_wrapResult($result, $this->result_types,
- $result_class, $result_wrap_class, $this->limit, $this->offset);
- $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'post', 'result' => $result));
- return $result;
- }
-
- // }}}
- // {{{ free()
-
- /**
- * Release resources allocated for the specified prepared query.
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function free()
- {
- if (is_null($this->positions)) {
- return $this->db->raiseError(MDB2_ERROR, null, null,
- 'Prepared statement has already been freed', __FUNCTION__);
- }
- $result = MDB2_OK;
-
- if (!is_null($this->statement)) {
- $connection = $this->db->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
- $query = 'DEALLOCATE PREPARE '.$this->statement;
- $result = $this->db->_doQuery($query, true, $connection);
- }
-
- parent::free();
- return $result;
- }
-}
-?>
diff --git a/data/module/MDB2/Driver/pgsql.php b/data/module/MDB2/Driver/pgsql.php
deleted file mode 100644
index 87b65c369ae..00000000000
--- a/data/module/MDB2/Driver/pgsql.php
+++ /dev/null
@@ -1,1583 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: pgsql.php 327317 2012-08-27 15:17:08Z danielc $
-
-/**
- * MDB2 PostGreSQL driver
- *
- * @package MDB2
- * @category Database
- * @author Paul Cooper
- */
-class MDB2_Driver_pgsql extends MDB2_Driver_Common
-{
- // {{{ properties
- var $string_quoting = array('start' => "'", 'end' => "'", 'escape' => "'", 'escape_pattern' => '\\');
-
- var $identifier_quoting = array('start' => '"', 'end' => '"', 'escape' => '"');
- // }}}
- // {{{ constructor
-
- /**
- * Constructor
- */
- function __construct()
- {
- parent::__construct();
-
- $this->phptype = 'pgsql';
- $this->dbsyntax = 'pgsql';
-
- $this->supported['sequences'] = true;
- $this->supported['indexes'] = true;
- $this->supported['affected_rows'] = true;
- $this->supported['summary_functions'] = true;
- $this->supported['order_by_text'] = true;
- $this->supported['transactions'] = true;
- $this->supported['savepoints'] = true;
- $this->supported['current_id'] = true;
- $this->supported['limit_queries'] = true;
- $this->supported['LOBs'] = true;
- $this->supported['replace'] = 'emulated';
- $this->supported['sub_selects'] = true;
- $this->supported['triggers'] = true;
- $this->supported['auto_increment'] = 'emulated';
- $this->supported['primary_key'] = true;
- $this->supported['result_introspection'] = true;
- $this->supported['prepared_statements'] = true;
- $this->supported['identifier_quoting'] = true;
- $this->supported['pattern_escaping'] = true;
- $this->supported['new_link'] = true;
-
- $this->options['DBA_username'] = false;
- $this->options['DBA_password'] = false;
- $this->options['multi_query'] = false;
- $this->options['disable_smart_seqname'] = true;
- $this->options['max_identifiers_length'] = 63;
- }
-
- // }}}
- // {{{ errorInfo()
-
- /**
- * This method is used to collect information about an error
- *
- * @param integer $error
- * @return array
- * @access public
- */
- function errorInfo($error = null)
- {
- // Fall back to MDB2_ERROR if there was no mapping.
- $error_code = MDB2_ERROR;
-
- $native_msg = '';
- if (is_resource($error)) {
- $native_msg = @pg_result_error($error);
- } elseif ($this->connection) {
- $native_msg = @pg_last_error($this->connection);
- if (!$native_msg && @pg_connection_status($this->connection) === PGSQL_CONNECTION_BAD) {
- $native_msg = 'Database connection has been lost.';
- $error_code = MDB2_ERROR_CONNECT_FAILED;
- }
- } else {
- $native_msg = @pg_last_error();
- }
-
- static $error_regexps;
- if (empty($error_regexps)) {
- $error_regexps = array(
- '/column .* (of relation .*)?does not exist/i'
- => MDB2_ERROR_NOSUCHFIELD,
- '/(relation|sequence|table).*does not exist|class .* not found/i'
- => MDB2_ERROR_NOSUCHTABLE,
- '/database .* does not exist/'
- => MDB2_ERROR_NOT_FOUND,
- '/constraint .* does not exist/'
- => MDB2_ERROR_NOT_FOUND,
- '/index .* does not exist/'
- => MDB2_ERROR_NOT_FOUND,
- '/database .* already exists/i'
- => MDB2_ERROR_ALREADY_EXISTS,
- '/relation .* already exists/i'
- => MDB2_ERROR_ALREADY_EXISTS,
- '/(divide|division) by zero$/i'
- => MDB2_ERROR_DIVZERO,
- '/pg_atoi: error in .*: can\'t parse /i'
- => MDB2_ERROR_INVALID_NUMBER,
- '/invalid input syntax for( type)? (integer|numeric)/i'
- => MDB2_ERROR_INVALID_NUMBER,
- '/value .* is out of range for type \w*int/i'
- => MDB2_ERROR_INVALID_NUMBER,
- '/integer out of range/i'
- => MDB2_ERROR_INVALID_NUMBER,
- '/value too long for type character/i'
- => MDB2_ERROR_INVALID,
- '/attribute .* not found|relation .* does not have attribute/i'
- => MDB2_ERROR_NOSUCHFIELD,
- '/column .* specified in USING clause does not exist in (left|right) table/i'
- => MDB2_ERROR_NOSUCHFIELD,
- '/parser: parse error at or near/i'
- => MDB2_ERROR_SYNTAX,
- '/syntax error at/'
- => MDB2_ERROR_SYNTAX,
- '/column reference .* is ambiguous/i'
- => MDB2_ERROR_SYNTAX,
- '/permission denied/'
- => MDB2_ERROR_ACCESS_VIOLATION,
- '/violates not-null constraint/'
- => MDB2_ERROR_CONSTRAINT_NOT_NULL,
- '/violates [\w ]+ constraint/'
- => MDB2_ERROR_CONSTRAINT,
- '/referential integrity violation/'
- => MDB2_ERROR_CONSTRAINT,
- '/more expressions than target columns/i'
- => MDB2_ERROR_VALUE_COUNT_ON_ROW,
- );
- }
- if (is_numeric($error) && $error < 0) {
- $error_code = $error;
- } else {
- foreach ($error_regexps as $regexp => $code) {
- if (preg_match($regexp, $native_msg)) {
- $error_code = $code;
- break;
- }
- }
- }
- return array($error_code, null, $native_msg);
- }
-
- // }}}
- // {{{ escape()
-
- /**
- * Quotes a string so it can be safely used in a query. It will quote
- * the text so it can safely be used within a query.
- *
- * @param string the input string to quote
- * @param bool escape wildcards
- *
- * @return string quoted string
- *
- * @access public
- */
- function escape($text, $escape_wildcards = false)
- {
- if ($escape_wildcards) {
- $text = $this->escapePattern($text);
- }
- $connection = $this->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
- if (is_resource($connection) && version_compare(PHP_VERSION, '5.2.0RC5', '>=')) {
- $text = @pg_escape_string($connection, $text);
- } else {
- $text = @pg_escape_string($text);
- }
- return $text;
- }
-
- // }}}
- // {{{ beginTransaction()
-
- /**
- * Start a transaction or set a savepoint.
- *
- * @param string name of a savepoint to set
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- */
- function beginTransaction($savepoint = null)
- {
- $this->debug('Starting transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
- if (null !== $savepoint) {
- if (!$this->in_transaction) {
- return $this->raiseError(MDB2_ERROR_INVALID, null, null,
- 'savepoint cannot be released when changes are auto committed', __FUNCTION__);
- }
- $query = 'SAVEPOINT '.$savepoint;
- return $this->_doQuery($query, true);
- }
- if ($this->in_transaction) {
- return MDB2_OK; //nothing to do
- }
- if (!$this->destructor_registered && $this->opened_persistent) {
- $this->destructor_registered = true;
- register_shutdown_function('MDB2_closeOpenTransactions');
- }
- $result = $this->_doQuery('BEGIN', true);
- if (MDB2::isError($result)) {
- return $result;
- }
- $this->in_transaction = true;
- return MDB2_OK;
- }
-
- // }}}
- // {{{ commit()
-
- /**
- * Commit the database changes done during a transaction that is in
- * progress or release a savepoint. This function may only be called when
- * auto-committing is disabled, otherwise it will fail. Therefore, a new
- * transaction is implicitly started after committing the pending changes.
- *
- * @param string name of a savepoint to release
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- */
- function commit($savepoint = null)
- {
- $this->debug('Committing transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
- if (!$this->in_transaction) {
- return $this->raiseError(MDB2_ERROR_INVALID, null, null,
- 'commit/release savepoint cannot be done changes are auto committed', __FUNCTION__);
- }
- if (null !== $savepoint) {
- $query = 'RELEASE SAVEPOINT '.$savepoint;
- return $this->_doQuery($query, true);
- }
-
- $result = $this->_doQuery('COMMIT', true);
- if (MDB2::isError($result)) {
- return $result;
- }
- $this->in_transaction = false;
- return MDB2_OK;
- }
-
- // }}}
- // {{{ rollback()
-
- /**
- * Cancel any database changes done during a transaction or since a specific
- * savepoint that is in progress. This function may only be called when
- * auto-committing is disabled, otherwise it will fail. Therefore, a new
- * transaction is implicitly started after canceling the pending changes.
- *
- * @param string name of a savepoint to rollback to
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- */
- function rollback($savepoint = null)
- {
- $this->debug('Rolling back transaction/savepoint', __FUNCTION__, array('is_manip' => true, 'savepoint' => $savepoint));
- if (!$this->in_transaction) {
- return $this->raiseError(MDB2_ERROR_INVALID, null, null,
- 'rollback cannot be done changes are auto committed', __FUNCTION__);
- }
- if (null !== $savepoint) {
- $query = 'ROLLBACK TO SAVEPOINT '.$savepoint;
- return $this->_doQuery($query, true);
- }
-
- $query = 'ROLLBACK';
- $result = $this->_doQuery($query, true);
- if (MDB2::isError($result)) {
- return $result;
- }
- $this->in_transaction = false;
- return MDB2_OK;
- }
-
- // }}}
- // {{{ function setTransactionIsolation()
-
- /**
- * Set the transacton isolation level.
- *
- * @param string standard isolation level
- * READ UNCOMMITTED (allows dirty reads)
- * READ COMMITTED (prevents dirty reads)
- * REPEATABLE READ (prevents nonrepeatable reads)
- * SERIALIZABLE (prevents phantom reads)
- * @param array some transaction options:
- * 'wait' => 'WAIT' | 'NO WAIT'
- * 'rw' => 'READ WRITE' | 'READ ONLY'
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- *
- * @access public
- * @since 2.1.1
- */
- function setTransactionIsolation($isolation, $options = array())
- {
- $this->debug('Setting transaction isolation level', __FUNCTION__, array('is_manip' => true));
- switch ($isolation) {
- case 'READ UNCOMMITTED':
- case 'READ COMMITTED':
- case 'REPEATABLE READ':
- case 'SERIALIZABLE':
- break;
- default:
- return $this->raiseError(MDB2_ERROR_UNSUPPORTED, null, null,
- 'isolation level is not supported: '.$isolation, __FUNCTION__);
- }
-
- $query = "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL $isolation";
- return $this->_doQuery($query, true);
- }
-
- // }}}
- // {{{ _doConnect()
-
- /**
- * Do the grunt work of connecting to the database
- *
- * @return mixed connection resource on success, MDB2 Error Object on failure
- * @access protected
- */
- function _doConnect($username, $password, $database_name, $persistent = false)
- {
- if (!extension_loaded($this->phptype)) {
- return $this->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- 'extension '.$this->phptype.' is not compiled into PHP', __FUNCTION__);
- }
-
- if ($database_name == '') {
- $database_name = 'template1';
- }
-
- $protocol = $this->dsn['protocol'] ? $this->dsn['protocol'] : 'tcp';
-
- $params = array('');
- if ($protocol == 'tcp') {
- if ($this->dsn['hostspec']) {
- $params[0].= 'host=' . $this->dsn['hostspec'];
- }
- if ($this->dsn['port']) {
- $params[0].= ' port=' . $this->dsn['port'];
- }
- } elseif ($protocol == 'unix') {
- // Allow for pg socket in non-standard locations.
- if ($this->dsn['socket']) {
- $params[0].= 'host=' . $this->dsn['socket'];
- }
- if ($this->dsn['port']) {
- $params[0].= ' port=' . $this->dsn['port'];
- }
- }
- if ($database_name) {
- $params[0].= ' dbname=\'' . addslashes($database_name) . '\'';
- }
- if ($username) {
- $params[0].= ' user=\'' . addslashes($username) . '\'';
- }
- if ($password) {
- $params[0].= ' password=\'' . addslashes($password) . '\'';
- }
- if (!empty($this->dsn['options'])) {
- $params[0].= ' options=' . $this->dsn['options'];
- }
- if (!empty($this->dsn['tty'])) {
- $params[0].= ' tty=' . $this->dsn['tty'];
- }
- if (!empty($this->dsn['connect_timeout'])) {
- $params[0].= ' connect_timeout=' . $this->dsn['connect_timeout'];
- }
- if (!empty($this->dsn['sslmode'])) {
- $params[0].= ' sslmode=' . $this->dsn['sslmode'];
- }
- if (!empty($this->dsn['service'])) {
- $params[0].= ' service=' . $this->dsn['service'];
- }
-
- if ($this->_isNewLinkSet()) {
- if (version_compare(phpversion(), '4.3.0', '>=')) {
- $params[] = PGSQL_CONNECT_FORCE_NEW;
- }
- }
-
- $connect_function = $persistent ? 'pg_pconnect' : 'pg_connect';
- $connection = @call_user_func_array($connect_function, $params);
- if (!$connection) {
- return $this->raiseError(MDB2_ERROR_CONNECT_FAILED, null, null,
- 'unable to establish a connection', __FUNCTION__);
- }
-
- if (empty($this->dsn['disable_iso_date'])) {
- if (!@pg_query($connection, "SET SESSION DATESTYLE = 'ISO'")) {
- return $this->raiseError(null, null, null,
- 'Unable to set date style to iso', __FUNCTION__);
- }
- }
-
- if (!empty($this->dsn['charset'])) {
- $result = $this->setCharset($this->dsn['charset'], $connection);
- if (MDB2::isError($result)) {
- return $result;
- }
- }
-
- // Enable extra compatibility settings on 8.2 and later
- if (function_exists('pg_parameter_status')) {
- $version = pg_parameter_status($connection, 'server_version');
- if ($version == false) {
- return $this->raiseError(null, null, null,
- 'Unable to retrieve server version', __FUNCTION__);
- }
- $version = explode ('.', $version);
- if ( $version['0'] > 8
- || ($version['0'] == 8 && $version['1'] >= 2)
- ) {
- if (!@pg_query($connection, "SET SESSION STANDARD_CONFORMING_STRINGS = OFF")) {
- return $this->raiseError(null, null, null,
- 'Unable to set standard_conforming_strings to off', __FUNCTION__);
- }
-
- if (!@pg_query($connection, "SET SESSION ESCAPE_STRING_WARNING = OFF")) {
- return $this->raiseError(null, null, null,
- 'Unable to set escape_string_warning to off', __FUNCTION__);
- }
- }
- }
-
- return $connection;
- }
-
- // }}}
- // {{{ connect()
-
- /**
- * Connect to the database
- *
- * @return true on success, MDB2 Error Object on failure
- * @access public
- */
- function connect()
- {
- if (is_resource($this->connection)) {
- //if (count(array_diff($this->connected_dsn, $this->dsn)) == 0
- if (MDB2::areEquals($this->connected_dsn, $this->dsn)
- && $this->connected_database_name == $this->database_name
- && ($this->opened_persistent == $this->options['persistent'])
- ) {
- return MDB2_OK;
- }
- $this->disconnect(false);
- }
-
- if ($this->database_name) {
- $connection = $this->_doConnect($this->dsn['username'],
- $this->dsn['password'],
- $this->database_name,
- $this->options['persistent']);
- if (MDB2::isError($connection)) {
- return $connection;
- }
-
- $this->connection = $connection;
- $this->connected_dsn = $this->dsn;
- $this->connected_database_name = $this->database_name;
- $this->opened_persistent = $this->options['persistent'];
- $this->dbsyntax = $this->dsn['dbsyntax'] ? $this->dsn['dbsyntax'] : $this->phptype;
- }
-
- return MDB2_OK;
- }
-
- // }}}
- // {{{ setCharset()
-
- /**
- * Set the charset on the current connection
- *
- * @param string charset
- * @param resource connection handle
- *
- * @return true on success, MDB2 Error Object on failure
- */
- function setCharset($charset, $connection = null)
- {
- if (null === $connection) {
- $connection = $this->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
- }
- if (is_array($charset)) {
- $charset = array_shift($charset);
- $this->warnings[] = 'postgresql does not support setting client collation';
- }
- $result = @pg_set_client_encoding($connection, $charset);
- if ($result == -1) {
- return $this->raiseError(null, null, null,
- 'Unable to set client charset: '.$charset, __FUNCTION__);
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ databaseExists()
-
- /**
- * check if given database name is exists?
- *
- * @param string $name name of the database that should be checked
- *
- * @return mixed true/false on success, a MDB2 error on failure
- * @access public
- */
- function databaseExists($name)
- {
- $res = $this->_doConnect($this->dsn['username'],
- $this->dsn['password'],
- $this->escape($name),
- $this->options['persistent']);
- if (!MDB2::isError($res)) {
- return true;
- }
-
- return false;
- }
-
- // }}}
- // {{{ disconnect()
-
- /**
- * Log out and disconnect from the database.
- *
- * @param boolean $force if the disconnect should be forced even if the
- * connection is opened persistently
- * @return mixed true on success, false if not connected and error
- * object on error
- * @access public
- */
- function disconnect($force = true)
- {
- if (is_resource($this->connection)) {
- if ($this->in_transaction) {
- $dsn = $this->dsn;
- $database_name = $this->database_name;
- $persistent = $this->options['persistent'];
- $this->dsn = $this->connected_dsn;
- $this->database_name = $this->connected_database_name;
- $this->options['persistent'] = $this->opened_persistent;
- $this->rollback();
- $this->dsn = $dsn;
- $this->database_name = $database_name;
- $this->options['persistent'] = $persistent;
- }
-
- if (!$this->opened_persistent || $force) {
- $ok = @pg_close($this->connection);
- if (!$ok) {
- return $this->raiseError(MDB2_ERROR_DISCONNECT_FAILED,
- null, null, null, __FUNCTION__);
- }
- }
- } else {
- return false;
- }
- return parent::disconnect($force);
- }
-
- // }}}
- // {{{ standaloneQuery()
-
- /**
- * execute a query as DBA
- *
- * @param string $query the SQL query
- * @param mixed $types array that contains the types of the columns in
- * the result set
- * @param boolean $is_manip if the query is a manipulation query
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function standaloneQuery($query, $types = null, $is_manip = false)
- {
- $user = $this->options['DBA_username']? $this->options['DBA_username'] : $this->dsn['username'];
- $pass = $this->options['DBA_password']? $this->options['DBA_password'] : $this->dsn['password'];
- $connection = $this->_doConnect($user, $pass, $this->database_name, $this->options['persistent']);
- if (MDB2::isError($connection)) {
- return $connection;
- }
-
- $offset = $this->offset;
- $limit = $this->limit;
- $this->offset = $this->limit = 0;
- $query = $this->_modifyQuery($query, $is_manip, $limit, $offset);
-
- $result = $this->_doQuery($query, $is_manip, $connection, $this->database_name);
- if (!MDB2::isError($result)) {
- if ($is_manip) {
- $result = $this->_affectedRows($connection, $result);
- } else {
- $result = $this->_wrapResult($result, $types, true, true, $limit, $offset);
- }
- }
-
- @pg_close($connection);
- return $result;
- }
-
- // }}}
- // {{{ _doQuery()
-
- /**
- * Execute a query
- * @param string $query query
- * @param boolean $is_manip if the query is a manipulation query
- * @param resource $connection
- * @param string $database_name
- * @return result or error object
- * @access protected
- */
- function _doQuery($query, $is_manip = false, $connection = null, $database_name = null)
- {
- $this->last_query = $query;
- $result = $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'pre'));
- if ($result) {
- if (MDB2::isError($result)) {
- return $result;
- }
- $query = $result;
- }
- if ($this->options['disable_query']) {
- $result = $is_manip ? 0 : null;
- return $result;
- }
-
- if (null === $connection) {
- $connection = $this->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
- }
-
- $function = $this->options['multi_query'] ? 'pg_send_query' : 'pg_query';
- $result = @$function($connection, $query);
- if (!$result) {
- $err = $this->raiseError(null, null, null,
- 'Could not execute statement', __FUNCTION__);
- return $err;
- } elseif ($this->options['multi_query']) {
- if (!($result = @pg_get_result($connection))) {
- $err = $this->raiseError(null, null, null,
- 'Could not get the first result from a multi query', __FUNCTION__);
- return $err;
- }
- }
-
- $this->debug($query, 'query', array('is_manip' => $is_manip, 'when' => 'post', 'result' => $result));
- return $result;
- }
-
- // }}}
- // {{{ _affectedRows()
-
- /**
- * Returns the number of rows affected
- *
- * @param resource $result
- * @param resource $connection
- * @return mixed MDB2 Error Object or the number of rows affected
- * @access private
- */
- function _affectedRows($connection, $result = null)
- {
- if (null === $connection) {
- $connection = $this->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
- }
- return @pg_affected_rows($result);
- }
-
- // }}}
- // {{{ _modifyQuery()
-
- /**
- * Changes a query string for various DBMS specific reasons
- *
- * @param string $query query to modify
- * @param boolean $is_manip if it is a DML query
- * @param integer $limit limit the number of rows
- * @param integer $offset start reading from given offset
- * @return string modified query
- * @access protected
- */
- function _modifyQuery($query, $is_manip, $limit, $offset)
- {
- if ($limit > 0
- && !preg_match('/LIMIT\s*\d(?:\s*(?:,|OFFSET)\s*\d+)?(?:[^\)]*)?$/i', $query)
- ) {
- $query = rtrim($query);
- if (substr($query, -1) == ';') {
- $query = substr($query, 0, -1);
- }
- if ($is_manip) {
- $query = $this->_modifyManipQuery($query, $limit);
- } else {
- $query.= " LIMIT $limit OFFSET $offset";
- }
- }
- return $query;
- }
-
- // }}}
- // {{{ _modifyManipQuery()
-
- /**
- * Changes a manip query string for various DBMS specific reasons
- *
- * @param string $query query to modify
- * @param integer $limit limit the number of rows
- * @return string modified query
- * @access protected
- */
- function _modifyManipQuery($query, $limit)
- {
- $pos = strpos(strtolower($query), 'where');
- $where = $pos ? substr($query, $pos) : '';
-
- $manip_clause = '(\bDELETE\b\s+(?:\*\s+)?\bFROM\b|\bUPDATE\b)';
- $from_clause = '([\w\.]+)';
- $where_clause = '(?:(.*)\bWHERE\b\s+(.*))|(.*)';
- $pattern = '/^'. $manip_clause . '\s+' . $from_clause .'(?:\s)*(?:'. $where_clause .')?$/i';
- $matches = preg_match($pattern, $query, $match);
- if ($matches) {
- $manip = $match[1];
- $from = $match[2];
- $what = (count($matches) == 6) ? $match[5] : $match[3];
- return $manip.' '.$from.' '.$what.' WHERE ctid=(SELECT ctid FROM '.$from.' '.$where.' LIMIT '.$limit.')';
- }
- //return error?
- return $query;
- }
-
- // }}}
- // {{{ getServerVersion()
-
- /**
- * return version information about the server
- *
- * @param bool $native determines if the raw version string should be returned
- * @return mixed array/string with version information or MDB2 error object
- * @access public
- */
- function getServerVersion($native = false)
- {
- $query = 'SHOW SERVER_VERSION';
- if ($this->connected_server_info) {
- $server_info = $this->connected_server_info;
- } else {
- $server_info = $this->queryOne($query, 'text');
- if (MDB2::isError($server_info)) {
- return $server_info;
- }
- }
- // cache server_info
- $this->connected_server_info = $server_info;
- if (!$native && !MDB2::isError($server_info)) {
- $tmp = explode('.', $server_info, 3);
- if (empty($tmp[2])
- && isset($tmp[1])
- && preg_match('/(\d+)(.*)/', $tmp[1], $tmp2)
- ) {
- $server_info = array(
- 'major' => $tmp[0],
- 'minor' => $tmp2[1],
- 'patch' => null,
- 'extra' => $tmp2[2],
- 'native' => $server_info,
- );
- } else {
- $server_info = array(
- 'major' => isset($tmp[0]) ? $tmp[0] : null,
- 'minor' => isset($tmp[1]) ? $tmp[1] : null,
- 'patch' => isset($tmp[2]) ? $tmp[2] : null,
- 'extra' => null,
- 'native' => $server_info,
- );
- }
- }
- return $server_info;
- }
-
- // }}}
- // {{{ prepare()
-
- /**
- * Prepares a query for multiple execution with execute().
- * With some database backends, this is emulated.
- * prepare() requires a generic query as string like
- * 'INSERT INTO numbers VALUES(?,?)' or
- * 'INSERT INTO numbers VALUES(:foo,:bar)'.
- * The ? and :name and are placeholders which can be set using
- * bindParam() and the query can be sent off using the execute() method.
- * The allowed format for :name can be set with the 'bindname_format' option.
- *
- * @param string $query the query to prepare
- * @param mixed $types array that contains the types of the placeholders
- * @param mixed $result_types array that contains the types of the columns in
- * the result set or MDB2_PREPARE_RESULT, if set to
- * MDB2_PREPARE_MANIP the query is handled as a manipulation query
- * @param mixed $lobs key (field) value (parameter) pair for all lob placeholders
- * @return mixed resource handle for the prepared query on success, a MDB2
- * error on failure
- * @access public
- * @see bindParam, execute
- */
- function prepare($query, $types = null, $result_types = null, $lobs = array())
- {
- if ($this->options['emulate_prepared']) {
- return parent::prepare($query, $types, $result_types, $lobs);
- }
- $is_manip = ($result_types === MDB2_PREPARE_MANIP);
- $offset = $this->offset;
- $limit = $this->limit;
- $this->offset = $this->limit = 0;
- $result = $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'pre'));
- if ($result) {
- if (MDB2::isError($result)) {
- return $result;
- }
- $query = $result;
- }
- $pgtypes = function_exists('pg_prepare') ? false : array();
- if ($pgtypes !== false && !empty($types)) {
- $this->loadModule('Datatype', null, true);
- }
- $query = $this->_modifyQuery($query, $is_manip, $limit, $offset);
- $placeholder_type_guess = $placeholder_type = null;
- $question = '?';
- $colon = ':';
- $positions = array();
- $position = $parameter = 0;
- while ($position < strlen($query)) {
- $q_position = strpos($query, $question, $position);
- $c_position = strpos($query, $colon, $position);
- //skip "::type" cast ("select id::varchar(20) from sometable where name=?")
- $doublecolon_position = strpos($query, '::', $position);
- if ($doublecolon_position !== false && $doublecolon_position == $c_position) {
- $c_position = strpos($query, $colon, $position+2);
- }
- if ($q_position && $c_position) {
- $p_position = min($q_position, $c_position);
- } elseif ($q_position) {
- $p_position = $q_position;
- } elseif ($c_position) {
- $p_position = $c_position;
- } else {
- break;
- }
- if (null === $placeholder_type) {
- $placeholder_type_guess = $query[$p_position];
- }
-
- $new_pos = $this->_skipDelimitedStrings($query, $position, $p_position);
- if (MDB2::isError($new_pos)) {
- return $new_pos;
- }
- if ($new_pos != $position) {
- $position = $new_pos;
- continue; //evaluate again starting from the new position
- }
-
- if ($query[$position] == $placeholder_type_guess) {
- if (null === $placeholder_type) {
- $placeholder_type = $query[$p_position];
- $question = $colon = $placeholder_type;
- if (!empty($types) && is_array($types)) {
- if ($placeholder_type == ':') {
- } else {
- $types = array_values($types);
- }
- }
- }
- if ($placeholder_type_guess == '?') {
- $length = 1;
- $name = $parameter;
- } else {
- $regexp = '/^.{'.($position+1).'}('.$this->options['bindname_format'].').*$/s';
- $param = preg_replace($regexp, '\\1', $query);
- if ($param === '') {
- $err = $this->raiseError(MDB2_ERROR_SYNTAX, null, null,
- 'named parameter name must match "bindname_format" option', __FUNCTION__);
- return $err;
- }
- $length = strlen($param) + 1;
- $name = $param;
- }
- if ($pgtypes !== false) {
- if (is_array($types) && array_key_exists($name, $types)) {
- $pgtypes[] = $this->datatype->mapPrepareDatatype($types[$name]);
- } elseif (is_array($types) && array_key_exists($parameter, $types)) {
- $pgtypes[] = $this->datatype->mapPrepareDatatype($types[$parameter]);
- } else {
- $pgtypes[] = 'text';
- }
- }
- if (($key_parameter = array_search($name, $positions)) !== false) {
- //$next_parameter = 1;
- $parameter = $key_parameter + 1;
- //foreach ($positions as $key => $value) {
- // if ($key_parameter == $key) {
- // break;
- // }
- // ++$next_parameter;
- //}
- } else {
- ++$parameter;
- //$next_parameter = $parameter;
- $positions[] = $name;
- }
- $query = substr_replace($query, '$'.$parameter, $position, $length);
- $position = $p_position + strlen($parameter);
- } else {
- $position = $p_position;
- }
- }
- $connection = $this->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
- static $prep_statement_counter = 1;
- $statement_name = sprintf($this->options['statement_format'], $this->phptype, $prep_statement_counter++ . sha1(microtime() + mt_rand()));
- $statement_name = substr(strtolower($statement_name), 0, $this->options['max_identifiers_length']);
- if (false === $pgtypes) {
- $result = @pg_prepare($connection, $statement_name, $query);
- if (!$result) {
- $err = $this->raiseError(null, null, null,
- 'Unable to create prepared statement handle', __FUNCTION__);
- return $err;
- }
- } else {
- $types_string = '';
- if ($pgtypes) {
- $types_string = ' ('.implode(', ', $pgtypes).') ';
- }
- $query = 'PREPARE '.$statement_name.$types_string.' AS '.$query;
- $statement = $this->_doQuery($query, true, $connection);
- if (MDB2::isError($statement)) {
- return $statement;
- }
- }
-
- $class_name = 'MDB2_Statement_'.$this->phptype;
- $obj = new $class_name($this, $statement_name, $positions, $query, $types, $result_types, $is_manip, $limit, $offset);
- $this->debug($query, __FUNCTION__, array('is_manip' => $is_manip, 'when' => 'post', 'result' => $obj));
- return $obj;
- }
-
- // }}}
- // {{{ function getSequenceName($sqn)
-
- /**
- * adds sequence name formatting to a sequence name
- *
- * @param string name of the sequence
- *
- * @return string formatted sequence name
- *
- * @access public
- */
- function getSequenceName($sqn)
- {
- if (false === $this->options['disable_smart_seqname']) {
- if (strpos($sqn, '_') !== false) {
- list($table, $field) = explode('_', $sqn, 2);
- }
- $schema_list = $this->queryOne("SELECT array_to_string(current_schemas(false), ',')");
- if (MDB2::isError($schema_list) || empty($schema_list) || count($schema_list) < 2) {
- $order_by = ' a.attnum';
- $schema_clause = ' AND n.nspname=current_schema()';
- } else {
- $schemas = explode(',', $schema_list);
- $schema_clause = ' AND n.nspname IN ('.$schema_list.')';
- $counter = 1;
- $order_by = ' CASE ';
- foreach ($schemas as $schema) {
- $order_by .= ' WHEN n.nspname='.$schema.' THEN '.$counter++;
- }
- $order_by .= ' ELSE '.$counter.' END, a.attnum';
- }
-
- $query = "SELECT substring((SELECT substring(pg_get_expr(d.adbin, d.adrelid) for 128)
- FROM pg_attrdef d
- WHERE d.adrelid = a.attrelid
- AND d.adnum = a.attnum
- AND a.atthasdef
- ) FROM 'nextval[^'']*''([^'']*)')
- FROM pg_attribute a
- LEFT JOIN pg_class c ON c.oid = a.attrelid
- LEFT JOIN pg_attrdef d ON d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef
- LEFT JOIN pg_namespace n ON c.relnamespace = n.oid
- WHERE (c.relname = ".$this->quote($sqn, 'text');
- if (!empty($field)) {
- $query .= " OR (c.relname = ".$this->quote($table, 'text')." AND a.attname = ".$this->quote($field, 'text').")";
- }
- $query .= " )"
- .$schema_clause."
- AND NOT a.attisdropped
- AND a.attnum > 0
- AND pg_get_expr(d.adbin, d.adrelid) LIKE 'nextval%'
- ORDER BY ".$order_by;
- $seqname = $this->queryOne($query);
- if (!MDB2::isError($seqname) && !empty($seqname) && is_string($seqname)) {
- return $seqname;
- }
- }
-
- return parent::getSequenceName($sqn);
- }
-
- // }}}
- // {{{ nextID()
-
- /**
- * Returns the next free id of a sequence
- *
- * @param string $seq_name name of the sequence
- * @param boolean $ondemand when true the sequence is
- * automatic created, if it
- * not exists
- * @return mixed MDB2 Error Object or id
- * @access public
- */
- function nextID($seq_name, $ondemand = true)
- {
- $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true);
- $query = "SELECT NEXTVAL('$sequence_name')";
- $this->pushErrorHandling(PEAR_ERROR_RETURN);
- $this->expectError(MDB2_ERROR_NOSUCHTABLE);
- $result = $this->queryOne($query, 'integer');
- $this->popExpect();
- $this->popErrorHandling();
- if (MDB2::isError($result)) {
- if ($ondemand && $result->getCode() == MDB2_ERROR_NOSUCHTABLE) {
- $this->loadModule('Manager', null, true);
- $result = $this->manager->createSequence($seq_name);
- if (MDB2::isError($result)) {
- return $this->raiseError($result, null, null,
- 'on demand sequence could not be created', __FUNCTION__);
- }
- return $this->nextId($seq_name, false);
- }
- }
- return $result;
- }
-
- // }}}
- // {{{ lastInsertID()
-
- /**
- * Returns the autoincrement ID if supported or $id or fetches the current
- * ID in a sequence called: $table.(empty($field) ? '' : '_'.$field)
- *
- * @param string $table name of the table into which a new row was inserted
- * @param string $field name of the field into which a new row was inserted
- * @return mixed MDB2 Error Object or id
- * @access public
- */
- function lastInsertID($table = null, $field = null)
- {
- if (empty($table) && empty($field)) {
- return $this->queryOne('SELECT lastval()', 'integer');
- }
- $seq = $table.(empty($field) ? '' : '_'.$field);
- $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq), true);
- return $this->queryOne("SELECT currval('$sequence_name')", 'integer');
- }
-
- // }}}
- // {{{ currID()
-
- /**
- * Returns the current id of a sequence
- *
- * @param string $seq_name name of the sequence
- * @return mixed MDB2 Error Object or id
- * @access public
- */
- function currID($seq_name)
- {
- $sequence_name = $this->quoteIdentifier($this->getSequenceName($seq_name), true);
- return $this->queryOne("SELECT last_value FROM $sequence_name", 'integer');
- }
-}
-
-/**
- * MDB2 PostGreSQL result driver
- *
- * @package MDB2
- * @category Database
- * @author Paul Cooper
- */
-class MDB2_Result_pgsql extends MDB2_Result_Common
-{
- // }}}
- // {{{ fetchRow()
-
- /**
- * Fetch a row and insert the data into an existing array.
- *
- * @param int $fetchmode how the array data should be indexed
- * @param int $rownum number of the row where the data can be found
- * @return int data array on success, a MDB2 error on failure
- * @access public
- */
- function fetchRow($fetchmode = MDB2_FETCHMODE_DEFAULT, $rownum = null)
- {
- if (null !== $rownum) {
- $seek = $this->seek($rownum);
- if (MDB2::isError($seek)) {
- return $seek;
- }
- }
- if ($fetchmode == MDB2_FETCHMODE_DEFAULT) {
- $fetchmode = $this->db->fetchmode;
- }
- if ( $fetchmode == MDB2_FETCHMODE_ASSOC
- || $fetchmode == MDB2_FETCHMODE_OBJECT
- ) {
- $row = @pg_fetch_array($this->result, null, PGSQL_ASSOC);
- if (is_array($row)
- && $this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE
- ) {
- $row = array_change_key_case($row, $this->db->options['field_case']);
- }
- } else {
- $row = @pg_fetch_row($this->result);
- }
- if (!$row) {
- if (false === $this->result) {
- $err = $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
- 'resultset has already been freed', __FUNCTION__);
- return $err;
- }
- return null;
- }
- $mode = $this->db->options['portability'] & MDB2_PORTABILITY_EMPTY_TO_NULL;
- $rtrim = false;
- if ($this->db->options['portability'] & MDB2_PORTABILITY_RTRIM) {
- if (empty($this->types)) {
- $mode += MDB2_PORTABILITY_RTRIM;
- } else {
- $rtrim = true;
- }
- }
- if ($mode) {
- $this->db->_fixResultArrayValues($row, $mode);
- }
- if ( ( $fetchmode != MDB2_FETCHMODE_ASSOC
- && $fetchmode != MDB2_FETCHMODE_OBJECT)
- && !empty($this->types)
- ) {
- $row = $this->db->datatype->convertResultRow($this->types, $row, $rtrim);
- } elseif (($fetchmode == MDB2_FETCHMODE_ASSOC
- || $fetchmode == MDB2_FETCHMODE_OBJECT)
- && !empty($this->types_assoc)
- ) {
- $row = $this->db->datatype->convertResultRow($this->types_assoc, $row, $rtrim);
- }
- if (!empty($this->values)) {
- $this->_assignBindColumns($row);
- }
- if ($fetchmode === MDB2_FETCHMODE_OBJECT) {
- $object_class = $this->db->options['fetch_class'];
- if ($object_class == 'stdClass') {
- $row = (object) $row;
- } else {
- $rowObj = new $object_class($row);
- $row = $rowObj;
- }
- }
- ++$this->rownum;
- return $row;
- }
-
- // }}}
- // {{{ _getColumnNames()
-
- /**
- * Retrieve the names of columns returned by the DBMS in a query result.
- *
- * @return mixed Array variable that holds the names of columns as keys
- * or an MDB2 error on failure.
- * Some DBMS may not return any columns when the result set
- * does not contain any rows.
- * @access private
- */
- function _getColumnNames()
- {
- $columns = array();
- $numcols = $this->numCols();
- if (MDB2::isError($numcols)) {
- return $numcols;
- }
- for ($column = 0; $column < $numcols; $column++) {
- $column_name = @pg_field_name($this->result, $column);
- $columns[$column_name] = $column;
- }
- if ($this->db->options['portability'] & MDB2_PORTABILITY_FIX_CASE) {
- $columns = array_change_key_case($columns, $this->db->options['field_case']);
- }
- return $columns;
- }
-
- // }}}
- // {{{ numCols()
-
- /**
- * Count the number of columns returned by the DBMS in a query result.
- *
- * @access public
- * @return mixed integer value with the number of columns, a MDB2 error
- * on failure
- */
- function numCols()
- {
- $cols = @pg_num_fields($this->result);
- if (null === $cols) {
- if (false === $this->result) {
- return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
- 'resultset has already been freed', __FUNCTION__);
- }
- if (null === $this->result) {
- return count($this->types);
- }
- return $this->db->raiseError(null, null, null,
- 'Could not get column count', __FUNCTION__);
- }
- return $cols;
- }
-
- // }}}
- // {{{ nextResult()
-
- /**
- * Move the internal result pointer to the next available result
- *
- * @return true on success, false if there is no more result set or an error object on failure
- * @access public
- */
- function nextResult()
- {
- $connection = $this->db->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
-
- if (!($this->result = @pg_get_result($connection))) {
- return false;
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ free()
-
- /**
- * Free the internal resources associated with result.
- *
- * @return boolean true on success, false if result is invalid
- * @access public
- */
- function free()
- {
- if (is_resource($this->result) && $this->db->connection) {
- $free = @pg_free_result($this->result);
- if (false === $free) {
- return $this->db->raiseError(null, null, null,
- 'Could not free result', __FUNCTION__);
- }
- }
- $this->result = false;
- return MDB2_OK;
- }
-}
-
-/**
- * MDB2 PostGreSQL buffered result driver
- *
- * @package MDB2
- * @category Database
- * @author Paul Cooper
- */
-class MDB2_BufferedResult_pgsql extends MDB2_Result_pgsql
-{
- // {{{ seek()
-
- /**
- * Seek to a specific row in a result set
- *
- * @param int $rownum number of the row where the data can be found
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function seek($rownum = 0)
- {
- if ($this->rownum != ($rownum - 1) && !@pg_result_seek($this->result, $rownum)) {
- if (false === $this->result) {
- return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
- 'resultset has already been freed', __FUNCTION__);
- }
- if (null === $this->result) {
- return MDB2_OK;
- }
- return $this->db->raiseError(MDB2_ERROR_INVALID, null, null,
- 'tried to seek to an invalid row number ('.$rownum.')', __FUNCTION__);
- }
- $this->rownum = $rownum - 1;
- return MDB2_OK;
- }
-
- // }}}
- // {{{ valid()
-
- /**
- * Check if the end of the result set has been reached
- *
- * @return mixed true or false on sucess, a MDB2 error on failure
- * @access public
- */
- function valid()
- {
- $numrows = $this->numRows();
- if (MDB2::isError($numrows)) {
- return $numrows;
- }
- return $this->rownum < ($numrows - 1);
- }
-
- // }}}
- // {{{ numRows()
-
- /**
- * Returns the number of rows in a result object
- *
- * @return mixed MDB2 Error Object or the number of rows
- * @access public
- */
- function numRows()
- {
- $rows = @pg_num_rows($this->result);
- if (null === $rows) {
- if (false === $this->result) {
- return $this->db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
- 'resultset has already been freed', __FUNCTION__);
- }
- if (null === $this->result) {
- return 0;
- }
- return $this->db->raiseError(null, null, null,
- 'Could not get row count', __FUNCTION__);
- }
- return $rows;
- }
-}
-
-/**
- * MDB2 PostGreSQL statement driver
- *
- * @package MDB2
- * @category Database
- * @author Paul Cooper
- */
-class MDB2_Statement_pgsql extends MDB2_Statement_Common
-{
- // {{{ _execute()
-
- /**
- * Execute a prepared query statement helper method.
- *
- * @param mixed $result_class string which specifies which result class to use
- * @param mixed $result_wrap_class string which specifies which class to wrap results in
- *
- * @return mixed MDB2_Result or integer (affected rows) on success,
- * a MDB2 error on failure
- * @access private
- */
- function _execute($result_class = true, $result_wrap_class = true)
- {
- if (null === $this->statement) {
- return parent::_execute($result_class, $result_wrap_class);
- }
- $this->db->last_query = $this->query;
- $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'pre', 'parameters' => $this->values));
- if ($this->db->getOption('disable_query')) {
- $result = $this->is_manip ? 0 : null;
- return $result;
- }
-
- $connection = $this->db->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
-
- $query = false;
- $parameters = array();
- // todo: disabled until pg_execute() bytea issues are cleared up
- if (true || !function_exists('pg_execute')) {
- $query = 'EXECUTE '.$this->statement;
- }
- if (!empty($this->positions)) {
- foreach ($this->positions as $parameter) {
- if (!array_key_exists($parameter, $this->values)) {
- return $this->db->raiseError(MDB2_ERROR_NOT_FOUND, null, null,
- 'Unable to bind to missing placeholder: '.$parameter, __FUNCTION__);
- }
- $value = $this->values[$parameter];
- $type = array_key_exists($parameter, $this->types) ? $this->types[$parameter] : null;
- if (is_resource($value) || $type == 'clob' || $type == 'blob' || $this->db->options['lob_allow_url_include']) {
- if (!is_resource($value) && preg_match('/^(\w+:\/\/)(.*)$/', $value, $match)) {
- if ($match[1] == 'file://') {
- $value = $match[2];
- }
- $value = @fopen($value, 'r');
- $close = true;
- }
- if (is_resource($value)) {
- $data = '';
- while (!@feof($value)) {
- $data.= @fread($value, $this->db->options['lob_buffer_length']);
- }
- if ($close) {
- @fclose($value);
- }
- $value = $data;
- }
- }
- $quoted = $this->db->quote($value, $type, $query);
- if (MDB2::isError($quoted)) {
- return $quoted;
- }
- $parameters[] = $quoted;
- }
- if ($query) {
- $query.= ' ('.implode(', ', $parameters).')';
- }
- }
-
- if (!$query) {
- $result = @pg_execute($connection, $this->statement, $parameters);
- if (!$result) {
- $err = $this->db->raiseError(null, null, null,
- 'Unable to execute statement', __FUNCTION__);
- return $err;
- }
- } else {
- $result = $this->db->_doQuery($query, $this->is_manip, $connection);
- if (MDB2::isError($result)) {
- return $result;
- }
- }
-
- if ($this->is_manip) {
- $affected_rows = $this->db->_affectedRows($connection, $result);
- return $affected_rows;
- }
-
- $result = $this->db->_wrapResult($result, $this->result_types,
- $result_class, $result_wrap_class, $this->limit, $this->offset);
- $this->db->debug($this->query, 'execute', array('is_manip' => $this->is_manip, 'when' => 'post', 'result' => $result));
- return $result;
- }
-
- // }}}
- // {{{ free()
-
- /**
- * Release resources allocated for the specified prepared query.
- *
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function free()
- {
- if (null === $this->positions) {
- return $this->db->raiseError(MDB2_ERROR, null, null,
- 'Prepared statement has already been freed', __FUNCTION__);
- }
- $result = MDB2_OK;
-
- if (null !== $this->statement) {
- $connection = $this->db->getConnection();
- if (MDB2::isError($connection)) {
- return $connection;
- }
- $query = 'DEALLOCATE PREPARE '.$this->statement;
- $result = $this->db->_doQuery($query, true, $connection);
- }
-
- parent::free();
- return $result;
- }
-
- /**
- * drop an existing table
- *
- * @param string $name name of the table that should be dropped
- * @return mixed MDB2_OK on success, a MDB2 error on failure
- * @access public
- */
- function dropTable($name)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $name = $db->quoteIdentifier($name, true);
- $result = $db->exec("DROP TABLE $name");
-
- if (MDB2::isError($result)) {
- $result = $db->exec("DROP TABLE $name CASCADE");
- }
-
- return $result;
- }
-}
-?>
diff --git a/data/module/MDB2/Extended.php b/data/module/MDB2/Extended.php
deleted file mode 100644
index ed47ab9192e..00000000000
--- a/data/module/MDB2/Extended.php
+++ /dev/null
@@ -1,723 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: Extended.php 327310 2012-08-27 15:16:18Z danielc $
-
-/**
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-
-/**
- * Used by autoPrepare()
- */
-define('MDB2_AUTOQUERY_INSERT', 1);
-define('MDB2_AUTOQUERY_UPDATE', 2);
-define('MDB2_AUTOQUERY_DELETE', 3);
-define('MDB2_AUTOQUERY_SELECT', 4);
-
-/**
- * MDB2_Extended: class which adds several high level methods to MDB2
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_Extended extends MDB2_Module_Common
-{
- // {{{ autoPrepare()
-
- /**
- * Generate an insert, update or delete query and call prepare() on it
- *
- * @param string table
- * @param array the fields names
- * @param int type of query to build
- * MDB2_AUTOQUERY_INSERT
- * MDB2_AUTOQUERY_UPDATE
- * MDB2_AUTOQUERY_DELETE
- * MDB2_AUTOQUERY_SELECT
- * @param string (in case of update and delete queries, this string will be put after the sql WHERE statement)
- * @param array that contains the types of the placeholders
- * @param mixed array that contains the types of the columns in
- * the result set or MDB2_PREPARE_RESULT, if set to
- * MDB2_PREPARE_MANIP the query is handled as a manipulation query
- *
- * @return resource handle for the query
- * @see buildManipSQL
- * @access public
- */
- function autoPrepare($table, $table_fields, $mode = MDB2_AUTOQUERY_INSERT,
- $where = false, $types = null, $result_types = MDB2_PREPARE_MANIP)
- {
- $query = $this->buildManipSQL($table, $table_fields, $mode, $where);
- if (MDB2::isError($query)) {
- return $query;
- }
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
- $lobs = array();
- foreach ((array)$types as $param => $type) {
- if (($type == 'clob') || ($type == 'blob')) {
- $lobs[$param] = $table_fields[$param];
- }
- }
- return $db->prepare($query, $types, $result_types, $lobs);
- }
-
- // }}}
- // {{{ autoExecute()
-
- /**
- * Generate an insert, update or delete query and call prepare() and execute() on it
- *
- * @param string name of the table
- * @param array assoc ($key=>$value) where $key is a field name and $value its value
- * @param int type of query to build
- * MDB2_AUTOQUERY_INSERT
- * MDB2_AUTOQUERY_UPDATE
- * MDB2_AUTOQUERY_DELETE
- * MDB2_AUTOQUERY_SELECT
- * @param string (in case of update and delete queries, this string will be put after the sql WHERE statement)
- * @param array that contains the types of the placeholders
- * @param string which specifies which result class to use
- * @param mixed array that contains the types of the columns in
- * the result set or MDB2_PREPARE_RESULT, if set to
- * MDB2_PREPARE_MANIP the query is handled as a manipulation query
- *
- * @return bool|MDB2_Error true on success, a MDB2 error on failure
- * @see buildManipSQL
- * @see autoPrepare
- * @access public
- */
- function autoExecute($table, $fields_values, $mode = MDB2_AUTOQUERY_INSERT,
- $where = false, $types = null, $result_class = true, $result_types = MDB2_PREPARE_MANIP)
- {
- $fields_values = (array)$fields_values;
- if ($mode == MDB2_AUTOQUERY_SELECT) {
- if (is_array($result_types)) {
- $keys = array_keys($result_types);
- } elseif (!empty($fields_values)) {
- $keys = $fields_values;
- } else {
- $keys = array();
- }
- } else {
- $keys = array_keys($fields_values);
- }
- $params = array_values($fields_values);
- if (empty($params)) {
- $query = $this->buildManipSQL($table, $keys, $mode, $where);
-
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
- if ($mode == MDB2_AUTOQUERY_SELECT) {
- $result = $db->query($query, $result_types, $result_class);
- } else {
- $result = $db->exec($query);
- }
- } else {
- $stmt = $this->autoPrepare($table, $keys, $mode, $where, $types, $result_types);
- if (MDB2::isError($stmt)) {
- return $stmt;
- }
- $result = $stmt->execute($params, $result_class);
- $stmt->free();
- }
- return $result;
- }
-
- // }}}
- // {{{ buildManipSQL()
-
- /**
- * Make automaticaly an sql query for prepare()
- *
- * Example : buildManipSQL('table_sql', array('field1', 'field2', 'field3'), MDB2_AUTOQUERY_INSERT)
- * will return the string : INSERT INTO table_sql (field1,field2,field3) VALUES (?,?,?)
- * NB : - This belongs more to a SQL Builder class, but this is a simple facility
- * - Be carefull ! If you don't give a $where param with an UPDATE/DELETE query, all
- * the records of the table will be updated/deleted !
- *
- * @param string name of the table
- * @param ordered array containing the fields names
- * @param int type of query to build
- * MDB2_AUTOQUERY_INSERT
- * MDB2_AUTOQUERY_UPDATE
- * MDB2_AUTOQUERY_DELETE
- * MDB2_AUTOQUERY_SELECT
- * @param string (in case of update and delete queries, this string will be put after the sql WHERE statement)
- *
- * @return string sql query for prepare()
- * @access public
- */
- function buildManipSQL($table, $table_fields, $mode, $where = false)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- if ($db->options['quote_identifier']) {
- $table = $db->quoteIdentifier($table);
- }
-
- if (!empty($table_fields) && $db->options['quote_identifier']) {
- foreach ($table_fields as $key => $field) {
- $table_fields[$key] = $db->quoteIdentifier($field);
- }
- }
-
- if ((false !== $where) && (null !== $where)) {
- if (is_array($where)) {
- $where = implode(' AND ', $where);
- }
- $where = ' WHERE '.$where;
- }
-
- switch ($mode) {
- case MDB2_AUTOQUERY_INSERT:
- if (empty($table_fields)) {
- return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
- 'Insert requires table fields', __FUNCTION__);
- }
- $cols = implode(', ', $table_fields);
- $values = '?'.str_repeat(', ?', (count($table_fields) - 1));
- return 'INSERT INTO '.$table.' ('.$cols.') VALUES ('.$values.')';
- break;
- case MDB2_AUTOQUERY_UPDATE:
- if (empty($table_fields)) {
- return $db->raiseError(MDB2_ERROR_NEED_MORE_DATA, null, null,
- 'Update requires table fields', __FUNCTION__);
- }
- $set = implode(' = ?, ', $table_fields).' = ?';
- $sql = 'UPDATE '.$table.' SET '.$set.$where;
- return $sql;
- break;
- case MDB2_AUTOQUERY_DELETE:
- $sql = 'DELETE FROM '.$table.$where;
- return $sql;
- break;
- case MDB2_AUTOQUERY_SELECT:
- $cols = !empty($table_fields) ? implode(', ', $table_fields) : '*';
- $sql = 'SELECT '.$cols.' FROM '.$table.$where;
- return $sql;
- break;
- }
- return $db->raiseError(MDB2_ERROR_SYNTAX, null, null,
- 'Non existant mode', __FUNCTION__);
- }
-
- // }}}
- // {{{ limitQuery()
-
- /**
- * Generates a limited query
- *
- * @param string query
- * @param array that contains the types of the columns in the result set
- * @param integer the numbers of rows to fetch
- * @param integer the row to start to fetching
- * @param string which specifies which result class to use
- * @param mixed string which specifies which class to wrap results in
- *
- * @return MDB2_Result|MDB2_Error result set on success, a MDB2 error on failure
- * @access public
- */
- function limitQuery($query, $types, $limit, $offset = 0, $result_class = true,
- $result_wrap_class = false)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- $result = $db->setLimit($limit, $offset);
- if (MDB2::isError($result)) {
- return $result;
- }
- return $db->query($query, $types, $result_class, $result_wrap_class);
- }
-
- // }}}
- // {{{ execParam()
-
- /**
- * Execute a parameterized DML statement.
- *
- * @param string the SQL query
- * @param array if supplied, prepare/execute will be used
- * with this array as execute parameters
- * @param array that contains the types of the values defined in $params
- *
- * @return int|MDB2_Error affected rows on success, a MDB2 error on failure
- * @access public
- */
- function execParam($query, $params = array(), $param_types = null)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- settype($params, 'array');
- if (empty($params)) {
- return $db->exec($query);
- }
-
- $stmt = $db->prepare($query, $param_types, MDB2_PREPARE_MANIP);
- if (MDB2::isError($stmt)) {
- return $stmt;
- }
-
- $result = $stmt->execute($params);
- if (MDB2::isError($result)) {
- return $result;
- }
-
- $stmt->free();
- return $result;
- }
-
- // }}}
- // {{{ getOne()
-
- /**
- * Fetch the first column of the first row of data returned from a query.
- * Takes care of doing the query and freeing the results when finished.
- *
- * @param string the SQL query
- * @param string that contains the type of the column in the result set
- * @param array if supplied, prepare/execute will be used
- * with this array as execute parameters
- * @param array that contains the types of the values defined in $params
- * @param int|string which column to return
- *
- * @return scalar|MDB2_Error data on success, a MDB2 error on failure
- * @access public
- */
- function getOne($query, $type = null, $params = array(),
- $param_types = null, $colnum = 0)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- settype($params, 'array');
- settype($type, 'array');
- if (empty($params)) {
- return $db->queryOne($query, $type, $colnum);
- }
-
- $stmt = $db->prepare($query, $param_types, $type);
- if (MDB2::isError($stmt)) {
- return $stmt;
- }
-
- $result = $stmt->execute($params);
- if (!MDB2::isResultCommon($result)) {
- return $result;
- }
-
- $one = $result->fetchOne($colnum);
- $stmt->free();
- $result->free();
- return $one;
- }
-
- // }}}
- // {{{ getRow()
-
- /**
- * Fetch the first row of data returned from a query. Takes care
- * of doing the query and freeing the results when finished.
- *
- * @param string the SQL query
- * @param array that contains the types of the columns in the result set
- * @param array if supplied, prepare/execute will be used
- * with this array as execute parameters
- * @param array that contains the types of the values defined in $params
- * @param int the fetch mode to use
- *
- * @return array|MDB2_Error data on success, a MDB2 error on failure
- * @access public
- */
- function getRow($query, $types = null, $params = array(),
- $param_types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- settype($params, 'array');
- if (empty($params)) {
- return $db->queryRow($query, $types, $fetchmode);
- }
-
- $stmt = $db->prepare($query, $param_types, $types);
- if (MDB2::isError($stmt)) {
- return $stmt;
- }
-
- $result = $stmt->execute($params);
- if (!MDB2::isResultCommon($result)) {
- return $result;
- }
-
- $row = $result->fetchRow($fetchmode);
- $stmt->free();
- $result->free();
- return $row;
- }
-
- // }}}
- // {{{ getCol()
-
- /**
- * Fetch a single column from a result set and return it as an
- * indexed array.
- *
- * @param string the SQL query
- * @param string that contains the type of the column in the result set
- * @param array if supplied, prepare/execute will be used
- * with this array as execute parameters
- * @param array that contains the types of the values defined in $params
- * @param int|string which column to return
- *
- * @return array|MDB2_Error data on success, a MDB2 error on failure
- * @access public
- */
- function getCol($query, $type = null, $params = array(),
- $param_types = null, $colnum = 0)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- settype($params, 'array');
- settype($type, 'array');
- if (empty($params)) {
- return $db->queryCol($query, $type, $colnum);
- }
-
- $stmt = $db->prepare($query, $param_types, $type);
- if (MDB2::isError($stmt)) {
- return $stmt;
- }
-
- $result = $stmt->execute($params);
- if (!MDB2::isResultCommon($result)) {
- return $result;
- }
-
- $col = $result->fetchCol($colnum);
- $stmt->free();
- $result->free();
- return $col;
- }
-
- // }}}
- // {{{ getAll()
-
- /**
- * Fetch all the rows returned from a query.
- *
- * @param string the SQL query
- * @param array that contains the types of the columns in the result set
- * @param array if supplied, prepare/execute will be used
- * with this array as execute parameters
- * @param array that contains the types of the values defined in $params
- * @param int the fetch mode to use
- * @param bool if set to true, the $all will have the first
- * column as its first dimension
- * @param bool $force_array used only when the query returns exactly
- * two columns. If true, the values of the returned array will be
- * one-element arrays instead of scalars.
- * @param bool $group if true, the values of the returned array is
- * wrapped in another array. If the same key value (in the first
- * column) repeats itself, the values will be appended to this array
- * instead of overwriting the existing values.
- *
- * @return array|MDB2_Error data on success, a MDB2 error on failure
- * @access public
- */
- function getAll($query, $types = null, $params = array(),
- $param_types = null, $fetchmode = MDB2_FETCHMODE_DEFAULT,
- $rekey = false, $force_array = false, $group = false)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- settype($params, 'array');
- if (empty($params)) {
- return $db->queryAll($query, $types, $fetchmode, $rekey, $force_array, $group);
- }
-
- $stmt = $db->prepare($query, $param_types, $types);
- if (MDB2::isError($stmt)) {
- return $stmt;
- }
-
- $result = $stmt->execute($params);
- if (!MDB2::isResultCommon($result)) {
- return $result;
- }
-
- $all = $result->fetchAll($fetchmode, $rekey, $force_array, $group);
- $stmt->free();
- $result->free();
- return $all;
- }
-
- // }}}
- // {{{ getAssoc()
-
- /**
- * Fetch the entire result set of a query and return it as an
- * associative array using the first column as the key.
- *
- * If the result set contains more than two columns, the value
- * will be an array of the values from column 2-n. If the result
- * set contains only two columns, the returned value will be a
- * scalar with the value of the second column (unless forced to an
- * array with the $force_array parameter). A MDB2 error code is
- * returned on errors. If the result set contains fewer than two
- * columns, a MDB2_ERROR_TRUNCATED error is returned.
- *
- * For example, if the table 'mytable' contains:
- *
- * ID TEXT DATE
- * --------------------------------
- * 1 'one' 944679408
- * 2 'two' 944679408
- * 3 'three' 944679408
- *
- * Then the call getAssoc('SELECT id,text FROM mytable') returns:
- *
- * array(
- * '1' => 'one',
- * '2' => 'two',
- * '3' => 'three',
- * )
- *
- * ...while the call getAssoc('SELECT id,text,date FROM mytable') returns:
- *
- * array(
- * '1' => array('one', '944679408'),
- * '2' => array('two', '944679408'),
- * '3' => array('three', '944679408')
- * )
- *
- *
- * If the more than one row occurs with the same value in the
- * first column, the last row overwrites all previous ones by
- * default. Use the $group parameter if you don't want to
- * overwrite like this. Example:
- *
- * getAssoc('SELECT category,id,name FROM mytable', null, null
- * MDB2_FETCHMODE_ASSOC, false, true) returns:
- * array(
- * '1' => array(array('id' => '4', 'name' => 'number four'),
- * array('id' => '6', 'name' => 'number six')
- * ),
- * '9' => array(array('id' => '4', 'name' => 'number four'),
- * array('id' => '6', 'name' => 'number six')
- * )
- * )
- *
- *
- * Keep in mind that database functions in PHP usually return string
- * values for results regardless of the database's internal type.
- *
- * @param string the SQL query
- * @param array that contains the types of the columns in the result set
- * @param array if supplied, prepare/execute will be used
- * with this array as execute parameters
- * @param array that contains the types of the values defined in $params
- * @param bool $force_array used only when the query returns
- * exactly two columns. If TRUE, the values of the returned array
- * will be one-element arrays instead of scalars.
- * @param bool $group if TRUE, the values of the returned array
- * is wrapped in another array. If the same key value (in the first
- * column) repeats itself, the values will be appended to this array
- * instead of overwriting the existing values.
- *
- * @return array|MDB2_Error data on success, a MDB2 error on failure
- * @access public
- */
- function getAssoc($query, $types = null, $params = array(), $param_types = null,
- $fetchmode = MDB2_FETCHMODE_DEFAULT, $force_array = false, $group = false)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- settype($params, 'array');
- if (empty($params)) {
- return $db->queryAll($query, $types, $fetchmode, true, $force_array, $group);
- }
-
- $stmt = $db->prepare($query, $param_types, $types);
- if (MDB2::isError($stmt)) {
- return $stmt;
- }
-
- $result = $stmt->execute($params);
- if (!MDB2::isResultCommon($result)) {
- return $result;
- }
-
- $all = $result->fetchAll($fetchmode, true, $force_array, $group);
- $stmt->free();
- $result->free();
- return $all;
- }
-
- // }}}
- // {{{ executeMultiple()
-
- /**
- * This function does several execute() calls on the same statement handle.
- * $params must be an array indexed numerically from 0, one execute call is
- * done for every 'row' in the array.
- *
- * If an error occurs during execute(), executeMultiple() does not execute
- * the unfinished rows, but rather returns that error.
- *
- * @param resource query handle from prepare()
- * @param array numeric array containing the data to insert into the query
- *
- * @return bool|MDB2_Error true on success, a MDB2 error on failure
- * @access public
- * @see prepare(), execute()
- */
- function executeMultiple($stmt, $params = null)
- {
- if (MDB2::isError($stmt)) {
- return $stmt;
- }
- for ($i = 0, $j = count($params); $i < $j; $i++) {
- $result = $stmt->execute($params[$i]);
- if (MDB2::isError($result)) {
- return $result;
- }
- }
- return MDB2_OK;
- }
-
- // }}}
- // {{{ getBeforeID()
-
- /**
- * Returns the next free id of a sequence if the RDBMS
- * does not support auto increment
- *
- * @param string name of the table into which a new row was inserted
- * @param string name of the field into which a new row was inserted
- * @param bool when true the sequence is automatic created, if it not exists
- * @param bool if the returned value should be quoted
- *
- * @return int|MDB2_Error id on success, a MDB2 error on failure
- * @access public
- */
- function getBeforeID($table, $field = null, $ondemand = true, $quote = true)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- if ($db->supports('auto_increment') !== true) {
- $seq = $table.(empty($field) ? '' : '_'.$field);
- $id = $db->nextID($seq, $ondemand);
- if (!$quote || MDB2::isError($id)) {
- return $id;
- }
- return $db->quote($id, 'integer');
- } elseif (!$quote) {
- return null;
- }
- return 'NULL';
- }
-
- // }}}
- // {{{ getAfterID()
-
- /**
- * Returns the autoincrement ID if supported or $id
- *
- * @param mixed value as returned by getBeforeId()
- * @param string name of the table into which a new row was inserted
- * @param string name of the field into which a new row was inserted
- *
- * @return int|MDB2_Error id on success, a MDB2 error on failure
- * @access public
- */
- function getAfterID($id, $table, $field = null)
- {
- $db = $this->getDBInstance();
- if (MDB2::isError($db)) {
- return $db;
- }
-
- if ($db->supports('auto_increment') !== true) {
- return $id;
- }
- return $db->lastInsertID($table, $field);
- }
-
- // }}}
-}
-?>
diff --git a/data/module/MDB2/Iterator.php b/data/module/MDB2/Iterator.php
deleted file mode 100644
index 17a3ac29ad2..00000000000
--- a/data/module/MDB2/Iterator.php
+++ /dev/null
@@ -1,262 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: Iterator.php 327310 2012-08-27 15:16:18Z danielc $
-
-/**
- * PHP5 Iterator
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_Iterator implements Iterator
-{
- protected $fetchmode;
- /**
- * @var MDB2_Result_Common
- */
- protected $result;
- protected $row;
-
- // {{{ constructor
-
- /**
- * Constructor
- */
- public function __construct(MDB2_Result_Common $result, $fetchmode = MDB2_FETCHMODE_DEFAULT)
- {
- $this->result = $result;
- $this->fetchmode = $fetchmode;
- }
- // }}}
-
- // {{{ seek()
-
- /**
- * Seek forward to a specific row in a result set
- *
- * @param int number of the row where the data can be found
- *
- * @return void
- * @access public
- */
- public function seek($rownum)
- {
- $this->row = null;
- if ($this->result) {
- $this->result->seek($rownum);
- }
- }
- // }}}
-
- // {{{ next()
-
- /**
- * Fetch next row of data
- *
- * @return void
- * @access public
- */
- public function next()
- {
- $this->row = null;
- }
- // }}}
-
- // {{{ current()
-
- /**
- * return a row of data
- *
- * @return void
- * @access public
- */
- public function current()
- {
- if (null === $this->row) {
- $row = $this->result->fetchRow($this->fetchmode);
- if (MDB2::isError($row)) {
- $row = false;
- }
- $this->row = $row;
- }
- return $this->row;
- }
- // }}}
-
- // {{{ valid()
-
- /**
- * Check if the end of the result set has been reached
- *
- * @return bool true/false, false is also returned on failure
- * @access public
- */
- public function valid()
- {
- return (bool)$this->current();
- }
- // }}}
-
- // {{{ free()
-
- /**
- * Free the internal resources associated with result.
- *
- * @return bool|MDB2_Error true on success, false|MDB2_Error if result is invalid
- * @access public
- */
- public function free()
- {
- if ($this->result) {
- return $this->result->free();
- }
- $this->result = false;
- $this->row = null;
- return false;
- }
- // }}}
-
- // {{{ key()
-
- /**
- * Returns the row number
- *
- * @return int|bool|MDB2_Error true on success, false|MDB2_Error if result is invalid
- * @access public
- */
- public function key()
- {
- if ($this->result) {
- return $this->result->rowCount();
- }
- return false;
- }
- // }}}
-
- // {{{ rewind()
-
- /**
- * Seek to the first row in a result set
- *
- * @return void
- * @access public
- */
- public function rewind()
- {
- }
- // }}}
-
- // {{{ destructor
-
- /**
- * Destructor
- */
- public function __destruct()
- {
- $this->free();
- }
- // }}}
-}
-
-/**
- * PHP5 buffered Iterator
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_BufferedIterator extends MDB2_Iterator implements SeekableIterator
-{
- // {{{ valid()
-
- /**
- * Check if the end of the result set has been reached
- *
- * @return bool|MDB2_Error true on success, false|MDB2_Error if result is invalid
- * @access public
- */
- public function valid()
- {
- if ($this->result) {
- return $this->result->valid();
- }
- return false;
- }
- // }}}
-
- // {{{count()
-
- /**
- * Returns the number of rows in a result object
- *
- * @return int|MDB2_Error number of rows, false|MDB2_Error if result is invalid
- * @access public
- */
- public function count()
- {
- if ($this->result) {
- return $this->result->numRows();
- }
- return false;
- }
- // }}}
-
- // {{{ rewind()
-
- /**
- * Seek to the first row in a result set
- *
- * @return void
- * @access public
- */
- public function rewind()
- {
- $this->seek(0);
- }
- // }}}
-}
-
-?>
diff --git a/data/module/MDB2/LOB.php b/data/module/MDB2/LOB.php
deleted file mode 100644
index ff2342dbb9a..00000000000
--- a/data/module/MDB2/LOB.php
+++ /dev/null
@@ -1,264 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-//
-// $Id: LOB.php 222350 2006-10-25 11:52:21Z lsmith $
-
-/**
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-
-require_once 'MDB2.php';
-
-/**
- * MDB2_LOB: user land stream wrapper implementation for LOB support
- *
- * @package MDB2
- * @category Database
- * @author Lukas Smith
- */
-class MDB2_LOB
-{
- /**
- * contains the key to the global MDB2 instance array of the associated
- * MDB2 instance
- *
- * @var integer
- * @access protected
- */
- var $db_index;
-
- /**
- * contains the key to the global MDB2_LOB instance array of the associated
- * MDB2_LOB instance
- *
- * @var integer
- * @access protected
- */
- var $lob_index;
-
- // {{{ stream_open()
-
- /**
- * open stream
- *
- * @param string specifies the URL that was passed to fopen()
- * @param string the mode used to open the file
- * @param int holds additional flags set by the streams API
- * @param string not used
- *
- * @return bool
- * @access public
- */
- function stream_open($path, $mode, $options, &$opened_path)
- {
- if (!preg_match('/^rb?\+?$/', $mode)) {
- return false;
- }
- $url = parse_url($path);
- if (empty($url['host'])) {
- return false;
- }
- $this->db_index = (int)$url['host'];
- if (!isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
- return false;
- }
- $db =& $GLOBALS['_MDB2_databases'][$this->db_index];
- $this->lob_index = (int)$url['user'];
- if (!isset($db->datatype->lobs[$this->lob_index])) {
- return false;
- }
- return true;
- }
- // }}}
-
- // {{{ stream_read()
-
- /**
- * read stream
- *
- * @param int number of bytes to read
- *
- * @return string
- * @access public
- */
- function stream_read($count)
- {
- if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
- $db =& $GLOBALS['_MDB2_databases'][$this->db_index];
- $db->datatype->_retrieveLOB($db->datatype->lobs[$this->lob_index]);
-
- $data = $db->datatype->_readLOB($db->datatype->lobs[$this->lob_index], $count);
- $length = strlen($data);
- if ($length == 0) {
- $db->datatype->lobs[$this->lob_index]['endOfLOB'] = true;
- }
- $db->datatype->lobs[$this->lob_index]['position'] += $length;
- return $data;
- }
- }
- // }}}
-
- // {{{ stream_write()
-
- /**
- * write stream, note implemented
- *
- * @param string data
- *
- * @return int
- * @access public
- */
- function stream_write($data)
- {
- return 0;
- }
- // }}}
-
- // {{{ stream_tell()
-
- /**
- * return the current position
- *
- * @return int current position
- * @access public
- */
- function stream_tell()
- {
- if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
- $db =& $GLOBALS['_MDB2_databases'][$this->db_index];
- return $db->datatype->lobs[$this->lob_index]['position'];
- }
- }
- // }}}
-
- // {{{ stream_eof()
-
- /**
- * Check if stream reaches EOF
- *
- * @return bool
- * @access public
- */
- function stream_eof()
- {
- if (!isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
- return true;
- }
-
- $db =& $GLOBALS['_MDB2_databases'][$this->db_index];
- $result = $db->datatype->_endOfLOB($db->datatype->lobs[$this->lob_index]);
- if (version_compare(phpversion(), "5.0", ">=")
- && version_compare(phpversion(), "5.1", "<")
- ) {
- return !$result;
- }
- return $result;
- }
- // }}}
-
- // {{{ stream_seek()
-
- /**
- * Seek stream, not implemented
- *
- * @param int offset
- * @param int whence
- *
- * @return bool
- * @access public
- */
- function stream_seek($offset, $whence)
- {
- return false;
- }
- // }}}
-
- // {{{ stream_stat()
-
- /**
- * return information about stream
- *
- * @access public
- */
- function stream_stat()
- {
- if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
- $db =& $GLOBALS['_MDB2_databases'][$this->db_index];
- return array(
- 'db_index' => $this->db_index,
- 'lob_index' => $this->lob_index,
- );
- }
- }
- // }}}
-
- // {{{ stream_close()
-
- /**
- * close stream
- *
- * @access public
- */
- function stream_close()
- {
- if (isset($GLOBALS['_MDB2_databases'][$this->db_index])) {
- $db =& $GLOBALS['_MDB2_databases'][$this->db_index];
- if (isset($db->datatype->lobs[$this->lob_index])) {
- $db->datatype->_destroyLOB($db->datatype->lobs[$this->lob_index]);
- unset($db->datatype->lobs[$this->lob_index]);
- }
- }
- }
- // }}}
-}
-
-// register streams wrapper
-if (!stream_wrapper_register("MDB2LOB", "MDB2_LOB")) {
- MDB2::raiseError();
- return false;
-}
-
-?>
diff --git a/data/module/Mail.php b/data/module/Mail.php
deleted file mode 100644
index 75132ac2a6c..00000000000
--- a/data/module/Mail.php
+++ /dev/null
@@ -1,270 +0,0 @@
-
- * @copyright 1997-2010 Chuck Hagenbuch
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: Mail.php 294747 2010-02-08 08:18:33Z clockwerx $
- * @link http://pear.php.net/package/Mail/
- */
-
-require_once 'PEAR.php';
-
-/**
- * PEAR's Mail:: interface. Defines the interface for implementing
- * mailers under the PEAR hierarchy, and provides supporting functions
- * useful in multiple mailer backends.
- *
- * @access public
- * @version $Revision: 294747 $
- * @package Mail
- */
-class Mail
-{
- /**
- * Line terminator used for separating header lines.
- * @var string
- */
- var $sep = "\r\n";
-
- /**
- * Provides an interface for generating Mail:: objects of various
- * types
- *
- * @param string $driver The kind of Mail:: object to instantiate.
- * @param array $params The parameters to pass to the Mail:: object.
- * @return object Mail a instance of the driver class or if fails a PEAR Error
- * @access public
- */
- function &factory($driver, $params = array())
- {
- $driver = strtolower($driver);
- @include_once 'Mail/' . $driver . '.php';
- $class = 'Mail_' . $driver;
- if (class_exists($class)) {
- $mailer = new $class($params);
- return $mailer;
- } else {
- return PEAR::raiseError('Unable to find class for driver ' . $driver);
- }
- }
-
- /**
- * Implements Mail::send() function using php's built-in mail()
- * command.
- *
- * @param mixed $recipients Either a comma-seperated list of recipients
- * (RFC822 compliant), or an array of recipients,
- * each RFC822 valid. This may contain recipients not
- * specified in the headers, for Bcc:, resending
- * messages, etc.
- *
- * @param array $headers The array of headers to send with the mail, in an
- * associative array, where the array key is the
- * header name (ie, 'Subject'), and the array value
- * is the header value (ie, 'test'). The header
- * produced from those values would be 'Subject:
- * test'.
- *
- * @param string $body The full text of the message body, including any
- * Mime parts, etc.
- *
- * @return mixed Returns true on success, or a PEAR_Error
- * containing a descriptive error message on
- * failure.
- *
- * @access public
- * @deprecated use Mail_mail::send instead
- */
- function send($recipients, $headers, $body)
- {
- if (!is_array($headers)) {
- return PEAR::raiseError('$headers must be an array');
- }
-
- $result = $this->_sanitizeHeaders($headers);
- if (is_a($result, 'PEAR_Error')) {
- return $result;
- }
-
- // if we're passed an array of recipients, implode it.
- if (is_array($recipients)) {
- $recipients = implode(', ', $recipients);
- }
-
- // get the Subject out of the headers array so that we can
- // pass it as a seperate argument to mail().
- $subject = '';
- if (isset($headers['Subject'])) {
- $subject = $headers['Subject'];
- unset($headers['Subject']);
- }
-
- // flatten the headers out.
- list(, $text_headers) = Mail::prepareHeaders($headers);
-
- return mail($recipients, $subject, $body, $text_headers);
- }
-
- /**
- * Sanitize an array of mail headers by removing any additional header
- * strings present in a legitimate header's value. The goal of this
- * filter is to prevent mail injection attacks.
- *
- * @param array $headers The associative array of headers to sanitize.
- *
- * @access private
- */
- function _sanitizeHeaders(&$headers)
- {
- foreach ($headers as $key => $value) {
- $headers[$key] =
- preg_replace('=((||0x0A/%0A|0x0D/%0D|\\n|\\r)\S).*=i',
- null, $value);
- }
- }
-
- /**
- * Take an array of mail headers and return a string containing
- * text usable in sending a message.
- *
- * @param array $headers The array of headers to prepare, in an associative
- * array, where the array key is the header name (ie,
- * 'Subject'), and the array value is the header
- * value (ie, 'test'). The header produced from those
- * values would be 'Subject: test'.
- *
- * @return mixed Returns false if it encounters a bad address,
- * otherwise returns an array containing two
- * elements: Any From: address found in the headers,
- * and the plain text version of the headers.
- * @access private
- */
- function prepareHeaders($headers)
- {
- $lines = array();
- $from = null;
-
- foreach ($headers as $key => $value) {
- if (strcasecmp($key, 'From') === 0) {
- include_once 'Mail/RFC822.php';
- $parser = new Mail_RFC822();
- $addresses = $parser->parseAddressList($value, 'localhost', false);
- if (is_a($addresses, 'PEAR_Error')) {
- return $addresses;
- }
-
- $from = $addresses[0]->mailbox . '@' . $addresses[0]->host;
-
- // Reject envelope From: addresses with spaces.
- if (strstr($from, ' ')) {
- return false;
- }
-
- $lines[] = $key . ': ' . $value;
- } elseif (strcasecmp($key, 'Received') === 0) {
- $received = array();
- if (is_array($value)) {
- foreach ($value as $line) {
- $received[] = $key . ': ' . $line;
- }
- }
- else {
- $received[] = $key . ': ' . $value;
- }
- // Put Received: headers at the top. Spam detectors often
- // flag messages with Received: headers after the Subject:
- // as spam.
- $lines = array_merge($received, $lines);
- } else {
- // If $value is an array (i.e., a list of addresses), convert
- // it to a comma-delimited string of its elements (addresses).
- if (is_array($value)) {
- $value = implode(', ', $value);
- }
- $lines[] = $key . ': ' . $value;
- }
- }
-
- return array($from, join($this->sep, $lines));
- }
-
- /**
- * Take a set of recipients and parse them, returning an array of
- * bare addresses (forward paths) that can be passed to sendmail
- * or an smtp server with the rcpt to: command.
- *
- * @param mixed Either a comma-seperated list of recipients
- * (RFC822 compliant), or an array of recipients,
- * each RFC822 valid.
- *
- * @return mixed An array of forward paths (bare addresses) or a PEAR_Error
- * object if the address list could not be parsed.
- * @access private
- */
- function parseRecipients($recipients)
- {
- include_once 'Mail/RFC822.php';
-
- // if we're passed an array, assume addresses are valid and
- // implode them before parsing.
- if (is_array($recipients)) {
- $recipients = implode(', ', $recipients);
- }
-
- // Parse recipients, leaving out all personal info. This is
- // for smtp recipients, etc. All relevant personal information
- // should already be in the headers.
- $addresses = Mail_RFC822::parseAddressList($recipients, 'localhost', false);
-
- // If parseAddressList() returned a PEAR_Error object, just return it.
- if (is_a($addresses, 'PEAR_Error')) {
- return $addresses;
- }
-
- $recipients = array();
- if (is_array($addresses)) {
- foreach ($addresses as $ob) {
- $recipients[] = $ob->mailbox . '@' . $ob->host;
- }
- }
-
- return $recipients;
- }
-
-}
diff --git a/data/module/Mail/RFC822.php b/data/module/Mail/RFC822.php
deleted file mode 100644
index 58d36465cba..00000000000
--- a/data/module/Mail/RFC822.php
+++ /dev/null
@@ -1,951 +0,0 @@
-
- * @author Chuck Hagenbuch (A comment), ted@example.com (Ted Bloggs), Barney;';
- * $structure = Mail_RFC822::parseAddressList($address_string, 'example.com', true)
- * print_r($structure);
- *
- * @author Richard Heyes
- * @author Chuck Hagenbuch
- * @version $Revision: 294749 $
- * @license BSD
- * @package Mail
- */
-class Mail_RFC822 {
-
- /**
- * The address being parsed by the RFC822 object.
- * @var string $address
- */
- var $address = '';
-
- /**
- * The default domain to use for unqualified addresses.
- * @var string $default_domain
- */
- var $default_domain = 'localhost';
-
- /**
- * Should we return a nested array showing groups, or flatten everything?
- * @var boolean $nestGroups
- */
- var $nestGroups = true;
-
- /**
- * Whether or not to validate atoms for non-ascii characters.
- * @var boolean $validate
- */
- var $validate = true;
-
- /**
- * The array of raw addresses built up as we parse.
- * @var array $addresses
- */
- var $addresses = array();
-
- /**
- * The final array of parsed address information that we build up.
- * @var array $structure
- */
- var $structure = array();
-
- /**
- * The current error message, if any.
- * @var string $error
- */
- var $error = null;
-
- /**
- * An internal counter/pointer.
- * @var integer $index
- */
- var $index = null;
-
- /**
- * The number of groups that have been found in the address list.
- * @var integer $num_groups
- * @access public
- */
- var $num_groups = 0;
-
- /**
- * A variable so that we can tell whether or not we're inside a
- * Mail_RFC822 object.
- * @var boolean $mailRFC822
- */
- var $mailRFC822 = true;
-
- /**
- * A limit after which processing stops
- * @var int $limit
- */
- var $limit = null;
-
- /**
- * Sets up the object. The address must either be set here or when
- * calling parseAddressList(). One or the other.
- *
- * @access public
- * @param string $address The address(es) to validate.
- * @param string $default_domain Default domain/host etc. If not supplied, will be set to localhost.
- * @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing.
- * @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance.
- *
- * @return object Mail_RFC822 A new Mail_RFC822 object.
- */
- function Mail_RFC822($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null)
- {
- if (isset($address)) $this->address = $address;
- if (isset($default_domain)) $this->default_domain = $default_domain;
- if (isset($nest_groups)) $this->nestGroups = $nest_groups;
- if (isset($validate)) $this->validate = $validate;
- if (isset($limit)) $this->limit = $limit;
- }
-
- /**
- * Starts the whole process. The address must either be set here
- * or when creating the object. One or the other.
- *
- * @access public
- * @param string $address The address(es) to validate.
- * @param string $default_domain Default domain/host etc.
- * @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing.
- * @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance.
- *
- * @return array A structured array of addresses.
- */
- function parseAddressList($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null)
- {
- if (!isset($this) || !isset($this->mailRFC822)) {
- $obj = new Mail_RFC822($address, $default_domain, $nest_groups, $validate, $limit);
- return $obj->parseAddressList();
- }
-
- if (isset($address)) $this->address = $address;
- if (isset($default_domain)) $this->default_domain = $default_domain;
- if (isset($nest_groups)) $this->nestGroups = $nest_groups;
- if (isset($validate)) $this->validate = $validate;
- if (isset($limit)) $this->limit = $limit;
-
- $this->structure = array();
- $this->addresses = array();
- $this->error = null;
- $this->index = null;
-
- // Unfold any long lines in $this->address.
- $this->address = preg_replace('/\r?\n/', "\r\n", $this->address);
- $this->address = preg_replace('/\r\n(\t| )+/', ' ', $this->address);
-
- while ($this->address = $this->_splitAddresses($this->address));
-
- if ($this->address === false || isset($this->error)) {
- require_once 'PEAR.php';
- return PEAR::raiseError($this->error);
- }
-
- // Validate each address individually. If we encounter an invalid
- // address, stop iterating and return an error immediately.
- foreach ($this->addresses as $address) {
- $valid = $this->_validateAddress($address);
-
- if ($valid === false || isset($this->error)) {
- require_once 'PEAR.php';
- return PEAR::raiseError($this->error);
- }
-
- if (!$this->nestGroups) {
- $this->structure = array_merge($this->structure, $valid);
- } else {
- $this->structure[] = $valid;
- }
- }
-
- return $this->structure;
- }
-
- /**
- * Splits an address into separate addresses.
- *
- * @access private
- * @param string $address The addresses to split.
- * @return boolean Success or failure.
- */
- function _splitAddresses($address)
- {
- if (!empty($this->limit) && count($this->addresses) == $this->limit) {
- return '';
- }
-
- if ($this->_isGroup($address) && !isset($this->error)) {
- $split_char = ';';
- $is_group = true;
- } elseif (!isset($this->error)) {
- $split_char = ',';
- $is_group = false;
- } elseif (isset($this->error)) {
- return false;
- }
-
- // Split the string based on the above ten or so lines.
- $parts = explode($split_char, $address);
- $string = $this->_splitCheck($parts, $split_char);
-
- // If a group...
- if ($is_group) {
- // If $string does not contain a colon outside of
- // brackets/quotes etc then something's fubar.
-
- // First check there's a colon at all:
- if (strpos($string, ':') === false) {
- $this->error = 'Invalid address: ' . $string;
- return false;
- }
-
- // Now check it's outside of brackets/quotes:
- if (!$this->_splitCheck(explode(':', $string), ':')) {
- return false;
- }
-
- // We must have a group at this point, so increase the counter:
- $this->num_groups++;
- }
-
- // $string now contains the first full address/group.
- // Add to the addresses array.
- $this->addresses[] = array(
- 'address' => trim($string),
- 'group' => $is_group
- );
-
- // Remove the now stored address from the initial line, the +1
- // is to account for the explode character.
- $address = trim(substr($address, strlen($string) + 1));
-
- // If the next char is a comma and this was a group, then
- // there are more addresses, otherwise, if there are any more
- // chars, then there is another address.
- if ($is_group && substr($address, 0, 1) == ','){
- $address = trim(substr($address, 1));
- return $address;
-
- } elseif (strlen($address) > 0) {
- return $address;
-
- } else {
- return '';
- }
-
- // If you got here then something's off
- return false;
- }
-
- /**
- * Checks for a group at the start of the string.
- *
- * @access private
- * @param string $address The address to check.
- * @return boolean Whether or not there is a group at the start of the string.
- */
- function _isGroup($address)
- {
- // First comma not in quotes, angles or escaped:
- $parts = explode(',', $address);
- $string = $this->_splitCheck($parts, ',');
-
- // Now we have the first address, we can reliably check for a
- // group by searching for a colon that's not escaped or in
- // quotes or angle brackets.
- if (count($parts = explode(':', $string)) > 1) {
- $string2 = $this->_splitCheck($parts, ':');
- return ($string2 !== $string);
- } else {
- return false;
- }
- }
-
- /**
- * A common function that will check an exploded string.
- *
- * @access private
- * @param array $parts The exloded string.
- * @param string $char The char that was exploded on.
- * @return mixed False if the string contains unclosed quotes/brackets, or the string on success.
- */
- function _splitCheck($parts, $char)
- {
- $string = $parts[0];
-
- for ($i = 0; $i < count($parts); $i++) {
- if ($this->_hasUnclosedQuotes($string)
- || $this->_hasUnclosedBrackets($string, '<>')
- || $this->_hasUnclosedBrackets($string, '[]')
- || $this->_hasUnclosedBrackets($string, '()')
- || substr($string, -1) == '\\') {
- if (isset($parts[$i + 1])) {
- $string = $string . $char . $parts[$i + 1];
- } else {
- $this->error = 'Invalid address spec. Unclosed bracket or quotes';
- return false;
- }
- } else {
- $this->index = $i;
- break;
- }
- }
-
- return $string;
- }
-
- /**
- * Checks if a string has unclosed quotes or not.
- *
- * @access private
- * @param string $string The string to check.
- * @return boolean True if there are unclosed quotes inside the string,
- * false otherwise.
- */
- function _hasUnclosedQuotes($string)
- {
- $string = trim($string);
- $iMax = strlen($string);
- $in_quote = false;
- $i = $slashes = 0;
-
- for (; $i < $iMax; ++$i) {
- switch ($string[$i]) {
- case '\\':
- ++$slashes;
- break;
-
- case '"':
- if ($slashes % 2 == 0) {
- $in_quote = !$in_quote;
- }
- // Fall through to default action below.
-
- default:
- $slashes = 0;
- break;
- }
- }
-
- return $in_quote;
- }
-
- /**
- * Checks if a string has an unclosed brackets or not. IMPORTANT:
- * This function handles both angle brackets and square brackets;
- *
- * @access private
- * @param string $string The string to check.
- * @param string $chars The characters to check for.
- * @return boolean True if there are unclosed brackets inside the string, false otherwise.
- */
- function _hasUnclosedBrackets($string, $chars)
- {
- $num_angle_start = substr_count($string, $chars[0]);
- $num_angle_end = substr_count($string, $chars[1]);
-
- $this->_hasUnclosedBracketsSub($string, $num_angle_start, $chars[0]);
- $this->_hasUnclosedBracketsSub($string, $num_angle_end, $chars[1]);
-
- if ($num_angle_start < $num_angle_end) {
- $this->error = 'Invalid address spec. Unmatched quote or bracket (' . $chars . ')';
- return false;
- } else {
- return ($num_angle_start > $num_angle_end);
- }
- }
-
- /**
- * Sub function that is used only by hasUnclosedBrackets().
- *
- * @access private
- * @param string $string The string to check.
- * @param integer &$num The number of occurences.
- * @param string $char The character to count.
- * @return integer The number of occurences of $char in $string, adjusted for backslashes.
- */
- function _hasUnclosedBracketsSub($string, &$num, $char)
- {
- $parts = explode($char, $string);
- for ($i = 0; $i < count($parts); $i++){
- if (substr($parts[$i], -1) == '\\' || $this->_hasUnclosedQuotes($parts[$i]))
- $num--;
- if (isset($parts[$i + 1]))
- $parts[$i + 1] = $parts[$i] . $char . $parts[$i + 1];
- }
-
- return $num;
- }
-
- /**
- * Function to begin checking the address.
- *
- * @access private
- * @param string $address The address to validate.
- * @return mixed False on failure, or a structured array of address information on success.
- */
- function _validateAddress($address)
- {
- $is_group = false;
- $addresses = array();
-
- if ($address['group']) {
- $is_group = true;
-
- // Get the group part of the name
- $parts = explode(':', $address['address']);
- $groupname = $this->_splitCheck($parts, ':');
- $structure = array();
-
- // And validate the group part of the name.
- if (!$this->_validatePhrase($groupname)){
- $this->error = 'Group name did not validate.';
- return false;
- } else {
- // Don't include groups if we are not nesting
- // them. This avoids returning invalid addresses.
- if ($this->nestGroups) {
- $structure = new stdClass;
- $structure->groupname = $groupname;
- }
- }
-
- $address['address'] = ltrim(substr($address['address'], strlen($groupname . ':')));
- }
-
- // If a group then split on comma and put into an array.
- // Otherwise, Just put the whole address in an array.
- if ($is_group) {
- while (strlen($address['address']) > 0) {
- $parts = explode(',', $address['address']);
- $addresses[] = $this->_splitCheck($parts, ',');
- $address['address'] = trim(substr($address['address'], strlen(end($addresses) . ',')));
- }
- } else {
- $addresses[] = $address['address'];
- }
-
- // Check that $addresses is set, if address like this:
- // Groupname:;
- // Then errors were appearing.
- if (!count($addresses)){
- $this->error = 'Empty group.';
- return false;
- }
-
- // Trim the whitespace from all of the address strings.
- array_map('trim', $addresses);
-
- // Validate each mailbox.
- // Format could be one of: name
- // geezer@domain.com
- // geezer
- // ... or any other format valid by RFC 822.
- for ($i = 0; $i < count($addresses); $i++) {
- if (!$this->validateMailbox($addresses[$i])) {
- if (empty($this->error)) {
- $this->error = 'Validation failed for: ' . $addresses[$i];
- }
- return false;
- }
- }
-
- // Nested format
- if ($this->nestGroups) {
- if ($is_group) {
- $structure->addresses = $addresses;
- } else {
- $structure = $addresses[0];
- }
-
- // Flat format
- } else {
- if ($is_group) {
- $structure = array_merge($structure, $addresses);
- } else {
- $structure = $addresses;
- }
- }
-
- return $structure;
- }
-
- /**
- * Function to validate a phrase.
- *
- * @access private
- * @param string $phrase The phrase to check.
- * @return boolean Success or failure.
- */
- function _validatePhrase($phrase)
- {
- // Splits on one or more Tab or space.
- $parts = preg_split('/[ \\x09]+/', $phrase, -1, PREG_SPLIT_NO_EMPTY);
-
- $phrase_parts = array();
- while (count($parts) > 0){
- $phrase_parts[] = $this->_splitCheck($parts, ' ');
- for ($i = 0; $i < $this->index + 1; $i++)
- array_shift($parts);
- }
-
- foreach ($phrase_parts as $part) {
- // If quoted string:
- if (substr($part, 0, 1) == '"') {
- if (!$this->_validateQuotedString($part)) {
- return false;
- }
- continue;
- }
-
- // Otherwise it's an atom:
- if (!$this->_validateAtom($part)) return false;
- }
-
- return true;
- }
-
- /**
- * Function to validate an atom which from rfc822 is:
- * atom = 1*
- *
- * If validation ($this->validate) has been turned off, then
- * validateAtom() doesn't actually check anything. This is so that you
- * can split a list of addresses up before encoding personal names
- * (umlauts, etc.), for example.
- *
- * @access private
- * @param string $atom The string to check.
- * @return boolean Success or failure.
- */
- function _validateAtom($atom)
- {
- if (!$this->validate) {
- // Validation has been turned off; assume the atom is okay.
- return true;
- }
-
- // Check for any char from ASCII 0 - ASCII 127
- if (!preg_match('/^[\\x00-\\x7E]+$/i', $atom, $matches)) {
- return false;
- }
-
- // Check for specials:
- if (preg_match('/[][()<>@,;\\:". ]/', $atom)) {
- return false;
- }
-
- // Check for control characters (ASCII 0-31):
- if (preg_match('/[\\x00-\\x1F]+/', $atom)) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Function to validate quoted string, which is:
- * quoted-string = <"> *(qtext/quoted-pair) <">
- *
- * @access private
- * @param string $qstring The string to check
- * @return boolean Success or failure.
- */
- function _validateQuotedString($qstring)
- {
- // Leading and trailing "
- $qstring = substr($qstring, 1, -1);
-
- // Perform check, removing quoted characters first.
- return !preg_match('/[\x0D\\\\"]/', preg_replace('/\\\\./', '', $qstring));
- }
-
- /**
- * Function to validate a mailbox, which is:
- * mailbox = addr-spec ; simple address
- * / phrase route-addr ; name and route-addr
- *
- * @access public
- * @param string &$mailbox The string to check.
- * @return boolean Success or failure.
- */
- function validateMailbox(&$mailbox)
- {
- // A couple of defaults.
- $phrase = '';
- $comment = '';
- $comments = array();
-
- // Catch any RFC822 comments and store them separately.
- $_mailbox = $mailbox;
- while (strlen(trim($_mailbox)) > 0) {
- $parts = explode('(', $_mailbox);
- $before_comment = $this->_splitCheck($parts, '(');
- if ($before_comment != $_mailbox) {
- // First char should be a (.
- $comment = substr(str_replace($before_comment, '', $_mailbox), 1);
- $parts = explode(')', $comment);
- $comment = $this->_splitCheck($parts, ')');
- $comments[] = $comment;
-
- // +2 is for the brackets
- $_mailbox = substr($_mailbox, strpos($_mailbox, '('.$comment)+strlen($comment)+2);
- } else {
- break;
- }
- }
-
- foreach ($comments as $comment) {
- $mailbox = str_replace("($comment)", '', $mailbox);
- }
-
- $mailbox = trim($mailbox);
-
- // Check for name + route-addr
- if (substr($mailbox, -1) == '>' && substr($mailbox, 0, 1) != '<') {
- $parts = explode('<', $mailbox);
- $name = $this->_splitCheck($parts, '<');
-
- $phrase = trim($name);
- $route_addr = trim(substr($mailbox, strlen($name.'<'), -1));
-
- if ($this->_validatePhrase($phrase) === false || ($route_addr = $this->_validateRouteAddr($route_addr)) === false) {
- return false;
- }
-
- // Only got addr-spec
- } else {
- // First snip angle brackets if present.
- if (substr($mailbox, 0, 1) == '<' && substr($mailbox, -1) == '>') {
- $addr_spec = substr($mailbox, 1, -1);
- } else {
- $addr_spec = $mailbox;
- }
-
- if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
- return false;
- }
- }
-
- // Construct the object that will be returned.
- $mbox = new stdClass();
-
- // Add the phrase (even if empty) and comments
- $mbox->personal = $phrase;
- $mbox->comment = isset($comments) ? $comments : array();
-
- if (isset($route_addr)) {
- $mbox->mailbox = $route_addr['local_part'];
- $mbox->host = $route_addr['domain'];
- $route_addr['adl'] !== '' ? $mbox->adl = $route_addr['adl'] : '';
- } else {
- $mbox->mailbox = $addr_spec['local_part'];
- $mbox->host = $addr_spec['domain'];
- }
-
- $mailbox = $mbox;
- return true;
- }
-
- /**
- * This function validates a route-addr which is:
- * route-addr = "<" [route] addr-spec ">"
- *
- * Angle brackets have already been removed at the point of
- * getting to this function.
- *
- * @access private
- * @param string $route_addr The string to check.
- * @return mixed False on failure, or an array containing validated address/route information on success.
- */
- function _validateRouteAddr($route_addr)
- {
- // Check for colon.
- if (strpos($route_addr, ':') !== false) {
- $parts = explode(':', $route_addr);
- $route = $this->_splitCheck($parts, ':');
- } else {
- $route = $route_addr;
- }
-
- // If $route is same as $route_addr then the colon was in
- // quotes or brackets or, of course, non existent.
- if ($route === $route_addr){
- unset($route);
- $addr_spec = $route_addr;
- if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
- return false;
- }
- } else {
- // Validate route part.
- if (($route = $this->_validateRoute($route)) === false) {
- return false;
- }
-
- $addr_spec = substr($route_addr, strlen($route . ':'));
-
- // Validate addr-spec part.
- if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
- return false;
- }
- }
-
- if (isset($route)) {
- $return['adl'] = $route;
- } else {
- $return['adl'] = '';
- }
-
- $return = array_merge($return, $addr_spec);
- return $return;
- }
-
- /**
- * Function to validate a route, which is:
- * route = 1#("@" domain) ":"
- *
- * @access private
- * @param string $route The string to check.
- * @return mixed False on failure, or the validated $route on success.
- */
- function _validateRoute($route)
- {
- // Split on comma.
- $domains = explode(',', trim($route));
-
- foreach ($domains as $domain) {
- $domain = str_replace('@', '', trim($domain));
- if (!$this->_validateDomain($domain)) return false;
- }
-
- return $route;
- }
-
- /**
- * Function to validate a domain, though this is not quite what
- * you expect of a strict internet domain.
- *
- * domain = sub-domain *("." sub-domain)
- *
- * @access private
- * @param string $domain The string to check.
- * @return mixed False on failure, or the validated domain on success.
- */
- function _validateDomain($domain)
- {
- // Note the different use of $subdomains and $sub_domains
- $subdomains = explode('.', $domain);
-
- while (count($subdomains) > 0) {
- $sub_domains[] = $this->_splitCheck($subdomains, '.');
- for ($i = 0; $i < $this->index + 1; $i++)
- array_shift($subdomains);
- }
-
- foreach ($sub_domains as $sub_domain) {
- if (!$this->_validateSubdomain(trim($sub_domain)))
- return false;
- }
-
- // Managed to get here, so return input.
- return $domain;
- }
-
- /**
- * Function to validate a subdomain:
- * subdomain = domain-ref / domain-literal
- *
- * @access private
- * @param string $subdomain The string to check.
- * @return boolean Success or failure.
- */
- function _validateSubdomain($subdomain)
- {
- if (preg_match('|^\[(.*)]$|', $subdomain, $arr)){
- if (!$this->_validateDliteral($arr[1])) return false;
- } else {
- if (!$this->_validateAtom($subdomain)) return false;
- }
-
- // Got here, so return successful.
- return true;
- }
-
- /**
- * Function to validate a domain literal:
- * domain-literal = "[" *(dtext / quoted-pair) "]"
- *
- * @access private
- * @param string $dliteral The string to check.
- * @return boolean Success or failure.
- */
- function _validateDliteral($dliteral)
- {
- return !preg_match('/(.)[][\x0D\\\\]/', $dliteral, $matches) && $matches[1] != '\\';
- }
-
- /**
- * Function to validate an addr-spec.
- *
- * addr-spec = local-part "@" domain
- *
- * @access private
- * @param string $addr_spec The string to check.
- * @return mixed False on failure, or the validated addr-spec on success.
- */
- function _validateAddrSpec($addr_spec)
- {
- $addr_spec = trim($addr_spec);
-
- // Split on @ sign if there is one.
- if (strpos($addr_spec, '@') !== false) {
- $parts = explode('@', $addr_spec);
- $local_part = $this->_splitCheck($parts, '@');
- $domain = substr($addr_spec, strlen($local_part . '@'));
-
- // No @ sign so assume the default domain.
- } else {
- $local_part = $addr_spec;
- $domain = $this->default_domain;
- }
-
- if (($local_part = $this->_validateLocalPart($local_part)) === false) return false;
- if (($domain = $this->_validateDomain($domain)) === false) return false;
-
- // Got here so return successful.
- return array('local_part' => $local_part, 'domain' => $domain);
- }
-
- /**
- * Function to validate the local part of an address:
- * local-part = word *("." word)
- *
- * @access private
- * @param string $local_part
- * @return mixed False on failure, or the validated local part on success.
- */
- function _validateLocalPart($local_part)
- {
- $parts = explode('.', $local_part);
- $words = array();
-
- // Split the local_part into words.
- while (count($parts) > 0){
- $words[] = $this->_splitCheck($parts, '.');
- for ($i = 0; $i < $this->index + 1; $i++) {
- array_shift($parts);
- }
- }
-
- // Validate each word.
- foreach ($words as $word) {
- // If this word contains an unquoted space, it is invalid. (6.2.4)
- if (strpos($word, ' ') && $word[0] !== '"')
- {
- return false;
- }
-
- if ($this->_validatePhrase(trim($word)) === false) return false;
- }
-
- // Managed to get here, so return the input.
- return $local_part;
- }
-
- /**
- * Returns an approximate count of how many addresses are in the
- * given string. This is APPROXIMATE as it only splits based on a
- * comma which has no preceding backslash. Could be useful as
- * large amounts of addresses will end up producing *large*
- * structures when used with parseAddressList().
- *
- * @param string $data Addresses to count
- * @return int Approximate count
- */
- function approximateCount($data)
- {
- return count(preg_split('/(?@. This can be sufficient for most
- * people. Optional stricter mode can be utilised which restricts
- * mailbox characters allowed to alphanumeric, full stop, hyphen
- * and underscore.
- *
- * @param string $data Address to check
- * @param boolean $strict Optional stricter mode
- * @return mixed False if it fails, an indexed array
- * username/domain if it matches
- */
- function isValidInetAddress($data, $strict = false)
- {
- $regex = $strict ? '/^([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i' : '/^([*+!.$|\'\\%\/0-9a-z^_`{}=?~:-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})$/i';
- if (preg_match($regex, trim($data), $matches)) {
- return array($matches[1], $matches[2]);
- } else {
- return false;
- }
- }
-
-}
diff --git a/data/module/Mail/mail.php b/data/module/Mail/mail.php
deleted file mode 100644
index 17547064259..00000000000
--- a/data/module/Mail/mail.php
+++ /dev/null
@@ -1,168 +0,0 @@
-
- * @copyright 2010 Chuck Hagenbuch
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id$
- * @link http://pear.php.net/package/Mail/
- */
-
-/**
- * internal PHP-mail() implementation of the PEAR Mail:: interface.
- * @package Mail
- * @version $Revision$
- */
-class Mail_mail extends Mail {
-
- /**
- * Any arguments to pass to the mail() function.
- * @var string
- */
- var $_params = '';
-
- /**
- * Constructor.
- *
- * Instantiates a new Mail_mail:: object based on the parameters
- * passed in.
- *
- * @param array $params Extra arguments for the mail() function.
- */
- function Mail_mail($params = null)
- {
- // The other mail implementations accept parameters as arrays.
- // In the interest of being consistent, explode an array into
- // a string of parameter arguments.
- if (is_array($params)) {
- $this->_params = join(' ', $params);
- } else {
- $this->_params = $params;
- }
-
- /* Because the mail() function may pass headers as command
- * line arguments, we can't guarantee the use of the standard
- * "\r\n" separator. Instead, we use the system's native line
- * separator. */
- if (defined('PHP_EOL')) {
- $this->sep = PHP_EOL;
- } else {
- $this->sep = (strpos(PHP_OS, 'WIN') === false) ? "\n" : "\r\n";
- }
- }
-
- /**
- * Implements Mail_mail::send() function using php's built-in mail()
- * command.
- *
- * @param mixed $recipients Either a comma-seperated list of recipients
- * (RFC822 compliant), or an array of recipients,
- * each RFC822 valid. This may contain recipients not
- * specified in the headers, for Bcc:, resending
- * messages, etc.
- *
- * @param array $headers The array of headers to send with the mail, in an
- * associative array, where the array key is the
- * header name (ie, 'Subject'), and the array value
- * is the header value (ie, 'test'). The header
- * produced from those values would be 'Subject:
- * test'.
- *
- * @param string $body The full text of the message body, including any
- * Mime parts, etc.
- *
- * @return mixed Returns true on success, or a PEAR_Error
- * containing a descriptive error message on
- * failure.
- *
- * @access public
- */
- function send($recipients, $headers, $body)
- {
- if (!is_array($headers)) {
- return PEAR::raiseError('$headers must be an array');
- }
-
- $result = $this->_sanitizeHeaders($headers);
- if (is_a($result, 'PEAR_Error')) {
- return $result;
- }
-
- // If we're passed an array of recipients, implode it.
- if (is_array($recipients)) {
- $recipients = implode(', ', $recipients);
- }
-
- // Get the Subject out of the headers array so that we can
- // pass it as a seperate argument to mail().
- $subject = '';
- if (isset($headers['Subject'])) {
- $subject = $headers['Subject'];
- unset($headers['Subject']);
- }
-
- // Also remove the To: header. The mail() function will add its own
- // To: header based on the contents of $recipients.
- unset($headers['To']);
-
- // Flatten the headers out.
- $headerElements = $this->prepareHeaders($headers);
- if (is_a($headerElements, 'PEAR_Error')) {
- return $headerElements;
- }
- list(, $text_headers) = $headerElements;
-
- // We only use mail()'s optional fifth parameter if the additional
- // parameters have been provided and we're not running in safe mode.
- if (empty($this->_params) || ini_get('safe_mode')) {
- $result = mail($recipients, $subject, $body, $text_headers);
- } else {
- $result = mail($recipients, $subject, $body, $text_headers,
- $this->_params);
- }
-
- // If the mail() function returned failure, we need to create a
- // PEAR_Error object and return it instead of the boolean result.
- if ($result === false) {
- $result = PEAR::raiseError('mail() returned failure');
- }
-
- return $result;
- }
-
-}
diff --git a/data/module/Mail/mime.php b/data/module/Mail/mime.php
deleted file mode 100644
index c5dd305fab8..00000000000
--- a/data/module/Mail/mime.php
+++ /dev/null
@@ -1,1468 +0,0 @@
-
- * Copyright (c) 2003-2006, PEAR
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * - Neither the name of the authors, nor the names of its contributors
- * may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- * @category Mail
- * @package Mail_Mime
- * @author Richard Heyes
- * @author Tomas V.V. Cox
- * @author Cipriano Groenendal
- * @author Sean Coates
- * @author Aleksander Machniak
- * @copyright 2003-2006 PEAR
- * @license http://www.opensource.org/licenses/bsd-license.php BSD License
- * @version CVS: $Id$
- * @link http://pear.php.net/package/Mail_mime
- *
- * This class is based on HTML Mime Mail class from
- * Richard Heyes which was based also
- * in the mime_mail.class by Tobias Ratschiller
- * and Sascha Schumann
- */
-
-
-/**
- * require PEAR
- *
- * This package depends on PEAR to raise errors.
- */
-require_once 'PEAR.php';
-
-/**
- * require Mail_mimePart
- *
- * Mail_mimePart contains the code required to
- * create all the different parts a mail can
- * consist of.
- */
-require_once 'Mail/mimePart.php';
-
-
-/**
- * The Mail_Mime class provides an OO interface to create MIME
- * enabled email messages. This way you can create emails that
- * contain plain-text bodies, HTML bodies, attachments, inline
- * images and specific headers.
- *
- * @category Mail
- * @package Mail_Mime
- * @author Richard Heyes
- * @author Tomas V.V. Cox
- * @author Cipriano Groenendal
- * @author Sean Coates
- * @copyright 2003-2006 PEAR
- * @license http://www.opensource.org/licenses/bsd-license.php BSD License
- * @version Release: @package_version@
- * @link http://pear.php.net/package/Mail_mime
- */
-class Mail_mime
-{
- /**
- * Contains the plain text part of the email
- *
- * @var string
- * @access private
- */
- var $_txtbody;
-
- /**
- * Contains the html part of the email
- *
- * @var string
- * @access private
- */
- var $_htmlbody;
-
- /**
- * list of the attached images
- *
- * @var array
- * @access private
- */
- var $_html_images = array();
-
- /**
- * list of the attachements
- *
- * @var array
- * @access private
- */
- var $_parts = array();
-
- /**
- * Headers for the mail
- *
- * @var array
- * @access private
- */
- var $_headers = array();
-
- /**
- * Build parameters
- *
- * @var array
- * @access private
- */
- var $_build_params = array(
- // What encoding to use for the headers
- // Options: quoted-printable or base64
- 'head_encoding' => 'quoted-printable',
- // What encoding to use for plain text
- // Options: 7bit, 8bit, base64, or quoted-printable
- 'text_encoding' => 'quoted-printable',
- // What encoding to use for html
- // Options: 7bit, 8bit, base64, or quoted-printable
- 'html_encoding' => 'quoted-printable',
- // The character set to use for html
- 'html_charset' => 'ISO-8859-1',
- // The character set to use for text
- 'text_charset' => 'ISO-8859-1',
- // The character set to use for headers
- 'head_charset' => 'ISO-8859-1',
- // End-of-line sequence
- 'eol' => "\r\n",
- // Delay attachment files IO until building the message
- 'delay_file_io' => false
- );
-
- /**
- * Constructor function
- *
- * @param mixed $params Build parameters that change the way the email
- * is built. Should be an associative array.
- * See $_build_params.
- *
- * @return void
- * @access public
- */
- function Mail_mime($params = array())
- {
- // Backward-compatible EOL setting
- if (is_string($params)) {
- $this->_build_params['eol'] = $params;
- } else if (defined('MAIL_MIME_CRLF') && !isset($params['eol'])) {
- $this->_build_params['eol'] = MAIL_MIME_CRLF;
- }
-
- // Update build parameters
- if (!empty($params) && is_array($params)) {
- while (list($key, $value) = each($params)) {
- $this->_build_params[$key] = $value;
- }
- }
- }
-
- /**
- * Set build parameter value
- *
- * @param string $name Parameter name
- * @param string $value Parameter value
- *
- * @return void
- * @access public
- * @since 1.6.0
- */
- function setParam($name, $value)
- {
- $this->_build_params[$name] = $value;
- }
-
- /**
- * Get build parameter value
- *
- * @param string $name Parameter name
- *
- * @return mixed Parameter value
- * @access public
- * @since 1.6.0
- */
- function getParam($name)
- {
- return isset($this->_build_params[$name]) ? $this->_build_params[$name] : null;
- }
-
- /**
- * Accessor function to set the body text. Body text is used if
- * it's not an html mail being sent or else is used to fill the
- * text/plain part that emails clients who don't support
- * html should show.
- *
- * @param string $data Either a string or
- * the file name with the contents
- * @param bool $isfile If true the first param should be treated
- * as a file name, else as a string (default)
- * @param bool $append If true the text or file is appended to
- * the existing body, else the old body is
- * overwritten
- *
- * @return mixed True on success or PEAR_Error object
- * @access public
- */
- function setTXTBody($data, $isfile = false, $append = false)
- {
- if (!$isfile) {
- if (!$append) {
- $this->_txtbody = $data;
- } else {
- $this->_txtbody .= $data;
- }
- } else {
- $cont = $this->_file2str($data);
- if (PEAR::isError($cont)) {
- return $cont;
- }
- if (!$append) {
- $this->_txtbody = $cont;
- } else {
- $this->_txtbody .= $cont;
- }
- }
- return true;
- }
-
- /**
- * Get message text body
- *
- * @return string Text body
- * @access public
- * @since 1.6.0
- */
- function getTXTBody()
- {
- return $this->_txtbody;
- }
-
- /**
- * Adds a html part to the mail.
- *
- * @param string $data Either a string or the file name with the
- * contents
- * @param bool $isfile A flag that determines whether $data is a
- * filename, or a string(false, default)
- *
- * @return bool True on success
- * @access public
- */
- function setHTMLBody($data, $isfile = false)
- {
- if (!$isfile) {
- $this->_htmlbody = $data;
- } else {
- $cont = $this->_file2str($data);
- if (PEAR::isError($cont)) {
- return $cont;
- }
- $this->_htmlbody = $cont;
- }
-
- return true;
- }
-
- /**
- * Get message HTML body
- *
- * @return string HTML body
- * @access public
- * @since 1.6.0
- */
- function getHTMLBody()
- {
- return $this->_htmlbody;
- }
-
- /**
- * Adds an image to the list of embedded images.
- *
- * @param string $file The image file name OR image data itself
- * @param string $c_type The content type
- * @param string $name The filename of the image.
- * Only used if $file is the image data.
- * @param bool $isfile Whether $file is a filename or not.
- * Defaults to true
- * @param string $content_id Desired Content-ID of MIME part
- * Defaults to generated unique ID
- *
- * @return bool True on success
- * @access public
- */
- function addHTMLImage($file,
- $c_type='application/octet-stream',
- $name = '',
- $isfile = true,
- $content_id = null
- ) {
- $bodyfile = null;
-
- if ($isfile) {
- // Don't load file into memory
- if ($this->_build_params['delay_file_io']) {
- $filedata = null;
- $bodyfile = $file;
- } else {
- if (PEAR::isError($filedata = $this->_file2str($file))) {
- return $filedata;
- }
- }
- $filename = ($name ? $name : $file);
- } else {
- $filedata = $file;
- $filename = $name;
- }
-
- if (!$content_id) {
- $content_id = md5(uniqid(time()));
- }
-
- $this->_html_images[] = array(
- 'body' => $filedata,
- 'body_file' => $bodyfile,
- 'name' => $filename,
- 'c_type' => $c_type,
- 'cid' => $content_id
- );
-
- return true;
- }
-
- /**
- * Adds a file to the list of attachments.
- *
- * @param string $file The file name of the file to attach
- * or the file contents itself
- * @param string $c_type The content type
- * @param string $name The filename of the attachment
- * Only use if $file is the contents
- * @param bool $isfile Whether $file is a filename or not. Defaults to true
- * @param string $encoding The type of encoding to use. Defaults to base64.
- * Possible values: 7bit, 8bit, base64 or quoted-printable.
- * @param string $disposition The content-disposition of this file
- * Defaults to attachment.
- * Possible values: attachment, inline.
- * @param string $charset The character set of attachment's content.
- * @param string $language The language of the attachment
- * @param string $location The RFC 2557.4 location of the attachment
- * @param string $n_encoding Encoding of the attachment's name in Content-Type
- * By default filenames are encoded using RFC2231 method
- * Here you can set RFC2047 encoding (quoted-printable
- * or base64) instead
- * @param string $f_encoding Encoding of the attachment's filename
- * in Content-Disposition header.
- * @param string $description Content-Description header
- * @param string $h_charset The character set of the headers e.g. filename
- * If not specified, $charset will be used
- *
- * @return mixed True on success or PEAR_Error object
- * @access public
- */
- function addAttachment($file,
- $c_type = 'application/octet-stream',
- $name = '',
- $isfile = true,
- $encoding = 'base64',
- $disposition = 'attachment',
- $charset = '',
- $language = '',
- $location = '',
- $n_encoding = null,
- $f_encoding = null,
- $description = '',
- $h_charset = null
- ) {
- $bodyfile = null;
-
- if ($isfile) {
- // Don't load file into memory
- if ($this->_build_params['delay_file_io']) {
- $filedata = null;
- $bodyfile = $file;
- } else {
- if (PEAR::isError($filedata = $this->_file2str($file))) {
- return $filedata;
- }
- }
- // Force the name the user supplied, otherwise use $file
- $filename = ($name ? $name : $file);
- } else {
- $filedata = $file;
- $filename = $name;
- }
-
- if (!strlen($filename)) {
- $msg = "The supplied filename for the attachment can't be empty";
- $err = PEAR::raiseError($msg);
- return $err;
- }
- $filename = $this->_basename($filename);
-
- $this->_parts[] = array(
- 'body' => $filedata,
- 'body_file' => $bodyfile,
- 'name' => $filename,
- 'c_type' => $c_type,
- 'charset' => $charset,
- 'encoding' => $encoding,
- 'language' => $language,
- 'location' => $location,
- 'disposition' => $disposition,
- 'description' => $description,
- 'name_encoding' => $n_encoding,
- 'filename_encoding' => $f_encoding,
- 'headers_charset' => $h_charset,
- );
-
- return true;
- }
-
- /**
- * Get the contents of the given file name as string
- *
- * @param string $file_name Path of file to process
- *
- * @return string Contents of $file_name
- * @access private
- */
- function &_file2str($file_name)
- {
- // Check state of file and raise an error properly
- if (!file_exists($file_name)) {
- $err = PEAR::raiseError('File not found: ' . $file_name);
- return $err;
- }
- if (!is_file($file_name)) {
- $err = PEAR::raiseError('Not a regular file: ' . $file_name);
- return $err;
- }
- if (!is_readable($file_name)) {
- $err = PEAR::raiseError('File is not readable: ' . $file_name);
- return $err;
- }
-
- // Temporarily reset magic_quotes_runtime and read file contents
- if ($magic_quote_setting = get_magic_quotes_runtime()) {
- @ini_set('magic_quotes_runtime', 0);
- }
- $cont = file_get_contents($file_name);
- if ($magic_quote_setting) {
- @ini_set('magic_quotes_runtime', $magic_quote_setting);
- }
-
- return $cont;
- }
-
- /**
- * Adds a text subpart to the mimePart object and
- * returns it during the build process.
- *
- * @param mixed &$obj The object to add the part to, or
- * null if a new object is to be created.
- * @param string $text The text to add.
- *
- * @return object The text mimePart object
- * @access private
- */
- function &_addTextPart(&$obj, $text)
- {
- $params['content_type'] = 'text/plain';
- $params['encoding'] = $this->_build_params['text_encoding'];
- $params['charset'] = $this->_build_params['text_charset'];
- $params['eol'] = $this->_build_params['eol'];
-
- if (is_object($obj)) {
- $ret = $obj->addSubpart($text, $params);
- return $ret;
- } else {
- $ret = new Mail_mimePart($text, $params);
- return $ret;
- }
- }
-
- /**
- * Adds a html subpart to the mimePart object and
- * returns it during the build process.
- *
- * @param mixed &$obj The object to add the part to, or
- * null if a new object is to be created.
- *
- * @return object The html mimePart object
- * @access private
- */
- function &_addHtmlPart(&$obj)
- {
- $params['content_type'] = 'text/html';
- $params['encoding'] = $this->_build_params['html_encoding'];
- $params['charset'] = $this->_build_params['html_charset'];
- $params['eol'] = $this->_build_params['eol'];
-
- if (is_object($obj)) {
- $ret = $obj->addSubpart($this->_htmlbody, $params);
- return $ret;
- } else {
- $ret = new Mail_mimePart($this->_htmlbody, $params);
- return $ret;
- }
- }
-
- /**
- * Creates a new mimePart object, using multipart/mixed as
- * the initial content-type and returns it during the
- * build process.
- *
- * @return object The multipart/mixed mimePart object
- * @access private
- */
- function &_addMixedPart()
- {
- $params = array();
- $params['content_type'] = 'multipart/mixed';
- $params['eol'] = $this->_build_params['eol'];
-
- // Create empty multipart/mixed Mail_mimePart object to return
- $ret = new Mail_mimePart('', $params);
- return $ret;
- }
-
- /**
- * Adds a multipart/alternative part to a mimePart
- * object (or creates one), and returns it during
- * the build process.
- *
- * @param mixed &$obj The object to add the part to, or
- * null if a new object is to be created.
- *
- * @return object The multipart/mixed mimePart object
- * @access private
- */
- function &_addAlternativePart(&$obj)
- {
- $params['content_type'] = 'multipart/alternative';
- $params['eol'] = $this->_build_params['eol'];
-
- if (is_object($obj)) {
- return $obj->addSubpart('', $params);
- } else {
- $ret = new Mail_mimePart('', $params);
- return $ret;
- }
- }
-
- /**
- * Adds a multipart/related part to a mimePart
- * object (or creates one), and returns it during
- * the build process.
- *
- * @param mixed &$obj The object to add the part to, or
- * null if a new object is to be created
- *
- * @return object The multipart/mixed mimePart object
- * @access private
- */
- function &_addRelatedPart(&$obj)
- {
- $params['content_type'] = 'multipart/related';
- $params['eol'] = $this->_build_params['eol'];
-
- if (is_object($obj)) {
- return $obj->addSubpart('', $params);
- } else {
- $ret = new Mail_mimePart('', $params);
- return $ret;
- }
- }
-
- /**
- * Adds an html image subpart to a mimePart object
- * and returns it during the build process.
- *
- * @param object &$obj The mimePart to add the image to
- * @param array $value The image information
- *
- * @return object The image mimePart object
- * @access private
- */
- function &_addHtmlImagePart(&$obj, $value)
- {
- $params['content_type'] = $value['c_type'];
- $params['encoding'] = 'base64';
- $params['disposition'] = 'inline';
- $params['filename'] = $value['name'];
- $params['cid'] = $value['cid'];
- $params['body_file'] = $value['body_file'];
- $params['eol'] = $this->_build_params['eol'];
-
- if (!empty($value['name_encoding'])) {
- $params['name_encoding'] = $value['name_encoding'];
- }
- if (!empty($value['filename_encoding'])) {
- $params['filename_encoding'] = $value['filename_encoding'];
- }
-
- $ret = $obj->addSubpart($value['body'], $params);
- return $ret;
- }
-
- /**
- * Adds an attachment subpart to a mimePart object
- * and returns it during the build process.
- *
- * @param object &$obj The mimePart to add the image to
- * @param array $value The attachment information
- *
- * @return object The image mimePart object
- * @access private
- */
- function &_addAttachmentPart(&$obj, $value)
- {
- $params['eol'] = $this->_build_params['eol'];
- $params['filename'] = $value['name'];
- $params['encoding'] = $value['encoding'];
- $params['content_type'] = $value['c_type'];
- $params['body_file'] = $value['body_file'];
- $params['disposition'] = isset($value['disposition']) ?
- $value['disposition'] : 'attachment';
-
- // content charset
- if (!empty($value['charset'])) {
- $params['charset'] = $value['charset'];
- }
- // headers charset (filename, description)
- if (!empty($value['headers_charset'])) {
- $params['headers_charset'] = $value['headers_charset'];
- }
- if (!empty($value['language'])) {
- $params['language'] = $value['language'];
- }
- if (!empty($value['location'])) {
- $params['location'] = $value['location'];
- }
- if (!empty($value['name_encoding'])) {
- $params['name_encoding'] = $value['name_encoding'];
- }
- if (!empty($value['filename_encoding'])) {
- $params['filename_encoding'] = $value['filename_encoding'];
- }
- if (!empty($value['description'])) {
- $params['description'] = $value['description'];
- }
-
- $ret = $obj->addSubpart($value['body'], $params);
- return $ret;
- }
-
- /**
- * Returns the complete e-mail, ready to send using an alternative
- * mail delivery method. Note that only the mailpart that is made
- * with Mail_Mime is created. This means that,
- * YOU WILL HAVE NO TO: HEADERS UNLESS YOU SET IT YOURSELF
- * using the $headers parameter!
- *
- * @param string $separation The separation between these two parts.
- * @param array $params The Build parameters passed to the
- * &get() function. See &get for more info.
- * @param array $headers The extra headers that should be passed
- * to the &headers() function.
- * See that function for more info.
- * @param bool $overwrite Overwrite the existing headers with new.
- *
- * @return mixed The complete e-mail or PEAR error object
- * @access public
- */
- function getMessage($separation = null, $params = null, $headers = null,
- $overwrite = false
- ) {
- if ($separation === null) {
- $separation = $this->_build_params['eol'];
- }
-
- $body = $this->get($params);
-
- if (PEAR::isError($body)) {
- return $body;
- }
-
- $head = $this->txtHeaders($headers, $overwrite);
- $mail = $head . $separation . $body;
- return $mail;
- }
-
- /**
- * Returns the complete e-mail body, ready to send using an alternative
- * mail delivery method.
- *
- * @param array $params The Build parameters passed to the
- * &get() function. See &get for more info.
- *
- * @return mixed The e-mail body or PEAR error object
- * @access public
- * @since 1.6.0
- */
- function getMessageBody($params = null)
- {
- return $this->get($params, null, true);
- }
-
- /**
- * Writes (appends) the complete e-mail into file.
- *
- * @param string $filename Output file location
- * @param array $params The Build parameters passed to the
- * &get() function. See &get for more info.
- * @param array $headers The extra headers that should be passed
- * to the &headers() function.
- * See that function for more info.
- * @param bool $overwrite Overwrite the existing headers with new.
- *
- * @return mixed True or PEAR error object
- * @access public
- * @since 1.6.0
- */
- function saveMessage($filename, $params = null, $headers = null, $overwrite = false)
- {
- // Check state of file and raise an error properly
- if (file_exists($filename) && !is_writable($filename)) {
- $err = PEAR::raiseError('File is not writable: ' . $filename);
- return $err;
- }
-
- // Temporarily reset magic_quotes_runtime and read file contents
- if ($magic_quote_setting = get_magic_quotes_runtime()) {
- @ini_set('magic_quotes_runtime', 0);
- }
-
- if (!($fh = fopen($filename, 'ab'))) {
- $err = PEAR::raiseError('Unable to open file: ' . $filename);
- return $err;
- }
-
- // Write message headers into file (skipping Content-* headers)
- $head = $this->txtHeaders($headers, $overwrite, true);
- if (fwrite($fh, $head) === false) {
- $err = PEAR::raiseError('Error writing to file: ' . $filename);
- return $err;
- }
-
- fclose($fh);
-
- if ($magic_quote_setting) {
- @ini_set('magic_quotes_runtime', $magic_quote_setting);
- }
-
- // Write the rest of the message into file
- $res = $this->get($params, $filename);
-
- return $res ? $res : true;
- }
-
- /**
- * Writes (appends) the complete e-mail body into file.
- *
- * @param string $filename Output file location
- * @param array $params The Build parameters passed to the
- * &get() function. See &get for more info.
- *
- * @return mixed True or PEAR error object
- * @access public
- * @since 1.6.0
- */
- function saveMessageBody($filename, $params = null)
- {
- // Check state of file and raise an error properly
- if (file_exists($filename) && !is_writable($filename)) {
- $err = PEAR::raiseError('File is not writable: ' . $filename);
- return $err;
- }
-
- // Temporarily reset magic_quotes_runtime and read file contents
- if ($magic_quote_setting = get_magic_quotes_runtime()) {
- @ini_set('magic_quotes_runtime', 0);
- }
-
- if (!($fh = fopen($filename, 'ab'))) {
- $err = PEAR::raiseError('Unable to open file: ' . $filename);
- return $err;
- }
-
- // Write the rest of the message into file
- $res = $this->get($params, $filename, true);
-
- return $res ? $res : true;
- }
-
- /**
- * Builds the multipart message from the list ($this->_parts) and
- * returns the mime content.
- *
- * @param array $params Build parameters that change the way the email
- * is built. Should be associative. See $_build_params.
- * @param resource $filename Output file where to save the message instead of
- * returning it
- * @param boolean $skip_head True if you want to return/save only the message
- * without headers
- *
- * @return mixed The MIME message content string, null or PEAR error object
- * @access public
- */
- function &get($params = null, $filename = null, $skip_head = false)
- {
- if (isset($params)) {
- while (list($key, $value) = each($params)) {
- $this->_build_params[$key] = $value;
- }
- }
-
- if (isset($this->_headers['From'])) {
- // Bug #11381: Illegal characters in domain ID
- if (preg_match('#(@[0-9a-zA-Z\-\.]+)#', $this->_headers['From'], $matches)) {
- $domainID = $matches[1];
- } else {
- $domainID = '@localhost';
- }
- foreach ($this->_html_images as $i => $img) {
- $cid = $this->_html_images[$i]['cid'];
- if (!preg_match('#'.preg_quote($domainID).'$#', $cid)) {
- $this->_html_images[$i]['cid'] = $cid . $domainID;
- }
- }
- }
-
- if (count($this->_html_images) && isset($this->_htmlbody)) {
- foreach ($this->_html_images as $key => $value) {
- $regex = array();
- $regex[] = '#(\s)((?i)src|background|href(?-i))\s*=\s*(["\']?)' .
- preg_quote($value['name'], '#') . '\3#';
- $regex[] = '#(?i)url(?-i)\(\s*(["\']?)' .
- preg_quote($value['name'], '#') . '\1\s*\)#';
-
- $rep = array();
- $rep[] = '\1\2=\3cid:' . $value['cid'] .'\3';
- $rep[] = 'url(\1cid:' . $value['cid'] . '\1)';
-
- $this->_htmlbody = preg_replace($regex, $rep, $this->_htmlbody);
- $this->_html_images[$key]['name']
- = $this->_basename($this->_html_images[$key]['name']);
- }
- }
-
- $this->_checkParams();
-
- $null = null;
- $attachments = count($this->_parts) ? true : false;
- $html_images = count($this->_html_images) ? true : false;
- $html = strlen($this->_htmlbody) ? true : false;
- $text = (!$html && strlen($this->_txtbody)) ? true : false;
-
- switch (true) {
- case $text && !$attachments:
- $message =& $this->_addTextPart($null, $this->_txtbody);
- break;
-
- case !$text && !$html && $attachments:
- $message =& $this->_addMixedPart();
- for ($i = 0; $i < count($this->_parts); $i++) {
- $this->_addAttachmentPart($message, $this->_parts[$i]);
- }
- break;
-
- case $text && $attachments:
- $message =& $this->_addMixedPart();
- $this->_addTextPart($message, $this->_txtbody);
- for ($i = 0; $i < count($this->_parts); $i++) {
- $this->_addAttachmentPart($message, $this->_parts[$i]);
- }
- break;
-
- case $html && !$attachments && !$html_images:
- if (isset($this->_txtbody)) {
- $message =& $this->_addAlternativePart($null);
- $this->_addTextPart($message, $this->_txtbody);
- $this->_addHtmlPart($message);
- } else {
- $message =& $this->_addHtmlPart($null);
- }
- break;
-
- case $html && !$attachments && $html_images:
- // * Content-Type: multipart/alternative;
- // * text
- // * Content-Type: multipart/related;
- // * html
- // * image...
- if (isset($this->_txtbody)) {
- $message =& $this->_addAlternativePart($null);
- $this->_addTextPart($message, $this->_txtbody);
-
- $ht =& $this->_addRelatedPart($message);
- $this->_addHtmlPart($ht);
- for ($i = 0; $i < count($this->_html_images); $i++) {
- $this->_addHtmlImagePart($ht, $this->_html_images[$i]);
- }
- } else {
- // * Content-Type: multipart/related;
- // * html
- // * image...
- $message =& $this->_addRelatedPart($null);
- $this->_addHtmlPart($message);
- for ($i = 0; $i < count($this->_html_images); $i++) {
- $this->_addHtmlImagePart($message, $this->_html_images[$i]);
- }
- }
- /*
- // #13444, #9725: the code below was a non-RFC compliant hack
- // * Content-Type: multipart/related;
- // * Content-Type: multipart/alternative;
- // * text
- // * html
- // * image...
- $message =& $this->_addRelatedPart($null);
- if (isset($this->_txtbody)) {
- $alt =& $this->_addAlternativePart($message);
- $this->_addTextPart($alt, $this->_txtbody);
- $this->_addHtmlPart($alt);
- } else {
- $this->_addHtmlPart($message);
- }
- for ($i = 0; $i < count($this->_html_images); $i++) {
- $this->_addHtmlImagePart($message, $this->_html_images[$i]);
- }
- */
- break;
-
- case $html && $attachments && !$html_images:
- $message =& $this->_addMixedPart();
- if (isset($this->_txtbody)) {
- $alt =& $this->_addAlternativePart($message);
- $this->_addTextPart($alt, $this->_txtbody);
- $this->_addHtmlPart($alt);
- } else {
- $this->_addHtmlPart($message);
- }
- for ($i = 0; $i < count($this->_parts); $i++) {
- $this->_addAttachmentPart($message, $this->_parts[$i]);
- }
- break;
-
- case $html && $attachments && $html_images:
- $message =& $this->_addMixedPart();
- if (isset($this->_txtbody)) {
- $alt =& $this->_addAlternativePart($message);
- $this->_addTextPart($alt, $this->_txtbody);
- $rel =& $this->_addRelatedPart($alt);
- } else {
- $rel =& $this->_addRelatedPart($message);
- }
- $this->_addHtmlPart($rel);
- for ($i = 0; $i < count($this->_html_images); $i++) {
- $this->_addHtmlImagePart($rel, $this->_html_images[$i]);
- }
- for ($i = 0; $i < count($this->_parts); $i++) {
- $this->_addAttachmentPart($message, $this->_parts[$i]);
- }
- break;
-
- }
-
- if (!isset($message)) {
- $ret = null;
- return $ret;
- }
-
- // Use saved boundary
- if (!empty($this->_build_params['boundary'])) {
- $boundary = $this->_build_params['boundary'];
- } else {
- $boundary = null;
- }
-
- // Write output to file
- if ($filename) {
- // Append mimePart message headers and body into file
- $headers = $message->encodeToFile($filename, $boundary, $skip_head);
- if (PEAR::isError($headers)) {
- return $headers;
- }
- $this->_headers = array_merge($this->_headers, $headers);
- $ret = null;
- return $ret;
- } else {
- $output = $message->encode($boundary, $skip_head);
- if (PEAR::isError($output)) {
- return $output;
- }
- $this->_headers = array_merge($this->_headers, $output['headers']);
- $body = $output['body'];
- return $body;
- }
- }
-
- /**
- * Returns an array with the headers needed to prepend to the email
- * (MIME-Version and Content-Type). Format of argument is:
- * $array['header-name'] = 'header-value';
- *
- * @param array $xtra_headers Assoc array with any extra headers (optional)
- * (Don't set Content-Type for multipart messages here!)
- * @param bool $overwrite Overwrite already existing headers.
- * @param bool $skip_content Don't return content headers: Content-Type,
- * Content-Disposition and Content-Transfer-Encoding
- *
- * @return array Assoc array with the mime headers
- * @access public
- */
- function &headers($xtra_headers = null, $overwrite = false, $skip_content = false)
- {
- // Add mime version header
- $headers['MIME-Version'] = '1.0';
-
- // Content-Type and Content-Transfer-Encoding headers should already
- // be present if get() was called, but we'll re-set them to make sure
- // we got them when called before get() or something in the message
- // has been changed after get() [#14780]
- if (!$skip_content) {
- $headers += $this->_contentHeaders();
- }
-
- if (!empty($xtra_headers)) {
- $headers = array_merge($headers, $xtra_headers);
- }
-
- if ($overwrite) {
- $this->_headers = array_merge($this->_headers, $headers);
- } else {
- $this->_headers = array_merge($headers, $this->_headers);
- }
-
- $headers = $this->_headers;
-
- if ($skip_content) {
- unset($headers['Content-Type']);
- unset($headers['Content-Transfer-Encoding']);
- unset($headers['Content-Disposition']);
- } else if (!empty($this->_build_params['ctype'])) {
- $headers['Content-Type'] = $this->_build_params['ctype'];
- }
-
- $encodedHeaders = $this->_encodeHeaders($headers);
- return $encodedHeaders;
- }
-
- /**
- * Get the text version of the headers
- * (usefull if you want to use the PHP mail() function)
- *
- * @param array $xtra_headers Assoc array with any extra headers (optional)
- * (Don't set Content-Type for multipart messages here!)
- * @param bool $overwrite Overwrite the existing headers with new.
- * @param bool $skip_content Don't return content headers: Content-Type,
- * Content-Disposition and Content-Transfer-Encoding
- *
- * @return string Plain text headers
- * @access public
- */
- function txtHeaders($xtra_headers = null, $overwrite = false, $skip_content = false)
- {
- $headers = $this->headers($xtra_headers, $overwrite, $skip_content);
-
- // Place Received: headers at the beginning of the message
- // Spam detectors often flag messages with it after the Subject: as spam
- if (isset($headers['Received'])) {
- $received = $headers['Received'];
- unset($headers['Received']);
- $headers = array('Received' => $received) + $headers;
- }
-
- $ret = '';
- $eol = $this->_build_params['eol'];
-
- foreach ($headers as $key => $val) {
- if (is_array($val)) {
- foreach ($val as $value) {
- $ret .= "$key: $value" . $eol;
- }
- } else {
- $ret .= "$key: $val" . $eol;
- }
- }
-
- return $ret;
- }
-
- /**
- * Sets message Content-Type header.
- * Use it to build messages with various content-types e.g. miltipart/raport
- * not supported by _contentHeaders() function.
- *
- * @param string $type Type name
- * @param array $params Hash array of header parameters
- *
- * @return void
- * @access public
- * @since 1.7.0
- */
- function setContentType($type, $params = array())
- {
- $header = $type;
-
- $eol = !empty($this->_build_params['eol'])
- ? $this->_build_params['eol'] : "\r\n";
-
- // add parameters
- $token_regexp = '#([^\x21,\x23-\x27,\x2A,\x2B,\x2D'
- . ',\x2E,\x30-\x39,\x41-\x5A,\x5E-\x7E])#';
- if (is_array($params)) {
- foreach ($params as $name => $value) {
- if ($name == 'boundary') {
- $this->_build_params['boundary'] = $value;
- }
- if (!preg_match($token_regexp, $value)) {
- $header .= ";$eol $name=$value";
- } else {
- $value = addcslashes($value, '\\"');
- $header .= ";$eol $name=\"$value\"";
- }
- }
- }
-
- // add required boundary parameter if not defined
- if (preg_match('/^multipart\//i', $type)) {
- if (empty($this->_build_params['boundary'])) {
- $this->_build_params['boundary'] = '=_' . md5(rand() . microtime());
- }
-
- $header .= ";$eol boundary=\"".$this->_build_params['boundary']."\"";
- }
-
- $this->_build_params['ctype'] = $header;
- }
-
- /**
- * Sets the Subject header
- *
- * @param string $subject String to set the subject to.
- *
- * @return void
- * @access public
- */
- function setSubject($subject)
- {
- $this->_headers['Subject'] = $subject;
- }
-
- /**
- * Set an email to the From (the sender) header
- *
- * @param string $email The email address to use
- *
- * @return void
- * @access public
- */
- function setFrom($email)
- {
- $this->_headers['From'] = $email;
- }
-
- /**
- * Add an email to the To header
- * (multiple calls to this method are allowed)
- *
- * @param string $email The email direction to add
- *
- * @return void
- * @access public
- */
- function addTo($email)
- {
- if (isset($this->_headers['To'])) {
- $this->_headers['To'] .= ", $email";
- } else {
- $this->_headers['To'] = $email;
- }
- }
-
- /**
- * Add an email to the Cc (carbon copy) header
- * (multiple calls to this method are allowed)
- *
- * @param string $email The email direction to add
- *
- * @return void
- * @access public
- */
- function addCc($email)
- {
- if (isset($this->_headers['Cc'])) {
- $this->_headers['Cc'] .= ", $email";
- } else {
- $this->_headers['Cc'] = $email;
- }
- }
-
- /**
- * Add an email to the Bcc (blank carbon copy) header
- * (multiple calls to this method are allowed)
- *
- * @param string $email The email direction to add
- *
- * @return void
- * @access public
- */
- function addBcc($email)
- {
- if (isset($this->_headers['Bcc'])) {
- $this->_headers['Bcc'] .= ", $email";
- } else {
- $this->_headers['Bcc'] = $email;
- }
- }
-
- /**
- * Since the PHP send function requires you to specify
- * recipients (To: header) separately from the other
- * headers, the To: header is not properly encoded.
- * To fix this, you can use this public method to
- * encode your recipients before sending to the send
- * function
- *
- * @param string $recipients A comma-delimited list of recipients
- *
- * @return string Encoded data
- * @access public
- */
- function encodeRecipients($recipients)
- {
- $input = array("To" => $recipients);
- $retval = $this->_encodeHeaders($input);
- return $retval["To"] ;
- }
-
- /**
- * Encodes headers as per RFC2047
- *
- * @param array $input The header data to encode
- * @param array $params Extra build parameters
- *
- * @return array Encoded data
- * @access private
- */
- function _encodeHeaders($input, $params = array())
- {
- $build_params = $this->_build_params;
- while (list($key, $value) = each($params)) {
- $build_params[$key] = $value;
- }
-
- foreach ($input as $hdr_name => $hdr_value) {
- if (is_array($hdr_value)) {
- foreach ($hdr_value as $idx => $value) {
- $input[$hdr_name][$idx] = $this->encodeHeader(
- $hdr_name, $value,
- $build_params['head_charset'], $build_params['head_encoding']
- );
- }
- } else {
- $input[$hdr_name] = $this->encodeHeader(
- $hdr_name, $hdr_value,
- $build_params['head_charset'], $build_params['head_encoding']
- );
- }
- }
-
- return $input;
- }
-
- /**
- * Encodes a header as per RFC2047
- *
- * @param string $name The header name
- * @param string $value The header data to encode
- * @param string $charset Character set name
- * @param string $encoding Encoding name (base64 or quoted-printable)
- *
- * @return string Encoded header data (without a name)
- * @access public
- * @since 1.5.3
- */
- function encodeHeader($name, $value, $charset, $encoding)
- {
- return Mail_mimePart::encodeHeader(
- $name, $value, $charset, $encoding, $this->_build_params['eol']
- );
- }
-
- /**
- * Get file's basename (locale independent)
- *
- * @param string $filename Filename
- *
- * @return string Basename
- * @access private
- */
- function _basename($filename)
- {
- // basename() is not unicode safe and locale dependent
- if (stristr(PHP_OS, 'win') || stristr(PHP_OS, 'netware')) {
- return preg_replace('/^.*[\\\\\\/]/', '', $filename);
- } else {
- return preg_replace('/^.*[\/]/', '', $filename);
- }
- }
-
- /**
- * Get Content-Type and Content-Transfer-Encoding headers of the message
- *
- * @return array Headers array
- * @access private
- */
- function _contentHeaders()
- {
- $attachments = count($this->_parts) ? true : false;
- $html_images = count($this->_html_images) ? true : false;
- $html = strlen($this->_htmlbody) ? true : false;
- $text = (!$html && strlen($this->_txtbody)) ? true : false;
- $headers = array();
-
- // See get()
- switch (true) {
- case $text && !$attachments:
- $headers['Content-Type'] = 'text/plain';
- break;
-
- case !$text && !$html && $attachments:
- case $text && $attachments:
- case $html && $attachments && !$html_images:
- case $html && $attachments && $html_images:
- $headers['Content-Type'] = 'multipart/mixed';
- break;
-
- case $html && !$attachments && !$html_images && isset($this->_txtbody):
- case $html && !$attachments && $html_images && isset($this->_txtbody):
- $headers['Content-Type'] = 'multipart/alternative';
- break;
-
- case $html && !$attachments && !$html_images && !isset($this->_txtbody):
- $headers['Content-Type'] = 'text/html';
- break;
-
- case $html && !$attachments && $html_images && !isset($this->_txtbody):
- $headers['Content-Type'] = 'multipart/related';
- break;
-
- default:
- return $headers;
- }
-
- $this->_checkParams();
-
- $eol = !empty($this->_build_params['eol'])
- ? $this->_build_params['eol'] : "\r\n";
-
- if ($headers['Content-Type'] == 'text/plain') {
- // single-part message: add charset and encoding
- $charset = 'charset=' . $this->_build_params['text_charset'];
- // place charset parameter in the same line, if possible
- // 26 = strlen("Content-Type: text/plain; ")
- $headers['Content-Type']
- .= (strlen($charset) + 26 <= 76) ? "; $charset" : ";$eol $charset";
- $headers['Content-Transfer-Encoding']
- = $this->_build_params['text_encoding'];
- } else if ($headers['Content-Type'] == 'text/html') {
- // single-part message: add charset and encoding
- $charset = 'charset=' . $this->_build_params['html_charset'];
- // place charset parameter in the same line, if possible
- $headers['Content-Type']
- .= (strlen($charset) + 25 <= 76) ? "; $charset" : ";$eol $charset";
- $headers['Content-Transfer-Encoding']
- = $this->_build_params['html_encoding'];
- } else {
- // multipart message: and boundary
- if (!empty($this->_build_params['boundary'])) {
- $boundary = $this->_build_params['boundary'];
- } else if (!empty($this->_headers['Content-Type'])
- && preg_match('/boundary="([^"]+)"/', $this->_headers['Content-Type'], $m)
- ) {
- $boundary = $m[1];
- } else {
- $boundary = '=_' . md5(rand() . microtime());
- }
-
- $this->_build_params['boundary'] = $boundary;
- $headers['Content-Type'] .= ";$eol boundary=\"$boundary\"";
- }
-
- return $headers;
- }
-
- /**
- * Validate and set build parameters
- *
- * @return void
- * @access private
- */
- function _checkParams()
- {
- $encodings = array('7bit', '8bit', 'base64', 'quoted-printable');
-
- $this->_build_params['text_encoding']
- = strtolower($this->_build_params['text_encoding']);
- $this->_build_params['html_encoding']
- = strtolower($this->_build_params['html_encoding']);
-
- if (!in_array($this->_build_params['text_encoding'], $encodings)) {
- $this->_build_params['text_encoding'] = '7bit';
- }
- if (!in_array($this->_build_params['html_encoding'], $encodings)) {
- $this->_build_params['html_encoding'] = '7bit';
- }
-
- // text body
- if ($this->_build_params['text_encoding'] == '7bit'
- && !preg_match('/ascii/i', $this->_build_params['text_charset'])
- && preg_match('/[^\x00-\x7F]/', $this->_txtbody)
- ) {
- $this->_build_params['text_encoding'] = 'quoted-printable';
- }
- // html body
- if ($this->_build_params['html_encoding'] == '7bit'
- && !preg_match('/ascii/i', $this->_build_params['html_charset'])
- && preg_match('/[^\x00-\x7F]/', $this->_htmlbody)
- ) {
- $this->_build_params['html_encoding'] = 'quoted-printable';
- }
- }
-
-} // End of class
diff --git a/data/module/Mail/mimeDecode.php b/data/module/Mail/mimeDecode.php
deleted file mode 100644
index 677d245e341..00000000000
--- a/data/module/Mail/mimeDecode.php
+++ /dev/null
@@ -1,1003 +0,0 @@
-
- * Copyright (c) 2003-2006, PEAR
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * - Neither the name of the authors, nor the names of its contributors
- * may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- * @category Mail
- * @package Mail_Mime
- * @author Richard Heyes
- * @author George Schlossnagle
- * @author Cipriano Groenendal
- * @author Sean Coates
- * @copyright 2003-2006 PEAR
- * @license http://www.opensource.org/licenses/bsd-license.php BSD License
- * @version CVS: $Id$
- * @link http://pear.php.net/package/Mail_mime
- */
-
-
-/**
- * require PEAR
- *
- * This package depends on PEAR to raise errors.
- */
-require_once 'PEAR.php';
-
-
-/**
- * The Mail_mimeDecode class is used to decode mail/mime messages
- *
- * This class will parse a raw mime email and return the structure.
- * Returned structure is similar to that returned by imap_fetchstructure().
- *
- * +----------------------------- IMPORTANT ------------------------------+
- * | Usage of this class compared to native php extensions such as |
- * | mailparse or imap, is slow and may be feature deficient. If available|
- * | you are STRONGLY recommended to use the php extensions. |
- * +----------------------------------------------------------------------+
- *
- * @category Mail
- * @package Mail_Mime
- * @author Richard Heyes
- * @author George Schlossnagle
- * @author Cipriano Groenendal
- * @author Sean Coates
- * @copyright 2003-2006 PEAR
- * @license http://www.opensource.org/licenses/bsd-license.php BSD License
- * @version Release: @package_version@
- * @link http://pear.php.net/package/Mail_mime
- */
-class Mail_mimeDecode extends PEAR
-{
- /**
- * The raw email to decode
- *
- * @var string
- * @access private
- */
- var $_input;
-
- /**
- * The header part of the input
- *
- * @var string
- * @access private
- */
- var $_header;
-
- /**
- * The body part of the input
- *
- * @var string
- * @access private
- */
- var $_body;
-
- /**
- * If an error occurs, this is used to store the message
- *
- * @var string
- * @access private
- */
- var $_error;
-
- /**
- * Flag to determine whether to include bodies in the
- * returned object.
- *
- * @var boolean
- * @access private
- */
- var $_include_bodies;
-
- /**
- * Flag to determine whether to decode bodies
- *
- * @var boolean
- * @access private
- */
- var $_decode_bodies;
-
- /**
- * Flag to determine whether to decode headers
- *
- * @var boolean
- * @access private
- */
- var $_decode_headers;
-
- /**
- * Flag to determine whether to include attached messages
- * as body in the returned object. Depends on $_include_bodies
- *
- * @var boolean
- * @access private
- */
- var $_rfc822_bodies;
-
- /**
- * Constructor.
- *
- * Sets up the object, initialise the variables, and splits and
- * stores the header and body of the input.
- *
- * @param string The input to decode
- * @access public
- */
- function Mail_mimeDecode($input)
- {
- list($header, $body) = $this->_splitBodyHeader($input);
-
- $this->_input = $input;
- $this->_header = $header;
- $this->_body = $body;
- $this->_decode_bodies = false;
- $this->_include_bodies = true;
- $this->_rfc822_bodies = false;
- }
-
- /**
- * Begins the decoding process. If called statically
- * it will create an object and call the decode() method
- * of it.
- *
- * @param array An array of various parameters that determine
- * various things:
- * include_bodies - Whether to include the body in the returned
- * object.
- * decode_bodies - Whether to decode the bodies
- * of the parts. (Transfer encoding)
- * decode_headers - Whether to decode headers
- * input - If called statically, this will be treated
- * as the input
- * @return object Decoded results
- * @access public
- */
- function decode($params = null)
- {
- // determine if this method has been called statically
- $isStatic = empty($this) || !is_a($this, __CLASS__);
-
- // Have we been called statically?
- // If so, create an object and pass details to that.
- if ($isStatic AND isset($params['input'])) {
-
- $obj = new Mail_mimeDecode($params['input']);
- $structure = $obj->decode($params);
-
- // Called statically but no input
- } elseif ($isStatic) {
- return PEAR::raiseError('Called statically and no input given');
-
- // Called via an object
- } else {
- $this->_include_bodies = isset($params['include_bodies']) ?
- $params['include_bodies'] : false;
- $this->_decode_bodies = isset($params['decode_bodies']) ?
- $params['decode_bodies'] : false;
- $this->_decode_headers = isset($params['decode_headers']) ?
- $params['decode_headers'] : false;
- $this->_rfc822_bodies = isset($params['rfc_822bodies']) ?
- $params['rfc_822bodies'] : false;
-
- $structure = $this->_decode($this->_header, $this->_body);
- if ($structure === false) {
- $structure = $this->raiseError($this->_error);
- }
- }
-
- return $structure;
- }
-
- /**
- * Performs the decoding. Decodes the body string passed to it
- * If it finds certain content-types it will call itself in a
- * recursive fashion
- *
- * @param string Header section
- * @param string Body section
- * @return object Results of decoding process
- * @access private
- */
- function _decode($headers, $body, $default_ctype = 'text/plain')
- {
- $return = new stdClass;
- $return->headers = array();
- $headers = $this->_parseHeaders($headers);
-
- foreach ($headers as $value) {
- $value['value'] = $this->_decode_headers ? $this->_decodeHeader($value['value']) : $value['value'];
- if (isset($return->headers[strtolower($value['name'])]) AND !is_array($return->headers[strtolower($value['name'])])) {
- $return->headers[strtolower($value['name'])] = array($return->headers[strtolower($value['name'])]);
- $return->headers[strtolower($value['name'])][] = $value['value'];
-
- } elseif (isset($return->headers[strtolower($value['name'])])) {
- $return->headers[strtolower($value['name'])][] = $value['value'];
-
- } else {
- $return->headers[strtolower($value['name'])] = $value['value'];
- }
- }
-
-
- foreach ($headers as $key => $value) {
- $headers[$key]['name'] = strtolower($headers[$key]['name']);
- switch ($headers[$key]['name']) {
-
- case 'content-type':
- $content_type = $this->_parseHeaderValue($headers[$key]['value']);
-
- if (preg_match('/([0-9a-z+.-]+)\/([0-9a-z+.-]+)/i', $content_type['value'], $regs)) {
- $return->ctype_primary = $regs[1];
- $return->ctype_secondary = $regs[2];
- }
-
- if (isset($content_type['other'])) {
- foreach($content_type['other'] as $p_name => $p_value) {
- $return->ctype_parameters[$p_name] = $p_value;
- }
- }
- break;
-
- case 'content-disposition':
- $content_disposition = $this->_parseHeaderValue($headers[$key]['value']);
- $return->disposition = $content_disposition['value'];
- if (isset($content_disposition['other'])) {
- foreach($content_disposition['other'] as $p_name => $p_value) {
- $return->d_parameters[$p_name] = $p_value;
- }
- }
- break;
-
- case 'content-transfer-encoding':
- $content_transfer_encoding = $this->_parseHeaderValue($headers[$key]['value']);
- break;
- }
- }
-
- if (isset($content_type)) {
- switch (strtolower($content_type['value'])) {
- case 'text/plain':
- $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit';
- $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body) : null;
- break;
-
- case 'text/html':
- $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit';
- $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body) : null;
- break;
-
- case 'multipart/parallel':
- case 'multipart/appledouble': // Appledouble mail
- case 'multipart/report': // RFC1892
- case 'multipart/signed': // PGP
- case 'multipart/digest':
- case 'multipart/alternative':
- case 'multipart/related':
- case 'multipart/mixed':
- case 'application/vnd.wap.multipart.related':
- if(!isset($content_type['other']['boundary'])){
- $this->_error = 'No boundary found for ' . $content_type['value'] . ' part';
- return false;
- }
-
- $default_ctype = (strtolower($content_type['value']) === 'multipart/digest') ? 'message/rfc822' : 'text/plain';
-
- $parts = $this->_boundarySplit($body, $content_type['other']['boundary']);
- for ($i = 0; $i < count($parts); $i++) {
- list($part_header, $part_body) = $this->_splitBodyHeader($parts[$i]);
- $part = $this->_decode($part_header, $part_body, $default_ctype);
- if($part === false)
- $part = $this->raiseError($this->_error);
- $return->parts[] = $part;
- }
- break;
-
- case 'message/rfc822':
- if ($this->_rfc822_bodies) {
- $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit';
- $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body);
- }
- $obj = new Mail_mimeDecode($body);
- $return->parts[] = $obj->decode(array('include_bodies' => $this->_include_bodies,
- 'decode_bodies' => $this->_decode_bodies,
- 'decode_headers' => $this->_decode_headers));
- unset($obj);
- break;
-
- default:
- if(!isset($content_transfer_encoding['value']))
- $content_transfer_encoding['value'] = '7bit';
- $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $content_transfer_encoding['value']) : $body) : null;
- break;
- }
-
- } else {
- $ctype = explode('/', $default_ctype);
- $return->ctype_primary = $ctype[0];
- $return->ctype_secondary = $ctype[1];
- $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body) : $body) : null;
- }
-
- return $return;
- }
-
- /**
- * Given the output of the above function, this will return an
- * array of references to the parts, indexed by mime number.
- *
- * @param object $structure The structure to go through
- * @param string $mime_number Internal use only.
- * @return array Mime numbers
- */
- function &getMimeNumbers(&$structure, $no_refs = false, $mime_number = '', $prepend = '')
- {
- $return = array();
- if (!empty($structure->parts)) {
- if ($mime_number != '') {
- $structure->mime_id = $prepend . $mime_number;
- $return[$prepend . $mime_number] = &$structure;
- }
- for ($i = 0; $i < count($structure->parts); $i++) {
-
-
- if (!empty($structure->headers['content-type']) AND substr(strtolower($structure->headers['content-type']), 0, 8) == 'message/') {
- $prepend = $prepend . $mime_number . '.';
- $_mime_number = '';
- } else {
- $_mime_number = ($mime_number == '' ? $i + 1 : sprintf('%s.%s', $mime_number, $i + 1));
- }
-
- $arr = &Mail_mimeDecode::getMimeNumbers($structure->parts[$i], $no_refs, $_mime_number, $prepend);
- foreach ($arr as $key => $val) {
- $no_refs ? $return[$key] = '' : $return[$key] = &$arr[$key];
- }
- }
- } else {
- if ($mime_number == '') {
- $mime_number = '1';
- }
- $structure->mime_id = $prepend . $mime_number;
- $no_refs ? $return[$prepend . $mime_number] = '' : $return[$prepend . $mime_number] = &$structure;
- }
-
- return $return;
- }
-
- /**
- * Given a string containing a header and body
- * section, this function will split them (at the first
- * blank line) and return them.
- *
- * @param string Input to split apart
- * @return array Contains header and body section
- * @access private
- */
- function _splitBodyHeader($input)
- {
- if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $input, $match)) {
- return array($match[1], $match[2]);
- }
- // bug #17325 - empty bodies are allowed. - we just check that at least one line
- // of headers exist..
- if (count(explode("\n",$input))) {
- return array($input, '');
- }
- $this->_error = 'Could not split header and body';
- return false;
- }
-
- /**
- * Parse headers given in $input and return
- * as assoc array.
- *
- * @param string Headers to parse
- * @return array Contains parsed headers
- * @access private
- */
- function _parseHeaders($input)
- {
-
- if ($input !== '') {
- // Unfold the input
- $input = preg_replace("/\r?\n/", "\r\n", $input);
- //#7065 - wrapping.. with encoded stuff.. - probably not needed,
- // wrapping space should only get removed if the trailing item on previous line is a
- // encoded character
- $input = preg_replace("/=\r\n(\t| )+/", '=', $input);
- $input = preg_replace("/\r\n(\t| )+/", ' ', $input);
-
- $headers = explode("\r\n", trim($input));
-
- foreach ($headers as $value) {
- $hdr_name = substr($value, 0, $pos = strpos($value, ':'));
- $hdr_value = substr($value, $pos+1);
- if($hdr_value[0] == ' ')
- $hdr_value = substr($hdr_value, 1);
-
- $return[] = array(
- 'name' => $hdr_name,
- 'value' => $hdr_value
- );
- }
- } else {
- $return = array();
- }
-
- return $return;
- }
-
- /**
- * Function to parse a header value,
- * extract first part, and any secondary
- * parts (after ;) This function is not as
- * robust as it could be. Eg. header comments
- * in the wrong place will probably break it.
- *
- * @param string Header value to parse
- * @return array Contains parsed result
- * @access private
- */
- function _parseHeaderValue($input)
- {
-
- if (($pos = strpos($input, ';')) === false) {
- $input = $this->_decode_headers ? $this->_decodeHeader($input) : $input;
- $return['value'] = trim($input);
- return $return;
- }
-
-
-
- $value = substr($input, 0, $pos);
- $value = $this->_decode_headers ? $this->_decodeHeader($value) : $value;
- $return['value'] = trim($value);
- $input = trim(substr($input, $pos+1));
-
- if (!strlen($input) > 0) {
- return $return;
- }
- // at this point input contains xxxx=".....";zzzz="...."
- // since we are dealing with quoted strings, we need to handle this properly..
- $i = 0;
- $l = strlen($input);
- $key = '';
- $val = false; // our string - including quotes..
- $q = false; // in quote..
- $lq = ''; // last quote..
-
- while ($i < $l) {
-
- $c = $input[$i];
- //var_dump(array('i'=>$i,'c'=>$c,'q'=>$q, 'lq'=>$lq, 'key'=>$key, 'val' =>$val));
-
- $escaped = false;
- if ($c == '\\') {
- $i++;
- if ($i == $l-1) { // end of string.
- break;
- }
- $escaped = true;
- $c = $input[$i];
- }
-
-
- // state - in key..
- if ($val === false) {
- if (!$escaped && $c == '=') {
- $val = '';
- $key = trim($key);
- $i++;
- continue;
- }
- if (!$escaped && $c == ';') {
- if ($key) { // a key without a value..
- $key= trim($key);
- $return['other'][$key] = '';
- $return['other'][strtolower($key)] = '';
- }
- $key = '';
- }
- $key .= $c;
- $i++;
- continue;
- }
-
- // state - in value.. (as $val is set..)
-
- if ($q === false) {
- // not in quote yet.
- if ((!strlen($val) || $lq !== false) && $c == ' ' || $c == "\t") {
- $i++;
- continue; // skip leading spaces after '=' or after '"'
- }
- if (!$escaped && ($c == '"' || $c == "'")) {
- // start quoted area..
- $q = $c;
- // in theory should not happen raw text in value part..
- // but we will handle it as a merged part of the string..
- $val = !strlen(trim($val)) ? '' : trim($val);
- $i++;
- continue;
- }
- // got end....
- if (!$escaped && $c == ';') {
-
- $val = trim($val);
- $added = false;
- if (preg_match('/\*[0-9]+$/', $key)) {
- // this is the extended aaa*0=...;aaa*1=.... code
- // it assumes the pieces arrive in order, and are valid...
- $key = preg_replace('/\*[0-9]+$/', '', $key);
- if (isset($return['other'][$key])) {
- $return['other'][$key] .= $val;
- if (strtolower($key) != $key) {
- $return['other'][strtolower($key)] .= $val;
- }
- $added = true;
- }
- // continue and use standard setters..
- }
- if (!$added) {
- $return['other'][$key] = $val;
- $return['other'][strtolower($key)] = $val;
- }
- $val = false;
- $key = '';
- $lq = false;
- $i++;
- continue;
- }
-
- $val .= $c;
- $i++;
- continue;
- }
-
- // state - in quote..
- if (!$escaped && $c == $q) { // potential exit state..
-
- // end of quoted string..
- $lq = $q;
- $q = false;
- $i++;
- continue;
- }
-
- // normal char inside of quoted string..
- $val.= $c;
- $i++;
- }
-
- // do we have anything left..
- if (strlen(trim($key)) || $val !== false) {
-
- $val = trim($val);
- $added = false;
- if ($val !== false && preg_match('/\*[0-9]+$/', $key)) {
- // no dupes due to our crazy regexp.
- $key = preg_replace('/\*[0-9]+$/', '', $key);
- if (isset($return['other'][$key])) {
- $return['other'][$key] .= $val;
- if (strtolower($key) != $key) {
- $return['other'][strtolower($key)] .= $val;
- }
- $added = true;
- }
- // continue and use standard setters..
- }
- if (!$added) {
- $return['other'][$key] = $val;
- $return['other'][strtolower($key)] = $val;
- }
- }
- // decode values.
- foreach($return['other'] as $key =>$val) {
- $return['other'][$key] = $this->_decode_headers ? $this->_decodeHeader($val) : $val;
- }
- //print_r($return);
- return $return;
- }
-
- /**
- * This function splits the input based
- * on the given boundary
- *
- * @param string Input to parse
- * @return array Contains array of resulting mime parts
- * @access private
- */
- function _boundarySplit($input, $boundary)
- {
- $parts = array();
-
- $bs_possible = substr($boundary, 2, -2);
- $bs_check = '\"' . $bs_possible . '\"';
-
- if ($boundary == $bs_check) {
- $boundary = $bs_possible;
- }
- $tmp = preg_split("/--".preg_quote($boundary, '/')."((?=\s)|--)/", $input);
-
- $len = count($tmp) -1;
- for ($i = 1; $i < $len; $i++) {
- if (strlen(trim($tmp[$i]))) {
- $parts[] = $tmp[$i];
- }
- }
-
- // add the last part on if it does not end with the 'closing indicator'
- if (!empty($tmp[$len]) && strlen(trim($tmp[$len])) && $tmp[$len][0] != '-') {
- $parts[] = $tmp[$len];
- }
- return $parts;
- }
-
- /**
- * Given a header, this function will decode it
- * according to RFC2047. Probably not *exactly*
- * conformant, but it does pass all the given
- * examples (in RFC2047).
- *
- * @param string Input header value to decode
- * @return string Decoded header value
- * @access private
- */
- function _decodeHeader($input)
- {
- // Remove white space between encoded-words
- $input = preg_replace('/(=\?[^?]+\?(q|b)\?[^?]*\?=)(\s)+=\?/i', '\1=?', $input);
-
- // For each encoded-word...
- while (preg_match('/(=\?([^?]+)\?(q|b)\?([^?]*)\?=)/i', $input, $matches)) {
-
- $encoded = $matches[1];
- $charset = $matches[2];
- $encoding = $matches[3];
- $text = $matches[4];
-
- switch (strtolower($encoding)) {
- case 'b':
- $text = base64_decode($text);
- break;
-
- case 'q':
- $text = str_replace('_', ' ', $text);
- preg_match_all('/=([a-f0-9]{2})/i', $text, $matches);
- foreach($matches[1] as $value)
- $text = str_replace('='.$value, chr(hexdec($value)), $text);
- break;
- }
-
- $input = str_replace($encoded, $text, $input);
- }
-
- return $input;
- }
-
- /**
- * Given a body string and an encoding type,
- * this function will decode and return it.
- *
- * @param string Input body to decode
- * @param string Encoding type to use.
- * @return string Decoded body
- * @access private
- */
- function _decodeBody($input, $encoding = '7bit')
- {
- switch (strtolower($encoding)) {
- case '7bit':
- return $input;
- break;
-
- case 'quoted-printable':
- return $this->_quotedPrintableDecode($input);
- break;
-
- case 'base64':
- return base64_decode($input);
- break;
-
- default:
- return $input;
- }
- }
-
- /**
- * Given a quoted-printable string, this
- * function will decode and return it.
- *
- * @param string Input body to decode
- * @return string Decoded body
- * @access private
- */
- function _quotedPrintableDecode($input)
- {
- // Remove soft line breaks
- $input = preg_replace("/=\r?\n/", '', $input);
-
- // Replace encoded characters
- $input = preg_replace('/=([a-f0-9]{2})/ie', "chr(hexdec('\\1'))", $input);
-
- return $input;
- }
-
- /**
- * Checks the input for uuencoded files and returns
- * an array of them. Can be called statically, eg:
- *
- * $files =& Mail_mimeDecode::uudecode($some_text);
- *
- * It will check for the begin 666 ... end syntax
- * however and won't just blindly decode whatever you
- * pass it.
- *
- * @param string Input body to look for attahcments in
- * @return array Decoded bodies, filenames and permissions
- * @access public
- * @author Unknown
- */
- function &uudecode($input)
- {
- // Find all uuencoded sections
- preg_match_all("/begin ([0-7]{3}) (.+)\r?\n(.+)\r?\nend/Us", $input, $matches);
-
- for ($j = 0; $j < count($matches[3]); $j++) {
-
- $str = $matches[3][$j];
- $filename = $matches[2][$j];
- $fileperm = $matches[1][$j];
-
- $file = '';
- $str = preg_split("/\r?\n/", trim($str));
- $strlen = count($str);
-
- for ($i = 0; $i < $strlen; $i++) {
- $pos = 1;
- $d = 0;
- $len=(int)(((ord(substr($str[$i],0,1)) -32) - ' ') & 077);
-
- while (($d + 3 <= $len) AND ($pos + 4 <= strlen($str[$i]))) {
- $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20);
- $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20);
- $c2 = (ord(substr($str[$i],$pos+2,1)) ^ 0x20);
- $c3 = (ord(substr($str[$i],$pos+3,1)) ^ 0x20);
- $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4));
-
- $file .= chr(((($c1 - ' ') & 077) << 4) | ((($c2 - ' ') & 077) >> 2));
-
- $file .= chr(((($c2 - ' ') & 077) << 6) | (($c3 - ' ') & 077));
-
- $pos += 4;
- $d += 3;
- }
-
- if (($d + 2 <= $len) && ($pos + 3 <= strlen($str[$i]))) {
- $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20);
- $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20);
- $c2 = (ord(substr($str[$i],$pos+2,1)) ^ 0x20);
- $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4));
-
- $file .= chr(((($c1 - ' ') & 077) << 4) | ((($c2 - ' ') & 077) >> 2));
-
- $pos += 3;
- $d += 2;
- }
-
- if (($d + 1 <= $len) && ($pos + 2 <= strlen($str[$i]))) {
- $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20);
- $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20);
- $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4));
-
- }
- }
- $files[] = array('filename' => $filename, 'fileperm' => $fileperm, 'filedata' => $file);
- }
-
- return $files;
- }
-
- /**
- * getSendArray() returns the arguments required for Mail::send()
- * used to build the arguments for a mail::send() call
- *
- * Usage:
- * $mailtext = Full email (for example generated by a template)
- * $decoder = new Mail_mimeDecode($mailtext);
- * $parts = $decoder->getSendArray();
- * if (!PEAR::isError($parts) {
- * list($recipents,$headers,$body) = $parts;
- * $mail = Mail::factory('smtp');
- * $mail->send($recipents,$headers,$body);
- * } else {
- * echo $parts->message;
- * }
- * @return mixed array of recipeint, headers,body or Pear_Error
- * @access public
- * @author Alan Knowles
- */
- function getSendArray()
- {
- // prevent warning if this is not set
- $this->_decode_headers = FALSE;
- $headerlist =$this->_parseHeaders($this->_header);
- $to = "";
- if (!$headerlist) {
- return $this->raiseError("Message did not contain headers");
- }
- foreach($headerlist as $item) {
- $header[$item['name']] = $item['value'];
- switch (strtolower($item['name'])) {
- case "to":
- case "cc":
- case "bcc":
- $to .= ",".$item['value'];
- default:
- break;
- }
- }
- if ($to == "") {
- return $this->raiseError("Message did not contain any recipents");
- }
- $to = substr($to,1);
- return array($to,$header,$this->_body);
- }
-
- /**
- * Returns a xml copy of the output of
- * Mail_mimeDecode::decode. Pass the output in as the
- * argument. This function can be called statically. Eg:
- *
- * $output = $obj->decode();
- * $xml = Mail_mimeDecode::getXML($output);
- *
- * The DTD used for this should have been in the package. Or
- * alternatively you can get it from cvs, or here:
- * http://www.phpguru.org/xmail/xmail.dtd.
- *
- * @param object Input to convert to xml. This should be the
- * output of the Mail_mimeDecode::decode function
- * @return string XML version of input
- * @access public
- */
- function getXML($input)
- {
- $crlf = "\r\n";
- $output = '' . $crlf .
- '' . $crlf .
- '' . $crlf .
- Mail_mimeDecode::_getXML($input) .
- '';
-
- return $output;
- }
-
- /**
- * Function that does the actual conversion to xml. Does a single
- * mimepart at a time.
- *
- * @param object Input to convert to xml. This is a mimepart object.
- * It may or may not contain subparts.
- * @param integer Number of tabs to indent
- * @return string XML version of input
- * @access private
- */
- function _getXML($input, $indent = 1)
- {
- $htab = "\t";
- $crlf = "\r\n";
- $output = '';
- $headers = @(array)$input->headers;
-
- foreach ($headers as $hdr_name => $hdr_value) {
-
- // Multiple headers with this name
- if (is_array($headers[$hdr_name])) {
- for ($i = 0; $i < count($hdr_value); $i++) {
- $output .= Mail_mimeDecode::_getXML_helper($hdr_name, $hdr_value[$i], $indent);
- }
-
- // Only one header of this sort
- } else {
- $output .= Mail_mimeDecode::_getXML_helper($hdr_name, $hdr_value, $indent);
- }
- }
-
- if (!empty($input->parts)) {
- for ($i = 0; $i < count($input->parts); $i++) {
- $output .= $crlf . str_repeat($htab, $indent) . '' . $crlf .
- Mail_mimeDecode::_getXML($input->parts[$i], $indent+1) .
- str_repeat($htab, $indent) . '' . $crlf;
- }
- } elseif (isset($input->body)) {
- $output .= $crlf . str_repeat($htab, $indent) . 'body . ']]>' . $crlf;
- }
-
- return $output;
- }
-
- /**
- * Helper function to _getXML(). Returns xml of a header.
- *
- * @param string Name of header
- * @param string Value of header
- * @param integer Number of tabs to indent
- * @return string XML version of input
- * @access private
- */
- function _getXML_helper($hdr_name, $hdr_value, $indent)
- {
- $htab = "\t";
- $crlf = "\r\n";
- $return = '';
-
- $new_hdr_value = ($hdr_name != 'received') ? Mail_mimeDecode::_parseHeaderValue($hdr_value) : array('value' => $hdr_value);
- $new_hdr_name = str_replace(' ', '-', ucwords(str_replace('-', ' ', $hdr_name)));
-
- // Sort out any parameters
- if (!empty($new_hdr_value['other'])) {
- foreach ($new_hdr_value['other'] as $paramname => $paramvalue) {
- $params[] = str_repeat($htab, $indent) . $htab . '' . $crlf .
- str_repeat($htab, $indent) . $htab . $htab . '' . htmlspecialchars($paramname) . '' . $crlf .
- str_repeat($htab, $indent) . $htab . $htab . '' . htmlspecialchars($paramvalue) . '' . $crlf .
- str_repeat($htab, $indent) . $htab . '' . $crlf;
- }
-
- $params = implode('', $params);
- } else {
- $params = '';
- }
-
- $return = str_repeat($htab, $indent) . '' . $crlf .
- str_repeat($htab, $indent) . $htab . '' . htmlspecialchars($new_hdr_name) . '' . $crlf .
- str_repeat($htab, $indent) . $htab . '' . htmlspecialchars($new_hdr_value['value']) . '' . $crlf .
- $params .
- str_repeat($htab, $indent) . '' . $crlf;
-
- return $return;
- }
-
-} // End of class
diff --git a/data/module/Mail/mimePart.php b/data/module/Mail/mimePart.php
deleted file mode 100644
index 60b3601e064..00000000000
--- a/data/module/Mail/mimePart.php
+++ /dev/null
@@ -1,1190 +0,0 @@
-
- * Copyright (c) 2003-2006, PEAR
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * - Neither the name of the authors, nor the names of its contributors
- * may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- * @category Mail
- * @package Mail_Mime
- * @author Richard Heyes
- * @author Cipriano Groenendal
- * @author Sean Coates
- * @author Aleksander Machniak
- * @copyright 2003-2006 PEAR
- * @license http://www.opensource.org/licenses/bsd-license.php BSD License
- * @version CVS: $Id$
- * @link http://pear.php.net/package/Mail_mime
- */
-
-
-/**
- * The Mail_mimePart class is used to create MIME E-mail messages
- *
- * This class enables you to manipulate and build a mime email
- * from the ground up. The Mail_Mime class is a userfriendly api
- * to this class for people who aren't interested in the internals
- * of mime mail.
- * This class however allows full control over the email.
- *
- * @category Mail
- * @package Mail_Mime
- * @author Richard Heyes
- * @author Cipriano Groenendal
- * @author Sean Coates
- * @author Aleksander Machniak
- * @copyright 2003-2006 PEAR
- * @license http://www.opensource.org/licenses/bsd-license.php BSD License
- * @version Release: @package_version@
- * @link http://pear.php.net/package/Mail_mime
- */
-class Mail_mimePart
-{
- /**
- * The encoding type of this part
- *
- * @var string
- * @access private
- */
- var $_encoding;
-
- /**
- * An array of subparts
- *
- * @var array
- * @access private
- */
- var $_subparts;
-
- /**
- * The output of this part after being built
- *
- * @var string
- * @access private
- */
- var $_encoded;
-
- /**
- * Headers for this part
- *
- * @var array
- * @access private
- */
- var $_headers;
-
- /**
- * The body of this part (not encoded)
- *
- * @var string
- * @access private
- */
- var $_body;
-
- /**
- * The location of file with body of this part (not encoded)
- *
- * @var string
- * @access private
- */
- var $_body_file;
-
- /**
- * The end-of-line sequence
- *
- * @var string
- * @access private
- */
- var $_eol = "\r\n";
-
- /**
- * Constructor.
- *
- * Sets up the object.
- *
- * @param string $body The body of the mime part if any.
- * @param array $params An associative array of optional parameters:
- * content_type - The content type for this part eg multipart/mixed
- * encoding - The encoding to use, 7bit, 8bit,
- * base64, or quoted-printable
- * charset - Content character set
- * cid - Content ID to apply
- * disposition - Content disposition, inline or attachment
- * dfilename - Filename parameter for content disposition
- * description - Content description
- * name_encoding - Encoding of the attachment name (Content-Type)
- * By default filenames are encoded using RFC2231
- * Here you can set RFC2047 encoding (quoted-printable
- * or base64) instead
- * filename_encoding - Encoding of the attachment filename (Content-Disposition)
- * See 'name_encoding'
- * headers_charset - Charset of the headers e.g. filename, description.
- * If not set, 'charset' will be used
- * eol - End of line sequence. Default: "\r\n"
- * body_file - Location of file with part's body (instead of $body)
- *
- * @access public
- */
- function Mail_mimePart($body = '', $params = array())
- {
- if (!empty($params['eol'])) {
- $this->_eol = $params['eol'];
- } else if (defined('MAIL_MIMEPART_CRLF')) { // backward-copat.
- $this->_eol = MAIL_MIMEPART_CRLF;
- }
-
- foreach ($params as $key => $value) {
- switch ($key) {
- case 'encoding':
- $this->_encoding = $value;
- $headers['Content-Transfer-Encoding'] = $value;
- break;
-
- case 'cid':
- $headers['Content-ID'] = '<' . $value . '>';
- break;
-
- case 'location':
- $headers['Content-Location'] = $value;
- break;
-
- case 'body_file':
- $this->_body_file = $value;
- break;
- }
- }
-
- // Default content-type
- if (empty($params['content_type'])) {
- $params['content_type'] = 'text/plain';
- }
-
- // Content-Type
- $headers['Content-Type'] = $params['content_type'];
- if (!empty($params['charset'])) {
- $charset = "charset={$params['charset']}";
- // place charset parameter in the same line, if possible
- if ((strlen($headers['Content-Type']) + strlen($charset) + 16) <= 76) {
- $headers['Content-Type'] .= '; ';
- } else {
- $headers['Content-Type'] .= ';' . $this->_eol . ' ';
- }
- $headers['Content-Type'] .= $charset;
-
- // Default headers charset
- if (!isset($params['headers_charset'])) {
- $params['headers_charset'] = $params['charset'];
- }
- }
- if (!empty($params['filename'])) {
- $headers['Content-Type'] .= ';' . $this->_eol;
- $headers['Content-Type'] .= $this->_buildHeaderParam(
- 'name', $params['filename'],
- !empty($params['headers_charset']) ? $params['headers_charset'] : 'US-ASCII',
- !empty($params['language']) ? $params['language'] : null,
- !empty($params['name_encoding']) ? $params['name_encoding'] : null
- );
- }
-
- // Content-Disposition
- if (!empty($params['disposition'])) {
- $headers['Content-Disposition'] = $params['disposition'];
- if (!empty($params['filename'])) {
- $headers['Content-Disposition'] .= ';' . $this->_eol;
- $headers['Content-Disposition'] .= $this->_buildHeaderParam(
- 'filename', $params['filename'],
- !empty($params['headers_charset']) ? $params['headers_charset'] : 'US-ASCII',
- !empty($params['language']) ? $params['language'] : null,
- !empty($params['filename_encoding']) ? $params['filename_encoding'] : null
- );
- }
- }
-
- if (!empty($params['description'])) {
- $headers['Content-Description'] = $this->encodeHeader(
- 'Content-Description', $params['description'],
- !empty($params['headers_charset']) ? $params['headers_charset'] : 'US-ASCII',
- !empty($params['name_encoding']) ? $params['name_encoding'] : 'quoted-printable',
- $this->_eol
- );
- }
-
- // Default encoding
- if (!isset($this->_encoding)) {
- $this->_encoding = '7bit';
- }
-
- // Assign stuff to member variables
- $this->_encoded = array();
- $this->_headers = $headers;
- $this->_body = $body;
- }
-
- /**
- * Encodes and returns the email. Also stores
- * it in the encoded member variable
- *
- * @param string $boundary Pre-defined boundary string
- *
- * @return An associative array containing two elements,
- * body and headers. The headers element is itself
- * an indexed array. On error returns PEAR error object.
- * @access public
- */
- function encode($boundary=null)
- {
- $encoded =& $this->_encoded;
-
- if (count($this->_subparts)) {
- $boundary = $boundary ? $boundary : '=_' . md5(rand() . microtime());
- $eol = $this->_eol;
-
- $this->_headers['Content-Type'] .= ";$eol boundary=\"$boundary\"";
-
- $encoded['body'] = '';
-
- for ($i = 0; $i < count($this->_subparts); $i++) {
- $encoded['body'] .= '--' . $boundary . $eol;
- $tmp = $this->_subparts[$i]->encode();
- if (PEAR::isError($tmp)) {
- return $tmp;
- }
- foreach ($tmp['headers'] as $key => $value) {
- $encoded['body'] .= $key . ': ' . $value . $eol;
- }
- $encoded['body'] .= $eol . $tmp['body'] . $eol;
- }
-
- $encoded['body'] .= '--' . $boundary . '--' . $eol;
-
- } else if ($this->_body) {
- $encoded['body'] = $this->_getEncodedData($this->_body, $this->_encoding);
- } else if ($this->_body_file) {
- // Temporarily reset magic_quotes_runtime for file reads and writes
- if ($magic_quote_setting = get_magic_quotes_runtime()) {
- @ini_set('magic_quotes_runtime', 0);
- }
- $body = $this->_getEncodedDataFromFile($this->_body_file, $this->_encoding);
- if ($magic_quote_setting) {
- @ini_set('magic_quotes_runtime', $magic_quote_setting);
- }
-
- if (PEAR::isError($body)) {
- return $body;
- }
- $encoded['body'] = $body;
- } else {
- $encoded['body'] = '';
- }
-
- // Add headers to $encoded
- $encoded['headers'] =& $this->_headers;
-
- return $encoded;
- }
-
- /**
- * Encodes and saves the email into file. File must exist.
- * Data will be appended to the file.
- *
- * @param string $filename Output file location
- * @param string $boundary Pre-defined boundary string
- * @param boolean $skip_head True if you don't want to save headers
- *
- * @return array An associative array containing message headers
- * or PEAR error object
- * @access public
- * @since 1.6.0
- */
- function encodeToFile($filename, $boundary=null, $skip_head=false)
- {
- if (file_exists($filename) && !is_writable($filename)) {
- $err = PEAR::raiseError('File is not writeable: ' . $filename);
- return $err;
- }
-
- if (!($fh = fopen($filename, 'ab'))) {
- $err = PEAR::raiseError('Unable to open file: ' . $filename);
- return $err;
- }
-
- // Temporarily reset magic_quotes_runtime for file reads and writes
- if ($magic_quote_setting = get_magic_quotes_runtime()) {
- @ini_set('magic_quotes_runtime', 0);
- }
-
- $res = $this->_encodePartToFile($fh, $boundary, $skip_head);
-
- fclose($fh);
-
- if ($magic_quote_setting) {
- @ini_set('magic_quotes_runtime', $magic_quote_setting);
- }
-
- return PEAR::isError($res) ? $res : $this->_headers;
- }
-
- /**
- * Encodes given email part into file
- *
- * @param string $fh Output file handle
- * @param string $boundary Pre-defined boundary string
- * @param boolean $skip_head True if you don't want to save headers
- *
- * @return array True on sucess or PEAR error object
- * @access private
- */
- function _encodePartToFile($fh, $boundary=null, $skip_head=false)
- {
- $eol = $this->_eol;
-
- if (count($this->_subparts)) {
- $boundary = $boundary ? $boundary : '=_' . md5(rand() . microtime());
- $this->_headers['Content-Type'] .= ";$eol boundary=\"$boundary\"";
- }
-
- if (!$skip_head) {
- foreach ($this->_headers as $key => $value) {
- fwrite($fh, $key . ': ' . $value . $eol);
- }
- $f_eol = $eol;
- } else {
- $f_eol = '';
- }
-
- if (count($this->_subparts)) {
- for ($i = 0; $i < count($this->_subparts); $i++) {
- fwrite($fh, $f_eol . '--' . $boundary . $eol);
- $res = $this->_subparts[$i]->_encodePartToFile($fh);
- if (PEAR::isError($res)) {
- return $res;
- }
- $f_eol = $eol;
- }
-
- fwrite($fh, $eol . '--' . $boundary . '--' . $eol);
-
- } else if ($this->_body) {
- fwrite($fh, $f_eol . $this->_getEncodedData($this->_body, $this->_encoding));
- } else if ($this->_body_file) {
- fwrite($fh, $f_eol);
- $res = $this->_getEncodedDataFromFile(
- $this->_body_file, $this->_encoding, $fh
- );
- if (PEAR::isError($res)) {
- return $res;
- }
- }
-
- return true;
- }
-
- /**
- * Adds a subpart to current mime part and returns
- * a reference to it
- *
- * @param string $body The body of the subpart, if any.
- * @param array $params The parameters for the subpart, same
- * as the $params argument for constructor.
- *
- * @return Mail_mimePart A reference to the part you just added. It is
- * crucial if using multipart/* in your subparts that
- * you use =& in your script when calling this function,
- * otherwise you will not be able to add further subparts.
- * @access public
- */
- function &addSubpart($body, $params)
- {
- $this->_subparts[] = new Mail_mimePart($body, $params);
- return $this->_subparts[count($this->_subparts) - 1];
- }
-
- /**
- * Returns encoded data based upon encoding passed to it
- *
- * @param string $data The data to encode.
- * @param string $encoding The encoding type to use, 7bit, base64,
- * or quoted-printable.
- *
- * @return string
- * @access private
- */
- function _getEncodedData($data, $encoding)
- {
- switch ($encoding) {
- case 'quoted-printable':
- return $this->_quotedPrintableEncode($data);
- break;
-
- case 'base64':
- return rtrim(chunk_split(base64_encode($data), 76, $this->_eol));
- break;
-
- case '8bit':
- case '7bit':
- default:
- return $data;
- }
- }
-
- /**
- * Returns encoded data based upon encoding passed to it
- *
- * @param string $filename Data file location
- * @param string $encoding The encoding type to use, 7bit, base64,
- * or quoted-printable.
- * @param resource $fh Output file handle. If set, data will be
- * stored into it instead of returning it
- *
- * @return string Encoded data or PEAR error object
- * @access private
- */
- function _getEncodedDataFromFile($filename, $encoding, $fh=null)
- {
- if (!is_readable($filename)) {
- $err = PEAR::raiseError('Unable to read file: ' . $filename);
- return $err;
- }
-
- if (!($fd = fopen($filename, 'rb'))) {
- $err = PEAR::raiseError('Could not open file: ' . $filename);
- return $err;
- }
-
- $data = '';
-
- switch ($encoding) {
- case 'quoted-printable':
- while (!feof($fd)) {
- $buffer = $this->_quotedPrintableEncode(fgets($fd));
- if ($fh) {
- fwrite($fh, $buffer);
- } else {
- $data .= $buffer;
- }
- }
- break;
-
- case 'base64':
- while (!feof($fd)) {
- // Should read in a multiple of 57 bytes so that
- // the output is 76 bytes per line. Don't use big chunks
- // because base64 encoding is memory expensive
- $buffer = fread($fd, 57 * 9198); // ca. 0.5 MB
- $buffer = base64_encode($buffer);
- $buffer = chunk_split($buffer, 76, $this->_eol);
- if (feof($fd)) {
- $buffer = rtrim($buffer);
- }
-
- if ($fh) {
- fwrite($fh, $buffer);
- } else {
- $data .= $buffer;
- }
- }
- break;
-
- case '8bit':
- case '7bit':
- default:
- while (!feof($fd)) {
- $buffer = fread($fd, 1048576); // 1 MB
- if ($fh) {
- fwrite($fh, $buffer);
- } else {
- $data .= $buffer;
- }
- }
- }
-
- fclose($fd);
-
- if (!$fh) {
- return $data;
- }
- }
-
- /**
- * Encodes data to quoted-printable standard.
- *
- * @param string $input The data to encode
- * @param int $line_max Optional max line length. Should
- * not be more than 76 chars
- *
- * @return string Encoded data
- *
- * @access private
- */
- function _quotedPrintableEncode($input , $line_max = 76)
- {
- $eol = $this->_eol;
- /*
- // imap_8bit() is extremely fast, but doesn't handle properly some characters
- if (function_exists('imap_8bit') && $line_max == 76) {
- $input = preg_replace('/\r?\n/', "\r\n", $input);
- $input = imap_8bit($input);
- if ($eol != "\r\n") {
- $input = str_replace("\r\n", $eol, $input);
- }
- return $input;
- }
- */
- $lines = preg_split("/\r?\n/", $input);
- $escape = '=';
- $output = '';
-
- while (list($idx, $line) = each($lines)) {
- $newline = '';
- $i = 0;
-
- while (isset($line[$i])) {
- $char = $line[$i];
- $dec = ord($char);
- $i++;
-
- if (($dec == 32) && (!isset($line[$i]))) {
- // convert space at eol only
- $char = '=20';
- } elseif ($dec == 9 && isset($line[$i])) {
- ; // Do nothing if a TAB is not on eol
- } elseif (($dec == 61) || ($dec < 32) || ($dec > 126)) {
- $char = $escape . sprintf('%02X', $dec);
- } elseif (($dec == 46) && (($newline == '')
- || ((strlen($newline) + strlen("=2E")) >= $line_max))
- ) {
- // Bug #9722: convert full-stop at bol,
- // some Windows servers need this, won't break anything (cipri)
- // Bug #11731: full-stop at bol also needs to be encoded
- // if this line would push us over the line_max limit.
- $char = '=2E';
- }
-
- // Note, when changing this line, also change the ($dec == 46)
- // check line, as it mimics this line due to Bug #11731
- // EOL is not counted
- if ((strlen($newline) + strlen($char)) >= $line_max) {
- // soft line break; " =\r\n" is okay
- $output .= $newline . $escape . $eol;
- $newline = '';
- }
- $newline .= $char;
- } // end of for
- $output .= $newline . $eol;
- unset($lines[$idx]);
- }
- // Don't want last crlf
- $output = substr($output, 0, -1 * strlen($eol));
- return $output;
- }
-
- /**
- * Encodes the paramater of a header.
- *
- * @param string $name The name of the header-parameter
- * @param string $value The value of the paramter
- * @param string $charset The characterset of $value
- * @param string $language The language used in $value
- * @param string $encoding Parameter encoding. If not set, parameter value
- * is encoded according to RFC2231
- * @param int $maxLength The maximum length of a line. Defauls to 75
- *
- * @return string
- *
- * @access private
- */
- function _buildHeaderParam($name, $value, $charset=null, $language=null,
- $encoding=null, $maxLength=75
- ) {
- // RFC 2045:
- // value needs encoding if contains non-ASCII chars or is longer than 78 chars
- if (!preg_match('#[^\x20-\x7E]#', $value)) {
- $token_regexp = '#([^\x21,\x23-\x27,\x2A,\x2B,\x2D'
- . ',\x2E,\x30-\x39,\x41-\x5A,\x5E-\x7E])#';
- if (!preg_match($token_regexp, $value)) {
- // token
- if (strlen($name) + strlen($value) + 3 <= $maxLength) {
- return " {$name}={$value}";
- }
- } else {
- // quoted-string
- $quoted = addcslashes($value, '\\"');
- if (strlen($name) + strlen($quoted) + 5 <= $maxLength) {
- return " {$name}=\"{$quoted}\"";
- }
- }
- }
-
- // RFC2047: use quoted-printable/base64 encoding
- if ($encoding == 'quoted-printable' || $encoding == 'base64') {
- return $this->_buildRFC2047Param($name, $value, $charset, $encoding);
- }
-
- // RFC2231:
- $encValue = preg_replace_callback(
- '/([^\x21,\x23,\x24,\x26,\x2B,\x2D,\x2E,\x30-\x39,\x41-\x5A,\x5E-\x7E])/',
- array($this, '_encodeReplaceCallback'), $value
- );
- $value = "$charset'$language'$encValue";
-
- $header = " {$name}*={$value}";
- if (strlen($header) <= $maxLength) {
- return $header;
- }
-
- $preLength = strlen(" {$name}*0*=");
- $maxLength = max(16, $maxLength - $preLength - 3);
- $maxLengthReg = "|(.{0,$maxLength}[^\%][^\%])|";
-
- $headers = array();
- $headCount = 0;
- while ($value) {
- $matches = array();
- $found = preg_match($maxLengthReg, $value, $matches);
- if ($found) {
- $headers[] = " {$name}*{$headCount}*={$matches[0]}";
- $value = substr($value, strlen($matches[0]));
- } else {
- $headers[] = " {$name}*{$headCount}*={$value}";
- $value = '';
- }
- $headCount++;
- }
-
- $headers = implode(';' . $this->_eol, $headers);
- return $headers;
- }
-
- /**
- * Encodes header parameter as per RFC2047 if needed
- *
- * @param string $name The parameter name
- * @param string $value The parameter value
- * @param string $charset The parameter charset
- * @param string $encoding Encoding type (quoted-printable or base64)
- * @param int $maxLength Encoded parameter max length. Default: 76
- *
- * @return string Parameter line
- * @access private
- */
- function _buildRFC2047Param($name, $value, $charset,
- $encoding='quoted-printable', $maxLength=76
- ) {
- // WARNING: RFC 2047 says: "An 'encoded-word' MUST NOT be used in
- // parameter of a MIME Content-Type or Content-Disposition field",
- // but... it's supported by many clients/servers
- $quoted = '';
-
- if ($encoding == 'base64') {
- $value = base64_encode($value);
- $prefix = '=?' . $charset . '?B?';
- $suffix = '?=';
-
- // 2 x SPACE, 2 x '"', '=', ';'
- $add_len = strlen($prefix . $suffix) + strlen($name) + 6;
- $len = $add_len + strlen($value);
-
- while ($len > $maxLength) {
- // We can cut base64-encoded string every 4 characters
- $real_len = floor(($maxLength - $add_len) / 4) * 4;
- $_quote = substr($value, 0, $real_len);
- $value = substr($value, $real_len);
-
- $quoted .= $prefix . $_quote . $suffix . $this->_eol . ' ';
- $add_len = strlen($prefix . $suffix) + 4; // 2 x SPACE, '"', ';'
- $len = strlen($value) + $add_len;
- }
- $quoted .= $prefix . $value . $suffix;
-
- } else {
- // quoted-printable
- $value = $this->encodeQP($value);
- $prefix = '=?' . $charset . '?Q?';
- $suffix = '?=';
-
- // 2 x SPACE, 2 x '"', '=', ';'
- $add_len = strlen($prefix . $suffix) + strlen($name) + 6;
- $len = $add_len + strlen($value);
-
- while ($len > $maxLength) {
- $length = $maxLength - $add_len;
- // don't break any encoded letters
- if (preg_match("/^(.{0,$length}[^\=][^\=])/", $value, $matches)) {
- $_quote = $matches[1];
- }
-
- $quoted .= $prefix . $_quote . $suffix . $this->_eol . ' ';
- $value = substr($value, strlen($_quote));
- $add_len = strlen($prefix . $suffix) + 4; // 2 x SPACE, '"', ';'
- $len = strlen($value) + $add_len;
- }
-
- $quoted .= $prefix . $value . $suffix;
- }
-
- return " {$name}=\"{$quoted}\"";
- }
-
- /**
- * Encodes a header as per RFC2047
- *
- * @param string $name The header name
- * @param string $value The header data to encode
- * @param string $charset Character set name
- * @param string $encoding Encoding name (base64 or quoted-printable)
- * @param string $eol End-of-line sequence. Default: "\r\n"
- *
- * @return string Encoded header data (without a name)
- * @access public
- * @since 1.6.1
- */
- function encodeHeader($name, $value, $charset='ISO-8859-1',
- $encoding='quoted-printable', $eol="\r\n"
- ) {
- // Structured headers
- $comma_headers = array(
- 'from', 'to', 'cc', 'bcc', 'sender', 'reply-to',
- 'resent-from', 'resent-to', 'resent-cc', 'resent-bcc',
- 'resent-sender', 'resent-reply-to',
- 'return-receipt-to', 'disposition-notification-to',
- );
- $other_headers = array(
- 'references', 'in-reply-to', 'message-id', 'resent-message-id',
- );
-
- $name = strtolower($name);
-
- if (in_array($name, $comma_headers)) {
- $separator = ',';
- } else if (in_array($name, $other_headers)) {
- $separator = ' ';
- }
-
- if (!$charset) {
- $charset = 'ISO-8859-1';
- }
-
- // Structured header (make sure addr-spec inside is not encoded)
- if (!empty($separator)) {
- $parts = Mail_mimePart::_explodeQuotedString($separator, $value);
- $value = '';
-
- foreach ($parts as $part) {
- $part = preg_replace('/\r?\n[\s\t]*/', $eol . ' ', $part);
- $part = trim($part);
-
- if (!$part) {
- continue;
- }
- if ($value) {
- $value .= $separator==',' ? $separator.' ' : ' ';
- } else {
- $value = $name . ': ';
- }
-
- // let's find phrase (name) and/or addr-spec
- if (preg_match('/^<\S+@\S+>$/', $part)) {
- $value .= $part;
- } else if (preg_match('/^\S+@\S+$/', $part)) {
- // address without brackets and without name
- $value .= $part;
- } else if (preg_match('/<*\S+@\S+>*$/', $part, $matches)) {
- // address with name (handle name)
- $address = $matches[0];
- $word = str_replace($address, '', $part);
- $word = trim($word);
- // check if phrase requires quoting
- if ($word) {
- // non-ASCII: require encoding
- if (preg_match('#([\x80-\xFF]){1}#', $word)) {
- if ($word[0] == '"' && $word[strlen($word)-1] == '"') {
- // de-quote quoted-string, encoding changes
- // string to atom
- $search = array("\\\"", "\\\\");
- $replace = array("\"", "\\");
- $word = str_replace($search, $replace, $word);
- $word = substr($word, 1, -1);
- }
- // find length of last line
- if (($pos = strrpos($value, $eol)) !== false) {
- $last_len = strlen($value) - $pos;
- } else {
- $last_len = strlen($value);
- }
- $word = Mail_mimePart::encodeHeaderValue(
- $word, $charset, $encoding, $last_len, $eol
- );
- } else if (($word[0] != '"' || $word[strlen($word)-1] != '"')
- && preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $word)
- ) {
- // ASCII: quote string if needed
- $word = '"'.addcslashes($word, '\\"').'"';
- }
- }
- $value .= $word.' '.$address;
- } else {
- // addr-spec not found, don't encode (?)
- $value .= $part;
- }
-
- // RFC2822 recommends 78 characters limit, use 76 from RFC2047
- $value = wordwrap($value, 76, $eol . ' ');
- }
-
- // remove header name prefix (there could be EOL too)
- $value = preg_replace(
- '/^'.$name.':('.preg_quote($eol, '/').')* /', '', $value
- );
-
- } else {
- // Unstructured header
- // non-ASCII: require encoding
- if (preg_match('#([\x80-\xFF]){1}#', $value)) {
- if ($value[0] == '"' && $value[strlen($value)-1] == '"') {
- // de-quote quoted-string, encoding changes
- // string to atom
- $search = array("\\\"", "\\\\");
- $replace = array("\"", "\\");
- $value = str_replace($search, $replace, $value);
- $value = substr($value, 1, -1);
- }
- $value = Mail_mimePart::encodeHeaderValue(
- $value, $charset, $encoding, strlen($name) + 2, $eol
- );
- } else if (strlen($name.': '.$value) > 78) {
- // ASCII: check if header line isn't too long and use folding
- $value = preg_replace('/\r?\n[\s\t]*/', $eol . ' ', $value);
- $tmp = wordwrap($name.': '.$value, 78, $eol . ' ');
- $value = preg_replace('/^'.$name.':\s*/', '', $tmp);
- // hard limit 998 (RFC2822)
- $value = wordwrap($value, 998, $eol . ' ', true);
- }
- }
-
- return $value;
- }
-
- /**
- * Explode quoted string
- *
- * @param string $delimiter Delimiter expression string for preg_match()
- * @param string $string Input string
- *
- * @return array String tokens array
- * @access private
- */
- function _explodeQuotedString($delimiter, $string)
- {
- $result = array();
- $strlen = strlen($string);
-
- for ($q=$p=$i=0; $i < $strlen; $i++) {
- if ($string[$i] == "\""
- && (empty($string[$i-1]) || $string[$i-1] != "\\")
- ) {
- $q = $q ? false : true;
- } else if (!$q && preg_match("/$delimiter/", $string[$i])) {
- $result[] = substr($string, $p, $i - $p);
- $p = $i + 1;
- }
- }
-
- $result[] = substr($string, $p);
- return $result;
- }
-
- /**
- * Encodes a header value as per RFC2047
- *
- * @param string $value The header data to encode
- * @param string $charset Character set name
- * @param string $encoding Encoding name (base64 or quoted-printable)
- * @param int $prefix_len Prefix length. Default: 0
- * @param string $eol End-of-line sequence. Default: "\r\n"
- *
- * @return string Encoded header data
- * @access public
- * @since 1.6.1
- */
- function encodeHeaderValue($value, $charset, $encoding, $prefix_len=0, $eol="\r\n")
- {
- // #17311: Use multibyte aware method (requires mbstring extension)
- if ($result = Mail_mimePart::encodeMB($value, $charset, $encoding, $prefix_len, $eol)) {
- return $result;
- }
-
- // Generate the header using the specified params and dynamicly
- // determine the maximum length of such strings.
- // 75 is the value specified in the RFC.
- $encoding = $encoding == 'base64' ? 'B' : 'Q';
- $prefix = '=?' . $charset . '?' . $encoding .'?';
- $suffix = '?=';
- $maxLength = 75 - strlen($prefix . $suffix);
- $maxLength1stLine = $maxLength - $prefix_len;
-
- if ($encoding == 'B') {
- // Base64 encode the entire string
- $value = base64_encode($value);
-
- // We can cut base64 every 4 characters, so the real max
- // we can get must be rounded down.
- $maxLength = $maxLength - ($maxLength % 4);
- $maxLength1stLine = $maxLength1stLine - ($maxLength1stLine % 4);
-
- $cutpoint = $maxLength1stLine;
- $output = '';
-
- while ($value) {
- // Split translated string at every $maxLength
- $part = substr($value, 0, $cutpoint);
- $value = substr($value, $cutpoint);
- $cutpoint = $maxLength;
- // RFC 2047 specifies that any split header should
- // be seperated by a CRLF SPACE.
- if ($output) {
- $output .= $eol . ' ';
- }
- $output .= $prefix . $part . $suffix;
- }
- $value = $output;
- } else {
- // quoted-printable encoding has been selected
- $value = Mail_mimePart::encodeQP($value);
-
- // This regexp will break QP-encoded text at every $maxLength
- // but will not break any encoded letters.
- $reg1st = "|(.{0,$maxLength1stLine}[^\=][^\=])|";
- $reg2nd = "|(.{0,$maxLength}[^\=][^\=])|";
-
- if (strlen($value) > $maxLength1stLine) {
- // Begin with the regexp for the first line.
- $reg = $reg1st;
- $output = '';
- while ($value) {
- // Split translated string at every $maxLength
- // But make sure not to break any translated chars.
- $found = preg_match($reg, $value, $matches);
-
- // After this first line, we need to use a different
- // regexp for the first line.
- $reg = $reg2nd;
-
- // Save the found part and encapsulate it in the
- // prefix & suffix. Then remove the part from the
- // $value_out variable.
- if ($found) {
- $part = $matches[0];
- $len = strlen($matches[0]);
- $value = substr($value, $len);
- } else {
- $part = $value;
- $value = '';
- }
-
- // RFC 2047 specifies that any split header should
- // be seperated by a CRLF SPACE
- if ($output) {
- $output .= $eol . ' ';
- }
- $output .= $prefix . $part . $suffix;
- }
- $value = $output;
- } else {
- $value = $prefix . $value . $suffix;
- }
- }
-
- return $value;
- }
-
- /**
- * Encodes the given string using quoted-printable
- *
- * @param string $str String to encode
- *
- * @return string Encoded string
- * @access public
- * @since 1.6.0
- */
- function encodeQP($str)
- {
- // Bug #17226 RFC 2047 restricts some characters
- // if the word is inside a phrase, permitted chars are only:
- // ASCII letters, decimal digits, "!", "*", "+", "-", "/", "=", and "_"
-
- // "=", "_", "?" must be encoded
- $regexp = '/([\x22-\x29\x2C\x2E\x3A-\x40\x5B-\x60\x7B-\x7E\x80-\xFF])/';
- $str = preg_replace_callback(
- $regexp, array('Mail_mimePart', '_qpReplaceCallback'), $str
- );
-
- return str_replace(' ', '_', $str);
- }
-
- /**
- * Encodes the given string using base64 or quoted-printable.
- * This method makes sure that encoded-word represents an integral
- * number of characters as per RFC2047.
- *
- * @param string $str String to encode
- * @param string $charset Character set name
- * @param string $encoding Encoding name (base64 or quoted-printable)
- * @param int $prefix_len Prefix length. Default: 0
- * @param string $eol End-of-line sequence. Default: "\r\n"
- *
- * @return string Encoded string
- * @access public
- * @since 1.8.0
- */
- function encodeMB($str, $charset, $encoding, $prefix_len=0, $eol="\r\n")
- {
- if (!function_exists('mb_substr') || !function_exists('mb_strlen')) {
- return;
- }
-
- $encoding = $encoding == 'base64' ? 'B' : 'Q';
- // 75 is the value specified in the RFC
- $prefix = '=?' . $charset . '?'.$encoding.'?';
- $suffix = '?=';
- $maxLength = 75 - strlen($prefix . $suffix);
-
- // A multi-octet character may not be split across adjacent encoded-words
- // So, we'll loop over each character
- // mb_stlen() with wrong charset will generate a warning here and return null
- $length = mb_strlen($str, $charset);
- $result = '';
- $line_length = $prefix_len;
-
- if ($encoding == 'B') {
- // base64
- $start = 0;
- $prev = '';
-
- for ($i=1; $i<=$length; $i++) {
- // See #17311
- $chunk = mb_substr($str, $start, $i-$start, $charset);
- $chunk = base64_encode($chunk);
- $chunk_len = strlen($chunk);
-
- if ($line_length + $chunk_len == $maxLength || $i == $length) {
- if ($result) {
- $result .= "\n";
- }
- $result .= $chunk;
- $line_length = 0;
- $start = $i;
- } else if ($line_length + $chunk_len > $maxLength) {
- if ($result) {
- $result .= "\n";
- }
- if ($prev) {
- $result .= $prev;
- }
- $line_length = 0;
- $start = $i - 1;
- } else {
- $prev = $chunk;
- }
- }
- } else {
- // quoted-printable
- // see encodeQP()
- $regexp = '/([\x22-\x29\x2C\x2E\x3A-\x40\x5B-\x60\x7B-\x7E\x80-\xFF])/';
-
- for ($i=0; $i<=$length; $i++) {
- $char = mb_substr($str, $i, 1, $charset);
- // RFC recommends underline (instead of =20) in place of the space
- // that's one of the reasons why we're not using iconv_mime_encode()
- if ($char == ' ') {
- $char = '_';
- $char_len = 1;
- } else {
- $char = preg_replace_callback(
- $regexp, array('Mail_mimePart', '_qpReplaceCallback'), $char
- );
- $char_len = strlen($char);
- }
-
- if ($line_length + $char_len > $maxLength) {
- if ($result) {
- $result .= "\n";
- }
- $line_length = 0;
- }
-
- $result .= $char;
- $line_length += $char_len;
- }
- }
-
- if ($result) {
- $result = $prefix
- .str_replace("\n", $suffix.$eol.' '.$prefix, $result).$suffix;
- }
-
- return $result;
- }
-
- /**
- * Callback function to replace extended characters (\x80-xFF) with their
- * ASCII values (RFC2047: quoted-printable)
- *
- * @param array $matches Preg_replace's matches array
- *
- * @return string Encoded character string
- * @access private
- */
- function _qpReplaceCallback($matches)
- {
- return sprintf('=%02X', ord($matches[1]));
- }
-
- /**
- * Callback function to replace extended characters (\x80-xFF) with their
- * ASCII values (RFC2231)
- *
- * @param array $matches Preg_replace's matches array
- *
- * @return string Encoded character string
- * @access private
- */
- function _encodeReplaceCallback($matches)
- {
- return sprintf('%%%02X', ord($matches[1]));
- }
-
-} // End of class
diff --git a/data/module/Mail/mock.php b/data/module/Mail/mock.php
deleted file mode 100644
index 61570ba408c..00000000000
--- a/data/module/Mail/mock.php
+++ /dev/null
@@ -1,143 +0,0 @@
-
- * @copyright 2010 Chuck Hagenbuch
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: mock.php 294747 2010-02-08 08:18:33Z clockwerx $
- * @link http://pear.php.net/package/Mail/
- */
-
-/**
- * Mock implementation of the PEAR Mail:: interface for testing.
- * @access public
- * @package Mail
- * @version $Revision: 294747 $
- */
-class Mail_mock extends Mail {
-
- /**
- * Array of messages that have been sent with the mock.
- *
- * @var array
- * @access public
- */
- var $sentMessages = array();
-
- /**
- * Callback before sending mail.
- *
- * @var callback
- */
- var $_preSendCallback;
-
- /**
- * Callback after sending mai.
- *
- * @var callback
- */
- var $_postSendCallback;
-
- /**
- * Constructor.
- *
- * Instantiates a new Mail_mock:: object based on the parameters
- * passed in. It looks for the following parameters, both optional:
- * preSendCallback Called before an email would be sent.
- * postSendCallback Called after an email would have been sent.
- *
- * @param array Hash containing any parameters.
- * @access public
- */
- function Mail_mock($params)
- {
- if (isset($params['preSendCallback']) &&
- is_callable($params['preSendCallback'])) {
- $this->_preSendCallback = $params['preSendCallback'];
- }
-
- if (isset($params['postSendCallback']) &&
- is_callable($params['postSendCallback'])) {
- $this->_postSendCallback = $params['postSendCallback'];
- }
- }
-
- /**
- * Implements Mail_mock::send() function. Silently discards all
- * mail.
- *
- * @param mixed $recipients Either a comma-seperated list of recipients
- * (RFC822 compliant), or an array of recipients,
- * each RFC822 valid. This may contain recipients not
- * specified in the headers, for Bcc:, resending
- * messages, etc.
- *
- * @param array $headers The array of headers to send with the mail, in an
- * associative array, where the array key is the
- * header name (ie, 'Subject'), and the array value
- * is the header value (ie, 'test'). The header
- * produced from those values would be 'Subject:
- * test'.
- *
- * @param string $body The full text of the message body, including any
- * Mime parts, etc.
- *
- * @return mixed Returns true on success, or a PEAR_Error
- * containing a descriptive error message on
- * failure.
- * @access public
- */
- function send($recipients, $headers, $body)
- {
- if ($this->_preSendCallback) {
- call_user_func_array($this->_preSendCallback,
- array(&$this, $recipients, $headers, $body));
- }
-
- $entry = array('recipients' => $recipients, 'headers' => $headers, 'body' => $body);
- $this->sentMessages[] = $entry;
-
- if ($this->_postSendCallback) {
- call_user_func_array($this->_postSendCallback,
- array(&$this, $recipients, $headers, $body));
- }
-
- return true;
- }
-
-}
diff --git a/data/module/Mail/null.php b/data/module/Mail/null.php
deleted file mode 100644
index c8d9fbc16c9..00000000000
--- a/data/module/Mail/null.php
+++ /dev/null
@@ -1,84 +0,0 @@
-
- * @copyright 2010 Phil Kernick
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id$
- * @link http://pear.php.net/package/Mail/
- */
-
-/**
- * Null implementation of the PEAR Mail:: interface.
- * @access public
- * @package Mail
- * @version $Revision$
- */
-class Mail_null extends Mail {
-
- /**
- * Implements Mail_null::send() function. Silently discards all
- * mail.
- *
- * @param mixed $recipients Either a comma-seperated list of recipients
- * (RFC822 compliant), or an array of recipients,
- * each RFC822 valid. This may contain recipients not
- * specified in the headers, for Bcc:, resending
- * messages, etc.
- *
- * @param array $headers The array of headers to send with the mail, in an
- * associative array, where the array key is the
- * header name (ie, 'Subject'), and the array value
- * is the header value (ie, 'test'). The header
- * produced from those values would be 'Subject:
- * test'.
- *
- * @param string $body The full text of the message body, including any
- * Mime parts, etc.
- *
- * @return mixed Returns true on success, or a PEAR_Error
- * containing a descriptive error message on
- * failure.
- * @access public
- */
- function send($recipients, $headers, $body)
- {
- return true;
- }
-
-}
diff --git a/data/module/Mail/sendmail.php b/data/module/Mail/sendmail.php
deleted file mode 100644
index 627b0e8f6a3..00000000000
--- a/data/module/Mail/sendmail.php
+++ /dev/null
@@ -1,171 +0,0 @@
- |
-// +----------------------------------------------------------------------+
-
-/**
- * Sendmail implementation of the PEAR Mail:: interface.
- * @access public
- * @package Mail
- * @version $Revision$
- */
-class Mail_sendmail extends Mail {
-
- /**
- * The location of the sendmail or sendmail wrapper binary on the
- * filesystem.
- * @var string
- */
- var $sendmail_path = '/usr/sbin/sendmail';
-
- /**
- * Any extra command-line parameters to pass to the sendmail or
- * sendmail wrapper binary.
- * @var string
- */
- var $sendmail_args = '-i';
-
- /**
- * Constructor.
- *
- * Instantiates a new Mail_sendmail:: object based on the parameters
- * passed in. It looks for the following parameters:
- * sendmail_path The location of the sendmail binary on the
- * filesystem. Defaults to '/usr/sbin/sendmail'.
- *
- * sendmail_args Any extra parameters to pass to the sendmail
- * or sendmail wrapper binary.
- *
- * If a parameter is present in the $params array, it replaces the
- * default.
- *
- * @param array $params Hash containing any parameters different from the
- * defaults.
- * @access public
- */
- function Mail_sendmail($params)
- {
- if (isset($params['sendmail_path'])) {
- $this->sendmail_path = $params['sendmail_path'];
- }
- if (isset($params['sendmail_args'])) {
- $this->sendmail_args = $params['sendmail_args'];
- }
-
- /*
- * Because we need to pass message headers to the sendmail program on
- * the commandline, we can't guarantee the use of the standard "\r\n"
- * separator. Instead, we use the system's native line separator.
- */
- if (defined('PHP_EOL')) {
- $this->sep = PHP_EOL;
- } else {
- $this->sep = (strpos(PHP_OS, 'WIN') === false) ? "\n" : "\r\n";
- }
- }
-
- /**
- * Implements Mail::send() function using the sendmail
- * command-line binary.
- *
- * @param mixed $recipients Either a comma-seperated list of recipients
- * (RFC822 compliant), or an array of recipients,
- * each RFC822 valid. This may contain recipients not
- * specified in the headers, for Bcc:, resending
- * messages, etc.
- *
- * @param array $headers The array of headers to send with the mail, in an
- * associative array, where the array key is the
- * header name (ie, 'Subject'), and the array value
- * is the header value (ie, 'test'). The header
- * produced from those values would be 'Subject:
- * test'.
- *
- * @param string $body The full text of the message body, including any
- * Mime parts, etc.
- *
- * @return mixed Returns true on success, or a PEAR_Error
- * containing a descriptive error message on
- * failure.
- * @access public
- */
- function send($recipients, $headers, $body)
- {
- if (!is_array($headers)) {
- return PEAR::raiseError('$headers must be an array');
- }
-
- $result = $this->_sanitizeHeaders($headers);
- if (is_a($result, 'PEAR_Error')) {
- return $result;
- }
-
- $recipients = $this->parseRecipients($recipients);
- if (is_a($recipients, 'PEAR_Error')) {
- return $recipients;
- }
- $recipients = implode(' ', array_map('escapeshellarg', $recipients));
-
- $headerElements = $this->prepareHeaders($headers);
- if (is_a($headerElements, 'PEAR_Error')) {
- return $headerElements;
- }
- list($from, $text_headers) = $headerElements;
-
- /* Since few MTAs are going to allow this header to be forged
- * unless it's in the MAIL FROM: exchange, we'll use
- * Return-Path instead of From: if it's set. */
- if (!empty($headers['Return-Path'])) {
- $from = $headers['Return-Path'];
- }
-
- if (!isset($from)) {
- return PEAR::raiseError('No from address given.');
- } elseif (strpos($from, ' ') !== false ||
- strpos($from, ';') !== false ||
- strpos($from, '&') !== false ||
- strpos($from, '`') !== false) {
- return PEAR::raiseError('From address specified with dangerous characters.');
- }
-
- $from = escapeshellarg($from); // Security bug #16200
-
- $mail = @popen($this->sendmail_path . (!empty($this->sendmail_args) ? ' ' . $this->sendmail_args : '') . " -f$from -- $recipients", 'w');
- if (!$mail) {
- return PEAR::raiseError('Failed to open sendmail [' . $this->sendmail_path . '] for execution.');
- }
-
- // Write the headers following by two newlines: one to end the headers
- // section and a second to separate the headers block from the body.
- fputs($mail, $text_headers . $this->sep . $this->sep);
-
- fputs($mail, $body);
- $result = pclose($mail);
- if (version_compare(phpversion(), '4.2.3') == -1) {
- // With older php versions, we need to shift the pclose
- // result to get the exit code.
- $result = $result >> 8 & 0xFF;
- }
-
- if ($result != 0) {
- return PEAR::raiseError('sendmail returned error code ' . $result,
- $result);
- }
-
- return true;
- }
-
-}
diff --git a/data/module/Mail/smtp.php b/data/module/Mail/smtp.php
deleted file mode 100644
index 52ea6020865..00000000000
--- a/data/module/Mail/smtp.php
+++ /dev/null
@@ -1,444 +0,0 @@
-
- * @author Chuck Hagenbuch
- * @copyright 2010 Chuck Hagenbuch
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: smtp.php 294747 2010-02-08 08:18:33Z clockwerx $
- * @link http://pear.php.net/package/Mail/
- */
-
-/** Error: Failed to create a Net_SMTP object */
-define('PEAR_MAIL_SMTP_ERROR_CREATE', 10000);
-
-/** Error: Failed to connect to SMTP server */
-define('PEAR_MAIL_SMTP_ERROR_CONNECT', 10001);
-
-/** Error: SMTP authentication failure */
-define('PEAR_MAIL_SMTP_ERROR_AUTH', 10002);
-
-/** Error: No From: address has been provided */
-define('PEAR_MAIL_SMTP_ERROR_FROM', 10003);
-
-/** Error: Failed to set sender */
-define('PEAR_MAIL_SMTP_ERROR_SENDER', 10004);
-
-/** Error: Failed to add recipient */
-define('PEAR_MAIL_SMTP_ERROR_RECIPIENT', 10005);
-
-/** Error: Failed to send data */
-define('PEAR_MAIL_SMTP_ERROR_DATA', 10006);
-
-/**
- * SMTP implementation of the PEAR Mail interface. Requires the Net_SMTP class.
- * @access public
- * @package Mail
- * @version $Revision: 294747 $
- */
-class Mail_smtp extends Mail {
-
- /**
- * SMTP connection object.
- *
- * @var object
- * @access private
- */
- var $_smtp = null;
-
- /**
- * The list of service extension parameters to pass to the Net_SMTP
- * mailFrom() command.
- * @var array
- */
- var $_extparams = array();
-
- /**
- * The SMTP host to connect to.
- * @var string
- */
- var $host = 'localhost';
-
- /**
- * The port the SMTP server is on.
- * @var integer
- */
- var $port = 25;
-
- /**
- * Should SMTP authentication be used?
- *
- * This value may be set to true, false or the name of a specific
- * authentication method.
- *
- * If the value is set to true, the Net_SMTP package will attempt to use
- * the best authentication method advertised by the remote SMTP server.
- *
- * @var mixed
- */
- var $auth = false;
-
- /**
- * The username to use if the SMTP server requires authentication.
- * @var string
- */
- var $username = '';
-
- /**
- * The password to use if the SMTP server requires authentication.
- * @var string
- */
- var $password = '';
-
- /**
- * Hostname or domain that will be sent to the remote SMTP server in the
- * HELO / EHLO message.
- *
- * @var string
- */
- var $localhost = 'localhost';
-
- /**
- * SMTP connection timeout value. NULL indicates no timeout.
- *
- * @var integer
- */
- var $timeout = null;
-
- /**
- * Turn on Net_SMTP debugging?
- *
- * @var boolean $debug
- */
- var $debug = false;
-
- /**
- * Indicates whether or not the SMTP connection should persist over
- * multiple calls to the send() method.
- *
- * @var boolean
- */
- var $persist = false;
-
- /**
- * Use SMTP command pipelining (specified in RFC 2920) if the SMTP server
- * supports it. This speeds up delivery over high-latency connections. By
- * default, use the default value supplied by Net_SMTP.
- * @var bool
- */
- var $pipelining;
-
- /**
- * Constructor.
- *
- * Instantiates a new Mail_smtp:: object based on the parameters
- * passed in. It looks for the following parameters:
- * host The server to connect to. Defaults to localhost.
- * port The port to connect to. Defaults to 25.
- * auth SMTP authentication. Defaults to none.
- * username The username to use for SMTP auth. No default.
- * password The password to use for SMTP auth. No default.
- * localhost The local hostname / domain. Defaults to localhost.
- * timeout The SMTP connection timeout. Defaults to none.
- * verp Whether to use VERP or not. Defaults to false.
- * DEPRECATED as of 1.2.0 (use setMailParams()).
- * debug Activate SMTP debug mode? Defaults to false.
- * persist Should the SMTP connection persist?
- * pipelining Use SMTP command pipelining
- *
- * If a parameter is present in the $params array, it replaces the
- * default.
- *
- * @param array Hash containing any parameters different from the
- * defaults.
- * @access public
- */
- function Mail_smtp($params)
- {
- if (isset($params['host'])) $this->host = $params['host'];
- if (isset($params['port'])) $this->port = $params['port'];
- if (isset($params['auth'])) $this->auth = $params['auth'];
- if (isset($params['username'])) $this->username = $params['username'];
- if (isset($params['password'])) $this->password = $params['password'];
- if (isset($params['localhost'])) $this->localhost = $params['localhost'];
- if (isset($params['timeout'])) $this->timeout = $params['timeout'];
- if (isset($params['debug'])) $this->debug = (bool)$params['debug'];
- if (isset($params['persist'])) $this->persist = (bool)$params['persist'];
- if (isset($params['pipelining'])) $this->pipelining = (bool)$params['pipelining'];
-
- // Deprecated options
- if (isset($params['verp'])) {
- $this->addServiceExtensionParameter('XVERP', is_bool($params['verp']) ? null : $params['verp']);
- }
-
- register_shutdown_function(array(&$this, '_Mail_smtp'));
- }
-
- /**
- * Destructor implementation to ensure that we disconnect from any
- * potentially-alive persistent SMTP connections.
- */
- function _Mail_smtp()
- {
- $this->disconnect();
- }
-
- /**
- * Implements Mail::send() function using SMTP.
- *
- * @param mixed $recipients Either a comma-seperated list of recipients
- * (RFC822 compliant), or an array of recipients,
- * each RFC822 valid. This may contain recipients not
- * specified in the headers, for Bcc:, resending
- * messages, etc.
- *
- * @param array $headers The array of headers to send with the mail, in an
- * associative array, where the array key is the
- * header name (e.g., 'Subject'), and the array value
- * is the header value (e.g., 'test'). The header
- * produced from those values would be 'Subject:
- * test'.
- *
- * @param string $body The full text of the message body, including any
- * MIME parts, etc.
- *
- * @return mixed Returns true on success, or a PEAR_Error
- * containing a descriptive error message on
- * failure.
- * @access public
- */
- function send($recipients, $headers, $body)
- {
- /* If we don't already have an SMTP object, create one. */
- $result = &$this->getSMTPObject();
- if (PEAR::isError($result)) {
- return $result;
- }
-
- if (!is_array($headers)) {
- return PEAR::raiseError('$headers must be an array');
- }
-
- $this->_sanitizeHeaders($headers);
-
- $headerElements = $this->prepareHeaders($headers);
- if (is_a($headerElements, 'PEAR_Error')) {
- $this->_smtp->rset();
- return $headerElements;
- }
- list($from, $textHeaders) = $headerElements;
-
- /* Since few MTAs are going to allow this header to be forged
- * unless it's in the MAIL FROM: exchange, we'll use
- * Return-Path instead of From: if it's set. */
- if (!empty($headers['Return-Path'])) {
- $from = $headers['Return-Path'];
- }
-
- if (!isset($from)) {
- $this->_smtp->rset();
- return PEAR::raiseError('No From: address has been provided',
- PEAR_MAIL_SMTP_ERROR_FROM);
- }
-
- $params = null;
- if (!empty($this->_extparams)) {
- foreach ($this->_extparams as $key => $val) {
- $params .= ' ' . $key . (is_null($val) ? '' : '=' . $val);
- }
- }
- if (PEAR::isError($res = $this->_smtp->mailFrom($from, ltrim($params)))) {
- $error = $this->_error("Failed to set sender: $from", $res);
- $this->_smtp->rset();
- return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_SENDER);
- }
-
- $recipients = $this->parseRecipients($recipients);
- if (is_a($recipients, 'PEAR_Error')) {
- $this->_smtp->rset();
- return $recipients;
- }
-
- foreach ($recipients as $recipient) {
- $res = $this->_smtp->rcptTo($recipient);
- if (is_a($res, 'PEAR_Error')) {
- $error = $this->_error("Failed to add recipient: $recipient", $res);
- $this->_smtp->rset();
- return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_RECIPIENT);
- }
- }
-
- /* Send the message's headers and the body as SMTP data. */
- $res = $this->_smtp->data($textHeaders . "\r\n\r\n" . $body);
- list(,$args) = $this->_smtp->getResponse();
-
- if (preg_match("/Ok: queued as (.*)/", $args, $queued)) {
- $this->queued_as = $queued[1];
- }
-
- /* we need the greeting; from it we can extract the authorative name of the mail server we've really connected to.
- * ideal if we're connecting to a round-robin of relay servers and need to track which exact one took the email */
- $this->greeting = $this->_smtp->getGreeting();
-
- if (is_a($res, 'PEAR_Error')) {
- $error = $this->_error('Failed to send data', $res);
- $this->_smtp->rset();
- return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_DATA);
- }
-
- /* If persistent connections are disabled, destroy our SMTP object. */
- if ($this->persist === false) {
- $this->disconnect();
- }
-
- return true;
- }
-
- /**
- * Connect to the SMTP server by instantiating a Net_SMTP object.
- *
- * @return mixed Returns a reference to the Net_SMTP object on success, or
- * a PEAR_Error containing a descriptive error message on
- * failure.
- *
- * @since 1.2.0
- * @access public
- */
- function &getSMTPObject()
- {
- if (is_object($this->_smtp) !== false) {
- return $this->_smtp;
- }
-
- include_once 'Net/SMTP.php';
- $this->_smtp = &new Net_SMTP($this->host,
- $this->port,
- $this->localhost);
-
- /* If we still don't have an SMTP object at this point, fail. */
- if (is_object($this->_smtp) === false) {
- return PEAR::raiseError('Failed to create a Net_SMTP object',
- PEAR_MAIL_SMTP_ERROR_CREATE);
- }
-
- /* Configure the SMTP connection. */
- if ($this->debug) {
- $this->_smtp->setDebug(true);
- }
-
- /* Attempt to connect to the configured SMTP server. */
- if (PEAR::isError($res = $this->_smtp->connect($this->timeout))) {
- $error = $this->_error('Failed to connect to ' .
- $this->host . ':' . $this->port,
- $res);
- return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_CONNECT);
- }
-
- /* Attempt to authenticate if authentication has been enabled. */
- if ($this->auth) {
- $method = is_string($this->auth) ? $this->auth : '';
-
- if (PEAR::isError($res = $this->_smtp->auth($this->username,
- $this->password,
- $method))) {
- $error = $this->_error("$method authentication failure",
- $res);
- $this->_smtp->rset();
- return PEAR::raiseError($error, PEAR_MAIL_SMTP_ERROR_AUTH);
- }
- }
-
- return $this->_smtp;
- }
-
- /**
- * Add parameter associated with a SMTP service extension.
- *
- * @param string Extension keyword.
- * @param string Any value the keyword needs.
- *
- * @since 1.2.0
- * @access public
- */
- function addServiceExtensionParameter($keyword, $value = null)
- {
- $this->_extparams[$keyword] = $value;
- }
-
- /**
- * Disconnect and destroy the current SMTP connection.
- *
- * @return boolean True if the SMTP connection no longer exists.
- *
- * @since 1.1.9
- * @access public
- */
- function disconnect()
- {
- /* If we have an SMTP object, disconnect and destroy it. */
- if (is_object($this->_smtp) && $this->_smtp->disconnect()) {
- $this->_smtp = null;
- }
-
- /* We are disconnected if we no longer have an SMTP object. */
- return ($this->_smtp === null);
- }
-
- /**
- * Build a standardized string describing the current SMTP error.
- *
- * @param string $text Custom string describing the error context.
- * @param object $error Reference to the current PEAR_Error object.
- *
- * @return string A string describing the current SMTP error.
- *
- * @since 1.1.7
- * @access private
- */
- function _error($text, &$error)
- {
- /* Split the SMTP response into a code and a response string. */
- list($code, $response) = $this->_smtp->getResponse();
-
- /* Build our standardized error string. */
- return $text
- . ' [SMTP: ' . $error->getMessage()
- . " (code: $code, response: $response)]";
- }
-
-}
diff --git a/data/module/Mail/smtpmx.php b/data/module/Mail/smtpmx.php
deleted file mode 100644
index f0b69408681..00000000000
--- a/data/module/Mail/smtpmx.php
+++ /dev/null
@@ -1,502 +0,0 @@
-
- * @copyright 2010 gERD Schaufelberger
- * @license http://opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id: smtpmx.php 294747 2010-02-08 08:18:33Z clockwerx $
- * @link http://pear.php.net/package/Mail/
- */
-
-require_once 'Net/SMTP.php';
-
-/**
- * SMTP MX implementation of the PEAR Mail interface. Requires the Net_SMTP class.
- *
- *
- * @access public
- * @author gERD Schaufelberger
- * @package Mail
- * @version $Revision: 294747 $
- */
-class Mail_smtpmx extends Mail {
-
- /**
- * SMTP connection object.
- *
- * @var object
- * @access private
- */
- var $_smtp = null;
-
- /**
- * The port the SMTP server is on.
- * @var integer
- * @see getservicebyname()
- */
- var $port = 25;
-
- /**
- * Hostname or domain that will be sent to the remote SMTP server in the
- * HELO / EHLO message.
- *
- * @var string
- * @see posix_uname()
- */
- var $mailname = 'localhost';
-
- /**
- * SMTP connection timeout value. NULL indicates no timeout.
- *
- * @var integer
- */
- var $timeout = 10;
-
- /**
- * use either PEAR:Net_DNS or getmxrr
- *
- * @var boolean
- */
- var $withNetDns = true;
-
- /**
- * PEAR:Net_DNS_Resolver
- *
- * @var object
- */
- var $resolver;
-
- /**
- * Whether to use VERP or not. If not a boolean, the string value
- * will be used as the VERP separators.
- *
- * @var mixed boolean or string
- */
- var $verp = false;
-
- /**
- * Whether to use VRFY or not.
- *
- * @var boolean $vrfy
- */
- var $vrfy = false;
-
- /**
- * Switch to test mode - don't send emails for real
- *
- * @var boolean $debug
- */
- var $test = false;
-
- /**
- * Turn on Net_SMTP debugging?
- *
- * @var boolean $peardebug
- */
- var $debug = false;
-
- /**
- * internal error codes
- *
- * translate internal error identifier to PEAR-Error codes and human
- * readable messages.
- *
- * @var boolean $debug
- * @todo as I need unique error-codes to identify what exactly went wrond
- * I did not use intergers as it should be. Instead I added a "namespace"
- * for each code. This avoids conflicts with error codes from different
- * classes. How can I use unique error codes and stay conform with PEAR?
- */
- var $errorCode = array(
- 'not_connected' => array(
- 'code' => 1,
- 'msg' => 'Could not connect to any mail server ({HOST}) at port {PORT} to send mail to {RCPT}.'
- ),
- 'failed_vrfy_rcpt' => array(
- 'code' => 2,
- 'msg' => 'Recipient "{RCPT}" could not be veryfied.'
- ),
- 'failed_set_from' => array(
- 'code' => 3,
- 'msg' => 'Failed to set sender: {FROM}.'
- ),
- 'failed_set_rcpt' => array(
- 'code' => 4,
- 'msg' => 'Failed to set recipient: {RCPT}.'
- ),
- 'failed_send_data' => array(
- 'code' => 5,
- 'msg' => 'Failed to send mail to: {RCPT}.'
- ),
- 'no_from' => array(
- 'code' => 5,
- 'msg' => 'No from address has be provided.'
- ),
- 'send_data' => array(
- 'code' => 7,
- 'msg' => 'Failed to create Net_SMTP object.'
- ),
- 'no_mx' => array(
- 'code' => 8,
- 'msg' => 'No MX-record for {RCPT} found.'
- ),
- 'no_resolver' => array(
- 'code' => 9,
- 'msg' => 'Could not start resolver! Install PEAR:Net_DNS or switch off "netdns"'
- ),
- 'failed_rset' => array(
- 'code' => 10,
- 'msg' => 'RSET command failed, SMTP-connection corrupt.'
- ),
- );
-
- /**
- * Constructor.
- *
- * Instantiates a new Mail_smtp:: object based on the parameters
- * passed in. It looks for the following parameters:
- * mailname The name of the local mail system (a valid hostname which matches the reverse lookup)
- * port smtp-port - the default comes from getservicebyname() and should work fine
- * timeout The SMTP connection timeout. Defaults to 30 seconds.
- * vrfy Whether to use VRFY or not. Defaults to false.
- * verp Whether to use VERP or not. Defaults to false.
- * test Activate test mode? Defaults to false.
- * debug Activate SMTP and Net_DNS debug mode? Defaults to false.
- * netdns whether to use PEAR:Net_DNS or the PHP build in function getmxrr, default is true
- *
- * If a parameter is present in the $params array, it replaces the
- * default.
- *
- * @access public
- * @param array Hash containing any parameters different from the
- * defaults.
- * @see _Mail_smtpmx()
- */
- function __construct($params)
- {
- if (isset($params['mailname'])) {
- $this->mailname = $params['mailname'];
- } else {
- // try to find a valid mailname
- if (function_exists('posix_uname')) {
- $uname = posix_uname();
- $this->mailname = $uname['nodename'];
- }
- }
-
- // port number
- if (isset($params['port'])) {
- $this->_port = $params['port'];
- } else {
- $this->_port = getservbyname('smtp', 'tcp');
- }
-
- if (isset($params['timeout'])) $this->timeout = $params['timeout'];
- if (isset($params['verp'])) $this->verp = $params['verp'];
- if (isset($params['test'])) $this->test = $params['test'];
- if (isset($params['peardebug'])) $this->test = $params['peardebug'];
- if (isset($params['netdns'])) $this->withNetDns = $params['netdns'];
- }
-
- /**
- * Constructor wrapper for PHP4
- *
- * @access public
- * @param array Hash containing any parameters different from the defaults
- * @see __construct()
- */
- function Mail_smtpmx($params)
- {
- $this->__construct($params);
- register_shutdown_function(array(&$this, '__destruct'));
- }
-
- /**
- * Destructor implementation to ensure that we disconnect from any
- * potentially-alive persistent SMTP connections.
- */
- function __destruct()
- {
- if (is_object($this->_smtp)) {
- $this->_smtp->disconnect();
- $this->_smtp = null;
- }
- }
-
- /**
- * Implements Mail::send() function using SMTP direct delivery
- *
- * @access public
- * @param mixed $recipients in RFC822 style or array
- * @param array $headers The array of headers to send with the mail.
- * @param string $body The full text of the message body,
- * @return mixed Returns true on success, or a PEAR_Error
- */
- function send($recipients, $headers, $body)
- {
- if (!is_array($headers)) {
- return PEAR::raiseError('$headers must be an array');
- }
-
- $result = $this->_sanitizeHeaders($headers);
- if (is_a($result, 'PEAR_Error')) {
- return $result;
- }
-
- // Prepare headers
- $headerElements = $this->prepareHeaders($headers);
- if (is_a($headerElements, 'PEAR_Error')) {
- return $headerElements;
- }
- list($from, $textHeaders) = $headerElements;
-
- // use 'Return-Path' if possible
- if (!empty($headers['Return-Path'])) {
- $from = $headers['Return-Path'];
- }
- if (!isset($from)) {
- return $this->_raiseError('no_from');
- }
-
- // Prepare recipients
- $recipients = $this->parseRecipients($recipients);
- if (is_a($recipients, 'PEAR_Error')) {
- return $recipients;
- }
-
- foreach ($recipients as $rcpt) {
- list($user, $host) = explode('@', $rcpt);
-
- $mx = $this->_getMx($host);
- if (is_a($mx, 'PEAR_Error')) {
- return $mx;
- }
-
- if (empty($mx)) {
- $info = array('rcpt' => $rcpt);
- return $this->_raiseError('no_mx', $info);
- }
-
- $connected = false;
- foreach ($mx as $mserver => $mpriority) {
- $this->_smtp = new Net_SMTP($mserver, $this->port, $this->mailname);
-
- // configure the SMTP connection.
- if ($this->debug) {
- $this->_smtp->setDebug(true);
- }
-
- // attempt to connect to the configured SMTP server.
- $res = $this->_smtp->connect($this->timeout);
- if (is_a($res, 'PEAR_Error')) {
- $this->_smtp = null;
- continue;
- }
-
- // connection established
- if ($res) {
- $connected = true;
- break;
- }
- }
-
- if (!$connected) {
- $info = array(
- 'host' => implode(', ', array_keys($mx)),
- 'port' => $this->port,
- 'rcpt' => $rcpt,
- );
- return $this->_raiseError('not_connected', $info);
- }
-
- // Verify recipient
- if ($this->vrfy) {
- $res = $this->_smtp->vrfy($rcpt);
- if (is_a($res, 'PEAR_Error')) {
- $info = array('rcpt' => $rcpt);
- return $this->_raiseError('failed_vrfy_rcpt', $info);
- }
- }
-
- // mail from:
- $args['verp'] = $this->verp;
- $res = $this->_smtp->mailFrom($from, $args);
- if (is_a($res, 'PEAR_Error')) {
- $info = array('from' => $from);
- return $this->_raiseError('failed_set_from', $info);
- }
-
- // rcpt to:
- $res = $this->_smtp->rcptTo($rcpt);
- if (is_a($res, 'PEAR_Error')) {
- $info = array('rcpt' => $rcpt);
- return $this->_raiseError('failed_set_rcpt', $info);
- }
-
- // Don't send anything in test mode
- if ($this->test) {
- $result = $this->_smtp->rset();
- $res = $this->_smtp->rset();
- if (is_a($res, 'PEAR_Error')) {
- return $this->_raiseError('failed_rset');
- }
-
- $this->_smtp->disconnect();
- $this->_smtp = null;
- return true;
- }
-
- // Send data
- $res = $this->_smtp->data("$textHeaders\r\n$body");
- if (is_a($res, 'PEAR_Error')) {
- $info = array('rcpt' => $rcpt);
- return $this->_raiseError('failed_send_data', $info);
- }
-
- $this->_smtp->disconnect();
- $this->_smtp = null;
- }
-
- return true;
- }
-
- /**
- * Recieve mx rexords for a spciefied host
- *
- * The MX records
- *
- * @access private
- * @param string $host mail host
- * @return mixed sorted
- */
- function _getMx($host)
- {
- $mx = array();
-
- if ($this->withNetDns) {
- $res = $this->_loadNetDns();
- if (is_a($res, 'PEAR_Error')) {
- return $res;
- }
-
- $response = $this->resolver->query($host, 'MX');
- if (!$response) {
- return false;
- }
-
- foreach ($response->answer as $rr) {
- if ($rr->type == 'MX') {
- $mx[$rr->exchange] = $rr->preference;
- }
- }
- } else {
- $mxHost = array();
- $mxWeight = array();
-
- if (!getmxrr($host, $mxHost, $mxWeight)) {
- return false;
- }
- for ($i = 0; $i < count($mxHost); ++$i) {
- $mx[$mxHost[$i]] = $mxWeight[$i];
- }
- }
-
- asort($mx);
- return $mx;
- }
-
- /**
- * initialize PEAR:Net_DNS_Resolver
- *
- * @access private
- * @return boolean true on success
- */
- function _loadNetDns()
- {
- if (is_object($this->resolver)) {
- return true;
- }
-
- if (!include_once 'Net/DNS.php') {
- return $this->_raiseError('no_resolver');
- }
-
- $this->resolver = new Net_DNS_Resolver();
- if ($this->debug) {
- $this->resolver->test = 1;
- }
-
- return true;
- }
-
- /**
- * raise standardized error
- *
- * include additional information in error message
- *
- * @access private
- * @param string $id maps error ids to codes and message
- * @param array $info optional information in associative array
- * @see _errorCode
- */
- function _raiseError($id, $info = array())
- {
- $code = $this->errorCode[$id]['code'];
- $msg = $this->errorCode[$id]['msg'];
-
- // include info to messages
- if (!empty($info)) {
- $search = array();
- $replace = array();
-
- foreach ($info as $key => $value) {
- array_push($search, '{' . strtoupper($key) . '}');
- array_push($replace, $value);
- }
-
- $msg = str_replace($search, $replace, $msg);
- }
-
- return PEAR::raiseError($msg, $code);
- }
-
-}
diff --git a/data/module/Mobile/Detect.php b/data/module/Mobile/Detect.php
deleted file mode 100755
index b6eb0da21b3..00000000000
--- a/data/module/Mobile/Detect.php
+++ /dev/null
@@ -1,1248 +0,0 @@
-, Nick Ilyin
- * Original author: Victor Stanciu
- *
- * @license Code and contributions have 'MIT License'
- * More details: https://github.com/serbanghita/Mobile-Detect/blob/master/LICENSE.txt
- *
- * @link Homepage: http://mobiledetect.net
- * GitHub Repo: https://github.com/serbanghita/Mobile-Detect
- * Google Code: http://code.google.com/p/php-mobile-detect/
- * README: https://github.com/serbanghita/Mobile-Detect/blob/master/README.md
- * HOWTO: https://github.com/serbanghita/Mobile-Detect/wiki/Code-examples
- *
- * @version 2.8.3
- */
-
-class Mobile_Detect
-{
- /**
- * Mobile detection type.
- *
- * @deprecated since version 2.6.9
- */
- const DETECTION_TYPE_MOBILE = 'mobile';
-
- /**
- * Extended detection type.
- *
- * @deprecated since version 2.6.9
- */
- const DETECTION_TYPE_EXTENDED = 'extended';
-
- /**
- * A frequently used regular expression to extract version #s.
- *
- * @deprecated since version 2.6.9
- */
- const VER = '([\w._\+]+)';
-
- /**
- * Top-level device.
- */
- const MOBILE_GRADE_A = 'A';
-
- /**
- * Mid-level device.
- */
- const MOBILE_GRADE_B = 'B';
-
- /**
- * Low-level device.
- */
- const MOBILE_GRADE_C = 'C';
-
- /**
- * Stores the version number of the current release.
- */
- const VERSION = '2.8.3';
-
- /**
- * A type for the version() method indicating a string return value.
- */
- const VERSION_TYPE_STRING = 'text';
-
- /**
- * A type for the version() method indicating a float return value.
- */
- const VERSION_TYPE_FLOAT = 'float';
-
- /**
- * The User-Agent HTTP header is stored in here.
- * @var string
- */
- protected $userAgent = null;
-
- /**
- * HTTP headers in the PHP-flavor. So HTTP_USER_AGENT and SERVER_SOFTWARE.
- * @var array
- */
- protected $httpHeaders = array();
-
- /**
- * The detection type, using self::DETECTION_TYPE_MOBILE or self::DETECTION_TYPE_EXTENDED.
- *
- * @deprecated since version 2.6.9
- *
- * @var string
- */
- protected $detectionType = self::DETECTION_TYPE_MOBILE;
-
- /**
- * HTTP headers that trigger the 'isMobile' detection
- * to be true.
- *
- * @var array
- */
- protected static $mobileHeaders = array(
-
- 'HTTP_ACCEPT' => array('matches' => array(
- // Opera Mini; @reference: http://dev.opera.com/articles/view/opera-binary-markup-language/
- 'application/x-obml2d',
- // BlackBerry devices.
- 'application/vnd.rim.html',
- 'text/vnd.wap.wml',
- 'application/vnd.wap.xhtml+xml'
- )),
- 'HTTP_X_WAP_PROFILE' => null,
- 'HTTP_X_WAP_CLIENTID' => null,
- 'HTTP_WAP_CONNECTION' => null,
- 'HTTP_PROFILE' => null,
- // Reported by Opera on Nokia devices (eg. C3).
- 'HTTP_X_OPERAMINI_PHONE_UA' => null,
- 'HTTP_X_NOKIA_GATEWAY_ID' => null,
- 'HTTP_X_ORANGE_ID' => null,
- 'HTTP_X_VODAFONE_3GPDPCONTEXT' => null,
- 'HTTP_X_HUAWEI_USERID' => null,
- // Reported by Windows Smartphones.
- 'HTTP_UA_OS' => null,
- // Reported by Verizon, Vodafone proxy system.
- 'HTTP_X_MOBILE_GATEWAY' => null,
- // Seend this on HTC Sensation. @ref: SensationXE_Beats_Z715e.
- 'HTTP_X_ATT_DEVICEID' => null,
- // Seen this on a HTC.
- 'HTTP_UA_CPU' => array('matches' => array('ARM')),
- );
-
- /**
- * List of mobile devices (phones).
- *
- * @var array
- */
- protected static $phoneDevices = array(
- 'iPhone' => '\biPhone.*(Mobile|PhoneGap)|\biPod', // |\biTunes
- 'BlackBerry' => 'BlackBerry|\bBB10\b|rim[0-9]+',
- 'HTC' => 'HTC|HTC.*(Sensation|Evo|Vision|Explorer|6800|8100|8900|A7272|S510e|C110e|Legend|Desire|T8282)|APX515CKT|Qtek9090|APA9292KT|HD_mini|Sensation.*Z710e|PG86100|Z715e|Desire.*(A8181|HD)|ADR6200|ADR6400L|ADR6425|001HT|Inspire 4G|Android.*\bEVO\b|T-Mobile G1|Z520m',
- 'Nexus' => 'Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus.*Mobile',
- // @todo: Is 'Dell Streak' a tablet or a phone? ;)
- 'Dell' => 'Dell.*Streak|Dell.*Aero|Dell.*Venue|DELL.*Venue Pro|Dell Flash|Dell Smoke|Dell Mini 3iX|XCD28|XCD35|\b001DL\b|\b101DL\b|\bGS01\b',
- 'Motorola' => 'Motorola|DROIDX|DROID BIONIC|\bDroid\b.*Build|Android.*Xoom|HRI39|MOT-|A1260|A1680|A555|A853|A855|A953|A955|A956|Motorola.*ELECTRIFY|Motorola.*i1|i867|i940|MB200|MB300|MB501|MB502|MB508|MB511|MB520|MB525|MB526|MB611|MB612|MB632|MB810|MB855|MB860|MB861|MB865|MB870|ME501|ME502|ME511|ME525|ME600|ME632|ME722|ME811|ME860|ME863|ME865|MT620|MT710|MT716|MT720|MT810|MT870|MT917|Motorola.*TITANIUM|WX435|WX445|XT300|XT301|XT311|XT316|XT317|XT319|XT320|XT390|XT502|XT530|XT531|XT532|XT535|XT603|XT610|XT611|XT615|XT681|XT701|XT702|XT711|XT720|XT800|XT806|XT860|XT862|XT875|XT882|XT883|XT894|XT901|XT907|XT909|XT910|XT912|XT928|XT926|XT915|XT919|XT925',
- 'Samsung' => 'Samsung|SGH-I337|BGT-S5230|GT-B2100|GT-B2700|GT-B2710|GT-B3210|GT-B3310|GT-B3410|GT-B3730|GT-B3740|GT-B5510|GT-B5512|GT-B5722|GT-B6520|GT-B7300|GT-B7320|GT-B7330|GT-B7350|GT-B7510|GT-B7722|GT-B7800|GT-C3010|GT-C3011|GT-C3060|GT-C3200|GT-C3212|GT-C3212I|GT-C3262|GT-C3222|GT-C3300|GT-C3300K|GT-C3303|GT-C3303K|GT-C3310|GT-C3322|GT-C3330|GT-C3350|GT-C3500|GT-C3510|GT-C3530|GT-C3630|GT-C3780|GT-C5010|GT-C5212|GT-C6620|GT-C6625|GT-C6712|GT-E1050|GT-E1070|GT-E1075|GT-E1080|GT-E1081|GT-E1085|GT-E1087|GT-E1100|GT-E1107|GT-E1110|GT-E1120|GT-E1125|GT-E1130|GT-E1160|GT-E1170|GT-E1175|GT-E1180|GT-E1182|GT-E1200|GT-E1210|GT-E1225|GT-E1230|GT-E1390|GT-E2100|GT-E2120|GT-E2121|GT-E2152|GT-E2220|GT-E2222|GT-E2230|GT-E2232|GT-E2250|GT-E2370|GT-E2550|GT-E2652|GT-E3210|GT-E3213|GT-I5500|GT-I5503|GT-I5700|GT-I5800|GT-I5801|GT-I6410|GT-I6420|GT-I7110|GT-I7410|GT-I7500|GT-I8000|GT-I8150|GT-I8160|GT-I8190|GT-I8320|GT-I8330|GT-I8350|GT-I8530|GT-I8700|GT-I8703|GT-I8910|GT-I9000|GT-I9001|GT-I9003|GT-I9010|GT-I9020|GT-I9023|GT-I9070|GT-I9082|GT-I9100|GT-I9103|GT-I9220|GT-I9250|GT-I9300|GT-I9305|GT-I9500|GT-I9505|GT-M3510|GT-M5650|GT-M7500|GT-M7600|GT-M7603|GT-M8800|GT-M8910|GT-N7000|GT-S3110|GT-S3310|GT-S3350|GT-S3353|GT-S3370|GT-S3650|GT-S3653|GT-S3770|GT-S3850|GT-S5210|GT-S5220|GT-S5229|GT-S5230|GT-S5233|GT-S5250|GT-S5253|GT-S5260|GT-S5263|GT-S5270|GT-S5300|GT-S5330|GT-S5350|GT-S5360|GT-S5363|GT-S5369|GT-S5380|GT-S5380D|GT-S5560|GT-S5570|GT-S5600|GT-S5603|GT-S5610|GT-S5620|GT-S5660|GT-S5670|GT-S5690|GT-S5750|GT-S5780|GT-S5830|GT-S5839|GT-S6102|GT-S6500|GT-S7070|GT-S7200|GT-S7220|GT-S7230|GT-S7233|GT-S7250|GT-S7500|GT-S7530|GT-S7550|GT-S7562|GT-S7710|GT-S8000|GT-S8003|GT-S8500|GT-S8530|GT-S8600|SCH-A310|SCH-A530|SCH-A570|SCH-A610|SCH-A630|SCH-A650|SCH-A790|SCH-A795|SCH-A850|SCH-A870|SCH-A890|SCH-A930|SCH-A950|SCH-A970|SCH-A990|SCH-I100|SCH-I110|SCH-I400|SCH-I405|SCH-I500|SCH-I510|SCH-I515|SCH-I600|SCH-I730|SCH-I760|SCH-I770|SCH-I830|SCH-I910|SCH-I920|SCH-I959|SCH-LC11|SCH-N150|SCH-N300|SCH-R100|SCH-R300|SCH-R351|SCH-R400|SCH-R410|SCH-T300|SCH-U310|SCH-U320|SCH-U350|SCH-U360|SCH-U365|SCH-U370|SCH-U380|SCH-U410|SCH-U430|SCH-U450|SCH-U460|SCH-U470|SCH-U490|SCH-U540|SCH-U550|SCH-U620|SCH-U640|SCH-U650|SCH-U660|SCH-U700|SCH-U740|SCH-U750|SCH-U810|SCH-U820|SCH-U900|SCH-U940|SCH-U960|SCS-26UC|SGH-A107|SGH-A117|SGH-A127|SGH-A137|SGH-A157|SGH-A167|SGH-A177|SGH-A187|SGH-A197|SGH-A227|SGH-A237|SGH-A257|SGH-A437|SGH-A517|SGH-A597|SGH-A637|SGH-A657|SGH-A667|SGH-A687|SGH-A697|SGH-A707|SGH-A717|SGH-A727|SGH-A737|SGH-A747|SGH-A767|SGH-A777|SGH-A797|SGH-A817|SGH-A827|SGH-A837|SGH-A847|SGH-A867|SGH-A877|SGH-A887|SGH-A897|SGH-A927|SGH-B100|SGH-B130|SGH-B200|SGH-B220|SGH-C100|SGH-C110|SGH-C120|SGH-C130|SGH-C140|SGH-C160|SGH-C170|SGH-C180|SGH-C200|SGH-C207|SGH-C210|SGH-C225|SGH-C230|SGH-C417|SGH-C450|SGH-D307|SGH-D347|SGH-D357|SGH-D407|SGH-D415|SGH-D780|SGH-D807|SGH-D980|SGH-E105|SGH-E200|SGH-E315|SGH-E316|SGH-E317|SGH-E335|SGH-E590|SGH-E635|SGH-E715|SGH-E890|SGH-F300|SGH-F480|SGH-I200|SGH-I300|SGH-I320|SGH-I550|SGH-I577|SGH-I600|SGH-I607|SGH-I617|SGH-I627|SGH-I637|SGH-I677|SGH-I700|SGH-I717|SGH-I727|SGH-i747M|SGH-I777|SGH-I780|SGH-I827|SGH-I847|SGH-I857|SGH-I896|SGH-I897|SGH-I900|SGH-I907|SGH-I917|SGH-I927|SGH-I937|SGH-I997|SGH-J150|SGH-J200|SGH-L170|SGH-L700|SGH-M110|SGH-M150|SGH-M200|SGH-N105|SGH-N500|SGH-N600|SGH-N620|SGH-N625|SGH-N700|SGH-N710|SGH-P107|SGH-P207|SGH-P300|SGH-P310|SGH-P520|SGH-P735|SGH-P777|SGH-Q105|SGH-R210|SGH-R220|SGH-R225|SGH-S105|SGH-S307|SGH-T109|SGH-T119|SGH-T139|SGH-T209|SGH-T219|SGH-T229|SGH-T239|SGH-T249|SGH-T259|SGH-T309|SGH-T319|SGH-T329|SGH-T339|SGH-T349|SGH-T359|SGH-T369|SGH-T379|SGH-T409|SGH-T429|SGH-T439|SGH-T459|SGH-T469|SGH-T479|SGH-T499|SGH-T509|SGH-T519|SGH-T539|SGH-T559|SGH-T589|SGH-T609|SGH-T619|SGH-T629|SGH-T639|SGH-T659|SGH-T669|SGH-T679|SGH-T709|SGH-T719|SGH-T729|SGH-T739|SGH-T746|SGH-T749|SGH-T759|SGH-T769|SGH-T809|SGH-T819|SGH-T839|SGH-T919|SGH-T929|SGH-T939|SGH-T959|SGH-T989|SGH-U100|SGH-U200|SGH-U800|SGH-V205|SGH-V206|SGH-X100|SGH-X105|SGH-X120|SGH-X140|SGH-X426|SGH-X427|SGH-X475|SGH-X495|SGH-X497|SGH-X507|SGH-X600|SGH-X610|SGH-X620|SGH-X630|SGH-X700|SGH-X820|SGH-X890|SGH-Z130|SGH-Z150|SGH-Z170|SGH-ZX10|SGH-ZX20|SHW-M110|SPH-A120|SPH-A400|SPH-A420|SPH-A460|SPH-A500|SPH-A560|SPH-A600|SPH-A620|SPH-A660|SPH-A700|SPH-A740|SPH-A760|SPH-A790|SPH-A800|SPH-A820|SPH-A840|SPH-A880|SPH-A900|SPH-A940|SPH-A960|SPH-D600|SPH-D700|SPH-D710|SPH-D720|SPH-I300|SPH-I325|SPH-I330|SPH-I350|SPH-I500|SPH-I600|SPH-I700|SPH-L700|SPH-M100|SPH-M220|SPH-M240|SPH-M300|SPH-M305|SPH-M320|SPH-M330|SPH-M350|SPH-M360|SPH-M370|SPH-M380|SPH-M510|SPH-M540|SPH-M550|SPH-M560|SPH-M570|SPH-M580|SPH-M610|SPH-M620|SPH-M630|SPH-M800|SPH-M810|SPH-M850|SPH-M900|SPH-M910|SPH-M920|SPH-M930|SPH-N100|SPH-N200|SPH-N240|SPH-N300|SPH-N400|SPH-Z400|SWC-E100|SCH-i909|GT-N7100|GT-N7105|SCH-I535|SM-N900A|SGH-I317|SGH-T999L|GT-S5360B|GT-I8262|GT-S6802|GT-S6312|GT-S6310|GT-S5312|GT-S5310|GT-I9105|GT-I8510|GT-S6790N|SM-G7105|SM-N9005|GT-S5301|GT-I9295|GT-I9195|SM-C101|GT-S7392|GT-S7560|GT-B7610|GT-I5510|GT-S7582|GT-S7530E',
- 'LG' => '\bLG\b;|LG[- ]?(C800|C900|E400|E610|E900|E-900|F160|F180K|F180L|F180S|730|855|L160|LS840|LS970|LU6200|MS690|MS695|MS770|MS840|MS870|MS910|P500|P700|P705|VM696|AS680|AS695|AX840|C729|E970|GS505|272|C395|E739BK|E960|L55C|L75C|LS696|LS860|P769BK|P350|P500|P509|P870|UN272|US730|VS840|VS950|LN272|LN510|LS670|LS855|LW690|MN270|MN510|P509|P769|P930|UN200|UN270|UN510|UN610|US670|US740|US760|UX265|UX840|VN271|VN530|VS660|VS700|VS740|VS750|VS910|VS920|VS930|VX9200|VX11000|AX840A|LW770|P506|P925|P999|E612|D955|D802)',
- 'Sony' => 'SonyST|SonyLT|SonyEricsson|SonyEricssonLT15iv|LT18i|E10i|LT28h|LT26w|SonyEricssonMT27i',
- 'Asus' => 'Asus.*Galaxy|PadFone.*Mobile',
- // @ref: http://www.micromaxinfo.com/mobiles/smartphones
- // Added because the codes might conflict with Acer Tablets.
- 'Micromax' => 'Micromax.*\b(A210|A92|A88|A72|A111|A110Q|A115|A116|A110|A90S|A26|A51|A35|A54|A25|A27|A89|A68|A65|A57|A90)\b',
- 'Palm' => 'PalmSource|Palm', // avantgo|blazer|elaine|hiptop|plucker|xiino ; @todo - complete the regex.
- 'Vertu' => 'Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature', // Just for fun ;)
- // @ref: http://www.pantech.co.kr/en/prod/prodList.do?gbrand=VEGA (PANTECH)
- // Most of the VEGA devices are legacy. PANTECH seem to be newer devices based on Android.
- 'Pantech' => 'PANTECH|IM-A850S|IM-A840S|IM-A830L|IM-A830K|IM-A830S|IM-A820L|IM-A810K|IM-A810S|IM-A800S|IM-T100K|IM-A725L|IM-A780L|IM-A775C|IM-A770K|IM-A760S|IM-A750K|IM-A740S|IM-A730S|IM-A720L|IM-A710K|IM-A690L|IM-A690S|IM-A650S|IM-A630K|IM-A600S|VEGA PTL21|PT003|P8010|ADR910L|P6030|P6020|P9070|P4100|P9060|P5000|CDM8992|TXT8045|ADR8995|IS11PT|P2030|P6010|P8000|PT002|IS06|CDM8999|P9050|PT001|TXT8040|P2020|P9020|P2000|P7040|P7000|C790',
- // @ref: http://www.fly-phone.com/devices/smartphones/ ; Included only smartphones.
- 'Fly' => 'IQ230|IQ444|IQ450|IQ440|IQ442|IQ441|IQ245|IQ256|IQ236|IQ255|IQ235|IQ245|IQ275|IQ240|IQ285|IQ280|IQ270|IQ260|IQ250',
- 'iMobile' => 'i-mobile (IQ|i-STYLE|idea|ZAA|Hitz)',
- // Added simvalley mobile just for fun. They have some interesting devices.
- // @ref: http://www.simvalley.fr/telephonie---gps-_22_telephonie-mobile_telephones_.html
- 'SimValley' => '\b(SP-80|XT-930|SX-340|XT-930|SX-310|SP-360|SP60|SPT-800|SP-120|SPT-800|SP-140|SPX-5|SPX-8|SP-100|SPX-8|SPX-12)\b',
- // @Tapatalk is a mobile app; @ref: http://support.tapatalk.com/threads/smf-2-0-2-os-and-browser-detection-plugin-and-tapatalk.15565/#post-79039
- 'GenericPhone' => 'Tapatalk|PDA;|SAGEM|\bmmp\b|pocket|\bpsp\b|symbian|Smartphone|smartfon|treo|up.browser|up.link|vodafone|\bwap\b|nokia|Series40|Series60|S60|SonyEricsson|N900|MAUI.*WAP.*Browser'
- );
-
- /**
- * List of tablet devices.
- *
- * @var array
- */
- protected static $tabletDevices = array(
- 'iPad' => 'iPad|iPad.*Mobile', // @todo: check for mobile friendly emails topic.
- 'NexusTablet' => 'Android.*Nexus[\s]+(7|10)|^.*Android.*Nexus(?:(?!Mobile).)*$',
- 'SamsungTablet' => 'SAMSUNG.*Tablet|Galaxy.*Tab|SC-01C|GT-P1000|GT-P1003|GT-P1010|GT-P3105|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SPH-P100|GT-P3100|GT-P3108|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7320|GT-P7511|GT-N8000|GT-P8510|SGH-I497|SPH-P500|SGH-T779|SCH-I705|SCH-I915|GT-N8013|GT-P3113|GT-P5113|GT-P8110|GT-N8010|GT-N8005|GT-N8020|GT-P1013|GT-P6201|GT-P7501|GT-N5100|GT-N5105|GT-N5110|SHV-E140K|SHV-E140L|SHV-E140S|SHV-E150S|SHV-E230K|SHV-E230L|SHV-E230S|SHW-M180K|SHW-M180L|SHW-M180S|SHW-M180W|SHW-M300W|SHW-M305W|SHW-M380K|SHW-M380S|SHW-M380W|SHW-M430W|SHW-M480K|SHW-M480S|SHW-M480W|SHW-M485W|SHW-M486W|SHW-M500W|GT-I9228|SCH-P739|SCH-I925|GT-I9200|GT-I9205|GT-P5200|GT-P5210|GT-P5210X|SM-T311|SM-T310|SM-T310X|SM-T210|SM-T210R|SM-T211|SM-P600|SM-P601|SM-P605|SM-P900|SM-P901|SM-T217|SM-T217A|SM-T217S|SM-P6000|SM-T3100|SGH-I467|XE500|SM-T110|GT-P5220|GT-I9200X|GT-N5110X|GT-N5120|SM-P905|SM-T111|SM-T2105|SM-T315|SM-T320|SM-T320X|SM-T321|SM-T520|SM-T525|SM-T530NU|SM-T230NU|SM-T330NU|SM-T900|XE500T1C|SM-P605V|SM-P905V|SM-P600X|SM-P900X|SM-T210X|SM-T230|SM-T230X|SM-T325|GT-P7503|SM-T531|SM-T330|SM-T530|SM-T705C|SM-T535|SM-T331', // SCH-P709|SCH-P729|SM-T2558 - Samsung Mega - treat them like a regular phone.
- // @reference: http://www.labnol.org/software/kindle-user-agent-string/20378/
- 'Kindle' => 'Kindle|Silk.*Accelerated|Android.*\b(KFOT|KFTT|KFJWI|KFJWA|KFOTE|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|WFJWAE)\b',
- // Only the Surface tablets with Windows RT are considered mobile.
- // @ref: http://msdn.microsoft.com/en-us/library/ie/hh920767(v=vs.85).aspx
- 'SurfaceTablet' => 'Windows NT [0-9.]+; ARM;',
- // @ref: http://shopping1.hp.com/is-bin/INTERSHOP.enfinity/WFS/WW-USSMBPublicStore-Site/en_US/-/USD/ViewStandardCatalog-Browse?CatalogCategoryID=JfIQ7EN5lqMAAAEyDcJUDwMT
- 'HPTablet' => 'HP Slate 7|HP ElitePad 900|hp-tablet|EliteBook.*Touch|HP 8',
- // @note: watch out for PadFone, see #132
- 'AsusTablet' => '^.*PadFone((?!Mobile).)*$|Transformer|TF101|TF101G|TF300T|TF300TG|TF300TL|TF700T|TF700KL|TF701T|TF810C|ME171|ME301T|ME302C|ME371MG|ME370T|ME372MG|ME172V|ME173X|ME400C|Slider SL101|\bK00F\b|TX201LA',
- 'BlackBerryTablet' => 'PlayBook|RIM Tablet',
- 'HTCtablet' => 'HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200',
- 'MotorolaTablet' => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617',
- 'NookTablet' => 'Android.*Nook|NookColor|nook browser|BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2',
- // @ref: http://www.acer.ro/ac/ro/RO/content/drivers
- // @ref: http://www.packardbell.co.uk/pb/en/GB/content/download (Packard Bell is part of Acer)
- // @ref: http://us.acer.com/ac/en/US/content/group/tablets
- // @note: Can conflict with Micromax and Motorola phones codes.
- 'AcerTablet' => 'Android.*; \b(A100|A101|A110|A200|A210|A211|A500|A501|A510|A511|A700|A701|W500|W500P|W501|W501P|W510|W511|W700|G100|G100W|B1-A71|B1-710|B1-711|A1-810|A1-830)\b|W3-810|\bA3-A10\b',
- // @ref: http://eu.computers.toshiba-europe.com/innovation/family/Tablets/1098744/banner_id/tablet_footerlink/
- // @ref: http://us.toshiba.com/tablets/tablet-finder
- // @ref: http://www.toshiba.co.jp/regza/tablet/
- 'ToshibaTablet' => 'Android.*(AT100|AT105|AT200|AT205|AT270|AT275|AT300|AT305|AT1S5|AT500|AT570|AT700|AT830)|TOSHIBA.*FOLIO',
- // @ref: http://www.nttdocomo.co.jp/english/service/developer/smart_phone/technical_info/spec/index.html
- // @ref: http://www.lg.com/us/tablets
- 'LGTablet' => '\bL-06C|LG-V900|LG-V500|LG-V909|LG-V500|LG-V510|LG-VK810\b',
- 'FujitsuTablet' => 'Android.*\b(F-01D|F-02F|F-05E|F-10D|M532|Q572)\b',
- // Prestigio Tablets http://www.prestigio.com/support
- 'PrestigioTablet' => 'PMP3170B|PMP3270B|PMP3470B|PMP7170B|PMP3370B|PMP3570C|PMP5870C|PMP3670B|PMP5570C|PMP5770D|PMP3970B|PMP3870C|PMP5580C|PMP5880D|PMP5780D|PMP5588C|PMP7280C|PMP7280C3G|PMP7280|PMP7880D|PMP5597D|PMP5597|PMP7100D|PER3464|PER3274|PER3574|PER3884|PER5274|PER5474|PMP5097CPRO|PMP5097|PMP7380D|PMP5297C|PMP5297C_QUAD',
- // @ref: http://support.lenovo.com/en_GB/downloads/default.page?#
- 'LenovoTablet' => 'IdeaTab|ThinkPad([ ]+)?Tablet|Lenovo.*(S2109|S2110|S5000|S6000|K3011|A3000|A1000|A2107|A2109|A1107|B6000|B8000|B8080-F)',
- // @ref: http://www.yarvik.com/en/matrix/tablets/
- 'YarvikTablet' => 'Android.*\b(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468|TAB07-100|TAB07-101|TAB07-150|TAB07-151|TAB07-152|TAB07-200|TAB07-201-3G|TAB07-210|TAB07-211|TAB07-212|TAB07-214|TAB07-220|TAB07-400|TAB07-485|TAB08-150|TAB08-200|TAB08-201-3G|TAB08-201-30|TAB09-100|TAB09-211|TAB09-410|TAB10-150|TAB10-201|TAB10-211|TAB10-400|TAB10-410|TAB13-201|TAB274EUK|TAB275EUK|TAB374EUK|TAB462EUK|TAB474EUK|TAB9-200)\b',
- 'MedionTablet' => 'Android.*\bOYO\b|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB',
- 'ArnovaTablet' => 'AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT',
- // http://www.intenso.de/kategorie_en.php?kategorie=33
- // @todo: http://www.nbhkdz.com/read/b8e64202f92a2df129126bff.html - investigate
- 'IntensoTablet' => 'INM8002KP|INM1010FP|INM805ND|Intenso Tab',
- // IRU.ru Tablets http://www.iru.ru/catalog/soho/planetable/
- 'IRUTablet' => 'M702pro',
- 'MegafonTablet' => 'MegaFon V9|\bZTE V9\b|Android.*\bMT7A\b',
- // @ref: http://www.e-boda.ro/tablete-pc.html
- 'EbodaTablet' => 'E-Boda (Supreme|Impresspeed|Izzycomm|Essential)',
- // @ref: http://www.allview.ro/produse/droseries/lista-tablete-pc/
- 'AllViewTablet' => 'Allview.*(Viva|Alldro|City|Speed|All TV|Frenzy|Quasar|Shine|TX1|AX1|AX2)',
- // @reference: http://wiki.archosfans.com/index.php?title=Main_Page
- 'ArchosTablet' => '\b(101G9|80G9|A101IT)\b|Qilive 97R|ARCHOS 101G10|Archos 101 Neon',
- // @ref: http://www.ainol.com/plugin.php?identifier=ainol&module=product
- 'AinolTablet' => 'NOVO7|NOVO8|NOVO10|Novo7Aurora|Novo7Basic|NOVO7PALADIN|novo9-Spark',
- // @todo: inspect http://esupport.sony.com/US/p/select-system.pl?DIRECTOR=DRIVER
- // @ref: Readers http://www.atsuhiro-me.net/ebook/sony-reader/sony-reader-web-browser
- // @ref: http://www.sony.jp/support/tablet/
- 'SonyTablet' => 'Sony.*Tablet|Xperia Tablet|Sony Tablet S|SO-03E|SGPT12|SGPT13|SGPT114|SGPT121|SGPT122|SGPT123|SGPT111|SGPT112|SGPT113|SGPT131|SGPT132|SGPT133|SGPT211|SGPT212|SGPT213|SGP311|SGP312|SGP321|EBRD1101|EBRD1102|EBRD1201|SGP351|SGP341|SGP511|SGP512|SGP521|SGP541|SGP551',
- // @ref: db + http://www.cube-tablet.com/buy-products.html
- 'CubeTablet' => 'Android.*(K8GT|U9GT|U10GT|U16GT|U17GT|U18GT|U19GT|U20GT|U23GT|U30GT)|CUBE U8GT',
- // @ref: http://www.cobyusa.com/?p=pcat&pcat_id=3001
- 'CobyTablet' => 'MID1042|MID1045|MID1125|MID1126|MID7012|MID7014|MID7015|MID7034|MID7035|MID7036|MID7042|MID7048|MID7127|MID8042|MID8048|MID8127|MID9042|MID9740|MID9742|MID7022|MID7010',
- // @ref: http://www.match.net.cn/products.asp
- 'MIDTablet' => 'M9701|M9000|M9100|M806|M1052|M806|T703|MID701|MID713|MID710|MID727|MID760|MID830|MID728|MID933|MID125|MID810|MID732|MID120|MID930|MID800|MID731|MID900|MID100|MID820|MID735|MID980|MID130|MID833|MID737|MID960|MID135|MID860|MID736|MID140|MID930|MID835|MID733',
- // @ref: http://pdadb.net/index.php?m=pdalist&list=SMiT (NoName Chinese Tablets)
- // @ref: http://www.imp3.net/14/show.php?itemid=20454
- 'SMiTTablet' => 'Android.*(\bMID\b|MID-560|MTV-T1200|MTV-PND531|MTV-P1101|MTV-PND530)',
- // @ref: http://www.rock-chips.com/index.php?do=prod&pid=2
- 'RockChipTablet' => 'Android.*(RK2818|RK2808A|RK2918|RK3066)|RK2738|RK2808A',
- // @ref: http://www.fly-phone.com/devices/tablets/ ; http://www.fly-phone.com/service/
- 'FlyTablet' => 'IQ310|Fly Vision',
- // @ref: http://www.bqreaders.com/gb/tablets-prices-sale.html
- 'bqTablet' => 'bq.*(Elcano|Curie|Edison|Maxwell|Kepler|Pascal|Tesla|Hypatia|Platon|Newton|Livingstone|Cervantes|Avant)|Maxwell.*Lite|Maxwell.*Plus',
- // @ref: http://www.huaweidevice.com/worldwide/productFamily.do?method=index&directoryId=5011&treeId=3290
- // @ref: http://www.huaweidevice.com/worldwide/downloadCenter.do?method=index&directoryId=3372&treeId=0&tb=1&type=software (including legacy tablets)
- 'HuaweiTablet' => 'MediaPad|MediaPad 7 Youth|IDEOS S7|S7-201c|S7-202u|S7-101|S7-103|S7-104|S7-105|S7-106|S7-201|S7-Slim',
- // Nec or Medias Tab
- 'NecTablet' => '\bN-06D|\bN-08D',
- // Pantech Tablets: http://www.pantechusa.com/phones/
- 'PantechTablet' => 'Pantech.*P4100',
- // Broncho Tablets: http://www.broncho.cn/ (hard to find)
- 'BronchoTablet' => 'Broncho.*(N701|N708|N802|a710)',
- // @ref: http://versusuk.com/support.html
- 'VersusTablet' => 'TOUCHPAD.*[78910]|\bTOUCHTAB\b',
- // @ref: http://www.zync.in/index.php/our-products/tablet-phablets
- 'ZyncTablet' => 'z1000|Z99 2G|z99|z930|z999|z990|z909|Z919|z900',
- // @ref: http://www.positivoinformatica.com.br/www/pessoal/tablet-ypy/
- 'PositivoTablet' => 'TB07STA|TB10STA|TB07FTA|TB10FTA',
- // @ref: https://www.nabitablet.com/
- 'NabiTablet' => 'Android.*\bNabi',
- 'KoboTablet' => 'Kobo Touch|\bK080\b|\bVox\b Build|\bArc\b Build',
- // French Danew Tablets http://www.danew.com/produits-tablette.php
- 'DanewTablet' => 'DSlide.*\b(700|701R|702|703R|704|802|970|971|972|973|974|1010|1012)\b',
- // Texet Tablets and Readers http://www.texet.ru/tablet/
- 'TexetTablet' => 'NaviPad|TB-772A|TM-7045|TM-7055|TM-9750|TM-7016|TM-7024|TM-7026|TM-7041|TM-7043|TM-7047|TM-8041|TM-9741|TM-9747|TM-9748|TM-9751|TM-7022|TM-7021|TM-7020|TM-7011|TM-7010|TM-7023|TM-7025|TM-7037W|TM-7038W|TM-7027W|TM-9720|TM-9725|TM-9737W|TM-1020|TM-9738W|TM-9740|TM-9743W|TB-807A|TB-771A|TB-727A|TB-725A|TB-719A|TB-823A|TB-805A|TB-723A|TB-715A|TB-707A|TB-705A|TB-709A|TB-711A|TB-890HD|TB-880HD|TB-790HD|TB-780HD|TB-770HD|TB-721HD|TB-710HD|TB-434HD|TB-860HD|TB-840HD|TB-760HD|TB-750HD|TB-740HD|TB-730HD|TB-722HD|TB-720HD|TB-700HD|TB-500HD|TB-470HD|TB-431HD|TB-430HD|TB-506|TB-504|TB-446|TB-436|TB-416|TB-146SE|TB-126SE',
- // @note: Avoid detecting 'PLAYSTATION 3' as mobile.
- 'PlaystationTablet' => 'Playstation.*(Portable|Vita)',
- // @ref: http://www.trekstor.de/surftabs.html
- 'TrekstorTablet' => 'ST10416-1|VT10416-1|ST70408-1|ST702xx-1|ST702xx-2|ST80208|ST97216|ST70104-2|VT10416-2|ST10216-2A',
- // @ref: http://www.pyleaudio.com/Products.aspx?%2fproducts%2fPersonal-Electronics%2fTablets
- 'PyleAudioTablet' => '\b(PTBL10CEU|PTBL10C|PTBL72BC|PTBL72BCEU|PTBL7CEU|PTBL7C|PTBL92BC|PTBL92BCEU|PTBL9CEU|PTBL9CUK|PTBL9C)\b',
- // @ref: http://www.advandigital.com/index.php?link=content-product&jns=JP001
- // @Note: because of the short codenames we have to include whitespaces to reduce the possible conflicts.
- 'AdvanTablet' => 'Android.* \b(E3A|T3X|T5C|T5B|T3E|T3C|T3B|T1J|T1F|T2A|T1H|T1i|E1C|T1-E|T5-A|T4|E1-B|T2Ci|T1-B|T1-D|O1-A|E1-A|T1-A|T3A|T4i)\b ',
- // @ref: http://www.danytech.com/category/tablet-pc
- 'DanyTechTablet' => 'Genius Tab G3|Genius Tab S2|Genius Tab Q3|Genius Tab G4|Genius Tab Q4|Genius Tab G-II|Genius TAB GII|Genius TAB GIII|Genius Tab S1',
- // @ref: http://www.galapad.net/product.html
- 'GalapadTablet' => 'Android.*\bG1\b',
- // @ref: http://www.micromaxinfo.com/tablet/funbook
- 'MicromaxTablet' => 'Funbook|Micromax.*\b(P250|P560|P360|P362|P600|P300|P350|P500|P275)\b',
- // http://www.karbonnmobiles.com/products_tablet.php
- 'KarbonnTablet' => 'Android.*\b(A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2)\b',
- // @ref: http://www.myallfine.com/Products.asp
- 'AllFineTablet' => 'Fine7 Genius|Fine7 Shine|Fine7 Air|Fine8 Style|Fine9 More|Fine10 Joy|Fine11 Wide',
- // @ref: http://www.proscanvideo.com/products-search.asp?itemClass=TABLET&itemnmbr=
- 'PROSCANTablet' => '\b(PEM63|PLT1023G|PLT1041|PLT1044|PLT1044G|PLT1091|PLT4311|PLT4311PL|PLT4315|PLT7030|PLT7033|PLT7033D|PLT7035|PLT7035D|PLT7044K|PLT7045K|PLT7045KB|PLT7071KG|PLT7072|PLT7223G|PLT7225G|PLT7777G|PLT7810K|PLT7849G|PLT7851G|PLT7852G|PLT8015|PLT8031|PLT8034|PLT8036|PLT8080K|PLT8082|PLT8088|PLT8223G|PLT8234G|PLT8235G|PLT8816K|PLT9011|PLT9045K|PLT9233G|PLT9735|PLT9760G|PLT9770G)\b',
- // @ref: http://www.yonesnav.com/products/products.php
- 'YONESTablet' => 'BQ1078|BC1003|BC1077|RK9702|BC9730|BC9001|IT9001|BC7008|BC7010|BC708|BC728|BC7012|BC7030|BC7027|BC7026',
- // @ref: http://www.cjshowroom.com/eproducts.aspx?classcode=004001001
- // China manufacturer makes tablets for different small brands (eg. http://www.zeepad.net/index.html)
- 'ChangJiaTablet' => 'TPC7102|TPC7103|TPC7105|TPC7106|TPC7107|TPC7201|TPC7203|TPC7205|TPC7210|TPC7708|TPC7709|TPC7712|TPC7110|TPC8101|TPC8103|TPC8105|TPC8106|TPC8203|TPC8205|TPC8503|TPC9106|TPC9701|TPC97101|TPC97103|TPC97105|TPC97106|TPC97111|TPC97113|TPC97203|TPC97603|TPC97809|TPC97205|TPC10101|TPC10103|TPC10106|TPC10111|TPC10203|TPC10205|TPC10503',
- // @ref: http://www.gloryunion.cn/products.asp
- // @ref: http://www.allwinnertech.com/en/apply/mobile.html
- // @ref: http://www.ptcl.com.pk/pd_content.php?pd_id=284 (EVOTAB)
- // @todo: Softwiner tablets?
- // aka. Cute or Cool tablets. Not sure yet, must research to avoid collisions.
- 'GUTablet' => 'TX-A1301|TX-M9002|Q702|kf026', // A12R|D75A|D77|D79|R83|A95|A106C|R15|A75|A76|D71|D72|R71|R73|R77|D82|R85|D92|A97|D92|R91|A10F|A77F|W71F|A78F|W78F|W81F|A97F|W91F|W97F|R16G|C72|C73E|K72|K73|R96G
- // @ref: http://www.pointofview-online.com/showroom.php?shop_mode=product_listing&category_id=118
- 'PointOfViewTablet' => 'TAB-P506|TAB-navi-7-3G-M|TAB-P517|TAB-P-527|TAB-P701|TAB-P703|TAB-P721|TAB-P731N|TAB-P741|TAB-P825|TAB-P905|TAB-P925|TAB-PR945|TAB-PL1015|TAB-P1025|TAB-PI1045|TAB-P1325|TAB-PROTAB[0-9]+|TAB-PROTAB25|TAB-PROTAB26|TAB-PROTAB27|TAB-PROTAB26XL|TAB-PROTAB2-IPS9|TAB-PROTAB30-IPS9|TAB-PROTAB25XXL|TAB-PROTAB26-IPS10|TAB-PROTAB30-IPS10',
- // @ref: http://www.overmax.pl/pl/katalog-produktow,p8/tablety,c14/
- // @todo: add more tests.
- 'OvermaxTablet' => 'OV-(SteelCore|NewBase|Basecore|Baseone|Exellen|Quattor|EduTab|Solution|ACTION|BasicTab|TeddyTab|MagicTab|Stream|TB-08|TB-09)',
- // @ref: http://hclmetablet.com/India/index.php
- 'HCLTablet' => 'HCL.*Tablet|Connect-3G-2.0|Connect-2G-2.0|ME Tablet U1|ME Tablet U2|ME Tablet G1|ME Tablet X1|ME Tablet Y2|ME Tablet Sync',
- // @ref: http://www.edigital.hu/Tablet_es_e-book_olvaso/Tablet-c18385.html
- 'DPSTablet' => 'DPS Dream 9|DPS Dual 7',
- // @ref: http://www.visture.com/index.asp
- 'VistureTablet' => 'V97 HD|i75 3G|Visture V4( HD)?|Visture V5( HD)?|Visture V10',
- // @ref: http://www.mijncresta.nl/tablet
- 'CrestaTablet' => 'CTP(-)?810|CTP(-)?818|CTP(-)?828|CTP(-)?838|CTP(-)?888|CTP(-)?978|CTP(-)?980|CTP(-)?987|CTP(-)?988|CTP(-)?989',
- // MediaTek - http://www.mediatek.com/_en/01_products/02_proSys.php?cata_sn=1&cata1_sn=1&cata2_sn=309
- 'MediatekTablet' => '\bMT8125|MT8389|MT8135|MT8377\b',
- // Concorde tab
- 'ConcordeTablet' => 'Concorde([ ]+)?Tab|ConCorde ReadMan',
- // GoClever Tablets - http://www.goclever.com/uk/products,c1/tablet,c5/
- 'GoCleverTablet' => 'GOCLEVER TAB|A7GOCLEVER|M1042|M7841|M742|R1042BK|R1041|TAB A975|TAB A7842|TAB A741|TAB A741L|TAB M723G|TAB M721|TAB A1021|TAB I921|TAB R721|TAB I720|TAB T76|TAB R70|TAB R76.2|TAB R106|TAB R83.2|TAB M813G|TAB I721|GCTA722|TAB I70|TAB I71|TAB S73|TAB R73|TAB R74|TAB R93|TAB R75|TAB R76.1|TAB A73|TAB A93|TAB A93.2|TAB T72|TAB R83|TAB R974|TAB R973|TAB A101|TAB A103|TAB A104|TAB A104.2|R105BK|M713G|A972BK|TAB A971|TAB R974.2|TAB R104|TAB R83.3|TAB A1042',
- // Modecom Tablets - http://www.modecom.eu/tablets/portal/
- 'ModecomTablet' => 'FreeTAB 9000|FreeTAB 7.4|FreeTAB 7004|FreeTAB 7800|FreeTAB 2096|FreeTAB 7.5|FreeTAB 1014|FreeTAB 1001 |FreeTAB 8001|FreeTAB 9706|FreeTAB 9702|FreeTAB 7003|FreeTAB 7002|FreeTAB 1002|FreeTAB 7801|FreeTAB 1331|FreeTAB 1004|FreeTAB 8002|FreeTAB 8014|FreeTAB 9704|FreeTAB 1003',
- // Vonino Tablets - http://www.vonino.eu/tablets
- 'VoninoTablet' => '\b(Argus[ _]?S|Diamond[ _]?79HD|Emerald[ _]?78E|Luna[ _]?70C|Onyx[ _]?S|Onyx[ _]?Z|Orin[ _]?HD|Orin[ _]?S|Otis[ _]?S|SpeedStar[ _]?S|Magnet[ _]?M9|Primus[ _]?94[ _]?3G|Primus[ _]?94HD|Primus[ _]?QS|Android.*\bQ8\b|Sirius[ _]?EVO[ _]?QS|Sirius[ _]?QS|Spirit[ _]?S)\b',
- // ECS Tablets - http://www.ecs.com.tw/ECSWebSite/Product/Product_Tablet_List.aspx?CategoryID=14&MenuID=107&childid=M_107&LanID=0
- 'ECSTablet' => 'V07OT2|TM105A|S10OT1|TR10CS1',
- // Storex Tablets - http://storex.fr/espace_client/support.html
- // @note: no need to add all the tablet codes since they are guided by the first regex.
- 'StorexTablet' => 'eZee[_\']?(Tab|Go)[0-9]+|TabLC7|Looney Tunes Tab',
- // Generic Vodafone tablets.
- 'VodafoneTablet' => 'SmartTab([ ]+)?[0-9]+|SmartTabII10',
- // French tablets - Essentiel B http://www.boulanger.fr/tablette_tactile_e-book/tablette_tactile_essentiel_b/cl_68908.htm?multiChoiceToDelete=brand&mc_brand=essentielb
- // Aka: http://www.essentielb.fr/
- 'EssentielBTablet' => 'Smart[ \']?TAB[ ]+?[0-9]+|Family[ \']?TAB2',
- // Ross & Moor - http://ross-moor.ru/
- 'RossMoorTablet' => 'RM-790|RM-997|RMD-878G|RMD-974R|RMT-705A|RMT-701|RME-601|RMT-501|RMT-711',
- // i-mobile http://product.i-mobilephone.com/Mobile_Device
- 'iMobileTablet' => 'i-mobile i-note',
- // @ref: http://www.tolino.de/de/vergleichen/
- 'TolinoTablet' => 'tolino tab [0-9.]+|tolino shine',
- // AudioSonic - a Kmart brand
- // http://www.kmart.com.au/webapp/wcs/stores/servlet/Search?langId=-1&storeId=10701&catalogId=10001&categoryId=193001&pageSize=72¤tPage=1&searchCategory=193001%2b4294965664&sortBy=p_MaxPrice%7c1
- 'AudioSonicTablet' => '\bC-22Q|T7-QC|T-17B|T-17P\b',
- // AMPE Tablets - http://www.ampe.com.my/product-category/tablets/
- // @todo: add them gradually to avoid conflicts.
- 'AMPETablet' => 'Android.* A78 ',
- // Skk Mobile - http://skkmobile.com.ph/product_tablets.php
- 'SkkTablet' => 'Android.* (SKYPAD|PHOENIX|CYCLOPS)',
- // Tecno Mobile (only tablet) - http://www.tecno-mobile.com/index.php/product?filterby=smart&list_order=all&page=1
- 'TecnoTablet' => 'TECNO P9',
- // JXD (consoles & tablets) - http://jxd.hk/products.asp?selectclassid=009008&clsid=3
- 'JXDTablet' => 'Android.*\b(F3000|A3300|JXD5000|JXD3000|JXD2000|JXD300B|JXD300|S5800|S7800|S602b|S5110b|S7300|S5300|S602|S603|S5100|S5110|S601|S7100a|P3000F|P3000s|P101|P200s|P1000m|P200m|P9100|P1000s|S6600b|S908|P1000|P300|S18|S6600|S9100)\b',
- // i-Joy tablets - http://www.i-joy.es/en/cat/products/tablets/
- 'iJoyTablet' => 'Tablet (Spirit 7|Essentia|Galatea|Fusion|Onix 7|Landa|Titan|Scooby|Deox|Stella|Themis|Argon|Unique 7|Sygnus|Hexen|Finity 7|Cream|Cream X2|Jade|Neon 7|Neron 7|Kandy|Scape|Saphyr 7|Rebel|Biox|Rebel|Rebel 8GB|Myst|Draco 7|Myst|Tab7-004|Myst|Tadeo Jones|Tablet Boing|Arrow|Draco Dual Cam|Aurix|Mint|Amity|Revolution|Finity 9|Neon 9|T9w|Amity 4GB Dual Cam|Stone 4GB|Stone 8GB|Andromeda|Silken|X2|Andromeda II|Halley|Flame|Saphyr 9,7|Touch 8|Planet|Triton|Unique 10|Hexen 10|Memphis 4GB|Memphis 8GB|Onix 10)',
- // http://www.intracon.eu/tablet
- 'FX2Tablet' => 'FX2 PAD7|FX2 PAD10',
- // http://www.xoro.de/produkte/
- // @note: Might be the same brand with 'Simply tablets'
- 'XoroTablet' => 'KidsPAD 701|PAD[ ]?712|PAD[ ]?714|PAD[ ]?716|PAD[ ]?717|PAD[ ]?718|PAD[ ]?720|PAD[ ]?721|PAD[ ]?722|PAD[ ]?790|PAD[ ]?792|PAD[ ]?900|PAD[ ]?9715D|PAD[ ]?9716DR|PAD[ ]?9718DR|PAD[ ]?9719QR|PAD[ ]?9720QR|TelePAD1030|Telepad1032|TelePAD730|TelePAD731|TelePAD732|TelePAD735Q|TelePAD830|TelePAD9730|TelePAD795|MegaPAD 1331|MegaPAD 1851|MegaPAD 2151',
- // http://www1.viewsonic.com/products/computing/tablets/
- 'ViewsonicTablet' => 'ViewPad 10pi|ViewPad 10e|ViewPad 10s|ViewPad E72|ViewPad7|ViewPad E100|ViewPad 7e|ViewSonic VB733|VB100a',
- // http://www.odys.de/web/internet-tablet_en.html
- 'OdysTablet' => 'LOOX|XENO10|ODYS Space',
- // http://www.captiva-power.de/products.html#tablets-en
- 'CaptivaTablet' => 'CAPTIVA PAD',
- // IconBIT - http://www.iconbit.com/products/tablets/
- 'IconbitTablet' => 'NetTAB|NT-3702|NT-3702S|NT-3702S|NT-3603P|NT-3603P|NT-0704S|NT-0704S|NT-3805C|NT-3805C|NT-0806C|NT-0806C|NT-0909T|NT-0909T|NT-0907S|NT-0907S|NT-0902S|NT-0902S',
- // @ref: http://www.tesco.com/direct/hudl/
- 'Hudl' => 'Hudl HT7S3',
- // @ref: http://www.telstra.com.au/home-phone/thub-2/
- 'TelstraTablet' => 'T-Hub2',
- 'GenericTablet' => 'Android.*\b97D\b|Tablet(?!.*PC)|BNTV250A|MID-WCDMA|LogicPD Zoom2|\bA7EB\b|CatNova8|A1_07|CT704|CT1002|\bM721\b|rk30sdk|\bEVOTAB\b|M758A|ET904|ALUMIUM10|Smartfren Tab|Endeavour 1010|Tablet-PC-4',
- );
-
- /**
- * List of mobile Operating Systems.
- *
- * @var array
- */
- protected static $operatingSystems = array(
- 'AndroidOS' => 'Android',
- 'BlackBerryOS' => 'blackberry|\bBB10\b|rim tablet os',
- 'PalmOS' => 'PalmOS|avantgo|blazer|elaine|hiptop|palm|plucker|xiino',
- 'SymbianOS' => 'Symbian|SymbOS|Series60|Series40|SYB-[0-9]+|\bS60\b',
- // @reference: http://en.wikipedia.org/wiki/Windows_Mobile
- 'WindowsMobileOS' => 'Windows CE.*(PPC|Smartphone|Mobile|[0-9]{3}x[0-9]{3})|Window Mobile|Windows Phone [0-9.]+|WCE;',
- // @reference: http://en.wikipedia.org/wiki/Windows_Phone
- // http://wifeng.cn/?r=blog&a=view&id=106
- // http://nicksnettravels.builttoroam.com/post/2011/01/10/Bogus-Windows-Phone-7-User-Agent-String.aspx
- 'WindowsPhoneOS' => 'Windows Phone 8.0|Windows Phone OS|XBLWP7|ZuneWP7',
- 'iOS' => '\biPhone.*Mobile|\biPod|\biPad',
- // http://en.wikipedia.org/wiki/MeeGo
- // @todo: research MeeGo in UAs
- 'MeeGoOS' => 'MeeGo',
- // http://en.wikipedia.org/wiki/Maemo
- // @todo: research Maemo in UAs
- 'MaemoOS' => 'Maemo',
- 'JavaOS' => 'J2ME/|\bMIDP\b|\bCLDC\b', // '|Java/' produces bug #135
- 'webOS' => 'webOS|hpwOS',
- 'badaOS' => '\bBada\b',
- 'BREWOS' => 'BREW',
- );
-
- /**
- * List of mobile User Agents.
- *
- * @var array
- */
- protected static $browsers = array(
- // @reference: https://developers.google.com/chrome/mobile/docs/user-agent
- 'Chrome' => '\bCrMo\b|CriOS|Android.*Chrome/[.0-9]* (Mobile)?',
- 'Dolfin' => '\bDolfin\b',
- 'Opera' => 'Opera.*Mini|Opera.*Mobi|Android.*Opera|Mobile.*OPR/[0-9.]+|Coast/[0-9.]+',
- 'Skyfire' => 'Skyfire',
- 'IE' => 'IEMobile|MSIEMobile', // |Trident/[.0-9]+
- 'Firefox' => 'fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile',
- 'Bolt' => 'bolt',
- 'TeaShark' => 'teashark',
- 'Blazer' => 'Blazer',
- // @reference: http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/OptimizingforSafarioniPhone/OptimizingforSafarioniPhone.html#//apple_ref/doc/uid/TP40006517-SW3
- 'Safari' => 'Version.*Mobile.*Safari|Safari.*Mobile',
- // @ref: http://en.wikipedia.org/wiki/Midori_(web_browser)
- //'Midori' => 'midori',
- 'Tizen' => 'Tizen',
- 'UCBrowser' => 'UC.*Browser|UCWEB',
- // @ref: https://github.com/serbanghita/Mobile-Detect/issues/7
- 'DiigoBrowser' => 'DiigoBrowser',
- // http://www.puffinbrowser.com/index.php
- 'Puffin' => 'Puffin',
- // @ref: http://mercury-browser.com/index.html
- 'Mercury' => '\bMercury\b',
- // @reference: http://en.wikipedia.org/wiki/Minimo
- // http://en.wikipedia.org/wiki/Vision_Mobile_Browser
- 'GenericBrowser' => 'NokiaBrowser|OviBrowser|OneBrowser|TwonkyBeamBrowser|SEMC.*Browser|FlyFlow|Minimo|NetFront|Novarra-Vision|MQQBrowser|MicroMessenger'
- );
-
- /**
- * Utilities.
- *
- * @var array
- */
- protected static $utilities = array(
- // Experimental. When a mobile device wants to switch to 'Desktop Mode'.
- // @ref: http://scottcate.com/technology/windows-phone-8-ie10-desktop-or-mobile/
- // @ref: https://github.com/serbanghita/Mobile-Detect/issues/57#issuecomment-15024011
- 'DesktopMode' => 'WPDesktop',
- 'TV' => 'SonyDTV|HbbTV', // experimental
- 'WebKit' => '(webkit)[ /]([\w.]+)',
- 'Bot' => 'Googlebot|DoCoMo|YandexBot|bingbot|ia_archiver|AhrefsBot|Ezooms|GSLFbot|WBSearchBot|Twitterbot|TweetmemeBot|Twikle|PaperLiBot|Wotbox|UnwindFetchor|facebookexternalhit',
- 'MobileBot' => 'Googlebot-Mobile|DoCoMo|YahooSeeker/M1A1-R2D2',
- // @todo: Include JXD consoles.
- 'Console' => '\b(Nintendo|Nintendo WiiU|PLAYSTATION|Xbox)\b',
- 'Watch' => 'SM-V700',
- );
-
- /**
- * All possible HTTP headers that represent the
- * User-Agent string.
- *
- * @var array
- */
- protected static $uaHttpHeaders = array(
- // The default User-Agent string.
- 'HTTP_USER_AGENT',
- // Header can occur on devices using Opera Mini.
- 'HTTP_X_OPERAMINI_PHONE_UA',
- // Vodafone specific header: http://www.seoprinciple.com/mobile-web-community-still-angry-at-vodafone/24/
- 'HTTP_X_DEVICE_USER_AGENT',
- 'HTTP_X_ORIGINAL_USER_AGENT',
- 'HTTP_X_SKYFIRE_PHONE',
- 'HTTP_X_BOLT_PHONE_UA',
- 'HTTP_DEVICE_STOCK_UA',
- 'HTTP_X_UCBROWSER_DEVICE_UA'
- );
-
- /**
- * The individual segments that could exist in a User-Agent string. VER refers to the regular
- * expression defined in the constant self::VER.
- *
- * @var array
- */
- protected static $properties = array(
-
- // Build
- 'Mobile' => 'Mobile/[VER]',
- 'Build' => 'Build/[VER]',
- 'Version' => 'Version/[VER]',
- 'VendorID' => 'VendorID/[VER]',
-
- // Devices
- 'iPad' => 'iPad.*CPU[a-z ]+[VER]',
- 'iPhone' => 'iPhone.*CPU[a-z ]+[VER]',
- 'iPod' => 'iPod.*CPU[a-z ]+[VER]',
- //'BlackBerry' => array('BlackBerry[VER]', 'BlackBerry [VER];'),
- 'Kindle' => 'Kindle/[VER]',
-
- // Browser
- 'Chrome' => array('Chrome/[VER]', 'CriOS/[VER]', 'CrMo/[VER]'),
- 'Coast' => array('Coast/[VER]'),
- 'Dolfin' => 'Dolfin/[VER]',
- // @reference: https://developer.mozilla.org/en-US/docs/User_Agent_Strings_Reference
- 'Firefox' => 'Firefox/[VER]',
- 'Fennec' => 'Fennec/[VER]',
- // @reference: http://msdn.microsoft.com/en-us/library/ms537503(v=vs.85).aspx
- 'IE' => array('IEMobile/[VER];', 'IEMobile [VER]', 'MSIE [VER];'),
- // http://en.wikipedia.org/wiki/NetFront
- 'NetFront' => 'NetFront/[VER]',
- 'NokiaBrowser' => 'NokiaBrowser/[VER]',
- 'Opera' => array( ' OPR/[VER]', 'Opera Mini/[VER]', 'Version/[VER]' ),
- 'Opera Mini' => 'Opera Mini/[VER]',
- 'Opera Mobi' => 'Version/[VER]',
- 'UC Browser' => 'UC Browser[VER]',
- 'MQQBrowser' => 'MQQBrowser/[VER]',
- 'MicroMessenger' => 'MicroMessenger/[VER]',
- // @note: Safari 7534.48.3 is actually Version 5.1.
- // @note: On BlackBerry the Version is overwriten by the OS.
- 'Safari' => array( 'Version/[VER]', 'Safari/[VER]' ),
- 'Skyfire' => 'Skyfire/[VER]',
- 'Tizen' => 'Tizen/[VER]',
- 'Webkit' => 'webkit[ /][VER]',
-
- // Engine
- 'Gecko' => 'Gecko/[VER]',
- 'Trident' => 'Trident/[VER]',
- 'Presto' => 'Presto/[VER]',
-
- // OS
- 'iOS' => ' \bOS\b [VER] ',
- 'Android' => 'Android [VER]',
- 'BlackBerry' => array('BlackBerry[\w]+/[VER]', 'BlackBerry.*Version/[VER]', 'Version/[VER]'),
- 'BREW' => 'BREW [VER]',
- 'Java' => 'Java/[VER]',
- // @reference: http://windowsteamblog.com/windows_phone/b/wpdev/archive/2011/08/29/introducing-the-ie9-on-windows-phone-mango-user-agent-string.aspx
- // @reference: http://en.wikipedia.org/wiki/Windows_NT#Releases
- 'Windows Phone OS' => array( 'Windows Phone OS [VER]', 'Windows Phone [VER]'),
- 'Windows Phone' => 'Windows Phone [VER]',
- 'Windows CE' => 'Windows CE/[VER]',
- // http://social.msdn.microsoft.com/Forums/en-US/windowsdeveloperpreviewgeneral/thread/6be392da-4d2f-41b4-8354-8dcee20c85cd
- 'Windows NT' => 'Windows NT [VER]',
- 'Symbian' => array('SymbianOS/[VER]', 'Symbian/[VER]'),
- 'webOS' => array('webOS/[VER]', 'hpwOS/[VER];'),
- );
-
- /**
- * Construct an instance of this class.
- *
- * @param array $headers Specify the headers as injection. Should be PHP _SERVER flavored.
- * If left empty, will use the global _SERVER['HTTP_*'] vars instead.
- * @param string $userAgent Inject the User-Agent header. If null, will use HTTP_USER_AGENT
- * from the $headers array instead.
- */
- public function __construct(
- array $headers = null,
- $userAgent = null
- ){
- $this->setHttpHeaders($headers);
- $this->setUserAgent($userAgent);
- }
-
- /**
- * Get the current script version.
- * This is useful for the demo.php file,
- * so people can check on what version they are testing
- * for mobile devices.
- *
- * @return string The version number in semantic version format.
- */
- public static function getScriptVersion()
- {
- return self::VERSION;
- }
-
- /**
- * Set the HTTP Headers. Must be PHP-flavored. This method will reset existing headers.
- *
- * @param array $httpHeaders The headers to set. If null, then using PHP's _SERVER to extract
- * the headers. The default null is left for backwards compatibilty.
- */
- public function setHttpHeaders($httpHeaders = null)
- {
- //use global _SERVER if $httpHeaders aren't defined
- if (!is_array($httpHeaders) || !count($httpHeaders)) {
- $httpHeaders = $_SERVER;
- }
-
- //clear existing headers
- $this->httpHeaders = array();
-
- //Only save HTTP headers. In PHP land, that means only _SERVER vars that
- //start with HTTP_.
- foreach ($httpHeaders as $key => $value) {
- if (substr($key,0,5) == 'HTTP_') {
- $this->httpHeaders[$key] = $value;
- }
- }
- }
-
- /**
- * Retrieves the HTTP headers.
- *
- * @return array
- */
- public function getHttpHeaders()
- {
- return $this->httpHeaders;
- }
-
- /**
- * Retrieves a particular header. If it doesn't exist, no exception/error is caused.
- * Simply null is returned.
- *
- * @param string $header The name of the header to retrieve. Can be HTTP compliant such as
- * "User-Agent" or "X-Device-User-Agent" or can be php-esque with the
- * all-caps, HTTP_ prefixed, underscore seperated awesomeness.
- *
- * @return string|null The value of the header.
- */
- public function getHttpHeader($header)
- {
- //are we using PHP-flavored headers?
- if (strpos($header, '_') === false) {
- $header = str_replace('-', '_', $header);
- $header = strtoupper($header);
- }
-
- //test the alternate, too
- $altHeader = 'HTTP_' . $header;
-
- //Test both the regular and the HTTP_ prefix
- if (isset($this->httpHeaders[$header])) {
- return $this->httpHeaders[$header];
- } elseif (isset($this->httpHeaders[$altHeader])) {
- return $this->httpHeaders[$altHeader];
- }
-
- return null;
- }
-
- public function getMobileHeaders()
- {
- return self::$mobileHeaders;
- }
-
- /**
- * Get all possible HTTP headers that
- * can contain the User-Agent string.
- *
- * @return array List of HTTP headers.
- */
- public function getUaHttpHeaders()
- {
- return self::$uaHttpHeaders;
- }
-
- /**
- * Set the User-Agent to be used.
- *
- * @param string $userAgent The user agent string to set.
- *
- * @return string|null
- */
- public function setUserAgent($userAgent = null)
- {
- if (!empty($userAgent)) {
- return $this->userAgent = $userAgent;
- } else {
-
- $this->userAgent = null;
-
- foreach($this->getUaHttpHeaders() as $altHeader){
- if(!empty($this->httpHeaders[$altHeader])){ // @todo: should use getHttpHeader(), but it would be slow. (Serban)
- $this->userAgent .= $this->httpHeaders[$altHeader] . " ";
- }
- }
-
- return $this->userAgent = (!empty($this->userAgent) ? trim($this->userAgent) : null);
-
- }
- }
-
- /**
- * Retrieve the User-Agent.
- *
- * @return string|null The user agent if it's set.
- */
- public function getUserAgent()
- {
- return $this->userAgent;
- }
-
- /**
- * Set the detection type. Must be one of self::DETECTION_TYPE_MOBILE or
- * self::DETECTION_TYPE_EXTENDED. Otherwise, nothing is set.
- *
- * @deprecated since version 2.6.9
- *
- * @param string $type The type. Must be a self::DETECTION_TYPE_* constant. The default
- * parameter is null which will default to self::DETECTION_TYPE_MOBILE.
- */
- public function setDetectionType($type = null)
- {
- if ($type === null) {
- $type = self::DETECTION_TYPE_MOBILE;
- }
-
- if ($type != self::DETECTION_TYPE_MOBILE && $type != self::DETECTION_TYPE_EXTENDED) {
- return;
- }
-
- $this->detectionType = $type;
- }
-
- /**
- * Retrieve the list of known phone devices.
- *
- * @return array List of phone devices.
- */
- public static function getPhoneDevices()
- {
- return self::$phoneDevices;
- }
-
- /**
- * Retrieve the list of known tablet devices.
- *
- * @return array List of tablet devices.
- */
- public static function getTabletDevices()
- {
- return self::$tabletDevices;
- }
-
- /**
- * Alias for getBrowsers() method.
- *
- * @return array List of user agents.
- */
- public static function getUserAgents()
- {
- return self::getBrowsers();
- }
-
- /**
- * Retrieve the list of known browsers. Specifically, the user agents.
- *
- * @return array List of browsers / user agents.
- */
- public static function getBrowsers()
- {
- return self::$browsers;
- }
-
- /**
- * Retrieve the list of known utilities.
- *
- * @return array List of utilities.
- */
- public static function getUtilities()
- {
- return self::$utilities;
- }
-
- /**
- * Method gets the mobile detection rules. This method is used for the magic methods $detect->is*().
- *
- * @deprecated since version 2.6.9
- *
- * @return array All the rules (but not extended).
- */
- public static function getMobileDetectionRules()
- {
- static $rules;
-
- if (!$rules) {
- $rules = array_merge(
- self::$phoneDevices,
- self::$tabletDevices,
- self::$operatingSystems,
- self::$browsers
- );
- }
-
- return $rules;
-
- }
-
- /**
- * Method gets the mobile detection rules + utilities.
- * The reason this is separate is because utilities rules
- * don't necessary imply mobile. This method is used inside
- * the new $detect->is('stuff') method.
- *
- * @deprecated since version 2.6.9
- *
- * @return array All the rules + extended.
- */
- public function getMobileDetectionRulesExtended()
- {
- static $rules;
-
- if (!$rules) {
- // Merge all rules together.
- $rules = array_merge(
- self::$phoneDevices,
- self::$tabletDevices,
- self::$operatingSystems,
- self::$browsers,
- self::$utilities
- );
- }
-
- return $rules;
- }
-
- /**
- * Retrieve the current set of rules.
- *
- * @deprecated since version 2.6.9
- *
- * @return array
- */
- public function getRules()
- {
- if ($this->detectionType == self::DETECTION_TYPE_EXTENDED) {
- return self::getMobileDetectionRulesExtended();
- } else {
- return self::getMobileDetectionRules();
- }
- }
-
- /**
- * Retrieve the list of mobile operating systems.
- *
- * @return array The list of mobile operating systems.
- */
- public static function getOperatingSystems()
- {
- return self::$operatingSystems;
- }
-
- /**
- * Check the HTTP headers for signs of mobile.
- * This is the fastest mobile check possible; it's used
- * inside isMobile() method.
- *
- * @return bool
- */
- public function checkHttpHeadersForMobile()
- {
-
- foreach($this->getMobileHeaders() as $mobileHeader => $matchType){
- if( isset($this->httpHeaders[$mobileHeader]) ){
- if( is_array($matchType['matches']) ){
- foreach($matchType['matches'] as $_match){
- if( strpos($this->httpHeaders[$mobileHeader], $_match) !== false ){
- return true;
- }
- }
- return false;
- } else {
- return true;
- }
- }
- }
-
- return false;
-
- }
-
- /**
- * Magic overloading method.
- *
- * @method boolean is[...]()
- * @param string $name
- * @param array $arguments
- * @return mixed
- * @throws BadMethodCallException when the method doesn't exist and doesn't start with 'is'
- */
- public function __call($name, $arguments)
- {
- //make sure the name starts with 'is', otherwise
- if (substr($name, 0, 2) != 'is') {
- throw new BadMethodCallException("No such method exists: $name");
- }
-
- $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
-
- $key = substr($name, 2);
-
- return $this->matchUAAgainstKey($key);
- }
-
- /**
- * Find a detection rule that matches the current User-agent.
- *
- * @param null $userAgent deprecated
- * @return boolean
- */
- protected function matchDetectionRulesAgainstUA($userAgent = null)
- {
- // Begin general search.
- foreach ($this->getRules() as $_regex) {
- if (empty($_regex)) {
- continue;
- }
- if ($this->match($_regex, $userAgent)) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Search for a certain key in the rules array.
- * If the key is found the try to match the corresponding
- * regex agains the User-Agent.
- *
- * @param string $key
- * @param null $userAgent deprecated
- * @return mixed
- */
- protected function matchUAAgainstKey($key, $userAgent = null)
- {
- // Make the keys lowercase so we can match: isIphone(), isiPhone(), isiphone(), etc.
- $key = strtolower($key);
-
- //change the keys to lower case
- $_rules = array_change_key_case($this->getRules());
-
- if (array_key_exists($key, $_rules)) {
- if (empty($_rules[$key])) {
- return null;
- }
-
- return $this->match($_rules[$key], $userAgent);
- }
-
- return false;
- }
-
- /**
- * Check if the device is mobile.
- * Returns true if any type of mobile device detected, including special ones
- * @param null $userAgent deprecated
- * @param null $httpHeaders deprecated
- * @return bool
- */
- public function isMobile($userAgent = null, $httpHeaders = null)
- {
-
- if ($httpHeaders) {
- $this->setHttpHeaders($httpHeaders);
- }
-
- if ($userAgent) {
- $this->setUserAgent($userAgent);
- }
-
- $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
-
- if ($this->checkHttpHeadersForMobile()) {
- return true;
- } else {
- return $this->matchDetectionRulesAgainstUA();
- }
-
- }
-
- /**
- * Check if the device is a tablet.
- * Return true if any type of tablet device is detected.
- *
- * @param string $userAgent deprecated
- * @param array $httpHeaders deprecated
- * @return bool
- */
- public function isTablet($userAgent = null, $httpHeaders = null)
- {
- $this->setDetectionType(self::DETECTION_TYPE_MOBILE);
-
- foreach (self::$tabletDevices as $_regex) {
- if ($this->match($_regex, $userAgent)) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * This method checks for a certain property in the
- * userAgent.
- * @todo: The httpHeaders part is not yet used.
- *
- * @param string $key
- * @param string $userAgent deprecated
- * @param string $httpHeaders deprecated
- * @return bool|int|null
- */
- public function is($key, $userAgent = null, $httpHeaders = null)
- {
- // Set the UA and HTTP headers only if needed (eg. batch mode).
- if ($httpHeaders) {
- $this->setHttpHeaders($httpHeaders);
- }
-
- if ($userAgent) {
- $this->setUserAgent($userAgent);
- }
-
- $this->setDetectionType(self::DETECTION_TYPE_EXTENDED);
-
- return $this->matchUAAgainstKey($key);
- }
-
- /**
- * Some detection rules are relative (not standard),
- * because of the diversity of devices, vendors and
- * their conventions in representing the User-Agent or
- * the HTTP headers.
- *
- * This method will be used to check custom regexes against
- * the User-Agent string.
- *
- * @param $regex
- * @param string $userAgent
- * @return bool
- *
- * @todo: search in the HTTP headers too.
- */
- public function match($regex, $userAgent = null)
- {
- // Escape the special character which is the delimiter.
- $regex = str_replace('/', '\/', $regex);
-
- return (bool) preg_match('/'.$regex.'/is', (!empty($userAgent) ? $userAgent : $this->userAgent));
- }
-
- /**
- * Get the properties array.
- *
- * @return array
- */
- public static function getProperties()
- {
- return self::$properties;
- }
-
- /**
- * Prepare the version number.
- *
- * @todo Remove the error supression from str_replace() call.
- *
- * @param string $ver The string version, like "2.6.21.2152";
- *
- * @return float
- */
- public function prepareVersionNo($ver)
- {
- $ver = str_replace(array('_', ' ', '/'), '.', $ver);
- $arrVer = explode('.', $ver, 2);
-
- if (isset($arrVer[1])) {
- $arrVer[1] = @str_replace('.', '', $arrVer[1]); // @todo: treat strings versions.
- }
-
- return (float) implode('.', $arrVer);
- }
-
- /**
- * Check the version of the given property in the User-Agent.
- * Will return a float number. (eg. 2_0 will return 2.0, 4.3.1 will return 4.31)
- *
- * @param string $propertyName The name of the property. See self::getProperties() array
- * keys for all possible properties.
- * @param string $type Either self::VERSION_TYPE_STRING to get a string value or
- * self::VERSION_TYPE_FLOAT indicating a float value. This parameter
- * is optional and defaults to self::VERSION_TYPE_STRING. Passing an
- * invalid parameter will default to the this type as well.
- *
- * @return string|float The version of the property we are trying to extract.
- */
- public function version($propertyName, $type = self::VERSION_TYPE_STRING)
- {
- if (empty($propertyName)) {
- return false;
- }
-
- //set the $type to the default if we don't recognize the type
- if ($type != self::VERSION_TYPE_STRING && $type != self::VERSION_TYPE_FLOAT) {
- $type = self::VERSION_TYPE_STRING;
- }
-
- $properties = self::getProperties();
-
- // Check if the property exists in the properties array.
- if (array_key_exists($propertyName, $properties)) {
-
- // Prepare the pattern to be matched.
- // Make sure we always deal with an array (string is converted).
- $properties[$propertyName] = (array) $properties[$propertyName];
-
- foreach ($properties[$propertyName] as $propertyMatchString) {
-
- $propertyPattern = str_replace('[VER]', self::VER, $propertyMatchString);
-
- // Escape the special character which is the delimiter.
- $propertyPattern = str_replace('/', '\/', $propertyPattern);
-
- // Identify and extract the version.
- preg_match('/'.$propertyPattern.'/is', $this->userAgent, $match);
-
- if (!empty($match[1])) {
- $version = ( $type == self::VERSION_TYPE_FLOAT ? $this->prepareVersionNo($match[1]) : $match[1] );
-
- return $version;
- }
-
- }
-
- }
-
- return false;
- }
-
- /**
- * Retrieve the mobile grading, using self::MOBILE_GRADE_* constants.
- *
- * @return string One of the self::MOBILE_GRADE_* constants.
- */
- public function mobileGrade()
- {
- $isMobile = $this->isMobile();
-
- if (
- // Apple iOS 3.2-5.1 - Tested on the original iPad (4.3 / 5.0), iPad 2 (4.3), iPad 3 (5.1), original iPhone (3.1), iPhone 3 (3.2), 3GS (4.3), 4 (4.3 / 5.0), and 4S (5.1)
- $this->isIOS() && $this->version('iPad', self::VERSION_TYPE_FLOAT)>=4.3 ||
- $this->isIOS() && $this->version('iPhone', self::VERSION_TYPE_FLOAT)>=3.1 ||
- $this->isIOS() && $this->version('iPod', self::VERSION_TYPE_FLOAT)>=3.1 ||
-
- // Android 2.1-2.3 - Tested on the HTC Incredible (2.2), original Droid (2.2), HTC Aria (2.1), Google Nexus S (2.3). Functional on 1.5 & 1.6 but performance may be sluggish, tested on Google G1 (1.5)
- // Android 3.1 (Honeycomb) - Tested on the Samsung Galaxy Tab 10.1 and Motorola XOOM
- // Android 4.0 (ICS) - Tested on a Galaxy Nexus. Note: transition performance can be poor on upgraded devices
- // Android 4.1 (Jelly Bean) - Tested on a Galaxy Nexus and Galaxy 7
- ( $this->version('Android', self::VERSION_TYPE_FLOAT)>2.1 && $this->is('Webkit') ) ||
-
- // Windows Phone 7-7.5 - Tested on the HTC Surround (7.0) HTC Trophy (7.5), LG-E900 (7.5), Nokia Lumia 800
- $this->version('Windows Phone OS', self::VERSION_TYPE_FLOAT)>=7.0 ||
-
- // Blackberry 7 - Tested on BlackBerry Torch 9810
- // Blackberry 6.0 - Tested on the Torch 9800 and Style 9670
- $this->is('BlackBerry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)>=6.0 ||
- // Blackberry Playbook (1.0-2.0) - Tested on PlayBook
- $this->match('Playbook.*Tablet') ||
-
- // Palm WebOS (1.4-2.0) - Tested on the Palm Pixi (1.4), Pre (1.4), Pre 2 (2.0)
- ( $this->version('webOS', self::VERSION_TYPE_FLOAT)>=1.4 && $this->match('Palm|Pre|Pixi') ) ||
- // Palm WebOS 3.0 - Tested on HP TouchPad
- $this->match('hp.*TouchPad') ||
-
- // Firefox Mobile (12 Beta) - Tested on Android 2.3 device
- ( $this->is('Firefox') && $this->version('Firefox', self::VERSION_TYPE_FLOAT)>=12 ) ||
-
- // Chrome for Android - Tested on Android 4.0, 4.1 device
- ( $this->is('Chrome') && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT)>=4.0 ) ||
-
- // Skyfire 4.1 - Tested on Android 2.3 device
- ( $this->is('Skyfire') && $this->version('Skyfire', self::VERSION_TYPE_FLOAT)>=4.1 && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT)>=2.3 ) ||
-
- // Opera Mobile 11.5-12: Tested on Android 2.3
- ( $this->is('Opera') && $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT)>11 && $this->is('AndroidOS') ) ||
-
- // Meego 1.2 - Tested on Nokia 950 and N9
- $this->is('MeeGoOS') ||
-
- // Tizen (pre-release) - Tested on early hardware
- $this->is('Tizen') ||
-
- // Samsung Bada 2.0 - Tested on a Samsung Wave 3, Dolphin browser
- // @todo: more tests here!
- $this->is('Dolfin') && $this->version('Bada', self::VERSION_TYPE_FLOAT)>=2.0 ||
-
- // UC Browser - Tested on Android 2.3 device
- ( ($this->is('UC Browser') || $this->is('Dolfin')) && $this->version('Android', self::VERSION_TYPE_FLOAT)>=2.3 ) ||
-
- // Kindle 3 and Fire - Tested on the built-in WebKit browser for each
- ( $this->match('Kindle Fire') ||
- $this->is('Kindle') && $this->version('Kindle', self::VERSION_TYPE_FLOAT)>=3.0 ) ||
-
- // Nook Color 1.4.1 - Tested on original Nook Color, not Nook Tablet
- $this->is('AndroidOS') && $this->is('NookTablet') ||
-
- // Chrome Desktop 11-21 - Tested on OS X 10.7 and Windows 7
- $this->version('Chrome', self::VERSION_TYPE_FLOAT)>=11 && !$isMobile ||
-
- // Safari Desktop 4-5 - Tested on OS X 10.7 and Windows 7
- $this->version('Safari', self::VERSION_TYPE_FLOAT)>=5.0 && !$isMobile ||
-
- // Firefox Desktop 4-13 - Tested on OS X 10.7 and Windows 7
- $this->version('Firefox', self::VERSION_TYPE_FLOAT)>=4.0 && !$isMobile ||
-
- // Internet Explorer 7-9 - Tested on Windows XP, Vista and 7
- $this->version('MSIE', self::VERSION_TYPE_FLOAT)>=7.0 && !$isMobile ||
-
- // Opera Desktop 10-12 - Tested on OS X 10.7 and Windows 7
- // @reference: http://my.opera.com/community/openweb/idopera/
- $this->version('Opera', self::VERSION_TYPE_FLOAT)>=10 && !$isMobile
-
- ){
- return self::MOBILE_GRADE_A;
- }
-
- if (
- $this->isIOS() && $this->version('iPad', self::VERSION_TYPE_FLOAT)<4.3 ||
- $this->isIOS() && $this->version('iPhone', self::VERSION_TYPE_FLOAT)<3.1 ||
- $this->isIOS() && $this->version('iPod', self::VERSION_TYPE_FLOAT)<3.1 ||
-
- // Blackberry 5.0: Tested on the Storm 2 9550, Bold 9770
- $this->is('Blackberry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)>=5 && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)<6 ||
-
- //Opera Mini (5.0-6.5) - Tested on iOS 3.2/4.3 and Android 2.3
- ( $this->version('Opera Mini', self::VERSION_TYPE_FLOAT)>=5.0 && $this->version('Opera Mini', self::VERSION_TYPE_FLOAT)<=6.5 &&
- ($this->version('Android', self::VERSION_TYPE_FLOAT)>=2.3 || $this->is('iOS')) ) ||
-
- // Nokia Symbian^3 - Tested on Nokia N8 (Symbian^3), C7 (Symbian^3), also works on N97 (Symbian^1)
- $this->match('NokiaN8|NokiaC7|N97.*Series60|Symbian/3') ||
-
- // @todo: report this (tested on Nokia N71)
- $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT)>=11 && $this->is('SymbianOS')
- ){
- return self::MOBILE_GRADE_B;
- }
-
- if (
- // Blackberry 4.x - Tested on the Curve 8330
- $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)<5.0 ||
- // Windows Mobile - Tested on the HTC Leo (WinMo 5.2)
- $this->match('MSIEMobile|Windows CE.*Mobile') || $this->version('Windows Mobile', self::VERSION_TYPE_FLOAT)<=5.2
-
- ){
- return self::MOBILE_GRADE_C;
- }
-
- //All older smartphone platforms and featurephones - Any device that doesn't support media queries
- //will receive the basic, C grade experience.
- return self::MOBILE_GRADE_C;
- }
-}
diff --git a/data/module/Net/SMTP.php b/data/module/Net/SMTP.php
deleted file mode 100644
index e9277ffb50a..00000000000
--- a/data/module/Net/SMTP.php
+++ /dev/null
@@ -1,1218 +0,0 @@
- |
-// | Jon Parise |
-// | Damian Alejandro Fernandez Sosa |
-// +----------------------------------------------------------------------+
-//
-// $Id: SMTP.php 304535 2010-10-20 06:48:06Z jon $
-
-require_once 'PEAR.php';
-require_once 'Net/Socket.php';
-
-/**
- * Provides an implementation of the SMTP protocol using PEAR's
- * Net_Socket:: class.
- *
- * @package Net_SMTP
- * @author Chuck Hagenbuch
- * @author Jon Parise
- * @author Damian Alejandro Fernandez Sosa
- *
- * @example basic.php A basic implementation of the Net_SMTP package.
- */
-class Net_SMTP
-{
- /**
- * The server to connect to.
- * @var string
- * @access public
- */
- var $host = 'localhost';
-
- /**
- * The port to connect to.
- * @var int
- * @access public
- */
- var $port = 25;
-
- /**
- * The value to give when sending EHLO or HELO.
- * @var string
- * @access public
- */
- var $localhost = 'localhost';
-
- /**
- * List of supported authentication methods, in preferential order.
- * @var array
- * @access public
- */
- var $auth_methods = array('DIGEST-MD5', 'CRAM-MD5', 'LOGIN', 'PLAIN');
-
- /**
- * Use SMTP command pipelining (specified in RFC 2920) if the SMTP
- * server supports it.
- *
- * When pipeling is enabled, rcptTo(), mailFrom(), sendFrom(),
- * somlFrom() and samlFrom() do not wait for a response from the
- * SMTP server but return immediately.
- *
- * @var bool
- * @access public
- */
- var $pipelining = false;
-
- /**
- * Number of pipelined commands.
- * @var int
- * @access private
- */
- var $_pipelined_commands = 0;
-
- /**
- * Should debugging output be enabled?
- * @var boolean
- * @access private
- */
- var $_debug = false;
-
- /**
- * Debug output handler.
- * @var callback
- * @access private
- */
- var $_debug_handler = null;
-
- /**
- * The socket resource being used to connect to the SMTP server.
- * @var resource
- * @access private
- */
- var $_socket = null;
-
- /**
- * The most recent server response code.
- * @var int
- * @access private
- */
- var $_code = -1;
-
- /**
- * The most recent server response arguments.
- * @var array
- * @access private
- */
- var $_arguments = array();
-
- /**
- * Stores the SMTP server's greeting string.
- * @var string
- * @access private
- */
- var $_greeting = null;
-
- /**
- * Stores detected features of the SMTP server.
- * @var array
- * @access private
- */
- var $_esmtp = array();
-
- /**
- * Instantiates a new Net_SMTP object, overriding any defaults
- * with parameters that are passed in.
- *
- * If you have SSL support in PHP, you can connect to a server
- * over SSL using an 'ssl://' prefix:
- *
- * // 465 is a common smtps port.
- * $smtp = new Net_SMTP('ssl://mail.host.com', 465);
- * $smtp->connect();
- *
- * @param string $host The server to connect to.
- * @param integer $port The port to connect to.
- * @param string $localhost The value to give when sending EHLO or HELO.
- * @param boolean $pipeling Use SMTP command pipelining
- *
- * @access public
- * @since 1.0
- */
- function Net_SMTP($host = null, $port = null, $localhost = null, $pipelining = false)
- {
- if (isset($host)) {
- $this->host = $host;
- }
- if (isset($port)) {
- $this->port = $port;
- }
- if (isset($localhost)) {
- $this->localhost = $localhost;
- }
- $this->pipelining = $pipelining;
-
- $this->_socket = new Net_Socket();
-
- /* Include the Auth_SASL package. If the package is not
- * available, we disable the authentication methods that
- * depend upon it. */
- if ((@include_once 'Auth/SASL.php') === false) {
- $pos = array_search('DIGEST-MD5', $this->auth_methods);
- unset($this->auth_methods[$pos]);
- $pos = array_search('CRAM-MD5', $this->auth_methods);
- unset($this->auth_methods[$pos]);
- }
- }
-
- /**
- * Set the value of the debugging flag.
- *
- * @param boolean $debug New value for the debugging flag.
- *
- * @access public
- * @since 1.1.0
- */
- function setDebug($debug, $handler = null)
- {
- $this->_debug = $debug;
- $this->_debug_handler = $handler;
- }
-
- /**
- * Write the given debug text to the current debug output handler.
- *
- * @param string $message Debug mesage text.
- *
- * @access private
- * @since 1.3.3
- */
- function _debug($message)
- {
- if ($this->_debug) {
- if ($this->_debug_handler) {
- call_user_func_array($this->_debug_handler,
- array(&$this, $message));
- } else {
- echo "DEBUG: $message\n";
- }
- }
- }
-
- /**
- * Send the given string of data to the server.
- *
- * @param string $data The string of data to send.
- *
- * @return mixed True on success or a PEAR_Error object on failure.
- *
- * @access private
- * @since 1.1.0
- */
- function _send($data)
- {
- $this->_debug("Send: $data");
-
- $error = $this->_socket->write($data);
- if ($error === false || PEAR::isError($error)) {
- $msg = ($error) ? $error->getMessage() : "unknown error";
- return PEAR::raiseError("Failed to write to socket: $msg");
- }
-
- return true;
- }
-
- /**
- * Send a command to the server with an optional string of
- * arguments. A carriage return / linefeed (CRLF) sequence will
- * be appended to each command string before it is sent to the
- * SMTP server - an error will be thrown if the command string
- * already contains any newline characters. Use _send() for
- * commands that must contain newlines.
- *
- * @param string $command The SMTP command to send to the server.
- * @param string $args A string of optional arguments to append
- * to the command.
- *
- * @return mixed The result of the _send() call.
- *
- * @access private
- * @since 1.1.0
- */
- function _put($command, $args = '')
- {
- if (!empty($args)) {
- $command .= ' ' . $args;
- }
-
- if (strcspn($command, "\r\n") !== strlen($command)) {
- return PEAR::raiseError('Commands cannot contain newlines');
- }
-
- return $this->_send($command . "\r\n");
- }
-
- /**
- * Read a reply from the SMTP server. The reply consists of a response
- * code and a response message.
- *
- * @param mixed $valid The set of valid response codes. These
- * may be specified as an array of integer
- * values or as a single integer value.
- * @param bool $later Do not parse the response now, but wait
- * until the last command in the pipelined
- * command group
- *
- * @return mixed True if the server returned a valid response code or
- * a PEAR_Error object is an error condition is reached.
- *
- * @access private
- * @since 1.1.0
- *
- * @see getResponse
- */
- function _parseResponse($valid, $later = false)
- {
- $this->_code = -1;
- $this->_arguments = array();
-
- if ($later) {
- $this->_pipelined_commands++;
- return true;
- }
-
- for ($i = 0; $i <= $this->_pipelined_commands; $i++) {
- while ($line = $this->_socket->readLine()) {
- $this->_debug("Recv: $line");
-
- /* If we receive an empty line, the connection has been closed. */
- if (empty($line)) {
- $this->disconnect();
- return PEAR::raiseError('Connection was unexpectedly closed');
- }
-
- /* Read the code and store the rest in the arguments array. */
- $code = substr($line, 0, 3);
- $this->_arguments[] = trim(substr($line, 4));
-
- /* Check the syntax of the response code. */
- if (is_numeric($code)) {
- $this->_code = (int)$code;
- } else {
- $this->_code = -1;
- break;
- }
-
- /* If this is not a multiline response, we're done. */
- if (substr($line, 3, 1) != '-') {
- break;
- }
- }
- }
-
- $this->_pipelined_commands = 0;
-
- /* Compare the server's response code with the valid code/codes. */
- if (is_int($valid) && ($this->_code === $valid)) {
- return true;
- } elseif (is_array($valid) && in_array($this->_code, $valid, true)) {
- return true;
- }
-
- return PEAR::raiseError('Invalid response code received from server',
- $this->_code);
- }
-
- /**
- * Return a 2-tuple containing the last response from the SMTP server.
- *
- * @return array A two-element array: the first element contains the
- * response code as an integer and the second element
- * contains the response's arguments as a string.
- *
- * @access public
- * @since 1.1.0
- */
- function getResponse()
- {
- return array($this->_code, join("\n", $this->_arguments));
- }
-
- /**
- * Return the SMTP server's greeting string.
- *
- * @return string A string containing the greeting string, or null if a
- * greeting has not been received.
- *
- * @access public
- * @since 1.3.3
- */
- function getGreeting()
- {
- return $this->_greeting;
- }
-
- /**
- * Attempt to connect to the SMTP server.
- *
- * @param int $timeout The timeout value (in seconds) for the
- * socket connection.
- * @param bool $persistent Should a persistent socket connection
- * be used?
- *
- * @return mixed Returns a PEAR_Error with an error message on any
- * kind of failure, or true on success.
- * @access public
- * @since 1.0
- */
- function connect($timeout = null, $persistent = false)
- {
- $this->_greeting = null;
- $result = $this->_socket->connect($this->host, $this->port,
- $persistent, $timeout);
- if (PEAR::isError($result)) {
- return PEAR::raiseError('Failed to connect socket: ' .
- $result->getMessage());
- }
-
- if (PEAR::isError($error = $this->_parseResponse(220))) {
- return $error;
- }
-
- /* Extract and store a copy of the server's greeting string. */
- list(, $this->_greeting) = $this->getResponse();
-
- if (PEAR::isError($error = $this->_negotiate())) {
- return $error;
- }
-
- return true;
- }
-
- /**
- * Attempt to disconnect from the SMTP server.
- *
- * @return mixed Returns a PEAR_Error with an error message on any
- * kind of failure, or true on success.
- * @access public
- * @since 1.0
- */
- function disconnect()
- {
- if (PEAR::isError($error = $this->_put('QUIT'))) {
- return $error;
- }
- if (PEAR::isError($error = $this->_parseResponse(221))) {
- return $error;
- }
- if (PEAR::isError($error = $this->_socket->disconnect())) {
- return PEAR::raiseError('Failed to disconnect socket: ' .
- $error->getMessage());
- }
-
- return true;
- }
-
- /**
- * Attempt to send the EHLO command and obtain a list of ESMTP
- * extensions available, and failing that just send HELO.
- *
- * @return mixed Returns a PEAR_Error with an error message on any
- * kind of failure, or true on success.
- *
- * @access private
- * @since 1.1.0
- */
- function _negotiate()
- {
- if (PEAR::isError($error = $this->_put('EHLO', $this->localhost))) {
- return $error;
- }
-
- if (PEAR::isError($this->_parseResponse(250))) {
- /* If we receive a 503 response, we're already authenticated. */
- if ($this->_code === 503) {
- return true;
- }
-
- /* If the EHLO failed, try the simpler HELO command. */
- if (PEAR::isError($error = $this->_put('HELO', $this->localhost))) {
- return $error;
- }
- if (PEAR::isError($this->_parseResponse(250))) {
- return PEAR::raiseError('HELO was not accepted: ', $this->_code);
- }
-
- return true;
- }
-
- foreach ($this->_arguments as $argument) {
- $verb = strtok($argument, ' ');
- $arguments = substr($argument, strlen($verb) + 1,
- strlen($argument) - strlen($verb) - 1);
- $this->_esmtp[$verb] = $arguments;
- }
-
- if (!isset($this->_esmtp['PIPELINING'])) {
- $this->pipelining = false;
- }
-
- return true;
- }
-
- /**
- * Returns the name of the best authentication method that the server
- * has advertised.
- *
- * @return mixed Returns a string containing the name of the best
- * supported authentication method or a PEAR_Error object
- * if a failure condition is encountered.
- * @access private
- * @since 1.1.0
- */
- function _getBestAuthMethod()
- {
- $available_methods = explode(' ', $this->_esmtp['AUTH']);
-
- foreach ($this->auth_methods as $method) {
- if (in_array($method, $available_methods)) {
- return $method;
- }
- }
-
- return PEAR::raiseError('No supported authentication methods');
- }
-
- /**
- * Attempt to do SMTP authentication.
- *
- * @param string The userid to authenticate as.
- * @param string The password to authenticate with.
- * @param string The requested authentication method. If none is
- * specified, the best supported method will be used.
- * @param bool Flag indicating whether or not TLS should be attempted.
- * @param string An optional authorization identifier. If specified, this
- * identifier will be used as the authorization proxy.
- *
- * @return mixed Returns a PEAR_Error with an error message on any
- * kind of failure, or true on success.
- * @access public
- * @since 1.0
- */
- function auth($uid, $pwd , $method = '', $tls = true, $authz = '')
- {
- /* We can only attempt a TLS connection if one has been requested,
- * we're running PHP 5.1.0 or later, have access to the OpenSSL
- * extension, are connected to an SMTP server which supports the
- * STARTTLS extension, and aren't already connected over a secure
- * (SSL) socket connection. */
- if ($tls && version_compare(PHP_VERSION, '5.1.0', '>=') &&
- extension_loaded('openssl') && isset($this->_esmtp['STARTTLS']) &&
- strncasecmp($this->host, 'ssl://', 6) !== 0) {
- /* Start the TLS connection attempt. */
- if (PEAR::isError($result = $this->_put('STARTTLS'))) {
- return $result;
- }
- if (PEAR::isError($result = $this->_parseResponse(220))) {
- return $result;
- }
- if (PEAR::isError($result = $this->_socket->enableCrypto(true, STREAM_CRYPTO_METHOD_TLS_CLIENT))) {
- return $result;
- } elseif ($result !== true) {
- return PEAR::raiseError('STARTTLS failed');
- }
-
- /* Send EHLO again to recieve the AUTH string from the
- * SMTP server. */
- $this->_negotiate();
- }
-
- if (empty($this->_esmtp['AUTH'])) {
- return PEAR::raiseError('SMTP server does not support authentication');
- }
-
- /* If no method has been specified, get the name of the best
- * supported method advertised by the SMTP server. */
- if (empty($method)) {
- if (PEAR::isError($method = $this->_getBestAuthMethod())) {
- /* Return the PEAR_Error object from _getBestAuthMethod(). */
- return $method;
- }
- } else {
- $method = strtoupper($method);
- if (!in_array($method, $this->auth_methods)) {
- return PEAR::raiseError("$method is not a supported authentication method");
- }
- }
-
- switch ($method) {
- case 'DIGEST-MD5':
- $result = $this->_authDigest_MD5($uid, $pwd, $authz);
- break;
-
- case 'CRAM-MD5':
- $result = $this->_authCRAM_MD5($uid, $pwd);
- break;
-
- case 'LOGIN':
- $result = $this->_authLogin($uid, $pwd);
- break;
-
- case 'PLAIN':
- $result = $this->_authPlain($uid, $pwd, $authz);
- break;
-
- default:
- $result = PEAR::raiseError("$method is not a supported authentication method");
- break;
- }
-
- /* If an error was encountered, return the PEAR_Error object. */
- if (PEAR::isError($result)) {
- return $result;
- }
-
- return true;
- }
-
- /**
- * Authenticates the user using the DIGEST-MD5 method.
- *
- * @param string The userid to authenticate as.
- * @param string The password to authenticate with.
- * @param string The optional authorization proxy identifier.
- *
- * @return mixed Returns a PEAR_Error with an error message on any
- * kind of failure, or true on success.
- * @access private
- * @since 1.1.0
- */
- function _authDigest_MD5($uid, $pwd, $authz = '')
- {
- if (PEAR::isError($error = $this->_put('AUTH', 'DIGEST-MD5'))) {
- return $error;
- }
- /* 334: Continue authentication request */
- if (PEAR::isError($error = $this->_parseResponse(334))) {
- /* 503: Error: already authenticated */
- if ($this->_code === 503) {
- return true;
- }
- return $error;
- }
-
- $challenge = base64_decode($this->_arguments[0]);
- $digest = &Auth_SASL::factory('digestmd5');
- $auth_str = base64_encode($digest->getResponse($uid, $pwd, $challenge,
- $this->host, "smtp"));
-
- if (PEAR::isError($error = $this->_put($auth_str))) {
- return $error;
- }
- /* 334: Continue authentication request */
- if (PEAR::isError($error = $this->_parseResponse(334))) {
- return $error;
- }
-
- /* We don't use the protocol's third step because SMTP doesn't
- * allow subsequent authentication, so we just silently ignore
- * it. */
- if (PEAR::isError($error = $this->_put(''))) {
- return $error;
- }
- /* 235: Authentication successful */
- if (PEAR::isError($error = $this->_parseResponse(235))) {
- return $error;
- }
- }
-
- /**
- * Authenticates the user using the CRAM-MD5 method.
- *
- * @param string The userid to authenticate as.
- * @param string The password to authenticate with.
- *
- * @return mixed Returns a PEAR_Error with an error message on any
- * kind of failure, or true on success.
- * @access private
- * @since 1.1.0
- */
- function _authCRAM_MD5($uid, $pwd)
- {
- if (PEAR::isError($error = $this->_put('AUTH', 'CRAM-MD5'))) {
- return $error;
- }
- /* 334: Continue authentication request */
- if (PEAR::isError($error = $this->_parseResponse(334))) {
- /* 503: Error: already authenticated */
- if ($this->_code === 503) {
- return true;
- }
- return $error;
- }
-
- $challenge = base64_decode($this->_arguments[0]);
- $cram = &Auth_SASL::factory('crammd5');
- $auth_str = base64_encode($cram->getResponse($uid, $pwd, $challenge));
-
- if (PEAR::isError($error = $this->_put($auth_str))) {
- return $error;
- }
-
- /* 235: Authentication successful */
- if (PEAR::isError($error = $this->_parseResponse(235))) {
- return $error;
- }
- }
-
- /**
- * Authenticates the user using the LOGIN method.
- *
- * @param string The userid to authenticate as.
- * @param string The password to authenticate with.
- *
- * @return mixed Returns a PEAR_Error with an error message on any
- * kind of failure, or true on success.
- * @access private
- * @since 1.1.0
- */
- function _authLogin($uid, $pwd)
- {
- if (PEAR::isError($error = $this->_put('AUTH', 'LOGIN'))) {
- return $error;
- }
- /* 334: Continue authentication request */
- if (PEAR::isError($error = $this->_parseResponse(334))) {
- /* 503: Error: already authenticated */
- if ($this->_code === 503) {
- return true;
- }
- return $error;
- }
-
- if (PEAR::isError($error = $this->_put(base64_encode($uid)))) {
- return $error;
- }
- /* 334: Continue authentication request */
- if (PEAR::isError($error = $this->_parseResponse(334))) {
- return $error;
- }
-
- if (PEAR::isError($error = $this->_put(base64_encode($pwd)))) {
- return $error;
- }
-
- /* 235: Authentication successful */
- if (PEAR::isError($error = $this->_parseResponse(235))) {
- return $error;
- }
-
- return true;
- }
-
- /**
- * Authenticates the user using the PLAIN method.
- *
- * @param string The userid to authenticate as.
- * @param string The password to authenticate with.
- * @param string The optional authorization proxy identifier.
- *
- * @return mixed Returns a PEAR_Error with an error message on any
- * kind of failure, or true on success.
- * @access private
- * @since 1.1.0
- */
- function _authPlain($uid, $pwd, $authz = '')
- {
- if (PEAR::isError($error = $this->_put('AUTH', 'PLAIN'))) {
- return $error;
- }
- /* 334: Continue authentication request */
- if (PEAR::isError($error = $this->_parseResponse(334))) {
- /* 503: Error: already authenticated */
- if ($this->_code === 503) {
- return true;
- }
- return $error;
- }
-
- $auth_str = base64_encode($authz . chr(0) . $uid . chr(0) . $pwd);
-
- if (PEAR::isError($error = $this->_put($auth_str))) {
- return $error;
- }
-
- /* 235: Authentication successful */
- if (PEAR::isError($error = $this->_parseResponse(235))) {
- return $error;
- }
-
- return true;
- }
-
- /**
- * Send the HELO command.
- *
- * @param string The domain name to say we are.
- *
- * @return mixed Returns a PEAR_Error with an error message on any
- * kind of failure, or true on success.
- * @access public
- * @since 1.0
- */
- function helo($domain)
- {
- if (PEAR::isError($error = $this->_put('HELO', $domain))) {
- return $error;
- }
- if (PEAR::isError($error = $this->_parseResponse(250))) {
- return $error;
- }
-
- return true;
- }
-
- /**
- * Return the list of SMTP service extensions advertised by the server.
- *
- * @return array The list of SMTP service extensions.
- * @access public
- * @since 1.3
- */
- function getServiceExtensions()
- {
- return $this->_esmtp;
- }
-
- /**
- * Send the MAIL FROM: command.
- *
- * @param string $sender The sender (reverse path) to set.
- * @param string $params String containing additional MAIL parameters,
- * such as the NOTIFY flags defined by RFC 1891
- * or the VERP protocol.
- *
- * If $params is an array, only the 'verp' option
- * is supported. If 'verp' is true, the XVERP
- * parameter is appended to the MAIL command. If
- * the 'verp' value is a string, the full
- * XVERP=value parameter is appended.
- *
- * @return mixed Returns a PEAR_Error with an error message on any
- * kind of failure, or true on success.
- * @access public
- * @since 1.0
- */
- function mailFrom($sender, $params = null)
- {
- $args = "FROM:<$sender>";
-
- /* Support the deprecated array form of $params. */
- if (is_array($params) && isset($params['verp'])) {
- /* XVERP */
- if ($params['verp'] === true) {
- $args .= ' XVERP';
-
- /* XVERP=something */
- } elseif (trim($params['verp'])) {
- $args .= ' XVERP=' . $params['verp'];
- }
- } elseif (is_string($params)) {
- $args .= ' ' . $params;
- }
-
- if (PEAR::isError($error = $this->_put('MAIL', $args))) {
- return $error;
- }
- if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) {
- return $error;
- }
-
- return true;
- }
-
- /**
- * Send the RCPT TO: command.
- *
- * @param string $recipient The recipient (forward path) to add.
- * @param string $params String containing additional RCPT parameters,
- * such as the NOTIFY flags defined by RFC 1891.
- *
- * @return mixed Returns a PEAR_Error with an error message on any
- * kind of failure, or true on success.
- *
- * @access public
- * @since 1.0
- */
- function rcptTo($recipient, $params = null)
- {
- $args = "TO:<$recipient>";
- if (is_string($params)) {
- $args .= ' ' . $params;
- }
-
- if (PEAR::isError($error = $this->_put('RCPT', $args))) {
- return $error;
- }
- if (PEAR::isError($error = $this->_parseResponse(array(250, 251), $this->pipelining))) {
- return $error;
- }
-
- return true;
- }
-
- /**
- * Quote the data so that it meets SMTP standards.
- *
- * This is provided as a separate public function to facilitate
- * easier overloading for the cases where it is desirable to
- * customize the quoting behavior.
- *
- * @param string $data The message text to quote. The string must be passed
- * by reference, and the text will be modified in place.
- *
- * @access public
- * @since 1.2
- */
- function quotedata(&$data)
- {
- /* Change Unix (\n) and Mac (\r) linefeeds into
- * Internet-standard CRLF (\r\n) linefeeds. */
- $data = preg_replace(array('/(?_esmtp['SIZE'])) ? $this->_esmtp['SIZE'] : 0;
- if ($limit > 0 && $size >= $limit) {
- $this->disconnect();
- return PEAR::raiseError('Message size exceeds server limit');
- }
-
- /* Initiate the DATA command. */
- if (PEAR::isError($error = $this->_put('DATA'))) {
- return $error;
- }
- if (PEAR::isError($error = $this->_parseResponse(354))) {
- return $error;
- }
-
- /* If we have a separate headers string, send it first. */
- if (!is_null($headers)) {
- $this->quotedata($headers);
- if (PEAR::isError($result = $this->_send($headers . "\r\n\r\n"))) {
- return $result;
- }
- }
-
- /* Now we can send the message body data. */
- if (is_resource($data)) {
- /* Stream the contents of the file resource out over our socket
- * connection, line by line. Each line must be run through the
- * quoting routine. */
- while ($line = fgets($data, 1024)) {
- $this->quotedata($line);
- if (PEAR::isError($result = $this->_send($line))) {
- return $result;
- }
- }
- } else {
- /*
- * Break up the data by sending one chunk (up to 512k) at a time.
- * This approach reduces our peak memory usage.
- */
- for ($offset = 0; $offset < $size;) {
- $end = $offset + 512000;
-
- /*
- * Ensure we don't read beyond our data size or span multiple
- * lines. quotedata() can't properly handle character data
- * that's split across two line break boundaries.
- */
- if ($end >= $size) {
- $end = $size;
- } else {
- for (; $end < $size; $end++) {
- if ($data[$end] != "\n") {
- break;
- }
- }
- }
-
- /* Extract our chunk and run it through the quoting routine. */
- $chunk = substr($data, $offset, $end - $offset);
- $this->quotedata($chunk);
-
- /* If we run into a problem along the way, abort. */
- if (PEAR::isError($result = $this->_send($chunk))) {
- return $result;
- }
-
- /* Advance the offset to the end of this chunk. */
- $offset = $end;
- }
- }
-
- /* Finally, send the DATA terminator sequence. */
- if (PEAR::isError($result = $this->_send("\r\n.\r\n"))) {
- return $result;
- }
-
- /* Verify that the data was successfully received by the server. */
- if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) {
- return $error;
- }
-
- return true;
- }
-
- /**
- * Send the SEND FROM: command.
- *
- * @param string The reverse path to send.
- *
- * @return mixed Returns a PEAR_Error with an error message on any
- * kind of failure, or true on success.
- * @access public
- * @since 1.2.6
- */
- function sendFrom($path)
- {
- if (PEAR::isError($error = $this->_put('SEND', "FROM:<$path>"))) {
- return $error;
- }
- if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) {
- return $error;
- }
-
- return true;
- }
-
- /**
- * Backwards-compatibility wrapper for sendFrom().
- *
- * @param string The reverse path to send.
- *
- * @return mixed Returns a PEAR_Error with an error message on any
- * kind of failure, or true on success.
- *
- * @access public
- * @since 1.0
- * @deprecated 1.2.6
- */
- function send_from($path)
- {
- return sendFrom($path);
- }
-
- /**
- * Send the SOML FROM: command.
- *
- * @param string The reverse path to send.
- *
- * @return mixed Returns a PEAR_Error with an error message on any
- * kind of failure, or true on success.
- * @access public
- * @since 1.2.6
- */
- function somlFrom($path)
- {
- if (PEAR::isError($error = $this->_put('SOML', "FROM:<$path>"))) {
- return $error;
- }
- if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) {
- return $error;
- }
-
- return true;
- }
-
- /**
- * Backwards-compatibility wrapper for somlFrom().
- *
- * @param string The reverse path to send.
- *
- * @return mixed Returns a PEAR_Error with an error message on any
- * kind of failure, or true on success.
- *
- * @access public
- * @since 1.0
- * @deprecated 1.2.6
- */
- function soml_from($path)
- {
- return somlFrom($path);
- }
-
- /**
- * Send the SAML FROM: command.
- *
- * @param string The reverse path to send.
- *
- * @return mixed Returns a PEAR_Error with an error message on any
- * kind of failure, or true on success.
- * @access public
- * @since 1.2.6
- */
- function samlFrom($path)
- {
- if (PEAR::isError($error = $this->_put('SAML', "FROM:<$path>"))) {
- return $error;
- }
- if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) {
- return $error;
- }
-
- return true;
- }
-
- /**
- * Backwards-compatibility wrapper for samlFrom().
- *
- * @param string The reverse path to send.
- *
- * @return mixed Returns a PEAR_Error with an error message on any
- * kind of failure, or true on success.
- *
- * @access public
- * @since 1.0
- * @deprecated 1.2.6
- */
- function saml_from($path)
- {
- return samlFrom($path);
- }
-
- /**
- * Send the RSET command.
- *
- * @return mixed Returns a PEAR_Error with an error message on any
- * kind of failure, or true on success.
- * @access public
- * @since 1.0
- */
- function rset()
- {
- if (PEAR::isError($error = $this->_put('RSET'))) {
- return $error;
- }
- if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) {
- return $error;
- }
-
- return true;
- }
-
- /**
- * Send the VRFY command.
- *
- * @param string The string to verify
- *
- * @return mixed Returns a PEAR_Error with an error message on any
- * kind of failure, or true on success.
- * @access public
- * @since 1.0
- */
- function vrfy($string)
- {
- /* Note: 251 is also a valid response code */
- if (PEAR::isError($error = $this->_put('VRFY', $string))) {
- return $error;
- }
- if (PEAR::isError($error = $this->_parseResponse(array(250, 252)))) {
- return $error;
- }
-
- return true;
- }
-
- /**
- * Send the NOOP command.
- *
- * @return mixed Returns a PEAR_Error with an error message on any
- * kind of failure, or true on success.
- * @access public
- * @since 1.0
- */
- function noop()
- {
- if (PEAR::isError($error = $this->_put('NOOP'))) {
- return $error;
- }
- if (PEAR::isError($error = $this->_parseResponse(250))) {
- return $error;
- }
-
- return true;
- }
-
- /**
- * Backwards-compatibility method. identifySender()'s functionality is
- * now handled internally.
- *
- * @return boolean This method always return true.
- *
- * @access public
- * @since 1.0
- */
- function identifySender()
- {
- return true;
- }
-
-}
diff --git a/data/module/Net/Socket.php b/data/module/Net/Socket.php
deleted file mode 100644
index dd1047c4310..00000000000
--- a/data/module/Net/Socket.php
+++ /dev/null
@@ -1,653 +0,0 @@
-
- * Chuck Hagenbuch
- *
- * @category Net
- * @package Net_Socket
- * @author Stig Bakken
- * @author Chuck Hagenbuch
- * @copyright 1997-2003 The PHP Group
- * @license http://www.php.net/license/2_02.txt PHP 2.02
- * @version CVS: $Id$
- * @link http://pear.php.net/packages/Net_Socket
- */
-
-require_once 'PEAR.php';
-
-define('NET_SOCKET_READ', 1);
-define('NET_SOCKET_WRITE', 2);
-define('NET_SOCKET_ERROR', 4);
-
-/**
- * Generalized Socket class.
- *
- * @category Net
- * @package Net_Socket
- * @author Stig Bakken
- * @author Chuck Hagenbuch
- * @copyright 1997-2003 The PHP Group
- * @license http://www.php.net/license/2_02.txt PHP 2.02
- * @link http://pear.php.net/packages/Net_Socket
- */
-class Net_Socket extends PEAR
-{
- /**
- * Socket file pointer.
- * @var resource $fp
- */
- var $fp = null;
-
- /**
- * Whether the socket is blocking. Defaults to true.
- * @var boolean $blocking
- */
- var $blocking = true;
-
- /**
- * Whether the socket is persistent. Defaults to false.
- * @var boolean $persistent
- */
- var $persistent = false;
-
- /**
- * The IP address to connect to.
- * @var string $addr
- */
- var $addr = '';
-
- /**
- * The port number to connect to.
- * @var integer $port
- */
- var $port = 0;
-
- /**
- * Number of seconds to wait on socket connections before assuming
- * there's no more data. Defaults to no timeout.
- * @var integer $timeout
- */
- var $timeout = false;
-
- /**
- * Number of bytes to read at a time in readLine() and
- * readAll(). Defaults to 2048.
- * @var integer $lineLength
- */
- var $lineLength = 2048;
-
- /**
- * The string to use as a newline terminator. Usually "\r\n" or "\n".
- * @var string $newline
- */
- var $newline = "\r\n";
-
- /**
- * Connect to the specified port. If called when the socket is
- * already connected, it disconnects and connects again.
- *
- * @param string $addr IP address or host name.
- * @param integer $port TCP port number.
- * @param boolean $persistent (optional) Whether the connection is
- * persistent (kept open between requests
- * by the web server).
- * @param integer $timeout (optional) How long to wait for data.
- * @param array $options See options for stream_context_create.
- *
- * @access public
- *
- * @return boolean | PEAR_Error True on success or a PEAR_Error on failure.
- */
- function connect($addr, $port = 0, $persistent = null,
- $timeout = null, $options = null)
- {
- if (is_resource($this->fp)) {
- @fclose($this->fp);
- $this->fp = null;
- }
-
- if (!$addr) {
- return $this->raiseError('$addr cannot be empty');
- } elseif (strspn($addr, '.0123456789') == strlen($addr) ||
- strstr($addr, '/') !== false) {
- $this->addr = $addr;
- } else {
- $this->addr = @gethostbyname($addr);
- }
-
- $this->port = $port % 65536;
-
- if ($persistent !== null) {
- $this->persistent = $persistent;
- }
-
- if ($timeout !== null) {
- $this->timeout = $timeout;
- }
-
- $openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen';
- $errno = 0;
- $errstr = '';
-
- $old_track_errors = @ini_set('track_errors', 1);
-
- if ($options && function_exists('stream_context_create')) {
- if ($this->timeout) {
- $timeout = $this->timeout;
- } else {
- $timeout = 0;
- }
- $context = stream_context_create($options);
-
- // Since PHP 5 fsockopen doesn't allow context specification
- if (function_exists('stream_socket_client')) {
- $flags = STREAM_CLIENT_CONNECT;
-
- if ($this->persistent) {
- $flags = STREAM_CLIENT_PERSISTENT;
- }
-
- $addr = $this->addr . ':' . $this->port;
- $fp = stream_socket_client($addr, $errno, $errstr,
- $timeout, $flags, $context);
- } else {
- $fp = @$openfunc($this->addr, $this->port, $errno,
- $errstr, $timeout, $context);
- }
- } else {
- if ($this->timeout) {
- $fp = @$openfunc($this->addr, $this->port, $errno,
- $errstr, $this->timeout);
- } else {
- $fp = @$openfunc($this->addr, $this->port, $errno, $errstr);
- }
- }
-
- if (!$fp) {
- if ($errno == 0 && !strlen($errstr) && isset($php_errormsg)) {
- $errstr = $php_errormsg;
- }
- @ini_set('track_errors', $old_track_errors);
- return $this->raiseError($errstr, $errno);
- }
-
- @ini_set('track_errors', $old_track_errors);
- $this->fp = $fp;
-
- return $this->setBlocking($this->blocking);
- }
-
- /**
- * Disconnects from the peer, closes the socket.
- *
- * @access public
- * @return mixed true on success or a PEAR_Error instance otherwise
- */
- function disconnect()
- {
- if (!is_resource($this->fp)) {
- return $this->raiseError('not connected');
- }
-
- @fclose($this->fp);
- $this->fp = null;
- return true;
- }
-
- /**
- * Set the newline character/sequence to use.
- *
- * @param string $newline Newline character(s)
- * @return boolean True
- */
- function setNewline($newline)
- {
- $this->newline = $newline;
- return true;
- }
-
- /**
- * Find out if the socket is in blocking mode.
- *
- * @access public
- * @return boolean The current blocking mode.
- */
- function isBlocking()
- {
- return $this->blocking;
- }
-
- /**
- * Sets whether the socket connection should be blocking or
- * not. A read call to a non-blocking socket will return immediately
- * if there is no data available, whereas it will block until there
- * is data for blocking sockets.
- *
- * @param boolean $mode True for blocking sockets, false for nonblocking.
- *
- * @access public
- * @return mixed true on success or a PEAR_Error instance otherwise
- */
- function setBlocking($mode)
- {
- if (!is_resource($this->fp)) {
- return $this->raiseError('not connected');
- }
-
- $this->blocking = $mode;
- stream_set_blocking($this->fp, (int)$this->blocking);
- return true;
- }
-
- /**
- * Sets the timeout value on socket descriptor,
- * expressed in the sum of seconds and microseconds
- *
- * @param integer $seconds Seconds.
- * @param integer $microseconds Microseconds.
- *
- * @access public
- * @return mixed true on success or a PEAR_Error instance otherwise
- */
- function setTimeout($seconds, $microseconds)
- {
- if (!is_resource($this->fp)) {
- return $this->raiseError('not connected');
- }
-
- return socket_set_timeout($this->fp, $seconds, $microseconds);
- }
-
- /**
- * Sets the file buffering size on the stream.
- * See php's stream_set_write_buffer for more information.
- *
- * @param integer $size Write buffer size.
- *
- * @access public
- * @return mixed on success or an PEAR_Error object otherwise
- */
- function setWriteBuffer($size)
- {
- if (!is_resource($this->fp)) {
- return $this->raiseError('not connected');
- }
-
- $returned = stream_set_write_buffer($this->fp, $size);
- if ($returned == 0) {
- return true;
- }
- return $this->raiseError('Cannot set write buffer.');
- }
-
- /**
- * Returns information about an existing socket resource.
- * Currently returns four entries in the result array:
- *
- *
- * timed_out (bool) - The socket timed out waiting for data
- * blocked (bool) - The socket was blocked
- * eof (bool) - Indicates EOF event
- * unread_bytes (int) - Number of bytes left in the socket buffer
- *
- *
- * @access public
- * @return mixed Array containing information about existing socket
- * resource or a PEAR_Error instance otherwise
- */
- function getStatus()
- {
- if (!is_resource($this->fp)) {
- return $this->raiseError('not connected');
- }
-
- return socket_get_status($this->fp);
- }
-
- /**
- * Get a specified line of data
- *
- * @param int $size ??
- *
- * @access public
- * @return $size bytes of data from the socket, or a PEAR_Error if
- * not connected.
- */
- function gets($size = null)
- {
- if (!is_resource($this->fp)) {
- return $this->raiseError('not connected');
- }
-
- if (is_null($size)) {
- return @fgets($this->fp);
- } else {
- return @fgets($this->fp, $size);
- }
- }
-
- /**
- * Read a specified amount of data. This is guaranteed to return,
- * and has the added benefit of getting everything in one fread()
- * chunk; if you know the size of the data you're getting
- * beforehand, this is definitely the way to go.
- *
- * @param integer $size The number of bytes to read from the socket.
- *
- * @access public
- * @return $size bytes of data from the socket, or a PEAR_Error if
- * not connected.
- */
- function read($size)
- {
- if (!is_resource($this->fp)) {
- return $this->raiseError('not connected');
- }
-
- return @fread($this->fp, $size);
- }
-
- /**
- * Write a specified amount of data.
- *
- * @param string $data Data to write.
- * @param integer $blocksize Amount of data to write at once.
- * NULL means all at once.
- *
- * @access public
- * @return mixed If the socket is not connected, returns an instance of
- * PEAR_Error
- * If the write succeeds, returns the number of bytes written
- * If the write fails, returns false.
- */
- function write($data, $blocksize = null)
- {
- if (!is_resource($this->fp)) {
- return $this->raiseError('not connected');
- }
-
- if (is_null($blocksize) && !OS_WINDOWS) {
- return @fwrite($this->fp, $data);
- } else {
- if (is_null($blocksize)) {
- $blocksize = 1024;
- }
-
- $pos = 0;
- $size = strlen($data);
- while ($pos < $size) {
- $written = @fwrite($this->fp, substr($data, $pos, $blocksize));
- if (!$written) {
- return $written;
- }
- $pos += $written;
- }
-
- return $pos;
- }
- }
-
- /**
- * Write a line of data to the socket, followed by a trailing newline.
- *
- * @param string $data Data to write
- *
- * @access public
- * @return mixed fputs result, or an error
- */
- function writeLine($data)
- {
- if (!is_resource($this->fp)) {
- return $this->raiseError('not connected');
- }
-
- return fwrite($this->fp, $data . $this->newline);
- }
-
- /**
- * Tests for end-of-file on a socket descriptor.
- *
- * Also returns true if the socket is disconnected.
- *
- * @access public
- * @return bool
- */
- function eof()
- {
- return (!is_resource($this->fp) || feof($this->fp));
- }
-
- /**
- * Reads a byte of data
- *
- * @access public
- * @return 1 byte of data from the socket, or a PEAR_Error if
- * not connected.
- */
- function readByte()
- {
- if (!is_resource($this->fp)) {
- return $this->raiseError('not connected');
- }
-
- return ord(@fread($this->fp, 1));
- }
-
- /**
- * Reads a word of data
- *
- * @access public
- * @return 1 word of data from the socket, or a PEAR_Error if
- * not connected.
- */
- function readWord()
- {
- if (!is_resource($this->fp)) {
- return $this->raiseError('not connected');
- }
-
- $buf = @fread($this->fp, 2);
- return (ord($buf[0]) + (ord($buf[1]) << 8));
- }
-
- /**
- * Reads an int of data
- *
- * @access public
- * @return integer 1 int of data from the socket, or a PEAR_Error if
- * not connected.
- */
- function readInt()
- {
- if (!is_resource($this->fp)) {
- return $this->raiseError('not connected');
- }
-
- $buf = @fread($this->fp, 4);
- return (ord($buf[0]) + (ord($buf[1]) << 8) +
- (ord($buf[2]) << 16) + (ord($buf[3]) << 24));
- }
-
- /**
- * Reads a zero-terminated string of data
- *
- * @access public
- * @return string, or a PEAR_Error if
- * not connected.
- */
- function readString()
- {
- if (!is_resource($this->fp)) {
- return $this->raiseError('not connected');
- }
-
- $string = '';
- while (($char = @fread($this->fp, 1)) != "\x00") {
- $string .= $char;
- }
- return $string;
- }
-
- /**
- * Reads an IP Address and returns it in a dot formatted string
- *
- * @access public
- * @return Dot formatted string, or a PEAR_Error if
- * not connected.
- */
- function readIPAddress()
- {
- if (!is_resource($this->fp)) {
- return $this->raiseError('not connected');
- }
-
- $buf = @fread($this->fp, 4);
- return sprintf('%d.%d.%d.%d', ord($buf[0]), ord($buf[1]),
- ord($buf[2]), ord($buf[3]));
- }
-
- /**
- * Read until either the end of the socket or a newline, whichever
- * comes first. Strips the trailing newline from the returned data.
- *
- * @access public
- * @return All available data up to a newline, without that
- * newline, or until the end of the socket, or a PEAR_Error if
- * not connected.
- */
- function readLine()
- {
- if (!is_resource($this->fp)) {
- return $this->raiseError('not connected');
- }
-
- $line = '';
-
- $timeout = time() + $this->timeout;
-
- while (!feof($this->fp) && (!$this->timeout || time() < $timeout)) {
- $line .= @fgets($this->fp, $this->lineLength);
- if (substr($line, -1) == "\n") {
- return rtrim($line, $this->newline);
- }
- }
- return $line;
- }
-
- /**
- * Read until the socket closes, or until there is no more data in
- * the inner PHP buffer. If the inner buffer is empty, in blocking
- * mode we wait for at least 1 byte of data. Therefore, in
- * blocking mode, if there is no data at all to be read, this
- * function will never exit (unless the socket is closed on the
- * remote end).
- *
- * @access public
- *
- * @return string All data until the socket closes, or a PEAR_Error if
- * not connected.
- */
- function readAll()
- {
- if (!is_resource($this->fp)) {
- return $this->raiseError('not connected');
- }
-
- $data = '';
- while (!feof($this->fp)) {
- $data .= @fread($this->fp, $this->lineLength);
- }
- return $data;
- }
-
- /**
- * Runs the equivalent of the select() system call on the socket
- * with a timeout specified by tv_sec and tv_usec.
- *
- * @param integer $state Which of read/write/error to check for.
- * @param integer $tv_sec Number of seconds for timeout.
- * @param integer $tv_usec Number of microseconds for timeout.
- *
- * @access public
- * @return False if select fails, integer describing which of read/write/error
- * are ready, or PEAR_Error if not connected.
- */
- function select($state, $tv_sec, $tv_usec = 0)
- {
- if (!is_resource($this->fp)) {
- return $this->raiseError('not connected');
- }
-
- $read = null;
- $write = null;
- $except = null;
- if ($state & NET_SOCKET_READ) {
- $read[] = $this->fp;
- }
- if ($state & NET_SOCKET_WRITE) {
- $write[] = $this->fp;
- }
- if ($state & NET_SOCKET_ERROR) {
- $except[] = $this->fp;
- }
- if (false === ($sr = stream_select($read, $write, $except,
- $tv_sec, $tv_usec))) {
- return false;
- }
-
- $result = 0;
- if (count($read)) {
- $result |= NET_SOCKET_READ;
- }
- if (count($write)) {
- $result |= NET_SOCKET_WRITE;
- }
- if (count($except)) {
- $result |= NET_SOCKET_ERROR;
- }
- return $result;
- }
-
- /**
- * Turns encryption on/off on a connected socket.
- *
- * @param bool $enabled Set this parameter to true to enable encryption
- * and false to disable encryption.
- * @param integer $type Type of encryption. See stream_socket_enable_crypto()
- * for values.
- *
- * @see http://se.php.net/manual/en/function.stream-socket-enable-crypto.php
- * @access public
- * @return false on error, true on success and 0 if there isn't enough data
- * and the user should try again (non-blocking sockets only).
- * A PEAR_Error object is returned if the socket is not
- * connected
- */
- function enableCrypto($enabled, $type)
- {
- if (version_compare(phpversion(), "5.1.0", ">=")) {
- if (!is_resource($this->fp)) {
- return $this->raiseError('not connected');
- }
- return @stream_socket_enable_crypto($this->fp, $enabled, $type);
- } else {
- $msg = 'Net_Socket::enableCrypto() requires php version >= 5.1.0';
- return $this->raiseError($msg);
- }
- }
-
-}
diff --git a/data/module/Net/URL.php b/data/module/Net/URL.php
deleted file mode 100644
index 5064a12ea79..00000000000
--- a/data/module/Net/URL.php
+++ /dev/null
@@ -1,485 +0,0 @@
- |
-// +-----------------------------------------------------------------------+
-//
-// $Id$
-//
-// Net_URL Class
-
-
-class Net_URL
-{
- var $options = array('encode_query_keys' => false);
- /**
- * Full url
- * @var string
- */
- var $url;
-
- /**
- * Protocol
- * @var string
- */
- var $protocol;
-
- /**
- * Username
- * @var string
- */
- var $username;
-
- /**
- * Password
- * @var string
- */
- var $password;
-
- /**
- * Host
- * @var string
- */
- var $host;
-
- /**
- * Port
- * @var integer
- */
- var $port;
-
- /**
- * Path
- * @var string
- */
- var $path;
-
- /**
- * Query string
- * @var array
- */
- var $querystring;
-
- /**
- * Anchor
- * @var string
- */
- var $anchor;
-
- /**
- * Whether to use []
- * @var bool
- */
- var $useBrackets;
-
- /**
- * PHP4 Constructor
- *
- * @see __construct()
- */
- function Net_URL($url = null, $useBrackets = true)
- {
- $this->__construct($url, $useBrackets);
- }
-
- /**
- * PHP5 Constructor
- *
- * Parses the given url and stores the various parts
- * Defaults are used in certain cases
- *
- * @param string $url Optional URL
- * @param bool $useBrackets Whether to use square brackets when
- * multiple querystrings with the same name
- * exist
- */
- function __construct($url = null, $useBrackets = true)
- {
- $this->url = $url;
- $this->useBrackets = $useBrackets;
-
- $this->initialize();
- }
-
- function initialize()
- {
- $HTTP_SERVER_VARS = !empty($_SERVER) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];
-
- $this->user = '';
- $this->pass = '';
- $this->host = '';
- $this->port = 80;
- $this->path = '';
- $this->querystring = array();
- $this->anchor = '';
-
- // Only use defaults if not an absolute URL given
- if (!preg_match('/^[a-z0-9]+:\/\//i', $this->url)) {
- $this->protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 'https' : 'http');
-
- /**
- * Figure out host/port
- */
- if (!empty($HTTP_SERVER_VARS['HTTP_HOST']) &&
- preg_match('/^(.*)(:([0-9]+))?$/U', $HTTP_SERVER_VARS['HTTP_HOST'], $matches))
- {
- $host = $matches[1];
- if (!empty($matches[3])) {
- $port = $matches[3];
- } else {
- $port = $this->getStandardPort($this->protocol);
- }
- }
-
- $this->user = '';
- $this->pass = '';
- $this->host = !empty($host) ? $host : (isset($HTTP_SERVER_VARS['SERVER_NAME']) ? $HTTP_SERVER_VARS['SERVER_NAME'] : 'localhost');
- $this->port = !empty($port) ? $port : (isset($HTTP_SERVER_VARS['SERVER_PORT']) ? $HTTP_SERVER_VARS['SERVER_PORT'] : $this->getStandardPort($this->protocol));
- $this->path = !empty($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : '/';
- $this->querystring = isset($HTTP_SERVER_VARS['QUERY_STRING']) ? $this->_parseRawQuerystring($HTTP_SERVER_VARS['QUERY_STRING']) : null;
- $this->anchor = '';
- }
-
- // Parse the url and store the various parts
- if (!empty($this->url)) {
- $urlinfo = parse_url($this->url);
-
- // Default querystring
- $this->querystring = array();
-
- foreach ($urlinfo as $key => $value) {
- switch ($key) {
- case 'scheme':
- $this->protocol = $value;
- $this->port = $this->getStandardPort($value);
- break;
-
- case 'user':
- case 'pass':
- case 'host':
- case 'port':
- $this->$key = $value;
- break;
-
- case 'path':
- if ($value{0} == '/') {
- $this->path = $value;
- } else {
- $path = dirname($this->path) == DIRECTORY_SEPARATOR ? '' : dirname($this->path);
- $this->path = sprintf('%s/%s', $path, $value);
- }
- break;
-
- case 'query':
- $this->querystring = $this->_parseRawQueryString($value);
- break;
-
- case 'fragment':
- $this->anchor = $value;
- break;
- }
- }
- }
- }
- /**
- * Returns full url
- *
- * @return string Full url
- * @access public
- */
- function getURL()
- {
- $querystring = $this->getQueryString();
-
- $this->url = $this->protocol . '://'
- . $this->user . (!empty($this->pass) ? ':' : '')
- . $this->pass . (!empty($this->user) ? '@' : '')
- . $this->host . ($this->port == $this->getStandardPort($this->protocol) ? '' : ':' . $this->port)
- . $this->path
- . (!empty($querystring) ? '?' . $querystring : '')
- . (!empty($this->anchor) ? '#' . $this->anchor : '');
-
- return $this->url;
- }
-
- /**
- * Adds or updates a querystring item (URL parameter).
- * Automatically encodes parameters with rawurlencode() if $preencoded
- * is false.
- * You can pass an array to $value, it gets mapped via [] in the URL if
- * $this->useBrackets is activated.
- *
- * @param string $name Name of item
- * @param string $value Value of item
- * @param bool $preencoded Whether value is urlencoded or not, default = not
- * @access public
- */
- function addQueryString($name, $value, $preencoded = false)
- {
- if ($this->getOption('encode_query_keys')) {
- $name = rawurlencode($name);
- }
-
- if ($preencoded) {
- $this->querystring[$name] = $value;
- } else {
- $this->querystring[$name] = is_array($value) ? array_map('rawurlencode', $value): rawurlencode($value);
- }
- }
-
- /**
- * Removes a querystring item
- *
- * @param string $name Name of item
- * @access public
- */
- function removeQueryString($name)
- {
- if ($this->getOption('encode_query_keys')) {
- $name = rawurlencode($name);
- }
-
- if (isset($this->querystring[$name])) {
- unset($this->querystring[$name]);
- }
- }
-
- /**
- * Sets the querystring to literally what you supply
- *
- * @param string $querystring The querystring data. Should be of the format foo=bar&x=y etc
- * @access public
- */
- function addRawQueryString($querystring)
- {
- $this->querystring = $this->_parseRawQueryString($querystring);
- }
-
- /**
- * Returns flat querystring
- *
- * @return string Querystring
- * @access public
- */
- function getQueryString()
- {
- if (!empty($this->querystring)) {
- foreach ($this->querystring as $name => $value) {
- // Encode var name
- $name = rawurlencode($name);
-
- if (is_array($value)) {
- foreach ($value as $k => $v) {
- $querystring[] = $this->useBrackets ? sprintf('%s[%s]=%s', $name, $k, $v) : ($name . '=' . $v);
- }
- } elseif (!is_null($value)) {
- $querystring[] = $name . '=' . $value;
- } else {
- $querystring[] = $name;
- }
- }
- $querystring = implode(ini_get('arg_separator.output'), $querystring);
- } else {
- $querystring = '';
- }
-
- return $querystring;
- }
-
- /**
- * Parses raw querystring and returns an array of it
- *
- * @param string $querystring The querystring to parse
- * @return array An array of the querystring data
- * @access private
- */
- function _parseRawQuerystring($querystring)
- {
- $parts = preg_split('/[' . preg_quote(ini_get('arg_separator.input'), '/') . ']/', $querystring, -1, PREG_SPLIT_NO_EMPTY);
- $return = array();
-
- foreach ($parts as $part) {
- if (strpos($part, '=') !== false) {
- $value = substr($part, strpos($part, '=') + 1);
- $key = substr($part, 0, strpos($part, '='));
- } else {
- $value = null;
- $key = $part;
- }
-
- if (!$this->getOption('encode_query_keys')) {
- $key = rawurldecode($key);
- }
-
- if (preg_match('#^(.*)\[([0-9a-z_-]*)\]#i', $key, $matches)) {
- $key = $matches[1];
- $idx = $matches[2];
-
- // Ensure is an array
- if (empty($return[$key]) || !is_array($return[$key])) {
- $return[$key] = array();
- }
-
- // Add data
- if ($idx === '') {
- $return[$key][] = $value;
- } else {
- $return[$key][$idx] = $value;
- }
- } elseif (!$this->useBrackets AND !empty($return[$key])) {
- $return[$key] = (array)$return[$key];
- $return[$key][] = $value;
- } else {
- $return[$key] = $value;
- }
- }
-
- return $return;
- }
-
- /**
- * Resolves //, ../ and ./ from a path and returns
- * the result. Eg:
- *
- * /foo/bar/../boo.php => /foo/boo.php
- * /foo/bar/../../boo.php => /boo.php
- * /foo/bar/.././/boo.php => /foo/boo.php
- *
- * This method can also be called statically.
- *
- * @param string $path URL path to resolve
- * @return string The result
- */
- function resolvePath($path)
- {
- $path = explode('/', str_replace('//', '/', $path));
-
- for ($i=0; $i 1 OR ($i == 1 AND $path[0] != '') ) ) {
- unset($path[$i]);
- unset($path[$i-1]);
- $path = array_values($path);
- $i -= 2;
-
- } elseif ($path[$i] == '..' AND $i == 1 AND $path[0] == '') {
- unset($path[$i]);
- $path = array_values($path);
- $i--;
-
- } else {
- continue;
- }
- }
-
- return implode('/', $path);
- }
-
- /**
- * Returns the standard port number for a protocol
- *
- * @param string $scheme The protocol to lookup
- * @return integer Port number or NULL if no scheme matches
- *
- * @author Philippe Jausions
- */
- function getStandardPort($scheme)
- {
- switch (strtolower($scheme)) {
- case 'http': return 80;
- case 'https': return 443;
- case 'ftp': return 21;
- case 'imap': return 143;
- case 'imaps': return 993;
- case 'pop3': return 110;
- case 'pop3s': return 995;
- default: return null;
- }
- }
-
- /**
- * Forces the URL to a particular protocol
- *
- * @param string $protocol Protocol to force the URL to
- * @param integer $port Optional port (standard port is used by default)
- */
- function setProtocol($protocol, $port = null)
- {
- $this->protocol = $protocol;
- $this->port = is_null($port) ? $this->getStandardPort($protocol) : $port;
- }
-
- /**
- * Set an option
- *
- * This function set an option
- * to be used thorough the script.
- *
- * @access public
- * @param string $optionName The optionname to set
- * @param string $value The value of this option.
- */
- function setOption($optionName, $value)
- {
- if (!array_key_exists($optionName, $this->options)) {
- return false;
- }
-
- $this->options[$optionName] = $value;
- $this->initialize();
- }
-
- /**
- * Get an option
- *
- * This function gets an option
- * from the $this->options array
- * and return it's value.
- *
- * @access public
- * @param string $opionName The name of the option to retrieve
- * @see $this->options
- */
- function getOption($optionName)
- {
- if (!isset($this->options[$optionName])) {
- return false;
- }
-
- return $this->options[$optionName];
- }
-
-}
-?>
diff --git a/data/module/Net/UserAgent/Mobile.php b/data/module/Net/UserAgent/Mobile.php
deleted file mode 100644
index 2f5b2274125..00000000000
--- a/data/module/Net/UserAgent/Mobile.php
+++ /dev/null
@@ -1,457 +0,0 @@
-,
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * @category Networking
- * @package Net_UserAgent_Mobile
- * @author KUBO Atsuhiro
- * @copyright 2003-2009 KUBO Atsuhiro
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id$
- * @since File available since Release 0.1
- */
-
-require_once dirname(__FILE__) . '/../../PEAR.php';
-require_once dirname(__FILE__) . '/Mobile/Error.php';
-
-// {{{ GLOBALS
-
-/**
- * globals for fallback on no match
- *
- * @global boolean $GLOBALS['NET_USERAGENT_MOBILE_FallbackOnNomatch']
- */
-$GLOBALS['NET_USERAGENT_MOBILE_FallbackOnNomatch'] = false;
-
-// }}}
-// {{{ Net_UserAgent_Mobile
-
-/**
- * HTTP mobile user agent string parser
- *
- * Net_UserAgent_Mobile parses HTTP_USER_AGENT strings of (mainly Japanese) mobile
- * HTTP user agents. It'll be useful in page dispatching by user agents.
- * This package was ported from Perl's HTTP::MobileAgent.
- * See {@link http://search.cpan.org/search?mode=module&query=HTTP-MobileAgent}
- *
- * SYNOPSIS:
- *
- * require_once 'Net/UserAgent/Mobile.php';
- *
- * $agent = &Net_UserAgent_Mobile::factory($agent_string);
- * // or $agent = &Net_UserAgent_Mobile::factory(); // to get from $_SERVER
- *
- * if ($agent->isDoCoMo()) {
- * // or if ($agent->getName() == 'DoCoMo')
- * // or if (strtolower(get_class($agent)) == 'http_mobileagent_docomo')
- * // it's NTT DoCoMo i-mode
- * // see what's available in Net_UserAgent_Mobile_DoCoMo
- * } elseif ($agent->isSoftBank()) {
- * // it's SoftBank
- * // see what's available in Net_UserAgent_Mobile_SoftBank
- * } elseif ($agent->isEZweb()) {
- * // it's KDDI/EZWeb
- * // see what's available in Net_UserAgent_Mobile_EZweb
- * } else {
- * // may be PC
- * // $agent is Net_UserAgent_Mobile_NonMobile
- * }
- *
- * $display = $agent->getDisplay(); // Net_UserAgent_Mobile_Display
- * if ($display->isColor()) {
- * ...
- * }
- *
- *
- * @category Networking
- * @package Net_UserAgent_Mobile
- * @author KUBO Atsuhiro
- * @copyright 2003-2009 KUBO Atsuhiro
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.0.0
- * @since Class available since Release 0.1
- */
-class Net_UserAgent_Mobile
-{
-
- // {{{ properties
-
- /**#@+
- * @access public
- */
-
- /**#@-*/
-
- /**#@+
- * @access private
- */
-
- /**#@-*/
-
- /**#@+
- * @access public
- * @static
- */
-
- // }}}
- // {{{ factory()
-
- /**
- * create a new {@link Net_UserAgent_Mobile_Common} subclass instance
- *
- * parses HTTP headers and constructs {@link Net_UserAgent_Mobile_Common}
- * subclass instance.
- * If no argument is supplied, $_SERVER{'HTTP_*'} is used.
- *
- * @param string $userAgent User-Agent string
- * @return Net_UserAgent_Mobile_Common a newly created or an existing
- * Net_UserAgent_Mobile_Common object
- * @throws Net_UserAgent_Mobile_Error
- */
- function &factory($userAgent = null)
- {
- if (is_null($userAgent)) {
- $userAgent = @$_SERVER['HTTP_USER_AGENT'];
- }
-
- // parse User-Agent string
- if (Net_UserAgent_Mobile::isDoCoMo($userAgent)) {
- $driver = 'DoCoMo';
- } elseif (Net_UserAgent_Mobile::isEZweb($userAgent)) {
- $driver = 'EZweb';
- } elseif (Net_UserAgent_Mobile::isSoftBank($userAgent)) {
- $driver = 'SoftBank';
- } elseif (Net_UserAgent_Mobile::isWillcom($userAgent)) {
- $driver = 'Willcom';
- } else {
- $driver = 'NonMobile';
- }
-
- $class = "Net_UserAgent_Mobile_$driver";
-
- if (!class_exists($class)) {
- $file = dirname(__FILE__) . "/Mobile/{$driver}.php";
- if (!include_once $file) {
- return PEAR::raiseError(null,
- NET_USERAGENT_MOBILE_ERROR_NOT_FOUND,
- null, null,
- "Unable to include the $file file",
- 'Net_UserAgent_Mobile_Error', true
- );
- }
- }
-
- PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
- $instance = new $class($userAgent);
- PEAR::staticPopErrorHandling();
- $error = &$instance->getError();
- if (Net_UserAgent_Mobile::isError($error)) {
- if ($GLOBALS['NET_USERAGENT_MOBILE_FallbackOnNomatch']
- && $error->getCode() == NET_USERAGENT_MOBILE_ERROR_NOMATCH
- ) {
- $instance = &Net_UserAgent_Mobile::factory('Net_UserAgent_Mobile_Fallback_On_NoMatch');
- return $instance;
- }
-
- return PEAR::raiseError($error);
- }
-
- return $instance;
- }
-
- // }}}
- // {{{ singleton()
-
- /**
- * creates a new {@link Net_UserAgent_Mobile_Common} subclass instance or returns
- * a instance from existent ones
- *
- * @param string $userAgent User-Agent string
- * @return Net_UserAgent_Mobile_Common a newly created or an existing
- * Net_UserAgent_Mobile_Common object
- * @throws Net_UserAgent_Mobile_Error
- */
- function &singleton($userAgent = null)
- {
- static $instances;
-
- if (!isset($instances)) {
- $instances = array();
- }
-
- if (is_null($userAgent)) {
- $userAgent = @$_SERVER['HTTP_USER_AGENT'];
- }
-
- if (!array_key_exists($userAgent, $instances)) {
- $instances[$userAgent] = Net_UserAgent_Mobile::factory($userAgent);
- }
-
- return $instances[$userAgent];
- }
-
- // }}}
- // {{{ isError()
-
- /**
- * tell whether a result code from a Net_UserAgent_Mobile method is an error
- *
- * @param integer $value result code
- * @return boolean whether $value is an {@link Net_UserAgent_Mobile_Error}
- */
- function isError($value)
- {
- return is_object($value)
- && (strtolower(get_class($value)) == strtolower('Net_UserAgent_Mobile_Error')
- || is_subclass_of($value, 'Net_UserAgent_Mobile_Error'));
- }
-
- // }}}
- // {{{ errorMessage()
-
- /**
- * return a textual error message for a Net_UserAgent_Mobile error code
- *
- * @param integer $value error code
- * @return string error message, or null if the error code was not recognized
- */
- function errorMessage($value)
- {
- static $errorMessages;
- if (!isset($errorMessages)) {
- $errorMessages = array(
- NET_USERAGENT_MOBILE_ERROR => 'unknown error',
- NET_USERAGENT_MOBILE_ERROR_NOMATCH => 'no match',
- NET_USERAGENT_MOBILE_ERROR_NOT_FOUND => 'not found',
- NET_USERAGENT_MOBILE_OK => 'no error'
- );
- }
-
- if (Net_UserAgent_Mobile::isError($value)) {
- $value = $value->getCode();
- }
-
- return isset($errorMessages[$value]) ?
- $errorMessages[$value] :
- $errorMessages[NET_USERAGENT_MOBILE_ERROR];
- }
-
- // }}}
- // {{{ isMobile()
-
- /**
- * Checks whether or not the user agent is mobile by a given user agent string.
- *
- * @param string $userAgent
- * @return boolean
- * @since Method available since Release 0.31.0
- */
- function isMobile($userAgent = null)
- {
- if (Net_UserAgent_Mobile::isDoCoMo($userAgent)) {
- return true;
- } elseif (Net_UserAgent_Mobile::isEZweb($userAgent)) {
- return true;
- } elseif (Net_UserAgent_Mobile::isSoftBank($userAgent)) {
- return true;
- } elseif (Net_UserAgent_Mobile::isWillcom($userAgent)) {
- return true;
- }
-
- return false;
- }
-
- // }}}
- // {{{ isDoCoMo()
-
- /**
- * Checks whether or not the user agent is DoCoMo by a given user agent string.
- *
- * @param string $userAgent
- * @return boolean
- * @since Method available since Release 0.31.0
- */
- function isDoCoMo($userAgent = null)
- {
- if (is_null($userAgent)) {
- $userAgent = @$_SERVER['HTTP_USER_AGENT'];
- }
-
- if (preg_match('!^DoCoMo!', $userAgent)) {
- return true;
- }
-
- return false;
- }
-
- // }}}
- // {{{ isEZweb()
-
- /**
- * Checks whether or not the user agent is EZweb by a given user agent string.
- *
- * @param string $userAgent
- * @return boolean
- * @since Method available since Release 0.31.0
- */
- function isEZweb($userAgent = null)
- {
- if (is_null($userAgent)) {
- $userAgent = @$_SERVER['HTTP_USER_AGENT'];
- }
-
- if (preg_match('!^KDDI-!', $userAgent)) {
- return true;
- } elseif (preg_match('!^UP\.Browser!', $userAgent)) {
- return true;
- }
-
- return false;
- }
-
- // }}}
- // {{{ isSoftBank()
-
- /**
- * Checks whether or not the user agent is SoftBank by a given user agent string.
- *
- * @param string $userAgent
- * @return boolean
- * @since Method available since Release 0.31.0
- */
- function isSoftBank($userAgent = null)
- {
- if (is_null($userAgent)) {
- $userAgent = @$_SERVER['HTTP_USER_AGENT'];
- }
-
- if (preg_match('!^SoftBank!', $userAgent)) {
- return true;
- } elseif (preg_match('!^Semulator!', $userAgent)) {
- return true;
- } elseif (preg_match('!^Vodafone!', $userAgent)) {
- return true;
- } elseif (preg_match('!^Vemulator!', $userAgent)) {
- return true;
- } elseif (preg_match('!^MOT-!', $userAgent)) {
- return true;
- } elseif (preg_match('!^MOTEMULATOR!', $userAgent)) {
- return true;
- } elseif (preg_match('!^J-PHONE!', $userAgent)) {
- return true;
- } elseif (preg_match('!^J-EMULATOR!', $userAgent)) {
- return true;
- }
-
- return false;
- }
-
- // }}}
- // {{{ isWillcom()
-
- /**
- * Checks whether or not the user agent is Willcom by a given user agent string.
- *
- * @param string $userAgent
- * @return boolean
- * @since Method available since Release 0.31.0
- */
- function isWillcom($userAgent = null)
- {
- if (is_null($userAgent)) {
- $userAgent = @$_SERVER['HTTP_USER_AGENT'];
- }
-
- if (preg_match('!^Mozilla/3\.0\((?:DDIPOCKET|WILLCOM);!', $userAgent)) {
- return true;
- }
-
- return false;
- }
-
- // }}}
- // {{{ isSmartphone()
-
- /**
- * Checks whether or not the user agent is Smartphone by a given user agent string.
- *
- * @param string $userAgent
- * @return boolean
- * @since Method available since Release 0.31.0
- */
- function isSmartphone($userAgent = null)
- {
- if (is_null($userAgent)) {
- $userAgent = @$_SERVER['HTTP_USER_AGENT'];
- }
-
- $useragents = array(
- 'iPhone', // Apple iPhone
- 'iPod', // Apple iPod touch
- 'Android', // 1.5+ Android
- 'dream', // Pre 1.5 Android
- 'CUPCAKE', // 1.5+ Android
- 'blackberry9500', // Storm
- 'blackberry9530', // Storm
- 'blackberry9520', // Storm v2
- 'blackberry9550', // Storm v2
- 'blackberry9800', // Torch
- 'webOS', // Palm Pre Experimental
- 'incognito', // Other iPhone browser
- 'webmate', // Other iPhone browser
- 'Windows Phone OS' // Windows Phone
- );
-
- $pattern = implode("|", $useragents);
- return preg_match('/'.$pattern.'/', $userAgent);
- }
-
- /**#@-*/
-
- /**#@+
- * @access private
- */
-
- /**#@-*/
-
- // }}}
-}
-
-// }}}
-
-/*
- * Local Variables:
- * mode: php
- * coding: iso-8859-1
- * tab-width: 4
- * c-basic-offset: 4
- * c-hanging-comment-ender-p: nil
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/data/module/Net/UserAgent/Mobile/Common.php b/data/module/Net/UserAgent/Mobile/Common.php
deleted file mode 100644
index dc8c8ee2611..00000000000
--- a/data/module/Net/UserAgent/Mobile/Common.php
+++ /dev/null
@@ -1,528 +0,0 @@
-,
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * @category Networking
- * @package Net_UserAgent_Mobile
- * @author KUBO Atsuhiro
- * @copyright 2003-2009 KUBO Atsuhiro
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version CVS: $Id$
- * @since File available since Release 0.1
- */
-
-require_once dirname(__FILE__) . '/Error.php';
-require_once dirname(__FILE__) . '/../../../PEAR.php';
-
-// {{{ Net_UserAgent_Mobile_Common
-
-/**
- * Base class that is extended by each user agents implementor
- *
- * Net_UserAgent_Mobile_Common is a class for mobile user agent
- * abstraction layer on Net_UserAgent_Mobile.
- *
- * @category Networking
- * @package Net_UserAgent_Mobile
- * @author KUBO Atsuhiro
- * @copyright 2003-2009 KUBO Atsuhiro
- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version Release: 1.0.0
- * @since Class available since Release 0.1
- */
-class Net_UserAgent_Mobile_Common
-{
-
- // {{{ properties
-
- /**#@+
- * @access public
- */
-
- /**
- * User-Agent name like 'DoCoMo'
- * @var string
- */
- var $name;
-
- /**
- * User-Agent version number like '1.0'
- * @var string
- */
- var $version;
-
- /**#@-*/
-
- /**#@+
- * @access private
- */
-
- /**
- * {@link Net_UserAgent_Mobile_Display} object
- * @var object {@link Net_UserAgent_Mobile_Display}
- */
- var $_display;
-
- /**
- * {@link Net_UserAgent_Mobile_Error} object for error handling in the constructor
- * @var object
- **/
- var $_error;
-
- /**
- * The User-Agent string.
- * @var string
- * @since Property available since Release 0.31.0
- **/
- var $_userAgent;
-
- /**
- * The model name of the user agent.
- *
- * @var string
- * @since Property available since Release 0.31.0
- */
- var $_model;
-
- /**
- * The raw model name of the user agent.
- *
- * @var string
- * @since Property available since Release 0.31.0
- */
- var $_rawModel;
-
- /**#@-*/
-
- /**#@+
- * @access public
- */
-
- // }}}
- // {{{ constructor
-
- /**
- * constructor
- *
- * @param string $userAgent User-Agent string
- */
- function Net_UserAgent_Mobile_Common($userAgent)
- {
- $this->_userAgent = $userAgent;
-
- $result = $this->parse($userAgent);
- if (PEAR::isError($result)) {
- $this->_error = &$result;
- }
- }
-
- // }}}
- // {{{ getError
-
- /**
- * Gets a Net_UserAgent_Mobile_Error object.
- *
- * @param object {@link Net_UserAgent_Mobile_Error} object when setting an error
- * @return Net_UserAgent_Mobile_Error
- * @since Method available since Release 1.0.0RC2
- */
- function &getError()
- {
- if (is_null($this->_error)) {
- $return = null;
- return $return;
- }
-
- return $this->_error;
- }
-
- // }}}
- // {{{ getUserAgent()
-
- /**
- * returns User-Agent string
- *
- * @return string
- */
- function getUserAgent()
- {
- return $this->_userAgent;
- }
-
- // }}}
- // {{{ getHeader()
-
- /**
- * returns a specified HTTP header
- *
- * @param string $header
- * @return string
- */
- function getHeader($header)
- {
- return @$_SERVER[ 'HTTP_' . str_replace('-', '_', $header) ];
- }
-
- // }}}
- // {{{ getName()
-
- /**
- * returns User-Agent name like 'DoCoMo'
- *
- * @return string
- */
- function getName()
- {
- return $this->name;
- }
-
- // }}}
- // {{{ getDisplay()
-
- /**
- * returns {@link Net_UserAgent_Mobile_Disply} object
- *
- * @return Net_UserAgent_Mobile_Display
- */
- function getDisplay()
- {
- if (is_null($this->_display)) {
- $this->_display = $this->makeDisplay();
- }
-
- return $this->_display;
- }
-
- // }}}
- // {{{ getVersion()
-
- /**
- * returns User-Agent version number like '1.0'
- *
- * @return string
- */
- function getVersion()
- {
- return $this->version;
- }
-
- // }}}
- // {{{ noMatch()
-
- /**
- * generates a warning message for new variants
- *
- * @throws Net_UserAgent_Mobile_Error
- */
- function noMatch()
- {
- return PEAR::raiseError($this->getUserAgent() . ': might be new variants. Please contact the author of Net_UserAgent_Mobile!',
- NET_USERAGENT_MOBILE_ERROR_NOMATCH,
- null,
- null,
- null,
- 'Net_UserAgent_Mobile_Error'
- );
- }
-
- // }}}
- // {{{ parse()
-
- /**
- * Parses HTTP_USER_AGENT string.
- *
- * @param string $userAgent User-Agent string
- * @abstract
- */
- function parse($userAgent) {}
-
- // }}}
- // {{{ makeDisplay()
-
- /**
- * create a new Net_UserAgent_Mobile_Display class instance (should be
- * implemented in subclasses)
- *
- * @return Net_UserAgent_Mobile_Display
- * @abstract
- */
- function makeDisplay() {}
-
- // }}}
- // {{{ isDoCoMo()
-
- /**
- * returns true if the agent is DoCoMo
- *
- * @return boolean
- */
- function isDoCoMo()
- {
- return false;
- }
-
- // }}}
- // {{{ isJPhone()
-
- /**
- * returns true if the agent is J-PHONE
- *
- * @return boolean
- */
- function isJPhone()
- {
- return false;
- }
-
- // }}}
- // {{{ isVodafone()
-
- /**
- * returns true if the agent is Vodafone
- *
- * @return boolean
- */
- function isVodafone()
- {
- return false;
- }
-
- // }}}
- // {{{ isEZweb()
-
- /**
- * returns true if the agent is EZweb
- *
- * @return boolean
- */
- function isEZweb()
- {
- return false;
- }
-
- // }}}
- // {{{ isAirHPhone()
-
- /**
- * returns true if the agent is AirH"PHONE
- *
- * @return boolean
- */
- function isAirHPhone()
- {
- return false;
- }
-
- // }}}
- // {{{ isNonMobile()
-
- /**
- * returns true if the agent is NonMobile
- *
- * @return boolean
- */
- function isNonMobile()
- {
- return false;
- }
-
- // }}}
- // {{{ isTUKa()
-
- /**
- * returns true if the agent is TU-Ka
- *
- * @return boolean
- */
- function isTUKa()
- {
- return false;
- }
-
- // }}}
- // {{{ isWAP1()
-
- /**
- * returns true if the agent can speak WAP1 protocol
- *
- * @return boolean
- */
- function isWAP1()
- {
- return $this->isEZweb() && !$this->isWAP2();
- }
-
- // }}}
- // {{{ isWAP2()
-
- /**
- * returns true if the agent can speak WAP2 protocol
- *
- * @return boolean
- */
- function isWAP2()
- {
- return $this->isEZweb() && $this->isXHTMLCompliant();
- }
-
- // }}}
- // {{{ getCarrierShortName()
-
- /**
- * returns the short name of the carrier
- *
- * @abstract
- */
- function getCarrierShortName()
- {
- die();
- }
-
- // }}}
- // {{{ getCarrierLongName()
-
- /**
- * returns the long name of the carrier
- *
- * @abstract
- */
- function getCarrierLongName()
- {
- die();
- }
-
- // }}}
- // {{{ isSoftBank()
-
- /**
- * Returns whether the agent is SoftBank or not.
- *
- * @return boolean
- * @since Method available since Release 0.31.0
- */
- function isSoftBank()
- {
- return false;
- }
-
- // }}}
- // {{{ isWillcom()
-
- /**
- * Returns whether the agent is Willcom or not.
- *
- * @return boolean
- * @since Method available since Release 0.31.0
- */
- function isWillcom()
- {
- return false;
- }
-
- // }}}
- // {{{ isSmartphone()
-
- /**
- * Returns whether the agent is Smartphone or not.
- *
- * @return boolean
- * @since Method available since Release 0.31.0
- */
- function isSmartphone()
- {
- return false;
- }
-
-
- // }}}
- // {{{ getModel()
-
- /**
- * Returns the model name of the user agent.
- *
- * @return string
- * @since Method available since Release 0.31.0
- */
- function getModel()
- {
- if (is_null($this->_model)) {
- return $this->_rawModel;
- } else {
- return $this->_model;
- }
- }
-
- // }}}
- // {{{ getRawModel()
-
- /**
- * Returns the raw model name of the user agent.
- *
- * @return string
- * @since Method available since Release 0.31.0
- */
- function getRawModel()
- {
- return $this->_rawModel;
- }
-
- // }}}
- // {{{ getUID()
-
- /**
- * Gets the UID of a subscriber.
- *
- * @return string
- * @since Method available since Release 1.0.0RC1
- */
- function getUID() {}
-
- /**#@-*/
-
- /**#@+
- * @access private
- */
-
- /**#@-*/
-
- // }}}
-}
-
-// }}}
-
-/*
- * Local Variables:
- * mode: php
- * coding: iso-8859-1
- * tab-width: 4
- * c-basic-offset: 4
- * c-hanging-comment-ender-p: nil
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/data/module/Net/UserAgent/Mobile/Display.php b/data/module/Net/UserAgent/Mobile/Display.php
deleted file mode 100644
index 41c03b0a7be..00000000000
--- a/data/module/Net/UserAgent/Mobile/Display.php
+++ /dev/null
@@ -1,285 +0,0 @@
-,
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * @category Networking
- * @package Net_UserAgent_Mobile
- * @author KUBO Atsuhiro |