From 2a50c098686714420865e2ed1945cecc8759e294 Mon Sep 17 00:00:00 2001 From: Nikos Papagiannopoulos Date: Mon, 26 Oct 2020 08:34:43 +0100 Subject: [PATCH 1/5] Remove system directory and update $system_path in public/index.php --- composer.json | 3 +- public/index.php | 2 +- system/.htaccess | 6 - system/core/Benchmark.php | 133 - system/core/CodeIgniter.php | 559 ---- system/core/Common.php | 849 ----- system/core/Config.php | 379 --- system/core/Controller.php | 96 - system/core/Exceptions.php | 274 -- system/core/Hooks.php | 266 -- system/core/Input.php | 895 ------ system/core/Lang.php | 203 -- system/core/Loader.php | 1415 --------- system/core/Log.php | 296 -- system/core/Model.php | 76 - system/core/Output.php | 842 ----- system/core/Router.php | 515 --- system/core/Security.php | 1090 ------- system/core/URI.php | 643 ---- system/core/Utf8.php | 164 - system/core/compat/hash.php | 254 -- system/core/compat/index.html | 11 - system/core/compat/mbstring.php | 149 - system/core/compat/password.php | 251 -- system/core/compat/standard.php | 182 -- system/core/index.html | 11 - system/database/DB.php | 218 -- system/database/DB_cache.php | 221 -- system/database/DB_driver.php | 1991 ------------ system/database/DB_forge.php | 1030 ------ system/database/DB_query_builder.php | 2808 ----------------- system/database/DB_result.php | 665 ---- system/database/DB_utility.php | 424 --- .../database/drivers/cubrid/cubrid_driver.php | 405 --- .../database/drivers/cubrid/cubrid_forge.php | 230 -- .../database/drivers/cubrid/cubrid_result.php | 177 -- .../drivers/cubrid/cubrid_utility.php | 79 - system/database/drivers/cubrid/index.html | 11 - .../database/drivers/ibase/ibase_driver.php | 413 --- system/database/drivers/ibase/ibase_forge.php | 251 -- .../database/drivers/ibase/ibase_result.php | 161 - .../database/drivers/ibase/ibase_utility.php | 69 - system/database/drivers/ibase/index.html | 11 - system/database/drivers/index.html | 11 - system/database/drivers/mssql/index.html | 11 - .../database/drivers/mssql/mssql_driver.php | 518 --- system/database/drivers/mssql/mssql_forge.php | 151 - .../database/drivers/mssql/mssql_result.php | 198 -- .../database/drivers/mssql/mssql_utility.php | 77 - system/database/drivers/mysql/index.html | 11 - .../database/drivers/mysql/mysql_driver.php | 494 --- system/database/drivers/mysql/mysql_forge.php | 243 -- .../database/drivers/mysql/mysql_result.php | 199 -- .../database/drivers/mysql/mysql_utility.php | 211 -- system/database/drivers/mysqli/index.html | 11 - .../database/drivers/mysqli/mysqli_driver.php | 544 ---- .../database/drivers/mysqli/mysqli_forge.php | 244 -- .../database/drivers/mysqli/mysqli_result.php | 232 -- .../drivers/mysqli/mysqli_utility.php | 211 -- system/database/drivers/oci8/index.html | 11 - system/database/drivers/oci8/oci8_driver.php | 701 ---- system/database/drivers/oci8/oci8_forge.php | 187 -- system/database/drivers/oci8/oci8_result.php | 229 -- system/database/drivers/oci8/oci8_utility.php | 68 - system/database/drivers/odbc/index.html | 11 - system/database/drivers/odbc/odbc_driver.php | 425 --- system/database/drivers/odbc/odbc_forge.php | 86 - system/database/drivers/odbc/odbc_result.php | 268 -- system/database/drivers/odbc/odbc_utility.php | 63 - system/database/drivers/pdo/index.html | 11 - system/database/drivers/pdo/pdo_driver.php | 329 -- system/database/drivers/pdo/pdo_forge.php | 65 - system/database/drivers/pdo/pdo_result.php | 198 -- system/database/drivers/pdo/pdo_utility.php | 63 - .../drivers/pdo/subdrivers/index.html | 11 - .../drivers/pdo/subdrivers/pdo_4d_driver.php | 200 -- .../drivers/pdo/subdrivers/pdo_4d_forge.php | 217 -- .../pdo/subdrivers/pdo_cubrid_driver.php | 209 -- .../pdo/subdrivers/pdo_cubrid_forge.php | 230 -- .../pdo/subdrivers/pdo_dblib_driver.php | 353 --- .../pdo/subdrivers/pdo_dblib_forge.php | 149 - .../pdo/subdrivers/pdo_firebird_driver.php | 279 -- .../pdo/subdrivers/pdo_firebird_forge.php | 237 -- .../drivers/pdo/subdrivers/pdo_ibm_driver.php | 244 -- .../drivers/pdo/subdrivers/pdo_ibm_forge.php | 154 - .../pdo/subdrivers/pdo_informix_driver.php | 309 -- .../pdo/subdrivers/pdo_informix_forge.php | 163 - .../pdo/subdrivers/pdo_mysql_driver.php | 374 --- .../pdo/subdrivers/pdo_mysql_forge.php | 256 -- .../drivers/pdo/subdrivers/pdo_oci_driver.php | 326 -- .../drivers/pdo/subdrivers/pdo_oci_forge.php | 176 -- .../pdo/subdrivers/pdo_odbc_driver.php | 229 -- .../drivers/pdo/subdrivers/pdo_odbc_forge.php | 70 - .../pdo/subdrivers/pdo_pgsql_driver.php | 384 --- .../pdo/subdrivers/pdo_pgsql_forge.php | 210 -- .../pdo/subdrivers/pdo_sqlite_driver.php | 219 -- .../pdo/subdrivers/pdo_sqlite_forge.php | 238 -- .../pdo/subdrivers/pdo_sqlsrv_driver.php | 369 --- .../pdo/subdrivers/pdo_sqlsrv_forge.php | 149 - system/database/drivers/postgre/index.html | 11 - .../drivers/postgre/postgre_driver.php | 619 ---- .../drivers/postgre/postgre_forge.php | 205 -- .../drivers/postgre/postgre_result.php | 182 -- .../drivers/postgre/postgre_utility.php | 78 - system/database/drivers/sqlite/index.html | 11 - .../database/drivers/sqlite/sqlite_driver.php | 330 -- .../database/drivers/sqlite/sqlite_forge.php | 205 -- .../database/drivers/sqlite/sqlite_result.php | 164 - .../drivers/sqlite/sqlite_utility.php | 61 - system/database/drivers/sqlite3/index.html | 11 - .../drivers/sqlite3/sqlite3_driver.php | 350 -- .../drivers/sqlite3/sqlite3_forge.php | 225 -- .../drivers/sqlite3/sqlite3_result.php | 194 -- .../drivers/sqlite3/sqlite3_utility.php | 61 - system/database/drivers/sqlsrv/index.html | 11 - .../database/drivers/sqlsrv/sqlsrv_driver.php | 543 ---- .../database/drivers/sqlsrv/sqlsrv_forge.php | 149 - .../database/drivers/sqlsrv/sqlsrv_result.php | 193 -- .../drivers/sqlsrv/sqlsrv_utility.php | 77 - system/database/index.html | 11 - system/fonts/index.html | 11 - system/fonts/texb.ttf | Bin 143830 -> 0 bytes system/helpers/array_helper.php | 115 - system/helpers/captcha_helper.php | 341 -- system/helpers/cookie_helper.php | 113 - system/helpers/date_helper.php | 742 ----- system/helpers/directory_helper.php | 101 - system/helpers/download_helper.php | 158 - system/helpers/email_helper.php | 84 - system/helpers/file_helper.php | 453 --- system/helpers/form_helper.php | 1055 ------- system/helpers/html_helper.php | 410 --- system/helpers/index.html | 11 - system/helpers/inflector_helper.php | 276 -- system/helpers/language_helper.php | 75 - system/helpers/number_helper.php | 94 - system/helpers/path_helper.php | 82 - system/helpers/security_helper.php | 137 - system/helpers/smiley_helper.php | 255 -- system/helpers/string_helper.php | 304 -- system/helpers/text_helper.php | 567 ---- system/helpers/typography_helper.php | 104 - system/helpers/url_helper.php | 569 ---- system/helpers/xml_helper.php | 90 - system/index.html | 11 - system/language/english/calendar_lang.php | 84 - system/language/english/date_lang.php | 94 - system/language/english/db_lang.php | 63 - system/language/english/email_lang.php | 58 - .../language/english/form_validation_lang.php | 68 - system/language/english/ftp_lang.php | 51 - system/language/english/imglib_lang.php | 57 - system/language/english/index.html | 11 - system/language/english/migration_lang.php | 47 - system/language/english/number_lang.php | 44 - system/language/english/pagination_lang.php | 43 - system/language/english/profiler_lang.php | 60 - system/language/english/unit_test_lang.php | 58 - system/language/english/upload_lang.php | 55 - system/language/index.html | 11 - system/libraries/Cache/Cache.php | 255 -- system/libraries/Cache/drivers/Cache_apc.php | 217 -- .../libraries/Cache/drivers/Cache_dummy.php | 172 - system/libraries/Cache/drivers/Cache_file.php | 286 -- .../Cache/drivers/Cache_memcached.php | 313 -- .../libraries/Cache/drivers/Cache_redis.php | 328 -- .../Cache/drivers/Cache_wincache.php | 217 -- system/libraries/Cache/drivers/index.html | 11 - system/libraries/Cache/index.html | 11 - system/libraries/Calendar.php | 546 ---- system/libraries/Cart.php | 567 ---- system/libraries/Driver.php | 342 -- system/libraries/Email.php | 2490 --------------- system/libraries/Encrypt.php | 521 --- system/libraries/Encryption.php | 941 ------ system/libraries/Form_validation.php | 1591 ---------- system/libraries/Ftp.php | 667 ---- system/libraries/Image_lib.php | 1842 ----------- system/libraries/Javascript.php | 856 ----- system/libraries/Javascript/Jquery.php | 1076 ------- system/libraries/Javascript/index.html | 11 - system/libraries/Migration.php | 477 --- system/libraries/Pagination.php | 704 ----- system/libraries/Parser.php | 248 -- system/libraries/Profiler.php | 574 ---- system/libraries/Session/Session.php | 983 ------ .../Session/SessionHandlerInterface.php | 59 - system/libraries/Session/Session_driver.php | 208 -- .../drivers/Session_database_driver.php | 446 --- .../Session/drivers/Session_files_driver.php | 424 --- .../drivers/Session_memcached_driver.php | 397 --- .../Session/drivers/Session_redis_driver.php | 417 --- system/libraries/Session/drivers/index.html | 11 - system/libraries/Session/index.html | 11 - system/libraries/Table.php | 538 ---- system/libraries/Trackback.php | 556 ---- system/libraries/Typography.php | 424 --- system/libraries/Unit_test.php | 406 --- system/libraries/Upload.php | 1326 -------- system/libraries/User_agent.php | 681 ---- system/libraries/Xmlrpc.php | 1920 ----------- system/libraries/Xmlrpcs.php | 619 ---- system/libraries/Zip.php | 532 ---- system/libraries/index.html | 11 - 204 files changed, 3 insertions(+), 66446 deletions(-) delete mode 100644 system/.htaccess delete mode 100644 system/core/Benchmark.php delete mode 100644 system/core/CodeIgniter.php delete mode 100644 system/core/Common.php delete mode 100644 system/core/Config.php delete mode 100644 system/core/Controller.php delete mode 100644 system/core/Exceptions.php delete mode 100644 system/core/Hooks.php delete mode 100644 system/core/Input.php delete mode 100644 system/core/Lang.php delete mode 100644 system/core/Loader.php delete mode 100644 system/core/Log.php delete mode 100644 system/core/Model.php delete mode 100644 system/core/Output.php delete mode 100644 system/core/Router.php delete mode 100644 system/core/Security.php delete mode 100644 system/core/URI.php delete mode 100644 system/core/Utf8.php delete mode 100644 system/core/compat/hash.php delete mode 100644 system/core/compat/index.html delete mode 100644 system/core/compat/mbstring.php delete mode 100644 system/core/compat/password.php delete mode 100644 system/core/compat/standard.php delete mode 100644 system/core/index.html delete mode 100644 system/database/DB.php delete mode 100644 system/database/DB_cache.php delete mode 100644 system/database/DB_driver.php delete mode 100644 system/database/DB_forge.php delete mode 100644 system/database/DB_query_builder.php delete mode 100644 system/database/DB_result.php delete mode 100644 system/database/DB_utility.php delete mode 100644 system/database/drivers/cubrid/cubrid_driver.php delete mode 100644 system/database/drivers/cubrid/cubrid_forge.php delete mode 100644 system/database/drivers/cubrid/cubrid_result.php delete mode 100644 system/database/drivers/cubrid/cubrid_utility.php delete mode 100644 system/database/drivers/cubrid/index.html delete mode 100644 system/database/drivers/ibase/ibase_driver.php delete mode 100644 system/database/drivers/ibase/ibase_forge.php delete mode 100644 system/database/drivers/ibase/ibase_result.php delete mode 100644 system/database/drivers/ibase/ibase_utility.php delete mode 100644 system/database/drivers/ibase/index.html delete mode 100644 system/database/drivers/index.html delete mode 100644 system/database/drivers/mssql/index.html delete mode 100644 system/database/drivers/mssql/mssql_driver.php delete mode 100644 system/database/drivers/mssql/mssql_forge.php delete mode 100644 system/database/drivers/mssql/mssql_result.php delete mode 100644 system/database/drivers/mssql/mssql_utility.php delete mode 100644 system/database/drivers/mysql/index.html delete mode 100644 system/database/drivers/mysql/mysql_driver.php delete mode 100644 system/database/drivers/mysql/mysql_forge.php delete mode 100644 system/database/drivers/mysql/mysql_result.php delete mode 100644 system/database/drivers/mysql/mysql_utility.php delete mode 100644 system/database/drivers/mysqli/index.html delete mode 100644 system/database/drivers/mysqli/mysqli_driver.php delete mode 100644 system/database/drivers/mysqli/mysqli_forge.php delete mode 100644 system/database/drivers/mysqli/mysqli_result.php delete mode 100644 system/database/drivers/mysqli/mysqli_utility.php delete mode 100644 system/database/drivers/oci8/index.html delete mode 100644 system/database/drivers/oci8/oci8_driver.php delete mode 100644 system/database/drivers/oci8/oci8_forge.php delete mode 100644 system/database/drivers/oci8/oci8_result.php delete mode 100644 system/database/drivers/oci8/oci8_utility.php delete mode 100644 system/database/drivers/odbc/index.html delete mode 100644 system/database/drivers/odbc/odbc_driver.php delete mode 100644 system/database/drivers/odbc/odbc_forge.php delete mode 100644 system/database/drivers/odbc/odbc_result.php delete mode 100644 system/database/drivers/odbc/odbc_utility.php delete mode 100644 system/database/drivers/pdo/index.html delete mode 100644 system/database/drivers/pdo/pdo_driver.php delete mode 100644 system/database/drivers/pdo/pdo_forge.php delete mode 100644 system/database/drivers/pdo/pdo_result.php delete mode 100644 system/database/drivers/pdo/pdo_utility.php delete mode 100644 system/database/drivers/pdo/subdrivers/index.html delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_4d_driver.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_4d_forge.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_firebird_forge.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_ibm_forge.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_informix_driver.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_informix_forge.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_oci_driver.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_oci_forge.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php delete mode 100644 system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php delete mode 100644 system/database/drivers/postgre/index.html delete mode 100644 system/database/drivers/postgre/postgre_driver.php delete mode 100644 system/database/drivers/postgre/postgre_forge.php delete mode 100644 system/database/drivers/postgre/postgre_result.php delete mode 100644 system/database/drivers/postgre/postgre_utility.php delete mode 100644 system/database/drivers/sqlite/index.html delete mode 100644 system/database/drivers/sqlite/sqlite_driver.php delete mode 100644 system/database/drivers/sqlite/sqlite_forge.php delete mode 100644 system/database/drivers/sqlite/sqlite_result.php delete mode 100644 system/database/drivers/sqlite/sqlite_utility.php delete mode 100644 system/database/drivers/sqlite3/index.html delete mode 100644 system/database/drivers/sqlite3/sqlite3_driver.php delete mode 100644 system/database/drivers/sqlite3/sqlite3_forge.php delete mode 100644 system/database/drivers/sqlite3/sqlite3_result.php delete mode 100644 system/database/drivers/sqlite3/sqlite3_utility.php delete mode 100644 system/database/drivers/sqlsrv/index.html delete mode 100644 system/database/drivers/sqlsrv/sqlsrv_driver.php delete mode 100644 system/database/drivers/sqlsrv/sqlsrv_forge.php delete mode 100644 system/database/drivers/sqlsrv/sqlsrv_result.php delete mode 100644 system/database/drivers/sqlsrv/sqlsrv_utility.php delete mode 100644 system/database/index.html delete mode 100644 system/fonts/index.html delete mode 100644 system/fonts/texb.ttf delete mode 100644 system/helpers/array_helper.php delete mode 100644 system/helpers/captcha_helper.php delete mode 100644 system/helpers/cookie_helper.php delete mode 100644 system/helpers/date_helper.php delete mode 100644 system/helpers/directory_helper.php delete mode 100644 system/helpers/download_helper.php delete mode 100644 system/helpers/email_helper.php delete mode 100644 system/helpers/file_helper.php delete mode 100644 system/helpers/form_helper.php delete mode 100644 system/helpers/html_helper.php delete mode 100644 system/helpers/index.html delete mode 100644 system/helpers/inflector_helper.php delete mode 100644 system/helpers/language_helper.php delete mode 100644 system/helpers/number_helper.php delete mode 100644 system/helpers/path_helper.php delete mode 100644 system/helpers/security_helper.php delete mode 100644 system/helpers/smiley_helper.php delete mode 100644 system/helpers/string_helper.php delete mode 100644 system/helpers/text_helper.php delete mode 100644 system/helpers/typography_helper.php delete mode 100644 system/helpers/url_helper.php delete mode 100644 system/helpers/xml_helper.php delete mode 100644 system/index.html delete mode 100644 system/language/english/calendar_lang.php delete mode 100644 system/language/english/date_lang.php delete mode 100644 system/language/english/db_lang.php delete mode 100644 system/language/english/email_lang.php delete mode 100644 system/language/english/form_validation_lang.php delete mode 100644 system/language/english/ftp_lang.php delete mode 100644 system/language/english/imglib_lang.php delete mode 100644 system/language/english/index.html delete mode 100644 system/language/english/migration_lang.php delete mode 100644 system/language/english/number_lang.php delete mode 100644 system/language/english/pagination_lang.php delete mode 100644 system/language/english/profiler_lang.php delete mode 100644 system/language/english/unit_test_lang.php delete mode 100644 system/language/english/upload_lang.php delete mode 100644 system/language/index.html delete mode 100644 system/libraries/Cache/Cache.php delete mode 100644 system/libraries/Cache/drivers/Cache_apc.php delete mode 100644 system/libraries/Cache/drivers/Cache_dummy.php delete mode 100644 system/libraries/Cache/drivers/Cache_file.php delete mode 100644 system/libraries/Cache/drivers/Cache_memcached.php delete mode 100644 system/libraries/Cache/drivers/Cache_redis.php delete mode 100644 system/libraries/Cache/drivers/Cache_wincache.php delete mode 100644 system/libraries/Cache/drivers/index.html delete mode 100644 system/libraries/Cache/index.html delete mode 100644 system/libraries/Calendar.php delete mode 100644 system/libraries/Cart.php delete mode 100644 system/libraries/Driver.php delete mode 100644 system/libraries/Email.php delete mode 100644 system/libraries/Encrypt.php delete mode 100644 system/libraries/Encryption.php delete mode 100644 system/libraries/Form_validation.php delete mode 100644 system/libraries/Ftp.php delete mode 100644 system/libraries/Image_lib.php delete mode 100644 system/libraries/Javascript.php delete mode 100644 system/libraries/Javascript/Jquery.php delete mode 100644 system/libraries/Javascript/index.html delete mode 100644 system/libraries/Migration.php delete mode 100644 system/libraries/Pagination.php delete mode 100644 system/libraries/Parser.php delete mode 100644 system/libraries/Profiler.php delete mode 100644 system/libraries/Session/Session.php delete mode 100644 system/libraries/Session/SessionHandlerInterface.php delete mode 100644 system/libraries/Session/Session_driver.php delete mode 100644 system/libraries/Session/drivers/Session_database_driver.php delete mode 100644 system/libraries/Session/drivers/Session_files_driver.php delete mode 100644 system/libraries/Session/drivers/Session_memcached_driver.php delete mode 100644 system/libraries/Session/drivers/Session_redis_driver.php delete mode 100644 system/libraries/Session/drivers/index.html delete mode 100644 system/libraries/Session/index.html delete mode 100644 system/libraries/Table.php delete mode 100644 system/libraries/Trackback.php delete mode 100644 system/libraries/Typography.php delete mode 100644 system/libraries/Unit_test.php delete mode 100644 system/libraries/Upload.php delete mode 100644 system/libraries/User_agent.php delete mode 100644 system/libraries/Xmlrpc.php delete mode 100644 system/libraries/Xmlrpcs.php delete mode 100644 system/libraries/Zip.php delete mode 100644 system/libraries/index.html diff --git a/composer.json b/composer.json index 9a9aa67..88a3bc1 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,8 @@ "php": ">=7.2", "craftsman/cli": "^5.1", "emporio/core": "@dev", - "emporio/ui": "@dev" + "emporio/ui": "@dev", + "codeigniter/framework": "^3.1" }, "repositories": [ { "type": "path", "url": "packages/emporio/core" }, diff --git a/public/index.php b/public/index.php index 2f27b92..bb64c64 100755 --- a/public/index.php +++ b/public/index.php @@ -97,7 +97,7 @@ * This variable must contain the name of your "system" directory. * Set the path if it is not in the same directory as this file. */ - $system_path = '../system'; + $system_path = '../vendor/codeigniter/framework/system'; /* *--------------------------------------------------------------- diff --git a/system/.htaccess b/system/.htaccess deleted file mode 100644 index 97c65d2..0000000 --- a/system/.htaccess +++ /dev/null @@ -1,6 +0,0 @@ - - Require all denied - - - Deny from all - \ No newline at end of file diff --git a/system/core/Benchmark.php b/system/core/Benchmark.php deleted file mode 100644 index d6e1336..0000000 --- a/system/core/Benchmark.php +++ /dev/null @@ -1,133 +0,0 @@ -marker[$name] = microtime(TRUE); - } - - // -------------------------------------------------------------------- - - /** - * Elapsed time - * - * Calculates the time difference between two marked points. - * - * If the first parameter is empty this function instead returns the - * {elapsed_time} pseudo-variable. This permits the full system - * execution time to be shown in a template. The output class will - * swap the real value for this variable. - * - * @param string $point1 A particular marked point - * @param string $point2 A particular marked point - * @param int $decimals Number of decimal places - * - * @return string Calculated elapsed time on success, - * an '{elapsed_string}' if $point1 is empty - * or an empty string if $point1 is not found. - */ - public function elapsed_time($point1 = '', $point2 = '', $decimals = 4) - { - if ($point1 === '') - { - return '{elapsed_time}'; - } - - if ( ! isset($this->marker[$point1])) - { - return ''; - } - - if ( ! isset($this->marker[$point2])) - { - $this->marker[$point2] = microtime(TRUE); - } - - return number_format($this->marker[$point2] - $this->marker[$point1], $decimals); - } - - // -------------------------------------------------------------------- - - /** - * Memory Usage - * - * Simply returns the {memory_usage} marker. - * - * This permits it to be put it anywhere in a template - * without the memory being calculated until the end. - * The output class will swap the real value for this variable. - * - * @return string '{memory_usage}' - */ - public function memory_usage() - { - return '{memory_usage}'; - } - -} diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php deleted file mode 100644 index 7b1dcc2..0000000 --- a/system/core/CodeIgniter.php +++ /dev/null @@ -1,559 +0,0 @@ - '_ENV', 'G' => '_GET', 'P' => '_POST', 'C' => '_COOKIE', 'S' => '_SERVER') as $key => $superglobal) - { - if (strpos($_registered, $key) === FALSE) - { - continue; - } - - foreach (array_keys($$superglobal) as $var) - { - if (isset($GLOBALS[$var]) && ! in_array($var, $_protected, TRUE)) - { - $GLOBALS[$var] = NULL; - } - } - } - } -} - - -/* - * ------------------------------------------------------ - * Define a custom error handler so we can log PHP errors - * ------------------------------------------------------ - */ - set_error_handler('_error_handler'); - set_exception_handler('_exception_handler'); - register_shutdown_function('_shutdown_handler'); - -/* - * ------------------------------------------------------ - * Set the subclass_prefix - * ------------------------------------------------------ - * - * Normally the "subclass_prefix" is set in the config file. - * The subclass prefix allows CI to know if a core class is - * being extended via a library in the local application - * "libraries" folder. Since CI allows config items to be - * overridden via data set in the main index.php file, - * before proceeding we need to know if a subclass_prefix - * override exists. If so, we will set this value now, - * before any classes are loaded - * Note: Since the config file data is cached it doesn't - * hurt to load it here. - */ - if ( ! empty($assign_to_config['subclass_prefix'])) - { - get_config(array('subclass_prefix' => $assign_to_config['subclass_prefix'])); - } - -/* - * ------------------------------------------------------ - * Should we use a Composer autoloader? - * ------------------------------------------------------ - */ - if ($composer_autoload = config_item('composer_autoload')) - { - if ($composer_autoload === TRUE) - { - file_exists(APPPATH.'vendor/autoload.php') - ? require_once(APPPATH.'vendor/autoload.php') - : log_message('error', '$config[\'composer_autoload\'] is set to TRUE but '.APPPATH.'vendor/autoload.php was not found.'); - } - elseif (file_exists($composer_autoload)) - { - require_once($composer_autoload); - } - else - { - log_message('error', 'Could not find the specified $config[\'composer_autoload\'] path: '.$composer_autoload); - } - } - -/* - * ------------------------------------------------------ - * Start the timer... tick tock tick tock... - * ------------------------------------------------------ - */ - $BM =& load_class('Benchmark', 'core'); - $BM->mark('total_execution_time_start'); - $BM->mark('loading_time:_base_classes_start'); - -/* - * ------------------------------------------------------ - * Instantiate the hooks class - * ------------------------------------------------------ - */ - $EXT =& load_class('Hooks', 'core'); - -/* - * ------------------------------------------------------ - * Is there a "pre_system" hook? - * ------------------------------------------------------ - */ - $EXT->call_hook('pre_system'); - -/* - * ------------------------------------------------------ - * Instantiate the config class - * ------------------------------------------------------ - * - * Note: It is important that Config is loaded first as - * most other classes depend on it either directly or by - * depending on another class that uses it. - * - */ - $CFG =& load_class('Config', 'core'); - - // Do we have any manually set config items in the index.php file? - if (isset($assign_to_config) && is_array($assign_to_config)) - { - foreach ($assign_to_config as $key => $value) - { - $CFG->set_item($key, $value); - } - } - -/* - * ------------------------------------------------------ - * Important charset-related stuff - * ------------------------------------------------------ - * - * Configure mbstring and/or iconv if they are enabled - * and set MB_ENABLED and ICONV_ENABLED constants, so - * that we don't repeatedly do extension_loaded() or - * function_exists() calls. - * - * Note: UTF-8 class depends on this. It used to be done - * in it's constructor, but it's _not_ class-specific. - * - */ - $charset = strtoupper(config_item('charset')); - ini_set('default_charset', $charset); - - if (extension_loaded('mbstring')) - { - define('MB_ENABLED', TRUE); - // mbstring.internal_encoding is deprecated starting with PHP 5.6 - // and it's usage triggers E_DEPRECATED messages. - @ini_set('mbstring.internal_encoding', $charset); - // This is required for mb_convert_encoding() to strip invalid characters. - // That's utilized by CI_Utf8, but it's also done for consistency with iconv. - mb_substitute_character('none'); - } - else - { - define('MB_ENABLED', FALSE); - } - - // There's an ICONV_IMPL constant, but the PHP manual says that using - // iconv's predefined constants is "strongly discouraged". - if (extension_loaded('iconv')) - { - define('ICONV_ENABLED', TRUE); - // iconv.internal_encoding is deprecated starting with PHP 5.6 - // and it's usage triggers E_DEPRECATED messages. - @ini_set('iconv.internal_encoding', $charset); - } - else - { - define('ICONV_ENABLED', FALSE); - } - - if (is_php('5.6')) - { - ini_set('php.internal_encoding', $charset); - } - -/* - * ------------------------------------------------------ - * Load compatibility features - * ------------------------------------------------------ - */ - - require_once(BASEPATH.'core/compat/mbstring.php'); - require_once(BASEPATH.'core/compat/hash.php'); - require_once(BASEPATH.'core/compat/password.php'); - require_once(BASEPATH.'core/compat/standard.php'); - -/* - * ------------------------------------------------------ - * Instantiate the UTF-8 class - * ------------------------------------------------------ - */ - $UNI =& load_class('Utf8', 'core'); - -/* - * ------------------------------------------------------ - * Instantiate the URI class - * ------------------------------------------------------ - */ - $URI =& load_class('URI', 'core'); - -/* - * ------------------------------------------------------ - * Instantiate the routing class and set the routing - * ------------------------------------------------------ - */ - $RTR =& load_class('Router', 'core', isset($routing) ? $routing : NULL); - -/* - * ------------------------------------------------------ - * Instantiate the output class - * ------------------------------------------------------ - */ - $OUT =& load_class('Output', 'core'); - -/* - * ------------------------------------------------------ - * Is there a valid cache file? If so, we're done... - * ------------------------------------------------------ - */ - if ($EXT->call_hook('cache_override') === FALSE && $OUT->_display_cache($CFG, $URI) === TRUE) - { - exit; - } - -/* - * ----------------------------------------------------- - * Load the security class for xss and csrf support - * ----------------------------------------------------- - */ - $SEC =& load_class('Security', 'core'); - -/* - * ------------------------------------------------------ - * Load the Input class and sanitize globals - * ------------------------------------------------------ - */ - $IN =& load_class('Input', 'core'); - -/* - * ------------------------------------------------------ - * Load the Language class - * ------------------------------------------------------ - */ - $LANG =& load_class('Lang', 'core'); - -/* - * ------------------------------------------------------ - * Load the app controller and local controller - * ------------------------------------------------------ - * - */ - // Load the base controller class - require_once BASEPATH.'core/Controller.php'; - - /** - * Reference to the CI_Controller method. - * - * Returns current CI instance object - * - * @return CI_Controller - */ - function &get_instance() - { - return CI_Controller::get_instance(); - } - - if (file_exists(APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php')) - { - require_once APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php'; - } - - // Set a mark point for benchmarking - $BM->mark('loading_time:_base_classes_end'); - -/* - * ------------------------------------------------------ - * Sanity checks - * ------------------------------------------------------ - * - * The Router class has already validated the request, - * leaving us with 3 options here: - * - * 1) an empty class name, if we reached the default - * controller, but it didn't exist; - * 2) a query string which doesn't go through a - * file_exists() check - * 3) a regular request for a non-existing page - * - * We handle all of these as a 404 error. - * - * Furthermore, none of the methods in the app controller - * or the loader class can be called via the URI, nor can - * controller methods that begin with an underscore. - */ - - $e404 = FALSE; - $class = ucfirst($RTR->class); - $method = $RTR->method; - - if (empty($class) OR ! file_exists(APPPATH.'controllers/'.$RTR->directory.$class.'.php')) - { - $e404 = TRUE; - } - else - { - require_once(APPPATH.'controllers/'.$RTR->directory.$class.'.php'); - - if ( ! class_exists($class, FALSE) OR $method[0] === '_' OR method_exists('CI_Controller', $method)) - { - $e404 = TRUE; - } - elseif (method_exists($class, '_remap')) - { - $params = array($method, array_slice($URI->rsegments, 2)); - $method = '_remap'; - } - elseif ( ! method_exists($class, $method)) - { - $e404 = TRUE; - } - /** - * DO NOT CHANGE THIS, NOTHING ELSE WORKS! - * - * - method_exists() returns true for non-public methods, which passes the previous elseif - * - is_callable() returns false for PHP 4-style constructors, even if there's a __construct() - * - method_exists($class, '__construct') won't work because CI_Controller::__construct() is inherited - * - People will only complain if this doesn't work, even though it is documented that it shouldn't. - * - * ReflectionMethod::isConstructor() is the ONLY reliable check, - * knowing which method will be executed as a constructor. - */ - elseif ( ! is_callable(array($class, $method))) - { - $reflection = new ReflectionMethod($class, $method); - if ( ! $reflection->isPublic() OR $reflection->isConstructor()) - { - $e404 = TRUE; - } - } - } - - if ($e404) - { - if ( ! empty($RTR->routes['404_override'])) - { - if (sscanf($RTR->routes['404_override'], '%[^/]/%s', $error_class, $error_method) !== 2) - { - $error_method = 'index'; - } - - $error_class = ucfirst($error_class); - - if ( ! class_exists($error_class, FALSE)) - { - if (file_exists(APPPATH.'controllers/'.$RTR->directory.$error_class.'.php')) - { - require_once(APPPATH.'controllers/'.$RTR->directory.$error_class.'.php'); - $e404 = ! class_exists($error_class, FALSE); - } - // Were we in a directory? If so, check for a global override - elseif ( ! empty($RTR->directory) && file_exists(APPPATH.'controllers/'.$error_class.'.php')) - { - require_once(APPPATH.'controllers/'.$error_class.'.php'); - if (($e404 = ! class_exists($error_class, FALSE)) === FALSE) - { - $RTR->directory = ''; - } - } - } - else - { - $e404 = FALSE; - } - } - - // Did we reset the $e404 flag? If so, set the rsegments, starting from index 1 - if ( ! $e404) - { - $class = $error_class; - $method = $error_method; - - $URI->rsegments = array( - 1 => $class, - 2 => $method - ); - } - else - { - show_404($RTR->directory.$class.'/'.$method); - } - } - - if ($method !== '_remap') - { - $params = array_slice($URI->rsegments, 2); - } - -/* - * ------------------------------------------------------ - * Is there a "pre_controller" hook? - * ------------------------------------------------------ - */ - $EXT->call_hook('pre_controller'); - -/* - * ------------------------------------------------------ - * Instantiate the requested controller - * ------------------------------------------------------ - */ - // Mark a start point so we can benchmark the controller - $BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_start'); - - $CI = new $class(); - -/* - * ------------------------------------------------------ - * Is there a "post_controller_constructor" hook? - * ------------------------------------------------------ - */ - $EXT->call_hook('post_controller_constructor'); - -/* - * ------------------------------------------------------ - * Call the requested method - * ------------------------------------------------------ - */ - call_user_func_array(array(&$CI, $method), $params); - - // Mark a benchmark end point - $BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_end'); - -/* - * ------------------------------------------------------ - * Is there a "post_controller" hook? - * ------------------------------------------------------ - */ - $EXT->call_hook('post_controller'); - -/* - * ------------------------------------------------------ - * Send the final rendered output to the browser - * ------------------------------------------------------ - */ - if ($EXT->call_hook('display_override') === FALSE) - { - $OUT->_display(); - } - -/* - * ------------------------------------------------------ - * Is there a "post_system" hook? - * ------------------------------------------------------ - */ - $EXT->call_hook('post_system'); diff --git a/system/core/Common.php b/system/core/Common.php deleted file mode 100644 index 6d60f23..0000000 --- a/system/core/Common.php +++ /dev/null @@ -1,849 +0,0 @@ -='); - } - - return $_is_php[$version]; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('is_really_writable')) -{ - /** - * Tests for file writability - * - * is_writable() returns TRUE on Windows servers when you really can't write to - * the file, based on the read-only attribute. is_writable() is also unreliable - * on Unix servers if safe_mode is on. - * - * @link https://bugs.php.net/bug.php?id=54709 - * @param string - * @return bool - */ - function is_really_writable($file) - { - // If we're on a Unix server with safe_mode off we call is_writable - if (DIRECTORY_SEPARATOR === '/' && (is_php('5.4') OR ! ini_get('safe_mode'))) - { - return is_writable($file); - } - - /* For Windows servers and safe_mode "on" installations we'll actually - * write a file then read it. Bah... - */ - if (is_dir($file)) - { - $file = rtrim($file, '/').'/'.md5(mt_rand()); - if (($fp = @fopen($file, 'ab')) === FALSE) - { - return FALSE; - } - - fclose($fp); - @chmod($file, 0777); - @unlink($file); - return TRUE; - } - elseif ( ! is_file($file) OR ($fp = @fopen($file, 'ab')) === FALSE) - { - return FALSE; - } - - fclose($fp); - return TRUE; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('load_class')) -{ - /** - * Class registry - * - * This function acts as a singleton. If the requested class does not - * exist it is instantiated and set to a static variable. If it has - * previously been instantiated the variable is returned. - * - * @param string the class name being requested - * @param string the directory where the class should be found - * @param mixed an optional argument to pass to the class constructor - * @return object - */ - function &load_class($class, $directory = 'libraries', $param = NULL) - { - static $_classes = array(); - - // Does the class exist? If so, we're done... - if (isset($_classes[$class])) - { - return $_classes[$class]; - } - - $name = FALSE; - - // Look for the class first in the local application/libraries folder - // then in the native system/libraries folder - foreach (array(APPPATH, BASEPATH) as $path) - { - if (file_exists($path.$directory.'/'.$class.'.php')) - { - $name = 'CI_'.$class; - - if (class_exists($name, FALSE) === FALSE) - { - require_once($path.$directory.'/'.$class.'.php'); - } - - break; - } - } - - // Is the request a class extension? If so we load it too - if (file_exists(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php')) - { - $name = config_item('subclass_prefix').$class; - - if (class_exists($name, FALSE) === FALSE) - { - require_once(APPPATH.$directory.'/'.$name.'.php'); - } - } - - // Did we find the class? - if ($name === FALSE) - { - // Note: We use exit() rather than show_error() in order to avoid a - // self-referencing loop with the Exceptions class - set_status_header(503); - echo 'Unable to locate the specified class: '.$class.'.php'; - exit(5); // EXIT_UNK_CLASS - } - - // Keep track of what we just loaded - is_loaded($class); - - $_classes[$class] = isset($param) - ? new $name($param) - : new $name(); - return $_classes[$class]; - } -} - -// -------------------------------------------------------------------- - -if ( ! function_exists('is_loaded')) -{ - /** - * Keeps track of which libraries have been loaded. This function is - * called by the load_class() function above - * - * @param string - * @return array - */ - function &is_loaded($class = '') - { - static $_is_loaded = array(); - - if ($class !== '') - { - $_is_loaded[strtolower($class)] = $class; - } - - return $_is_loaded; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('get_config')) -{ - /** - * Loads the main config.php file - * - * This function lets us grab the config file even if the Config class - * hasn't been instantiated yet - * - * @param array - * @return array - */ - function &get_config(Array $replace = array()) - { - static $config; - - if (empty($config)) - { - $file_path = APPPATH.'config/config.php'; - $found = FALSE; - if (file_exists($file_path)) - { - $found = TRUE; - require($file_path); - } - - // Is the config file in the environment folder? - if (file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config.php')) - { - require($file_path); - } - elseif ( ! $found) - { - set_status_header(503); - echo 'The configuration file does not exist.'; - exit(3); // EXIT_CONFIG - } - - // Does the $config array exist in the file? - if ( ! isset($config) OR ! is_array($config)) - { - set_status_header(503); - echo 'Your config file does not appear to be formatted correctly.'; - exit(3); // EXIT_CONFIG - } - } - - // Are any values being dynamically added or replaced? - foreach ($replace as $key => $val) - { - $config[$key] = $val; - } - - return $config; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('config_item')) -{ - /** - * Returns the specified config item - * - * @param string - * @return mixed - */ - function config_item($item) - { - static $_config; - - if (empty($_config)) - { - // references cannot be directly assigned to static variables, so we use an array - $_config[0] =& get_config(); - } - - return isset($_config[0][$item]) ? $_config[0][$item] : NULL; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('get_mimes')) -{ - /** - * Returns the MIME types array from config/mimes.php - * - * @return array - */ - function &get_mimes() - { - static $_mimes; - - if (empty($_mimes)) - { - $_mimes = file_exists(APPPATH.'config/mimes.php') - ? include(APPPATH.'config/mimes.php') - : array(); - - if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/mimes.php')) - { - $_mimes = array_merge($_mimes, include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php')); - } - } - - return $_mimes; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('is_https')) -{ - /** - * Is HTTPS? - * - * Determines if the application is accessed via an encrypted - * (HTTPS) connection. - * - * @return bool - */ - function is_https() - { - if ( ! empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') - { - return TRUE; - } - elseif (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https') - { - return TRUE; - } - elseif ( ! empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) !== 'off') - { - return TRUE; - } - - return FALSE; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('is_cli')) -{ - - /** - * Is CLI? - * - * Test to see if a request was made from the command line. - * - * @return bool - */ - function is_cli() - { - return (PHP_SAPI === 'cli' OR defined('STDIN')); - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('show_error')) -{ - /** - * Error Handler - * - * This function lets us invoke the exception class and - * display errors using the standard error template located - * in application/views/errors/error_general.php - * This function will send the error page directly to the - * browser and exit. - * - * @param string - * @param int - * @param string - * @return void - */ - function show_error($message, $status_code = 500, $heading = 'An Error Was Encountered') - { - $status_code = abs($status_code); - if ($status_code < 100) - { - $exit_status = $status_code + 9; // 9 is EXIT__AUTO_MIN - $status_code = 500; - } - else - { - $exit_status = 1; // EXIT_ERROR - } - - $_error =& load_class('Exceptions', 'core'); - echo $_error->show_error($heading, $message, 'error_general', $status_code); - exit($exit_status); - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('show_404')) -{ - /** - * 404 Page Handler - * - * This function is similar to the show_error() function above - * However, instead of the standard error template it displays - * 404 errors. - * - * @param string - * @param bool - * @return void - */ - function show_404($page = '', $log_error = TRUE) - { - $_error =& load_class('Exceptions', 'core'); - $_error->show_404($page, $log_error); - exit(4); // EXIT_UNKNOWN_FILE - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('log_message')) -{ - /** - * Error Logging Interface - * - * We use this as a simple mechanism to access the logging - * class and send messages to be logged. - * - * @param string the error level: 'error', 'debug' or 'info' - * @param string the error message - * @return void - */ - function log_message($level, $message) - { - static $_log; - - if ($_log === NULL) - { - // references cannot be directly assigned to static variables, so we use an array - $_log[0] =& load_class('Log', 'core'); - } - - $_log[0]->write_log($level, $message); - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('set_status_header')) -{ - /** - * Set HTTP Status Header - * - * @param int the status code - * @param string - * @return void - */ - function set_status_header($code = 200, $text = '') - { - if (is_cli()) - { - return; - } - - if (empty($code) OR ! is_numeric($code)) - { - show_error('Status codes must be numeric', 500); - } - - if (empty($text)) - { - is_int($code) OR $code = (int) $code; - $stati = array( - 100 => 'Continue', - 101 => 'Switching Protocols', - - 200 => 'OK', - 201 => 'Created', - 202 => 'Accepted', - 203 => 'Non-Authoritative Information', - 204 => 'No Content', - 205 => 'Reset Content', - 206 => 'Partial Content', - - 300 => 'Multiple Choices', - 301 => 'Moved Permanently', - 302 => 'Found', - 303 => 'See Other', - 304 => 'Not Modified', - 305 => 'Use Proxy', - 307 => 'Temporary Redirect', - - 400 => 'Bad Request', - 401 => 'Unauthorized', - 402 => 'Payment Required', - 403 => 'Forbidden', - 404 => 'Not Found', - 405 => 'Method Not Allowed', - 406 => 'Not Acceptable', - 407 => 'Proxy Authentication Required', - 408 => 'Request Timeout', - 409 => 'Conflict', - 410 => 'Gone', - 411 => 'Length Required', - 412 => 'Precondition Failed', - 413 => 'Request Entity Too Large', - 414 => 'Request-URI Too Long', - 415 => 'Unsupported Media Type', - 416 => 'Requested Range Not Satisfiable', - 417 => 'Expectation Failed', - 422 => 'Unprocessable Entity', - 426 => 'Upgrade Required', - 428 => 'Precondition Required', - 429 => 'Too Many Requests', - 431 => 'Request Header Fields Too Large', - - 500 => 'Internal Server Error', - 501 => 'Not Implemented', - 502 => 'Bad Gateway', - 503 => 'Service Unavailable', - 504 => 'Gateway Timeout', - 505 => 'HTTP Version Not Supported', - 511 => 'Network Authentication Required', - ); - - if (isset($stati[$code])) - { - $text = $stati[$code]; - } - else - { - show_error('No status text available. Please check your status code number or supply your own message text.', 500); - } - } - - if (strpos(PHP_SAPI, 'cgi') === 0) - { - header('Status: '.$code.' '.$text, TRUE); - return; - } - - $server_protocol = (isset($_SERVER['SERVER_PROTOCOL']) && in_array($_SERVER['SERVER_PROTOCOL'], array('HTTP/1.0', 'HTTP/1.1', 'HTTP/2'), TRUE)) - ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1'; - header($server_protocol.' '.$code.' '.$text, TRUE, $code); - } -} - -// -------------------------------------------------------------------- - -if ( ! function_exists('_error_handler')) -{ - /** - * Error Handler - * - * This is the custom error handler that is declared at the (relative) - * top of CodeIgniter.php. The main reason we use this is to permit - * PHP errors to be logged in our own log files since the user may - * not have access to server logs. Since this function effectively - * intercepts PHP errors, however, we also need to display errors - * based on the current error_reporting level. - * We do that with the use of a PHP error template. - * - * @param int $severity - * @param string $message - * @param string $filepath - * @param int $line - * @return void - */ - function _error_handler($severity, $message, $filepath, $line) - { - $is_error = (((E_ERROR | E_PARSE | E_COMPILE_ERROR | E_CORE_ERROR | E_USER_ERROR) & $severity) === $severity); - - // When an error occurred, set the status header to '500 Internal Server Error' - // to indicate to the client something went wrong. - // This can't be done within the $_error->show_php_error method because - // it is only called when the display_errors flag is set (which isn't usually - // the case in a production environment) or when errors are ignored because - // they are above the error_reporting threshold. - if ($is_error) - { - set_status_header(500); - } - - // Should we ignore the error? We'll get the current error_reporting - // level and add its bits with the severity bits to find out. - if (($severity & error_reporting()) !== $severity) - { - return; - } - - $_error =& load_class('Exceptions', 'core'); - $_error->log_exception($severity, $message, $filepath, $line); - - // Should we display the error? - if (str_ireplace(array('off', 'none', 'no', 'false', 'null'), '', ini_get('display_errors'))) - { - $_error->show_php_error($severity, $message, $filepath, $line); - } - - // If the error is fatal, the execution of the script should be stopped because - // errors can't be recovered from. Halting the script conforms with PHP's - // default error handling. See http://www.php.net/manual/en/errorfunc.constants.php - if ($is_error) - { - exit(1); // EXIT_ERROR - } - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('_exception_handler')) -{ - /** - * Exception Handler - * - * Sends uncaught exceptions to the logger and displays them - * only if display_errors is On so that they don't show up in - * production environments. - * - * @param Exception $exception - * @return void - */ - function _exception_handler($exception) - { - $_error =& load_class('Exceptions', 'core'); - $_error->log_exception('error', 'Exception: '.$exception->getMessage(), $exception->getFile(), $exception->getLine()); - - is_cli() OR set_status_header(500); - // Should we display the error? - if (str_ireplace(array('off', 'none', 'no', 'false', 'null'), '', ini_get('display_errors'))) - { - $_error->show_exception($exception); - } - - exit(1); // EXIT_ERROR - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('_shutdown_handler')) -{ - /** - * Shutdown Handler - * - * This is the shutdown handler that is declared at the top - * of CodeIgniter.php. The main reason we use this is to simulate - * a complete custom exception handler. - * - * E_STRICT is purposively neglected because such events may have - * been caught. Duplication or none? None is preferred for now. - * - * @link http://insomanic.me.uk/post/229851073/php-trick-catching-fatal-errors-e-error-with-a - * @return void - */ - function _shutdown_handler() - { - $last_error = error_get_last(); - if (isset($last_error) && - ($last_error['type'] & (E_ERROR | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING))) - { - _error_handler($last_error['type'], $last_error['message'], $last_error['file'], $last_error['line']); - } - } -} - -// -------------------------------------------------------------------- - -if ( ! function_exists('remove_invisible_characters')) -{ - /** - * Remove Invisible Characters - * - * This prevents sandwiching null characters - * between ascii characters, like Java\0script. - * - * @param string - * @param bool - * @return string - */ - function remove_invisible_characters($str, $url_encoded = TRUE) - { - $non_displayables = array(); - - // every control character except newline (dec 10), - // carriage return (dec 13) and horizontal tab (dec 09) - if ($url_encoded) - { - $non_displayables[] = '/%0[0-8bcef]/i'; // url encoded 00-08, 11, 12, 14, 15 - $non_displayables[] = '/%1[0-9a-f]/i'; // url encoded 16-31 - $non_displayables[] = '/%7f/i'; // url encoded 127 - } - - $non_displayables[] = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S'; // 00-08, 11, 12, 14-31, 127 - - do - { - $str = preg_replace($non_displayables, '', $str, -1, $count); - } - while ($count); - - return $str; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('html_escape')) -{ - /** - * Returns HTML escaped variable. - * - * @param mixed $var The input string or array of strings to be escaped. - * @param bool $double_encode $double_encode set to FALSE prevents escaping twice. - * @return mixed The escaped string or array of strings as a result. - */ - function html_escape($var, $double_encode = TRUE) - { - if (empty($var)) - { - return $var; - } - - if (is_array($var)) - { - foreach (array_keys($var) as $key) - { - $var[$key] = html_escape($var[$key], $double_encode); - } - - return $var; - } - - return htmlspecialchars($var, ENT_QUOTES, config_item('charset'), $double_encode); - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('_stringify_attributes')) -{ - /** - * Stringify attributes for use in HTML tags. - * - * Helper function used to convert a string, array, or object - * of attributes to a string. - * - * @param mixed string, array, object - * @param bool - * @return string - */ - function _stringify_attributes($attributes, $js = FALSE) - { - $atts = NULL; - - if (empty($attributes)) - { - return $atts; - } - - if (is_string($attributes)) - { - return ' '.$attributes; - } - - $attributes = (array) $attributes; - - foreach ($attributes as $key => $val) - { - $atts .= ($js) ? $key.'='.$val.',' : ' '.$key.'="'.$val.'"'; - } - - return rtrim($atts, ','); - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('function_usable')) -{ - /** - * Function usable - * - * Executes a function_exists() check, and if the Suhosin PHP - * extension is loaded - checks whether the function that is - * checked might be disabled in there as well. - * - * This is useful as function_exists() will return FALSE for - * functions disabled via the *disable_functions* php.ini - * setting, but not for *suhosin.executor.func.blacklist* and - * *suhosin.executor.disable_eval*. These settings will just - * terminate script execution if a disabled function is executed. - * - * The above described behavior turned out to be a bug in Suhosin, - * but even though a fix was committed for 0.9.34 on 2012-02-12, - * that version is yet to be released. This function will therefore - * be just temporary, but would probably be kept for a few years. - * - * @link http://www.hardened-php.net/suhosin/ - * @param string $function_name Function to check for - * @return bool TRUE if the function exists and is safe to call, - * FALSE otherwise. - */ - function function_usable($function_name) - { - static $_suhosin_func_blacklist; - - if (function_exists($function_name)) - { - if ( ! isset($_suhosin_func_blacklist)) - { - $_suhosin_func_blacklist = extension_loaded('suhosin') - ? explode(',', trim(ini_get('suhosin.executor.func.blacklist'))) - : array(); - } - - return ! in_array($function_name, $_suhosin_func_blacklist, TRUE); - } - - return FALSE; - } -} diff --git a/system/core/Config.php b/system/core/Config.php deleted file mode 100644 index 8136dd2..0000000 --- a/system/core/Config.php +++ /dev/null @@ -1,379 +0,0 @@ -config =& get_config(); - - // Set the base_url automatically if none was provided - if (empty($this->config['base_url'])) - { - if (isset($_SERVER['SERVER_ADDR'])) - { - if (strpos($_SERVER['SERVER_ADDR'], ':') !== FALSE) - { - $server_addr = '['.$_SERVER['SERVER_ADDR'].']'; - } - else - { - $server_addr = $_SERVER['SERVER_ADDR']; - } - - $base_url = (is_https() ? 'https' : 'http').'://'.$server_addr - .substr($_SERVER['SCRIPT_NAME'], 0, strpos($_SERVER['SCRIPT_NAME'], basename($_SERVER['SCRIPT_FILENAME']))); - } - else - { - $base_url = 'http://localhost/'; - } - - $this->set_item('base_url', $base_url); - } - - log_message('info', 'Config Class Initialized'); - } - - // -------------------------------------------------------------------- - - /** - * Load Config File - * - * @param string $file Configuration file name - * @param bool $use_sections Whether configuration values should be loaded into their own section - * @param bool $fail_gracefully Whether to just return FALSE or display an error message - * @return bool TRUE if the file was loaded correctly or FALSE on failure - */ - public function load($file = '', $use_sections = FALSE, $fail_gracefully = FALSE) - { - $file = ($file === '') ? 'config' : str_replace('.php', '', $file); - $loaded = FALSE; - - foreach ($this->_config_paths as $path) - { - foreach (array($file, ENVIRONMENT.DIRECTORY_SEPARATOR.$file) as $location) - { - $file_path = $path.'config/'.$location.'.php'; - if (in_array($file_path, $this->is_loaded, TRUE)) - { - return TRUE; - } - - if ( ! file_exists($file_path)) - { - continue; - } - - include($file_path); - - if ( ! isset($config) OR ! is_array($config)) - { - if ($fail_gracefully === TRUE) - { - return FALSE; - } - - show_error('Your '.$file_path.' file does not appear to contain a valid configuration array.'); - } - - if ($use_sections === TRUE) - { - $this->config[$file] = isset($this->config[$file]) - ? array_merge($this->config[$file], $config) - : $config; - } - else - { - $this->config = array_merge($this->config, $config); - } - - $this->is_loaded[] = $file_path; - $config = NULL; - $loaded = TRUE; - log_message('debug', 'Config file loaded: '.$file_path); - } - } - - if ($loaded === TRUE) - { - return TRUE; - } - elseif ($fail_gracefully === TRUE) - { - return FALSE; - } - - show_error('The configuration file '.$file.'.php does not exist.'); - } - - // -------------------------------------------------------------------- - - /** - * Fetch a config file item - * - * @param string $item Config item name - * @param string $index Index name - * @return string|null The configuration item or NULL if the item doesn't exist - */ - public function item($item, $index = '') - { - if ($index == '') - { - return isset($this->config[$item]) ? $this->config[$item] : NULL; - } - - return isset($this->config[$index], $this->config[$index][$item]) ? $this->config[$index][$item] : NULL; - } - - // -------------------------------------------------------------------- - - /** - * Fetch a config file item with slash appended (if not empty) - * - * @param string $item Config item name - * @return string|null The configuration item or NULL if the item doesn't exist - */ - public function slash_item($item) - { - if ( ! isset($this->config[$item])) - { - return NULL; - } - elseif (trim($this->config[$item]) === '') - { - return ''; - } - - return rtrim($this->config[$item], '/').'/'; - } - - // -------------------------------------------------------------------- - - /** - * Site URL - * - * Returns base_url . index_page [. uri_string] - * - * @uses CI_Config::_uri_string() - * - * @param string|string[] $uri URI string or an array of segments - * @param string $protocol - * @return string - */ - public function site_url($uri = '', $protocol = NULL) - { - $base_url = $this->slash_item('base_url'); - - if (isset($protocol)) - { - // For protocol-relative links - if ($protocol === '') - { - $base_url = substr($base_url, strpos($base_url, '//')); - } - else - { - $base_url = $protocol.substr($base_url, strpos($base_url, '://')); - } - } - - if (empty($uri)) - { - return $base_url.$this->item('index_page'); - } - - $uri = $this->_uri_string($uri); - - if ($this->item('enable_query_strings') === FALSE) - { - $suffix = isset($this->config['url_suffix']) ? $this->config['url_suffix'] : ''; - - if ($suffix !== '') - { - if (($offset = strpos($uri, '?')) !== FALSE) - { - $uri = substr($uri, 0, $offset).$suffix.substr($uri, $offset); - } - else - { - $uri .= $suffix; - } - } - - return $base_url.$this->slash_item('index_page').$uri; - } - elseif (strpos($uri, '?') === FALSE) - { - $uri = '?'.$uri; - } - - return $base_url.$this->item('index_page').$uri; - } - - // ------------------------------------------------------------- - - /** - * Base URL - * - * Returns base_url [. uri_string] - * - * @uses CI_Config::_uri_string() - * - * @param string|string[] $uri URI string or an array of segments - * @param string $protocol - * @return string - */ - public function base_url($uri = '', $protocol = NULL) - { - $base_url = $this->slash_item('base_url'); - - if (isset($protocol)) - { - // For protocol-relative links - if ($protocol === '') - { - $base_url = substr($base_url, strpos($base_url, '//')); - } - else - { - $base_url = $protocol.substr($base_url, strpos($base_url, '://')); - } - } - - return $base_url.$this->_uri_string($uri); - } - - // ------------------------------------------------------------- - - /** - * Build URI string - * - * @used-by CI_Config::site_url() - * @used-by CI_Config::base_url() - * - * @param string|string[] $uri URI string or an array of segments - * @return string - */ - protected function _uri_string($uri) - { - if ($this->item('enable_query_strings') === FALSE) - { - is_array($uri) && $uri = implode('/', $uri); - return ltrim($uri, '/'); - } - elseif (is_array($uri)) - { - return http_build_query($uri); - } - - return $uri; - } - - // -------------------------------------------------------------------- - - /** - * System URL - * - * @deprecated 3.0.0 Encourages insecure practices - * @return string - */ - public function system_url() - { - $x = explode('/', preg_replace('|/*(.+?)/*$|', '\\1', BASEPATH)); - return $this->slash_item('base_url').end($x).'/'; - } - - // -------------------------------------------------------------------- - - /** - * Set a config file item - * - * @param string $item Config item key - * @param string $value Config item value - * @return void - */ - public function set_item($item, $value) - { - $this->config[$item] = $value; - } - -} diff --git a/system/core/Controller.php b/system/core/Controller.php deleted file mode 100644 index ec9aa2a..0000000 --- a/system/core/Controller.php +++ /dev/null @@ -1,96 +0,0 @@ - $class) - { - $this->$var =& load_class($class); - } - - $this->load =& load_class('Loader', 'core'); - $this->load->initialize(); - log_message('info', 'Controller Class Initialized'); - } - - // -------------------------------------------------------------------- - - /** - * Get the CI singleton - * - * @static - * @return object - */ - public static function &get_instance() - { - return self::$instance; - } - -} diff --git a/system/core/Exceptions.php b/system/core/Exceptions.php deleted file mode 100644 index 5a78376..0000000 --- a/system/core/Exceptions.php +++ /dev/null @@ -1,274 +0,0 @@ - 'Error', - E_WARNING => 'Warning', - E_PARSE => 'Parsing Error', - E_NOTICE => 'Notice', - E_CORE_ERROR => 'Core Error', - E_CORE_WARNING => 'Core Warning', - E_COMPILE_ERROR => 'Compile Error', - E_COMPILE_WARNING => 'Compile Warning', - E_USER_ERROR => 'User Error', - E_USER_WARNING => 'User Warning', - E_USER_NOTICE => 'User Notice', - E_STRICT => 'Runtime Notice' - ); - - /** - * Class constructor - * - * @return void - */ - public function __construct() - { - $this->ob_level = ob_get_level(); - // Note: Do not log messages from this constructor. - } - - // -------------------------------------------------------------------- - - /** - * Exception Logger - * - * Logs PHP generated error messages - * - * @param int $severity Log level - * @param string $message Error message - * @param string $filepath File path - * @param int $line Line number - * @return void - */ - public function log_exception($severity, $message, $filepath, $line) - { - $severity = isset($this->levels[$severity]) ? $this->levels[$severity] : $severity; - log_message('error', 'Severity: '.$severity.' --> '.$message.' '.$filepath.' '.$line); - } - - // -------------------------------------------------------------------- - - /** - * 404 Error Handler - * - * @uses CI_Exceptions::show_error() - * - * @param string $page Page URI - * @param bool $log_error Whether to log the error - * @return void - */ - public function show_404($page = '', $log_error = TRUE) - { - if (is_cli()) - { - $heading = 'Not Found'; - $message = 'The controller/method pair you requested was not found.'; - } - else - { - $heading = '404 Page Not Found'; - $message = 'The page you requested was not found.'; - } - - // By default we log this, but allow a dev to skip it - if ($log_error) - { - log_message('error', $heading.': '.$page); - } - - echo $this->show_error($heading, $message, 'error_404', 404); - exit(4); // EXIT_UNKNOWN_FILE - } - - // -------------------------------------------------------------------- - - /** - * General Error Page - * - * Takes an error message as input (either as a string or an array) - * and displays it using the specified template. - * - * @param string $heading Page heading - * @param string|string[] $message Error message - * @param string $template Template name - * @param int $status_code (default: 500) - * - * @return string Error page output - */ - public function show_error($heading, $message, $template = 'error_general', $status_code = 500) - { - $templates_path = config_item('error_views_path'); - if (empty($templates_path)) - { - $templates_path = VIEWPATH.'errors'.DIRECTORY_SEPARATOR; - } - - if (is_cli()) - { - $message = "\t".(is_array($message) ? implode("\n\t", $message) : $message); - $template = 'cli'.DIRECTORY_SEPARATOR.$template; - } - else - { - set_status_header($status_code); - $message = '

'.(is_array($message) ? implode('

', $message) : $message).'

'; - $template = 'html'.DIRECTORY_SEPARATOR.$template; - } - - if (ob_get_level() > $this->ob_level + 1) - { - ob_end_flush(); - } - ob_start(); - include($templates_path.$template.'.php'); - $buffer = ob_get_contents(); - ob_end_clean(); - return $buffer; - } - - // -------------------------------------------------------------------- - - public function show_exception($exception) - { - $templates_path = config_item('error_views_path'); - if (empty($templates_path)) - { - $templates_path = VIEWPATH.'errors'.DIRECTORY_SEPARATOR; - } - - $message = $exception->getMessage(); - if (empty($message)) - { - $message = '(null)'; - } - - if (is_cli()) - { - $templates_path .= 'cli'.DIRECTORY_SEPARATOR; - } - else - { - $templates_path .= 'html'.DIRECTORY_SEPARATOR; - } - - if (ob_get_level() > $this->ob_level + 1) - { - ob_end_flush(); - } - - ob_start(); - include($templates_path.'error_exception.php'); - $buffer = ob_get_contents(); - ob_end_clean(); - echo $buffer; - } - - // -------------------------------------------------------------------- - - /** - * Native PHP error handler - * - * @param int $severity Error level - * @param string $message Error message - * @param string $filepath File path - * @param int $line Line number - * @return void - */ - public function show_php_error($severity, $message, $filepath, $line) - { - $templates_path = config_item('error_views_path'); - if (empty($templates_path)) - { - $templates_path = VIEWPATH.'errors'.DIRECTORY_SEPARATOR; - } - - $severity = isset($this->levels[$severity]) ? $this->levels[$severity] : $severity; - - // For safety reasons we don't show the full file path in non-CLI requests - if ( ! is_cli()) - { - $filepath = str_replace('\\', '/', $filepath); - if (FALSE !== strpos($filepath, '/')) - { - $x = explode('/', $filepath); - $filepath = $x[count($x)-2].'/'.end($x); - } - - $template = 'html'.DIRECTORY_SEPARATOR.'error_php'; - } - else - { - $template = 'cli'.DIRECTORY_SEPARATOR.'error_php'; - } - - if (ob_get_level() > $this->ob_level + 1) - { - ob_end_flush(); - } - ob_start(); - include($templates_path.$template.'.php'); - $buffer = ob_get_contents(); - ob_end_clean(); - echo $buffer; - } - -} diff --git a/system/core/Hooks.php b/system/core/Hooks.php deleted file mode 100644 index 82c68b1..0000000 --- a/system/core/Hooks.php +++ /dev/null @@ -1,266 +0,0 @@ -item('enable_hooks') === FALSE) - { - return; - } - - // Grab the "hooks" definition file. - if (file_exists(APPPATH.'config/hooks.php')) - { - include(APPPATH.'config/hooks.php'); - } - - if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/hooks.php')) - { - include(APPPATH.'config/'.ENVIRONMENT.'/hooks.php'); - } - - // If there are no hooks, we're done. - if ( ! isset($hook) OR ! is_array($hook)) - { - return; - } - - $this->hooks =& $hook; - $this->enabled = TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Call Hook - * - * Calls a particular hook. Called by CodeIgniter.php. - * - * @uses CI_Hooks::_run_hook() - * - * @param string $which Hook name - * @return bool TRUE on success or FALSE on failure - */ - public function call_hook($which = '') - { - if ( ! $this->enabled OR ! isset($this->hooks[$which])) - { - return FALSE; - } - - if (is_array($this->hooks[$which]) && ! isset($this->hooks[$which]['function'])) - { - foreach ($this->hooks[$which] as $val) - { - $this->_run_hook($val); - } - } - else - { - $this->_run_hook($this->hooks[$which]); - } - - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Run Hook - * - * Runs a particular hook - * - * @param array $data Hook details - * @return bool TRUE on success or FALSE on failure - */ - protected function _run_hook($data) - { - // Closures/lambda functions and array($object, 'method') callables - if (is_callable($data)) - { - is_array($data) - ? $data[0]->{$data[1]}() - : $data(); - - return TRUE; - } - elseif ( ! is_array($data)) - { - return FALSE; - } - - // ----------------------------------- - // Safety - Prevents run-away loops - // ----------------------------------- - - // If the script being called happens to have the same - // hook call within it a loop can happen - if ($this->_in_progress === TRUE) - { - return; - } - - // ----------------------------------- - // Set file path - // ----------------------------------- - - if ( ! isset($data['filepath'], $data['filename'])) - { - return FALSE; - } - - $filepath = APPPATH.$data['filepath'].'/'.$data['filename']; - - if ( ! file_exists($filepath)) - { - return FALSE; - } - - // Determine and class and/or function names - $class = empty($data['class']) ? FALSE : $data['class']; - $function = empty($data['function']) ? FALSE : $data['function']; - $params = isset($data['params']) ? $data['params'] : ''; - - if (empty($function)) - { - return FALSE; - } - - // Set the _in_progress flag - $this->_in_progress = TRUE; - - // Call the requested class and/or function - if ($class !== FALSE) - { - // The object is stored? - if (isset($this->_objects[$class])) - { - if (method_exists($this->_objects[$class], $function)) - { - $this->_objects[$class]->$function($params); - } - else - { - return $this->_in_progress = FALSE; - } - } - else - { - class_exists($class, FALSE) OR require_once($filepath); - - if ( ! class_exists($class, FALSE) OR ! method_exists($class, $function)) - { - return $this->_in_progress = FALSE; - } - - // Store the object and execute the method - $this->_objects[$class] = new $class(); - $this->_objects[$class]->$function($params); - } - } - else - { - function_exists($function) OR require_once($filepath); - - if ( ! function_exists($function)) - { - return $this->_in_progress = FALSE; - } - - $function($params); - } - - $this->_in_progress = FALSE; - return TRUE; - } - -} diff --git a/system/core/Input.php b/system/core/Input.php deleted file mode 100644 index 143babf..0000000 --- a/system/core/Input.php +++ /dev/null @@ -1,895 +0,0 @@ -_allow_get_array = (config_item('allow_get_array') !== FALSE); - $this->_enable_xss = (config_item('global_xss_filtering') === TRUE); - $this->_enable_csrf = (config_item('csrf_protection') === TRUE); - $this->_standardize_newlines = (bool) config_item('standardize_newlines'); - - $this->security =& load_class('Security', 'core'); - - // Do we need the UTF-8 class? - if (UTF8_ENABLED === TRUE) - { - $this->uni =& load_class('Utf8', 'core'); - } - - // Sanitize global arrays - $this->_sanitize_globals(); - - // CSRF Protection check - if ($this->_enable_csrf === TRUE && ! is_cli()) - { - $this->security->csrf_verify(); - } - - log_message('info', 'Input Class Initialized'); - } - - // -------------------------------------------------------------------- - - /** - * Fetch from array - * - * Internal method used to retrieve values from global arrays. - * - * @param array &$array $_GET, $_POST, $_COOKIE, $_SERVER, etc. - * @param mixed $index Index for item to be fetched from $array - * @param bool $xss_clean Whether to apply XSS filtering - * @return mixed - */ - protected function _fetch_from_array(&$array, $index = NULL, $xss_clean = NULL) - { - is_bool($xss_clean) OR $xss_clean = $this->_enable_xss; - - // If $index is NULL, it means that the whole $array is requested - isset($index) OR $index = array_keys($array); - - // allow fetching multiple keys at once - if (is_array($index)) - { - $output = array(); - foreach ($index as $key) - { - $output[$key] = $this->_fetch_from_array($array, $key, $xss_clean); - } - - return $output; - } - - if (isset($array[$index])) - { - $value = $array[$index]; - } - elseif (($count = preg_match_all('/(?:^[^\[]+)|\[[^]]*\]/', $index, $matches)) > 1) // Does the index contain array notation - { - $value = $array; - for ($i = 0; $i < $count; $i++) - { - $key = trim($matches[0][$i], '[]'); - if ($key === '') // Empty notation will return the value as array - { - break; - } - - if (isset($value[$key])) - { - $value = $value[$key]; - } - else - { - return NULL; - } - } - } - else - { - return NULL; - } - - return ($xss_clean === TRUE) - ? $this->security->xss_clean($value) - : $value; - } - - // -------------------------------------------------------------------- - - /** - * Fetch an item from the GET array - * - * @param mixed $index Index for item to be fetched from $_GET - * @param bool $xss_clean Whether to apply XSS filtering - * @return mixed - */ - public function get($index = NULL, $xss_clean = NULL) - { - return $this->_fetch_from_array($_GET, $index, $xss_clean); - } - - // -------------------------------------------------------------------- - - /** - * Fetch an item from the POST array - * - * @param mixed $index Index for item to be fetched from $_POST - * @param bool $xss_clean Whether to apply XSS filtering - * @return mixed - */ - public function post($index = NULL, $xss_clean = NULL) - { - return $this->_fetch_from_array($_POST, $index, $xss_clean); - } - - // -------------------------------------------------------------------- - - /** - * Fetch an item from POST data with fallback to GET - * - * @param string $index Index for item to be fetched from $_POST or $_GET - * @param bool $xss_clean Whether to apply XSS filtering - * @return mixed - */ - public function post_get($index, $xss_clean = NULL) - { - return isset($_POST[$index]) - ? $this->post($index, $xss_clean) - : $this->get($index, $xss_clean); - } - - // -------------------------------------------------------------------- - - /** - * Fetch an item from GET data with fallback to POST - * - * @param string $index Index for item to be fetched from $_GET or $_POST - * @param bool $xss_clean Whether to apply XSS filtering - * @return mixed - */ - public function get_post($index, $xss_clean = NULL) - { - return isset($_GET[$index]) - ? $this->get($index, $xss_clean) - : $this->post($index, $xss_clean); - } - - // -------------------------------------------------------------------- - - /** - * Fetch an item from the COOKIE array - * - * @param mixed $index Index for item to be fetched from $_COOKIE - * @param bool $xss_clean Whether to apply XSS filtering - * @return mixed - */ - public function cookie($index = NULL, $xss_clean = NULL) - { - return $this->_fetch_from_array($_COOKIE, $index, $xss_clean); - } - - // -------------------------------------------------------------------- - - /** - * Fetch an item from the SERVER array - * - * @param mixed $index Index for item to be fetched from $_SERVER - * @param bool $xss_clean Whether to apply XSS filtering - * @return mixed - */ - public function server($index, $xss_clean = NULL) - { - return $this->_fetch_from_array($_SERVER, $index, $xss_clean); - } - - // ------------------------------------------------------------------------ - - /** - * Fetch an item from the php://input stream - * - * Useful when you need to access PUT, DELETE or PATCH request data. - * - * @param string $index Index for item to be fetched - * @param bool $xss_clean Whether to apply XSS filtering - * @return mixed - */ - public function input_stream($index = NULL, $xss_clean = NULL) - { - // Prior to PHP 5.6, the input stream can only be read once, - // so we'll need to check if we have already done that first. - if ( ! is_array($this->_input_stream)) - { - // $this->raw_input_stream will trigger __get(). - parse_str($this->raw_input_stream, $this->_input_stream); - is_array($this->_input_stream) OR $this->_input_stream = array(); - } - - return $this->_fetch_from_array($this->_input_stream, $index, $xss_clean); - } - - // ------------------------------------------------------------------------ - - /** - * Set cookie - * - * Accepts an arbitrary number of parameters (up to 7) or an associative - * array in the first parameter containing all the values. - * - * @param string|mixed[] $name Cookie name or an array containing parameters - * @param string $value Cookie value - * @param int $expire Cookie expiration time in seconds - * @param string $domain Cookie domain (e.g.: '.yourdomain.com') - * @param string $path Cookie path (default: '/') - * @param string $prefix Cookie name prefix - * @param bool $secure Whether to only transfer cookies via SSL - * @param bool $httponly Whether to only makes the cookie accessible via HTTP (no javascript) - * @return void - */ - public function set_cookie($name, $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = NULL, $httponly = NULL) - { - if (is_array($name)) - { - // always leave 'name' in last place, as the loop will break otherwise, due to $$item - foreach (array('value', 'expire', 'domain', 'path', 'prefix', 'secure', 'httponly', 'name') as $item) - { - if (isset($name[$item])) - { - $$item = $name[$item]; - } - } - } - - if ($prefix === '' && config_item('cookie_prefix') !== '') - { - $prefix = config_item('cookie_prefix'); - } - - if ($domain == '' && config_item('cookie_domain') != '') - { - $domain = config_item('cookie_domain'); - } - - if ($path === '/' && config_item('cookie_path') !== '/') - { - $path = config_item('cookie_path'); - } - - $secure = ($secure === NULL && config_item('cookie_secure') !== NULL) - ? (bool) config_item('cookie_secure') - : (bool) $secure; - - $httponly = ($httponly === NULL && config_item('cookie_httponly') !== NULL) - ? (bool) config_item('cookie_httponly') - : (bool) $httponly; - - if ( ! is_numeric($expire)) - { - $expire = time() - 86500; - } - else - { - $expire = ($expire > 0) ? time() + $expire : 0; - } - - setcookie($prefix.$name, $value, $expire, $path, $domain, $secure, $httponly); - } - - // -------------------------------------------------------------------- - - /** - * Fetch the IP Address - * - * Determines and validates the visitor's IP address. - * - * @return string IP address - */ - public function ip_address() - { - if ($this->ip_address !== FALSE) - { - return $this->ip_address; - } - - $proxy_ips = config_item('proxy_ips'); - if ( ! empty($proxy_ips) && ! is_array($proxy_ips)) - { - $proxy_ips = explode(',', str_replace(' ', '', $proxy_ips)); - } - - $this->ip_address = $this->server('REMOTE_ADDR'); - - if ($proxy_ips) - { - foreach (array('HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'HTTP_X_CLIENT_IP', 'HTTP_X_CLUSTER_CLIENT_IP') as $header) - { - if (($spoof = $this->server($header)) !== NULL) - { - // Some proxies typically list the whole chain of IP - // addresses through which the client has reached us. - // e.g. client_ip, proxy_ip1, proxy_ip2, etc. - sscanf($spoof, '%[^,]', $spoof); - - if ( ! $this->valid_ip($spoof)) - { - $spoof = NULL; - } - else - { - break; - } - } - } - - if ($spoof) - { - for ($i = 0, $c = count($proxy_ips); $i < $c; $i++) - { - // Check if we have an IP address or a subnet - if (strpos($proxy_ips[$i], '/') === FALSE) - { - // An IP address (and not a subnet) is specified. - // We can compare right away. - if ($proxy_ips[$i] === $this->ip_address) - { - $this->ip_address = $spoof; - break; - } - - continue; - } - - // We have a subnet ... now the heavy lifting begins - isset($separator) OR $separator = $this->valid_ip($this->ip_address, 'ipv6') ? ':' : '.'; - - // If the proxy entry doesn't match the IP protocol - skip it - if (strpos($proxy_ips[$i], $separator) === FALSE) - { - continue; - } - - // Convert the REMOTE_ADDR IP address to binary, if needed - if ( ! isset($ip, $sprintf)) - { - if ($separator === ':') - { - // Make sure we're have the "full" IPv6 format - $ip = explode(':', - str_replace('::', - str_repeat(':', 9 - substr_count($this->ip_address, ':')), - $this->ip_address - ) - ); - - for ($j = 0; $j < 8; $j++) - { - $ip[$j] = intval($ip[$j], 16); - } - - $sprintf = '%016b%016b%016b%016b%016b%016b%016b%016b'; - } - else - { - $ip = explode('.', $this->ip_address); - $sprintf = '%08b%08b%08b%08b'; - } - - $ip = vsprintf($sprintf, $ip); - } - - // Split the netmask length off the network address - sscanf($proxy_ips[$i], '%[^/]/%d', $netaddr, $masklen); - - // Again, an IPv6 address is most likely in a compressed form - if ($separator === ':') - { - $netaddr = explode(':', str_replace('::', str_repeat(':', 9 - substr_count($netaddr, ':')), $netaddr)); - for ($j = 0; $j < 8; $j++) - { - $netaddr[$j] = intval($netaddr[$j], 16); - } - } - else - { - $netaddr = explode('.', $netaddr); - } - - // Convert to binary and finally compare - if (strncmp($ip, vsprintf($sprintf, $netaddr), $masklen) === 0) - { - $this->ip_address = $spoof; - break; - } - } - } - } - - if ( ! $this->valid_ip($this->ip_address)) - { - return $this->ip_address = '0.0.0.0'; - } - - return $this->ip_address; - } - - // -------------------------------------------------------------------- - - /** - * Validate IP Address - * - * @param string $ip IP address - * @param string $which IP protocol: 'ipv4' or 'ipv6' - * @return bool - */ - public function valid_ip($ip, $which = '') - { - switch (strtolower($which)) - { - case 'ipv4': - $which = FILTER_FLAG_IPV4; - break; - case 'ipv6': - $which = FILTER_FLAG_IPV6; - break; - default: - $which = NULL; - break; - } - - return (bool) filter_var($ip, FILTER_VALIDATE_IP, $which); - } - - // -------------------------------------------------------------------- - - /** - * Fetch User Agent string - * - * @return string|null User Agent string or NULL if it doesn't exist - */ - public function user_agent($xss_clean = NULL) - { - return $this->_fetch_from_array($_SERVER, 'HTTP_USER_AGENT', $xss_clean); - } - - // -------------------------------------------------------------------- - - /** - * Sanitize Globals - * - * Internal method serving for the following purposes: - * - * - Unsets $_GET data, if query strings are not enabled - * - Cleans POST, COOKIE and SERVER data - * - Standardizes newline characters to PHP_EOL - * - * @return void - */ - protected function _sanitize_globals() - { - // Is $_GET data allowed? If not we'll set the $_GET to an empty array - if ($this->_allow_get_array === FALSE) - { - $_GET = array(); - } - elseif (is_array($_GET)) - { - foreach ($_GET as $key => $val) - { - $_GET[$this->_clean_input_keys($key)] = $this->_clean_input_data($val); - } - } - - // Clean $_POST Data - if (is_array($_POST)) - { - foreach ($_POST as $key => $val) - { - $_POST[$this->_clean_input_keys($key)] = $this->_clean_input_data($val); - } - } - - // Clean $_COOKIE Data - if (is_array($_COOKIE)) - { - // Also get rid of specially treated cookies that might be set by a server - // or silly application, that are of no use to a CI application anyway - // but that when present will trip our 'Disallowed Key Characters' alarm - // http://www.ietf.org/rfc/rfc2109.txt - // note that the key names below are single quoted strings, and are not PHP variables - unset( - $_COOKIE['$Version'], - $_COOKIE['$Path'], - $_COOKIE['$Domain'] - ); - - foreach ($_COOKIE as $key => $val) - { - if (($cookie_key = $this->_clean_input_keys($key)) !== FALSE) - { - $_COOKIE[$cookie_key] = $this->_clean_input_data($val); - } - else - { - unset($_COOKIE[$key]); - } - } - } - - // Sanitize PHP_SELF - $_SERVER['PHP_SELF'] = strip_tags($_SERVER['PHP_SELF']); - - log_message('debug', 'Global POST, GET and COOKIE data sanitized'); - } - - // -------------------------------------------------------------------- - - /** - * Clean Input Data - * - * Internal method that aids in escaping data and - * standardizing newline characters to PHP_EOL. - * - * @param string|string[] $str Input string(s) - * @return string - */ - protected function _clean_input_data($str) - { - if (is_array($str)) - { - $new_array = array(); - foreach (array_keys($str) as $key) - { - $new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($str[$key]); - } - return $new_array; - } - - /* We strip slashes if magic quotes is on to keep things consistent - - NOTE: In PHP 5.4 get_magic_quotes_gpc() will always return 0 and - it will probably not exist in future versions at all. - */ - if ( ! is_php('5.4') && get_magic_quotes_gpc()) - { - $str = stripslashes($str); - } - - // Clean UTF-8 if supported - if (UTF8_ENABLED === TRUE) - { - $str = $this->uni->clean_string($str); - } - - // Remove control characters - $str = remove_invisible_characters($str, FALSE); - - // Standardize newlines if needed - if ($this->_standardize_newlines === TRUE) - { - return preg_replace('/(?:\r\n|[\r\n])/', PHP_EOL, $str); - } - - return $str; - } - - // -------------------------------------------------------------------- - - /** - * Clean Keys - * - * Internal method that helps to prevent malicious users - * from trying to exploit keys we make sure that keys are - * only named with alpha-numeric text and a few other items. - * - * @param string $str Input string - * @param bool $fatal Whether to terminate script exection - * or to return FALSE if an invalid - * key is encountered - * @return string|bool - */ - protected function _clean_input_keys($str, $fatal = TRUE) - { - if ( ! preg_match('/^[a-z0-9:_\/|-]+$/i', $str)) - { - if ($fatal === TRUE) - { - return FALSE; - } - else - { - set_status_header(503); - echo 'Disallowed Key Characters.'; - exit(7); // EXIT_USER_INPUT - } - } - - // Clean UTF-8 if supported - if (UTF8_ENABLED === TRUE) - { - return $this->uni->clean_string($str); - } - - return $str; - } - - // -------------------------------------------------------------------- - - /** - * Request Headers - * - * @param bool $xss_clean Whether to apply XSS filtering - * @return array - */ - public function request_headers($xss_clean = FALSE) - { - // If header is already defined, return it immediately - if ( ! empty($this->headers)) - { - return $this->_fetch_from_array($this->headers, NULL, $xss_clean); - } - - // In Apache, you can simply call apache_request_headers() - if (function_exists('apache_request_headers')) - { - $this->headers = apache_request_headers(); - } - else - { - isset($_SERVER['CONTENT_TYPE']) && $this->headers['Content-Type'] = $_SERVER['CONTENT_TYPE']; - - foreach ($_SERVER as $key => $val) - { - if (sscanf($key, 'HTTP_%s', $header) === 1) - { - // take SOME_HEADER and turn it into Some-Header - $header = str_replace('_', ' ', strtolower($header)); - $header = str_replace(' ', '-', ucwords($header)); - - $this->headers[$header] = $_SERVER[$key]; - } - } - } - - return $this->_fetch_from_array($this->headers, NULL, $xss_clean); - } - - // -------------------------------------------------------------------- - - /** - * Get Request Header - * - * Returns the value of a single member of the headers class member - * - * @param string $index Header name - * @param bool $xss_clean Whether to apply XSS filtering - * @return string|null The requested header on success or NULL on failure - */ - public function get_request_header($index, $xss_clean = FALSE) - { - static $headers; - - if ( ! isset($headers)) - { - empty($this->headers) && $this->request_headers(); - foreach ($this->headers as $key => $value) - { - $headers[strtolower($key)] = $value; - } - } - - $index = strtolower($index); - - if ( ! isset($headers[$index])) - { - return NULL; - } - - return ($xss_clean === TRUE) - ? $this->security->xss_clean($headers[$index]) - : $headers[$index]; - } - - // -------------------------------------------------------------------- - - /** - * Is AJAX request? - * - * Test to see if a request contains the HTTP_X_REQUESTED_WITH header. - * - * @return bool - */ - public function is_ajax_request() - { - return ( ! empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest'); - } - - // -------------------------------------------------------------------- - - /** - * Is CLI request? - * - * Test to see if a request was made from the command line. - * - * @deprecated 3.0.0 Use is_cli() instead - * @return bool - */ - public function is_cli_request() - { - return is_cli(); - } - - // -------------------------------------------------------------------- - - /** - * Get Request Method - * - * Return the request method - * - * @param bool $upper Whether to return in upper or lower case - * (default: FALSE) - * @return string - */ - public function method($upper = FALSE) - { - return ($upper) - ? strtoupper($this->server('REQUEST_METHOD')) - : strtolower($this->server('REQUEST_METHOD')); - } - - // ------------------------------------------------------------------------ - - /** - * Magic __get() - * - * Allows read access to protected properties - * - * @param string $name - * @return mixed - */ - public function __get($name) - { - if ($name === 'raw_input_stream') - { - isset($this->_raw_input_stream) OR $this->_raw_input_stream = file_get_contents('php://input'); - return $this->_raw_input_stream; - } - elseif ($name === 'ip_address') - { - return $this->ip_address; - } - } - -} diff --git a/system/core/Lang.php b/system/core/Lang.php deleted file mode 100644 index 39fdd06..0000000 --- a/system/core/Lang.php +++ /dev/null @@ -1,203 +0,0 @@ -load($value, $idiom, $return, $add_suffix, $alt_path); - } - - return; - } - - $langfile = str_replace('.php', '', $langfile); - - if ($add_suffix === TRUE) - { - $langfile = preg_replace('/_lang$/', '', $langfile).'_lang'; - } - - $langfile .= '.php'; - - if (empty($idiom) OR ! preg_match('/^[a-z_-]+$/i', $idiom)) - { - $config =& get_config(); - $idiom = empty($config['language']) ? 'english' : $config['language']; - } - - if ($return === FALSE && isset($this->is_loaded[$langfile]) && $this->is_loaded[$langfile] === $idiom) - { - return; - } - - // Load the base file, so any others found can override it - $basepath = BASEPATH.'language/'.$idiom.'/'.$langfile; - if (($found = file_exists($basepath)) === TRUE) - { - include($basepath); - } - - // Do we have an alternative path to look in? - if ($alt_path !== '') - { - $alt_path .= 'language/'.$idiom.'/'.$langfile; - if (file_exists($alt_path)) - { - include($alt_path); - $found = TRUE; - } - } - else - { - foreach (get_instance()->load->get_package_paths(TRUE) as $package_path) - { - $package_path .= 'language/'.$idiom.'/'.$langfile; - if ($basepath !== $package_path && file_exists($package_path)) - { - include($package_path); - $found = TRUE; - break; - } - } - } - - if ($found !== TRUE) - { - show_error('Unable to load the requested language file: language/'.$idiom.'/'.$langfile); - } - - if ( ! isset($lang) OR ! is_array($lang)) - { - log_message('error', 'Language file contains no data: language/'.$idiom.'/'.$langfile); - - if ($return === TRUE) - { - return array(); - } - return; - } - - if ($return === TRUE) - { - return $lang; - } - - $this->is_loaded[$langfile] = $idiom; - $this->language = array_merge($this->language, $lang); - - log_message('info', 'Language file loaded: language/'.$idiom.'/'.$langfile); - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Language line - * - * Fetches a single line of text from the language array - * - * @param string $line Language line key - * @param bool $log_errors Whether to log an error message if the line is not found - * @return string Translation - */ - public function line($line, $log_errors = TRUE) - { - $value = isset($this->language[$line]) ? $this->language[$line] : FALSE; - - // Because killer robots like unicorns! - if ($value === FALSE && $log_errors === TRUE) - { - log_message('error', 'Could not find the language line "'.$line.'"'); - } - - return $value; - } - -} diff --git a/system/core/Loader.php b/system/core/Loader.php deleted file mode 100644 index c84aff3..0000000 --- a/system/core/Loader.php +++ /dev/null @@ -1,1415 +0,0 @@ - TRUE); - - /** - * List of paths to load libraries from - * - * @var array - */ - protected $_ci_library_paths = array(APPPATH, BASEPATH); - - /** - * List of paths to load models from - * - * @var array - */ - protected $_ci_model_paths = array(APPPATH); - - /** - * List of paths to load helpers from - * - * @var array - */ - protected $_ci_helper_paths = array(APPPATH, BASEPATH); - - /** - * List of cached variables - * - * @var array - */ - protected $_ci_cached_vars = array(); - - /** - * List of loaded classes - * - * @var array - */ - protected $_ci_classes = array(); - - /** - * List of loaded models - * - * @var array - */ - protected $_ci_models = array(); - - /** - * List of loaded helpers - * - * @var array - */ - protected $_ci_helpers = array(); - - /** - * List of class name mappings - * - * @var array - */ - protected $_ci_varmap = array( - 'unit_test' => 'unit', - 'user_agent' => 'agent' - ); - - // -------------------------------------------------------------------- - - /** - * Class constructor - * - * Sets component load paths, gets the initial output buffering level. - * - * @return void - */ - public function __construct() - { - $this->_ci_ob_level = ob_get_level(); - $this->_ci_classes =& is_loaded(); - - log_message('info', 'Loader Class Initialized'); - } - - // -------------------------------------------------------------------- - - /** - * Initializer - * - * @todo Figure out a way to move this to the constructor - * without breaking *package_path*() methods. - * @uses CI_Loader::_ci_autoloader() - * @used-by CI_Controller::__construct() - * @return void - */ - public function initialize() - { - $this->_ci_autoloader(); - } - - // -------------------------------------------------------------------- - - /** - * Is Loaded - * - * A utility method to test if a class is in the self::$_ci_classes array. - * - * @used-by Mainly used by Form Helper function _get_validation_object(). - * - * @param string $class Class name to check for - * @return string|bool Class object name if loaded or FALSE - */ - public function is_loaded($class) - { - return array_search(ucfirst($class), $this->_ci_classes, TRUE); - } - - // -------------------------------------------------------------------- - - /** - * Library Loader - * - * Loads and instantiates libraries. - * Designed to be called from application controllers. - * - * @param mixed $library Library name - * @param array $params Optional parameters to pass to the library class constructor - * @param string $object_name An optional object name to assign to - * @return object - */ - public function library($library, $params = NULL, $object_name = NULL) - { - if (empty($library)) - { - return $this; - } - elseif (is_array($library)) - { - foreach ($library as $key => $value) - { - if (is_int($key)) - { - $this->library($value, $params); - } - else - { - $this->library($key, $params, $value); - } - } - - return $this; - } - - if ($params !== NULL && ! is_array($params)) - { - $params = NULL; - } - - $this->_ci_load_library($library, $params, $object_name); - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Model Loader - * - * Loads and instantiates models. - * - * @param mixed $model Model name - * @param string $name An optional object name to assign to - * @param bool $db_conn An optional database connection configuration to initialize - * @return object - */ - public function model($model, $name = '', $db_conn = FALSE) - { - if (empty($model)) - { - return $this; - } - elseif (is_array($model)) - { - foreach ($model as $key => $value) - { - is_int($key) ? $this->model($value, '', $db_conn) : $this->model($key, $value, $db_conn); - } - - return $this; - } - - $path = ''; - - // Is the model in a sub-folder? If so, parse out the filename and path. - if (($last_slash = strrpos($model, '/')) !== FALSE) - { - // The path is in front of the last slash - $path = substr($model, 0, ++$last_slash); - - // And the model name behind it - $model = substr($model, $last_slash); - } - - if (empty($name)) - { - $name = $model; - } - - if (in_array($name, $this->_ci_models, TRUE)) - { - return $this; - } - - $CI =& get_instance(); - if (isset($CI->$name)) - { - throw new RuntimeException('The model name you are loading is the name of a resource that is already being used: '.$name); - } - - if ($db_conn !== FALSE && ! class_exists('CI_DB', FALSE)) - { - if ($db_conn === TRUE) - { - $db_conn = ''; - } - - $this->database($db_conn, FALSE, TRUE); - } - - // Note: All of the code under this condition used to be just: - // - // load_class('Model', 'core'); - // - // However, load_class() instantiates classes - // to cache them for later use and that prevents - // MY_Model from being an abstract class and is - // sub-optimal otherwise anyway. - if ( ! class_exists('CI_Model', FALSE)) - { - $app_path = APPPATH.'core'.DIRECTORY_SEPARATOR; - if (file_exists($app_path.'Model.php')) - { - require_once($app_path.'Model.php'); - if ( ! class_exists('CI_Model', FALSE)) - { - throw new RuntimeException($app_path."Model.php exists, but doesn't declare class CI_Model"); - } - - log_message('info', 'CI_Model class loaded'); - } - elseif ( ! class_exists('CI_Model', FALSE)) - { - require_once(BASEPATH.'core'.DIRECTORY_SEPARATOR.'Model.php'); - } - - $class = config_item('subclass_prefix').'Model'; - if (file_exists($app_path.$class.'.php')) - { - require_once($app_path.$class.'.php'); - if ( ! class_exists($class, FALSE)) - { - throw new RuntimeException($app_path.$class.".php exists, but doesn't declare class ".$class); - } - - log_message('info', config_item('subclass_prefix').'Model class loaded'); - } - } - - $model = ucfirst($model); - if ( ! class_exists($model, FALSE)) - { - foreach ($this->_ci_model_paths as $mod_path) - { - if ( ! file_exists($mod_path.'models/'.$path.$model.'.php')) - { - continue; - } - - require_once($mod_path.'models/'.$path.$model.'.php'); - if ( ! class_exists($model, FALSE)) - { - throw new RuntimeException($mod_path."models/".$path.$model.".php exists, but doesn't declare class ".$model); - } - - break; - } - - if ( ! class_exists($model, FALSE)) - { - throw new RuntimeException('Unable to locate the model you have specified: '.$model); - } - } - elseif ( ! is_subclass_of($model, 'CI_Model')) - { - throw new RuntimeException("Class ".$model." already exists and doesn't extend CI_Model"); - } - - $this->_ci_models[] = $name; - $model = new $model(); - $CI->$name = $model; - log_message('info', 'Model "'.get_class($model).'" initialized'); - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Database Loader - * - * @param mixed $params Database configuration options - * @param bool $return Whether to return the database object - * @param bool $query_builder Whether to enable Query Builder - * (overrides the configuration setting) - * - * @return object|bool Database object if $return is set to TRUE, - * FALSE on failure, CI_Loader instance in any other case - */ - public function database($params = '', $return = FALSE, $query_builder = NULL) - { - // Grab the super object - $CI =& get_instance(); - - // Do we even need to load the database class? - if ($return === FALSE && $query_builder === NULL && isset($CI->db) && is_object($CI->db) && ! empty($CI->db->conn_id)) - { - return FALSE; - } - - require_once(BASEPATH.'database/DB.php'); - - if ($return === TRUE) - { - return DB($params, $query_builder); - } - - // Initialize the db variable. Needed to prevent - // reference errors with some configurations - $CI->db = ''; - - // Load the DB class - $CI->db =& DB($params, $query_builder); - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Load the Database Utilities Class - * - * @param object $db Database object - * @param bool $return Whether to return the DB Utilities class object or not - * @return object - */ - public function dbutil($db = NULL, $return = FALSE) - { - $CI =& get_instance(); - - if ( ! is_object($db) OR ! ($db instanceof CI_DB)) - { - class_exists('CI_DB', FALSE) OR $this->database(); - $db =& $CI->db; - } - - require_once(BASEPATH.'database/DB_utility.php'); - require_once(BASEPATH.'database/drivers/'.$db->dbdriver.'/'.$db->dbdriver.'_utility.php'); - $class = 'CI_DB_'.$db->dbdriver.'_utility'; - - if ($return === TRUE) - { - return new $class($db); - } - - $CI->dbutil = new $class($db); - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Load the Database Forge Class - * - * @param object $db Database object - * @param bool $return Whether to return the DB Forge class object or not - * @return object - */ - public function dbforge($db = NULL, $return = FALSE) - { - $CI =& get_instance(); - if ( ! is_object($db) OR ! ($db instanceof CI_DB)) - { - class_exists('CI_DB', FALSE) OR $this->database(); - $db =& $CI->db; - } - - require_once(BASEPATH.'database/DB_forge.php'); - require_once(BASEPATH.'database/drivers/'.$db->dbdriver.'/'.$db->dbdriver.'_forge.php'); - - if ( ! empty($db->subdriver)) - { - $driver_path = BASEPATH.'database/drivers/'.$db->dbdriver.'/subdrivers/'.$db->dbdriver.'_'.$db->subdriver.'_forge.php'; - if (file_exists($driver_path)) - { - require_once($driver_path); - $class = 'CI_DB_'.$db->dbdriver.'_'.$db->subdriver.'_forge'; - } - } - else - { - $class = 'CI_DB_'.$db->dbdriver.'_forge'; - } - - if ($return === TRUE) - { - return new $class($db); - } - - $CI->dbforge = new $class($db); - return $this; - } - - // -------------------------------------------------------------------- - - /** - * View Loader - * - * Loads "view" files. - * - * @param string $view View name - * @param array $vars An associative array of data - * to be extracted for use in the view - * @param bool $return Whether to return the view output - * or leave it to the Output class - * @return object|string - */ - public function view($view, $vars = array(), $return = FALSE) - { - return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_prepare_view_vars($vars), '_ci_return' => $return)); - } - - // -------------------------------------------------------------------- - - /** - * Generic File Loader - * - * @param string $path File path - * @param bool $return Whether to return the file output - * @return object|string - */ - public function file($path, $return = FALSE) - { - return $this->_ci_load(array('_ci_path' => $path, '_ci_return' => $return)); - } - - // -------------------------------------------------------------------- - - /** - * Set Variables - * - * Once variables are set they become available within - * the controller class and its "view" files. - * - * @param array|object|string $vars - * An associative array or object containing values - * to be set, or a value's name if string - * @param string $val Value to set, only used if $vars is a string - * @return object - */ - public function vars($vars, $val = '') - { - $vars = is_string($vars) - ? array($vars => $val) - : $this->_ci_prepare_view_vars($vars); - - foreach ($vars as $key => $val) - { - $this->_ci_cached_vars[$key] = $val; - } - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Clear Cached Variables - * - * Clears the cached variables. - * - * @return CI_Loader - */ - public function clear_vars() - { - $this->_ci_cached_vars = array(); - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Get Variable - * - * Check if a variable is set and retrieve it. - * - * @param string $key Variable name - * @return mixed The variable or NULL if not found - */ - public function get_var($key) - { - return isset($this->_ci_cached_vars[$key]) ? $this->_ci_cached_vars[$key] : NULL; - } - - // -------------------------------------------------------------------- - - /** - * Get Variables - * - * Retrieves all loaded variables. - * - * @return array - */ - public function get_vars() - { - return $this->_ci_cached_vars; - } - - // -------------------------------------------------------------------- - - /** - * Helper Loader - * - * @param string|string[] $helpers Helper name(s) - * @return object - */ - public function helper($helpers = array()) - { - is_array($helpers) OR $helpers = array($helpers); - foreach ($helpers as &$helper) - { - $filename = basename($helper); - $filepath = ($filename === $helper) ? '' : substr($helper, 0, strlen($helper) - strlen($filename)); - $filename = strtolower(preg_replace('#(_helper)?(\.php)?$#i', '', $filename)).'_helper'; - $helper = $filepath.$filename; - - if (isset($this->_ci_helpers[$helper])) - { - continue; - } - - // Is this a helper extension request? - $ext_helper = config_item('subclass_prefix').$filename; - $ext_loaded = FALSE; - foreach ($this->_ci_helper_paths as $path) - { - if (file_exists($path.'helpers/'.$ext_helper.'.php')) - { - include_once($path.'helpers/'.$ext_helper.'.php'); - $ext_loaded = TRUE; - } - } - - // If we have loaded extensions - check if the base one is here - if ($ext_loaded === TRUE) - { - $base_helper = BASEPATH.'helpers/'.$helper.'.php'; - if ( ! file_exists($base_helper)) - { - show_error('Unable to load the requested file: helpers/'.$helper.'.php'); - } - - include_once($base_helper); - $this->_ci_helpers[$helper] = TRUE; - log_message('info', 'Helper loaded: '.$helper); - continue; - } - - // No extensions found ... try loading regular helpers and/or overrides - foreach ($this->_ci_helper_paths as $path) - { - if (file_exists($path.'helpers/'.$helper.'.php')) - { - include_once($path.'helpers/'.$helper.'.php'); - - $this->_ci_helpers[$helper] = TRUE; - log_message('info', 'Helper loaded: '.$helper); - break; - } - } - - // unable to load the helper - if ( ! isset($this->_ci_helpers[$helper])) - { - show_error('Unable to load the requested file: helpers/'.$helper.'.php'); - } - } - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Load Helpers - * - * An alias for the helper() method in case the developer has - * written the plural form of it. - * - * @uses CI_Loader::helper() - * @param string|string[] $helpers Helper name(s) - * @return object - */ - public function helpers($helpers = array()) - { - return $this->helper($helpers); - } - - // -------------------------------------------------------------------- - - /** - * Language Loader - * - * Loads language files. - * - * @param string|string[] $files List of language file names to load - * @param string Language name - * @return object - */ - public function language($files, $lang = '') - { - get_instance()->lang->load($files, $lang); - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Config Loader - * - * Loads a config file (an alias for CI_Config::load()). - * - * @uses CI_Config::load() - * @param string $file Configuration file name - * @param bool $use_sections Whether configuration values should be loaded into their own section - * @param bool $fail_gracefully Whether to just return FALSE or display an error message - * @return bool TRUE if the file was loaded correctly or FALSE on failure - */ - public function config($file, $use_sections = FALSE, $fail_gracefully = FALSE) - { - return get_instance()->config->load($file, $use_sections, $fail_gracefully); - } - - // -------------------------------------------------------------------- - - /** - * Driver Loader - * - * Loads a driver library. - * - * @param string|string[] $library Driver name(s) - * @param array $params Optional parameters to pass to the driver - * @param string $object_name An optional object name to assign to - * - * @return object|bool Object or FALSE on failure if $library is a string - * and $object_name is set. CI_Loader instance otherwise. - */ - public function driver($library, $params = NULL, $object_name = NULL) - { - if (is_array($library)) - { - foreach ($library as $key => $value) - { - if (is_int($key)) - { - $this->driver($value, $params); - } - else - { - $this->driver($key, $params, $value); - } - } - - return $this; - } - elseif (empty($library)) - { - return FALSE; - } - - if ( ! class_exists('CI_Driver_Library', FALSE)) - { - // We aren't instantiating an object here, just making the base class available - require BASEPATH.'libraries/Driver.php'; - } - - // We can save the loader some time since Drivers will *always* be in a subfolder, - // and typically identically named to the library - if ( ! strpos($library, '/')) - { - $library = ucfirst($library).'/'.$library; - } - - return $this->library($library, $params, $object_name); - } - - // -------------------------------------------------------------------- - - /** - * Add Package Path - * - * Prepends a parent path to the library, model, helper and config - * path arrays. - * - * @see CI_Loader::$_ci_library_paths - * @see CI_Loader::$_ci_model_paths - * @see CI_Loader::$_ci_helper_paths - * @see CI_Config::$_config_paths - * - * @param string $path Path to add - * @param bool $view_cascade (default: TRUE) - * @return object - */ - public function add_package_path($path, $view_cascade = TRUE) - { - $path = rtrim($path, '/').'/'; - - array_unshift($this->_ci_library_paths, $path); - array_unshift($this->_ci_model_paths, $path); - array_unshift($this->_ci_helper_paths, $path); - - $this->_ci_view_paths = array($path.'views/' => $view_cascade) + $this->_ci_view_paths; - - // Add config file path - $config =& $this->_ci_get_component('config'); - $config->_config_paths[] = $path; - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Get Package Paths - * - * Return a list of all package paths. - * - * @param bool $include_base Whether to include BASEPATH (default: FALSE) - * @return array - */ - public function get_package_paths($include_base = FALSE) - { - return ($include_base === TRUE) ? $this->_ci_library_paths : $this->_ci_model_paths; - } - - // -------------------------------------------------------------------- - - /** - * Remove Package Path - * - * Remove a path from the library, model, helper and/or config - * path arrays if it exists. If no path is provided, the most recently - * added path will be removed removed. - * - * @param string $path Path to remove - * @return object - */ - public function remove_package_path($path = '') - { - $config =& $this->_ci_get_component('config'); - - if ($path === '') - { - array_shift($this->_ci_library_paths); - array_shift($this->_ci_model_paths); - array_shift($this->_ci_helper_paths); - array_shift($this->_ci_view_paths); - array_pop($config->_config_paths); - } - else - { - $path = rtrim($path, '/').'/'; - foreach (array('_ci_library_paths', '_ci_model_paths', '_ci_helper_paths') as $var) - { - if (($key = array_search($path, $this->{$var})) !== FALSE) - { - unset($this->{$var}[$key]); - } - } - - if (isset($this->_ci_view_paths[$path.'views/'])) - { - unset($this->_ci_view_paths[$path.'views/']); - } - - if (($key = array_search($path, $config->_config_paths)) !== FALSE) - { - unset($config->_config_paths[$key]); - } - } - - // make sure the application default paths are still in the array - $this->_ci_library_paths = array_unique(array_merge($this->_ci_library_paths, array(APPPATH, BASEPATH))); - $this->_ci_helper_paths = array_unique(array_merge($this->_ci_helper_paths, array(APPPATH, BASEPATH))); - $this->_ci_model_paths = array_unique(array_merge($this->_ci_model_paths, array(APPPATH))); - $this->_ci_view_paths = array_merge($this->_ci_view_paths, array(APPPATH.'views/' => TRUE)); - $config->_config_paths = array_unique(array_merge($config->_config_paths, array(APPPATH))); - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Internal CI Data Loader - * - * Used to load views and files. - * - * Variables are prefixed with _ci_ to avoid symbol collision with - * variables made available to view files. - * - * @used-by CI_Loader::view() - * @used-by CI_Loader::file() - * @param array $_ci_data Data to load - * @return object - */ - protected function _ci_load($_ci_data) - { - // Set the default data variables - foreach (array('_ci_view', '_ci_vars', '_ci_path', '_ci_return') as $_ci_val) - { - $$_ci_val = isset($_ci_data[$_ci_val]) ? $_ci_data[$_ci_val] : FALSE; - } - - $file_exists = FALSE; - - // Set the path to the requested file - if (is_string($_ci_path) && $_ci_path !== '') - { - $_ci_x = explode('/', $_ci_path); - $_ci_file = end($_ci_x); - } - else - { - $_ci_ext = pathinfo($_ci_view, PATHINFO_EXTENSION); - $_ci_file = ($_ci_ext === '') ? $_ci_view.'.php' : $_ci_view; - - foreach ($this->_ci_view_paths as $_ci_view_file => $cascade) - { - if (file_exists($_ci_view_file.$_ci_file)) - { - $_ci_path = $_ci_view_file.$_ci_file; - $file_exists = TRUE; - break; - } - - if ( ! $cascade) - { - break; - } - } - } - - if ( ! $file_exists && ! file_exists($_ci_path)) - { - show_error('Unable to load the requested file: '.$_ci_file); - } - - // This allows anything loaded using $this->load (views, files, etc.) - // to become accessible from within the Controller and Model functions. - $_ci_CI =& get_instance(); - foreach (get_object_vars($_ci_CI) as $_ci_key => $_ci_var) - { - if ( ! isset($this->$_ci_key)) - { - $this->$_ci_key =& $_ci_CI->$_ci_key; - } - } - - /* - * Extract and cache variables - * - * You can either set variables using the dedicated $this->load->vars() - * function or via the second parameter of this function. We'll merge - * the two types and cache them so that views that are embedded within - * other views can have access to these variables. - */ - empty($_ci_vars) OR $this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars); - extract($this->_ci_cached_vars); - - /* - * Buffer the output - * - * We buffer the output for two reasons: - * 1. Speed. You get a significant speed boost. - * 2. So that the final rendered template can be post-processed by - * the output class. Why do we need post processing? For one thing, - * in order to show the elapsed page load time. Unless we can - * intercept the content right before it's sent to the browser and - * then stop the timer it won't be accurate. - */ - ob_start(); - - // If the PHP installation does not support short tags we'll - // do a little string replacement, changing the short tags - // to standard PHP echo statements. - if ( ! is_php('5.4') && ! ini_get('short_open_tag') && config_item('rewrite_short_tags') === TRUE) - { - echo eval('?>'.preg_replace('/;*\s*\?>/', '; ?>', str_replace(' $this->_ci_ob_level + 1) - { - ob_end_flush(); - } - else - { - $_ci_CI->output->append_output(ob_get_contents()); - @ob_end_clean(); - } - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Internal CI Library Loader - * - * @used-by CI_Loader::library() - * @uses CI_Loader::_ci_init_library() - * - * @param string $class Class name to load - * @param mixed $params Optional parameters to pass to the class constructor - * @param string $object_name Optional object name to assign to - * @return void - */ - protected function _ci_load_library($class, $params = NULL, $object_name = NULL) - { - // Get the class name, and while we're at it trim any slashes. - // The directory path can be included as part of the class name, - // but we don't want a leading slash - $class = str_replace('.php', '', trim($class, '/')); - - // Was the path included with the class name? - // We look for a slash to determine this - if (($last_slash = strrpos($class, '/')) !== FALSE) - { - // Extract the path - $subdir = substr($class, 0, ++$last_slash); - - // Get the filename from the path - $class = substr($class, $last_slash); - } - else - { - $subdir = ''; - } - - $class = ucfirst($class); - - // Is this a stock library? There are a few special conditions if so ... - if (file_exists(BASEPATH.'libraries/'.$subdir.$class.'.php')) - { - return $this->_ci_load_stock_library($class, $subdir, $params, $object_name); - } - - // Safety: Was the class already loaded by a previous call? - if (class_exists($class, FALSE)) - { - $property = $object_name; - if (empty($property)) - { - $property = strtolower($class); - isset($this->_ci_varmap[$property]) && $property = $this->_ci_varmap[$property]; - } - - $CI =& get_instance(); - if (isset($CI->$property)) - { - log_message('debug', $class.' class already loaded. Second attempt ignored.'); - return; - } - - return $this->_ci_init_library($class, '', $params, $object_name); - } - - // Let's search for the requested library file and load it. - foreach ($this->_ci_library_paths as $path) - { - // BASEPATH has already been checked for - if ($path === BASEPATH) - { - continue; - } - - $filepath = $path.'libraries/'.$subdir.$class.'.php'; - // Does the file exist? No? Bummer... - if ( ! file_exists($filepath)) - { - continue; - } - - include_once($filepath); - return $this->_ci_init_library($class, '', $params, $object_name); - } - - // One last attempt. Maybe the library is in a subdirectory, but it wasn't specified? - if ($subdir === '') - { - return $this->_ci_load_library($class.'/'.$class, $params, $object_name); - } - - // If we got this far we were unable to find the requested class. - log_message('error', 'Unable to load the requested class: '.$class); - show_error('Unable to load the requested class: '.$class); - } - - // -------------------------------------------------------------------- - - /** - * Internal CI Stock Library Loader - * - * @used-by CI_Loader::_ci_load_library() - * @uses CI_Loader::_ci_init_library() - * - * @param string $library_name Library name to load - * @param string $file_path Path to the library filename, relative to libraries/ - * @param mixed $params Optional parameters to pass to the class constructor - * @param string $object_name Optional object name to assign to - * @return void - */ - protected function _ci_load_stock_library($library_name, $file_path, $params, $object_name) - { - $prefix = 'CI_'; - - if (class_exists($prefix.$library_name, FALSE)) - { - if (class_exists(config_item('subclass_prefix').$library_name, FALSE)) - { - $prefix = config_item('subclass_prefix'); - } - - $property = $object_name; - if (empty($property)) - { - $property = strtolower($library_name); - isset($this->_ci_varmap[$property]) && $property = $this->_ci_varmap[$property]; - } - - $CI =& get_instance(); - if ( ! isset($CI->$property)) - { - return $this->_ci_init_library($library_name, $prefix, $params, $object_name); - } - - log_message('debug', $library_name.' class already loaded. Second attempt ignored.'); - return; - } - - $paths = $this->_ci_library_paths; - array_pop($paths); // BASEPATH - array_pop($paths); // APPPATH (needs to be the first path checked) - array_unshift($paths, APPPATH); - - foreach ($paths as $path) - { - if (file_exists($path = $path.'libraries/'.$file_path.$library_name.'.php')) - { - // Override - include_once($path); - if (class_exists($prefix.$library_name, FALSE)) - { - return $this->_ci_init_library($library_name, $prefix, $params, $object_name); - } - - log_message('debug', $path.' exists, but does not declare '.$prefix.$library_name); - } - } - - include_once(BASEPATH.'libraries/'.$file_path.$library_name.'.php'); - - // Check for extensions - $subclass = config_item('subclass_prefix').$library_name; - foreach ($paths as $path) - { - if (file_exists($path = $path.'libraries/'.$file_path.$subclass.'.php')) - { - include_once($path); - if (class_exists($subclass, FALSE)) - { - $prefix = config_item('subclass_prefix'); - break; - } - - log_message('debug', $path.' exists, but does not declare '.$subclass); - } - } - - return $this->_ci_init_library($library_name, $prefix, $params, $object_name); - } - - // -------------------------------------------------------------------- - - /** - * Internal CI Library Instantiator - * - * @used-by CI_Loader::_ci_load_stock_library() - * @used-by CI_Loader::_ci_load_library() - * - * @param string $class Class name - * @param string $prefix Class name prefix - * @param array|null|bool $config Optional configuration to pass to the class constructor: - * FALSE to skip; - * NULL to search in config paths; - * array containing configuration data - * @param string $object_name Optional object name to assign to - * @return void - */ - protected function _ci_init_library($class, $prefix, $config = FALSE, $object_name = NULL) - { - // Is there an associated config file for this class? Note: these should always be lowercase - if ($config === NULL) - { - // Fetch the config paths containing any package paths - $config_component = $this->_ci_get_component('config'); - - if (is_array($config_component->_config_paths)) - { - $found = FALSE; - foreach ($config_component->_config_paths as $path) - { - // We test for both uppercase and lowercase, for servers that - // are case-sensitive with regard to file names. Load global first, - // override with environment next - if (file_exists($path.'config/'.strtolower($class).'.php')) - { - include($path.'config/'.strtolower($class).'.php'); - $found = TRUE; - } - elseif (file_exists($path.'config/'.ucfirst(strtolower($class)).'.php')) - { - include($path.'config/'.ucfirst(strtolower($class)).'.php'); - $found = TRUE; - } - - if (file_exists($path.'config/'.ENVIRONMENT.'/'.strtolower($class).'.php')) - { - include($path.'config/'.ENVIRONMENT.'/'.strtolower($class).'.php'); - $found = TRUE; - } - elseif (file_exists($path.'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php')) - { - include($path.'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php'); - $found = TRUE; - } - - // Break on the first found configuration, thus package - // files are not overridden by default paths - if ($found === TRUE) - { - break; - } - } - } - } - - $class_name = $prefix.$class; - - // Is the class name valid? - if ( ! class_exists($class_name, FALSE)) - { - log_message('error', 'Non-existent class: '.$class_name); - show_error('Non-existent class: '.$class_name); - } - - // Set the variable name we will assign the class to - // Was a custom class name supplied? If so we'll use it - if (empty($object_name)) - { - $object_name = strtolower($class); - if (isset($this->_ci_varmap[$object_name])) - { - $object_name = $this->_ci_varmap[$object_name]; - } - } - - // Don't overwrite existing properties - $CI =& get_instance(); - if (isset($CI->$object_name)) - { - if ($CI->$object_name instanceof $class_name) - { - log_message('debug', $class_name." has already been instantiated as '".$object_name."'. Second attempt aborted."); - return; - } - - show_error("Resource '".$object_name."' already exists and is not a ".$class_name." instance."); - } - - // Save the class name and object name - $this->_ci_classes[$object_name] = $class; - - // Instantiate the class - $CI->$object_name = isset($config) - ? new $class_name($config) - : new $class_name(); - } - - // -------------------------------------------------------------------- - - /** - * CI Autoloader - * - * Loads component listed in the config/autoload.php file. - * - * @used-by CI_Loader::initialize() - * @return void - */ - protected function _ci_autoloader() - { - if (file_exists(APPPATH.'config/autoload.php')) - { - include(APPPATH.'config/autoload.php'); - } - - if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/autoload.php')) - { - include(APPPATH.'config/'.ENVIRONMENT.'/autoload.php'); - } - - if ( ! isset($autoload)) - { - return; - } - - // Autoload packages - if (isset($autoload['packages'])) - { - foreach ($autoload['packages'] as $package_path) - { - $this->add_package_path($package_path); - } - } - - // Load any custom config file - if (count($autoload['config']) > 0) - { - foreach ($autoload['config'] as $val) - { - $this->config($val); - } - } - - // Autoload helpers and languages - foreach (array('helper', 'language') as $type) - { - if (isset($autoload[$type]) && count($autoload[$type]) > 0) - { - $this->$type($autoload[$type]); - } - } - - // Autoload drivers - if (isset($autoload['drivers'])) - { - $this->driver($autoload['drivers']); - } - - // Load libraries - if (isset($autoload['libraries']) && count($autoload['libraries']) > 0) - { - // Load the database driver. - if (in_array('database', $autoload['libraries'])) - { - $this->database(); - $autoload['libraries'] = array_diff($autoload['libraries'], array('database')); - } - - // Load all other libraries - $this->library($autoload['libraries']); - } - - // Autoload models - if (isset($autoload['model'])) - { - $this->model($autoload['model']); - } - } - - // -------------------------------------------------------------------- - - /** - * Prepare variables for _ci_vars, to be later extract()-ed inside views - * - * Converts objects to associative arrays and filters-out internal - * variable names (i.e. keys prefixed with '_ci_'). - * - * @param mixed $vars - * @return array - */ - protected function _ci_prepare_view_vars($vars) - { - if ( ! is_array($vars)) - { - $vars = is_object($vars) - ? get_object_vars($vars) - : array(); - } - - foreach (array_keys($vars) as $key) - { - if (strncmp($key, '_ci_', 4) === 0) - { - unset($vars[$key]); - } - } - - return $vars; - } - - // -------------------------------------------------------------------- - - /** - * CI Component getter - * - * Get a reference to a specific library or model. - * - * @param string $component Component name - * @return bool - */ - protected function &_ci_get_component($component) - { - $CI =& get_instance(); - return $CI->$component; - } -} diff --git a/system/core/Log.php b/system/core/Log.php deleted file mode 100644 index a2b464c..0000000 --- a/system/core/Log.php +++ /dev/null @@ -1,296 +0,0 @@ - 1, 'DEBUG' => 2, 'INFO' => 3, 'ALL' => 4); - - /** - * mbstring.func_overload flag - * - * @var bool - */ - protected static $func_overload; - - // -------------------------------------------------------------------- - - /** - * Class constructor - * - * @return void - */ - public function __construct() - { - $config =& get_config(); - - isset(self::$func_overload) OR self::$func_overload = (extension_loaded('mbstring') && ini_get('mbstring.func_overload')); - - $this->_log_path = ($config['log_path'] !== '') ? $config['log_path'] : APPPATH.'logs/'; - $this->_file_ext = (isset($config['log_file_extension']) && $config['log_file_extension'] !== '') - ? ltrim($config['log_file_extension'], '.') : 'php'; - - file_exists($this->_log_path) OR mkdir($this->_log_path, 0755, TRUE); - - if ( ! is_dir($this->_log_path) OR ! is_really_writable($this->_log_path)) - { - $this->_enabled = FALSE; - } - - if (is_numeric($config['log_threshold'])) - { - $this->_threshold = (int) $config['log_threshold']; - } - elseif (is_array($config['log_threshold'])) - { - $this->_threshold = 0; - $this->_threshold_array = array_flip($config['log_threshold']); - } - - if ( ! empty($config['log_date_format'])) - { - $this->_date_fmt = $config['log_date_format']; - } - - if ( ! empty($config['log_file_permissions']) && is_int($config['log_file_permissions'])) - { - $this->_file_permissions = $config['log_file_permissions']; - } - } - - // -------------------------------------------------------------------- - - /** - * Write Log File - * - * Generally this function will be called using the global log_message() function - * - * @param string $level The error level: 'error', 'debug' or 'info' - * @param string $msg The error message - * @return bool - */ - public function write_log($level, $msg) - { - if ($this->_enabled === FALSE) - { - return FALSE; - } - - $level = strtoupper($level); - - if (( ! isset($this->_levels[$level]) OR ($this->_levels[$level] > $this->_threshold)) - && ! isset($this->_threshold_array[$this->_levels[$level]])) - { - return FALSE; - } - - $filepath = $this->_log_path.'log-'.date('Y-m-d').'.'.$this->_file_ext; - $message = ''; - - if ( ! file_exists($filepath)) - { - $newfile = TRUE; - // Only add protection to php files - if ($this->_file_ext === 'php') - { - $message .= "\n\n"; - } - } - - if ( ! $fp = @fopen($filepath, 'ab')) - { - return FALSE; - } - - flock($fp, LOCK_EX); - - // Instantiating DateTime with microseconds appended to initial date is needed for proper support of this format - if (strpos($this->_date_fmt, 'u') !== FALSE) - { - $microtime_full = microtime(TRUE); - $microtime_short = sprintf("%06d", ($microtime_full - floor($microtime_full)) * 1000000); - $date = new DateTime(date('Y-m-d H:i:s.'.$microtime_short, $microtime_full)); - $date = $date->format($this->_date_fmt); - } - else - { - $date = date($this->_date_fmt); - } - - $message .= $this->_format_line($level, $date, $msg); - - for ($written = 0, $length = self::strlen($message); $written < $length; $written += $result) - { - if (($result = fwrite($fp, self::substr($message, $written))) === FALSE) - { - break; - } - } - - flock($fp, LOCK_UN); - fclose($fp); - - if (isset($newfile) && $newfile === TRUE) - { - chmod($filepath, $this->_file_permissions); - } - - return is_int($result); - } - - // -------------------------------------------------------------------- - - /** - * Format the log line. - * - * This is for extensibility of log formatting - * If you want to change the log format, extend the CI_Log class and override this method - * - * @param string $level The error level - * @param string $date Formatted date string - * @param string $message The log message - * @return string Formatted log line with a new line character '\n' at the end - */ - protected function _format_line($level, $date, $message) - { - return $level.' - '.$date.' --> '.$message."\n"; - } - - // -------------------------------------------------------------------- - - /** - * Byte-safe strlen() - * - * @param string $str - * @return int - */ - protected static function strlen($str) - { - return (self::$func_overload) - ? mb_strlen($str, '8bit') - : strlen($str); - } - - // -------------------------------------------------------------------- - - /** - * Byte-safe substr() - * - * @param string $str - * @param int $start - * @param int $length - * @return string - */ - protected static function substr($str, $start, $length = NULL) - { - if (self::$func_overload) - { - // mb_substr($str, $start, null, '8bit') returns an empty - // string on PHP 5.3 - isset($length) OR $length = ($start >= 0 ? self::strlen($str) - $start : -$start); - return mb_substr($str, $start, $length, '8bit'); - } - - return isset($length) - ? substr($str, $start, $length) - : substr($str, $start); - } -} diff --git a/system/core/Model.php b/system/core/Model.php deleted file mode 100644 index dd11dd2..0000000 --- a/system/core/Model.php +++ /dev/null @@ -1,76 +0,0 @@ -$key; - } - -} diff --git a/system/core/Output.php b/system/core/Output.php deleted file mode 100644 index 3cda062..0000000 --- a/system/core/Output.php +++ /dev/null @@ -1,842 +0,0 @@ -_zlib_oc = (bool) ini_get('zlib.output_compression'); - $this->_compress_output = ( - $this->_zlib_oc === FALSE - && config_item('compress_output') === TRUE - && extension_loaded('zlib') - ); - - isset(self::$func_overload) OR self::$func_overload = (extension_loaded('mbstring') && ini_get('mbstring.func_overload')); - - // Get mime types for later - $this->mimes =& get_mimes(); - - log_message('info', 'Output Class Initialized'); - } - - // -------------------------------------------------------------------- - - /** - * Get Output - * - * Returns the current output string. - * - * @return string - */ - public function get_output() - { - return $this->final_output; - } - - // -------------------------------------------------------------------- - - /** - * Set Output - * - * Sets the output string. - * - * @param string $output Output data - * @return CI_Output - */ - public function set_output($output) - { - $this->final_output = $output; - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Append Output - * - * Appends data onto the output string. - * - * @param string $output Data to append - * @return CI_Output - */ - public function append_output($output) - { - $this->final_output .= $output; - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Set Header - * - * Lets you set a server header which will be sent with the final output. - * - * Note: If a file is cached, headers will not be sent. - * @todo We need to figure out how to permit headers to be cached. - * - * @param string $header Header - * @param bool $replace Whether to replace the old header value, if already set - * @return CI_Output - */ - public function set_header($header, $replace = TRUE) - { - // If zlib.output_compression is enabled it will compress the output, - // but it will not modify the content-length header to compensate for - // the reduction, causing the browser to hang waiting for more data. - // We'll just skip content-length in those cases. - if ($this->_zlib_oc && strncasecmp($header, 'content-length', 14) === 0) - { - return $this; - } - - $this->headers[] = array($header, $replace); - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Set Content-Type Header - * - * @param string $mime_type Extension of the file we're outputting - * @param string $charset Character set (default: NULL) - * @return CI_Output - */ - public function set_content_type($mime_type, $charset = NULL) - { - if (strpos($mime_type, '/') === FALSE) - { - $extension = ltrim($mime_type, '.'); - - // Is this extension supported? - if (isset($this->mimes[$extension])) - { - $mime_type =& $this->mimes[$extension]; - - if (is_array($mime_type)) - { - $mime_type = current($mime_type); - } - } - } - - $this->mime_type = $mime_type; - - if (empty($charset)) - { - $charset = config_item('charset'); - } - - $header = 'Content-Type: '.$mime_type - .(empty($charset) ? '' : '; charset='.$charset); - - $this->headers[] = array($header, TRUE); - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Get Current Content-Type Header - * - * @return string 'text/html', if not already set - */ - public function get_content_type() - { - for ($i = 0, $c = count($this->headers); $i < $c; $i++) - { - if (sscanf($this->headers[$i][0], 'Content-Type: %[^;]', $content_type) === 1) - { - return $content_type; - } - } - - return 'text/html'; - } - - // -------------------------------------------------------------------- - - /** - * Get Header - * - * @param string $header - * @return string - */ - public function get_header($header) - { - // Combine headers already sent with our batched headers - $headers = array_merge( - // We only need [x][0] from our multi-dimensional array - array_map('array_shift', $this->headers), - headers_list() - ); - - if (empty($headers) OR empty($header)) - { - return NULL; - } - - // Count backwards, in order to get the last matching header - for ($c = count($headers) - 1; $c > -1; $c--) - { - if (strncasecmp($header, $headers[$c], $l = self::strlen($header)) === 0) - { - return trim(self::substr($headers[$c], $l+1)); - } - } - - return NULL; - } - - // -------------------------------------------------------------------- - - /** - * Set HTTP Status Header - * - * As of version 1.7.2, this is an alias for common function - * set_status_header(). - * - * @param int $code Status code (default: 200) - * @param string $text Optional message - * @return CI_Output - */ - public function set_status_header($code = 200, $text = '') - { - set_status_header($code, $text); - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Enable/disable Profiler - * - * @param bool $val TRUE to enable or FALSE to disable - * @return CI_Output - */ - public function enable_profiler($val = TRUE) - { - $this->enable_profiler = is_bool($val) ? $val : TRUE; - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Set Profiler Sections - * - * Allows override of default/config settings for - * Profiler section display. - * - * @param array $sections Profiler sections - * @return CI_Output - */ - public function set_profiler_sections($sections) - { - if (isset($sections['query_toggle_count'])) - { - $this->_profiler_sections['query_toggle_count'] = (int) $sections['query_toggle_count']; - unset($sections['query_toggle_count']); - } - - foreach ($sections as $section => $enable) - { - $this->_profiler_sections[$section] = ($enable !== FALSE); - } - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Set Cache - * - * @param int $time Cache expiration time in minutes - * @return CI_Output - */ - public function cache($time) - { - $this->cache_expiration = is_numeric($time) ? $time : 0; - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Display Output - * - * Processes and sends finalized output data to the browser along - * with any server headers and profile data. It also stops benchmark - * timers so the page rendering speed and memory usage can be shown. - * - * Note: All "view" data is automatically put into $this->final_output - * by controller class. - * - * @uses CI_Output::$final_output - * @param string $output Output data override - * @return void - */ - public function _display($output = '') - { - // Note: We use load_class() because we can't use $CI =& get_instance() - // since this function is sometimes called by the caching mechanism, - // which happens before the CI super object is available. - $BM =& load_class('Benchmark', 'core'); - $CFG =& load_class('Config', 'core'); - - // Grab the super object if we can. - if (class_exists('CI_Controller', FALSE)) - { - $CI =& get_instance(); - } - - // -------------------------------------------------------------------- - - // Set the output data - if ($output === '') - { - $output =& $this->final_output; - } - - // -------------------------------------------------------------------- - - // Do we need to write a cache file? Only if the controller does not have its - // own _output() method and we are not dealing with a cache file, which we - // can determine by the existence of the $CI object above - if ($this->cache_expiration > 0 && isset($CI) && ! method_exists($CI, '_output')) - { - $this->_write_cache($output); - } - - // -------------------------------------------------------------------- - - // Parse out the elapsed time and memory usage, - // then swap the pseudo-variables with the data - - $elapsed = $BM->elapsed_time('total_execution_time_start', 'total_execution_time_end'); - - if ($this->parse_exec_vars === TRUE) - { - $memory = round(memory_get_usage() / 1024 / 1024, 2).'MB'; - $output = str_replace(array('{elapsed_time}', '{memory_usage}'), array($elapsed, $memory), $output); - } - - // -------------------------------------------------------------------- - - // Is compression requested? - if (isset($CI) // This means that we're not serving a cache file, if we were, it would already be compressed - && $this->_compress_output === TRUE - && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE) - { - ob_start('ob_gzhandler'); - } - - // -------------------------------------------------------------------- - - // Are there any server headers to send? - if (count($this->headers) > 0) - { - foreach ($this->headers as $header) - { - @header($header[0], $header[1]); - } - } - - // -------------------------------------------------------------------- - - // Does the $CI object exist? - // If not we know we are dealing with a cache file so we'll - // simply echo out the data and exit. - if ( ! isset($CI)) - { - if ($this->_compress_output === TRUE) - { - if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE) - { - header('Content-Encoding: gzip'); - header('Content-Length: '.self::strlen($output)); - } - else - { - // User agent doesn't support gzip compression, - // so we'll have to decompress our cache - $output = gzinflate(self::substr($output, 10, -8)); - } - } - - echo $output; - log_message('info', 'Final output sent to browser'); - log_message('debug', 'Total execution time: '.$elapsed); - return; - } - - // -------------------------------------------------------------------- - - // Do we need to generate profile data? - // If so, load the Profile class and run it. - if ($this->enable_profiler === TRUE) - { - $CI->load->library('profiler'); - if ( ! empty($this->_profiler_sections)) - { - $CI->profiler->set_sections($this->_profiler_sections); - } - - // If the output data contains closing and tags - // we will remove them and add them back after we insert the profile data - $output = preg_replace('|.*?|is', '', $output, -1, $count).$CI->profiler->run(); - if ($count > 0) - { - $output .= ''; - } - } - - // Does the controller contain a function named _output()? - // If so send the output there. Otherwise, echo it. - if (method_exists($CI, '_output')) - { - $CI->_output($output); - } - else - { - echo $output; // Send it to the browser! - } - - log_message('info', 'Final output sent to browser'); - log_message('debug', 'Total execution time: '.$elapsed); - } - - // -------------------------------------------------------------------- - - /** - * Write Cache - * - * @param string $output Output data to cache - * @return void - */ - public function _write_cache($output) - { - $CI =& get_instance(); - $path = $CI->config->item('cache_path'); - $cache_path = ($path === '') ? APPPATH.'cache/' : $path; - - if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path)) - { - log_message('error', 'Unable to write cache file: '.$cache_path); - return; - } - - $uri = $CI->config->item('base_url') - .$CI->config->item('index_page') - .$CI->uri->uri_string(); - - if (($cache_query_string = $CI->config->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING'])) - { - if (is_array($cache_query_string)) - { - $uri .= '?'.http_build_query(array_intersect_key($_GET, array_flip($cache_query_string))); - } - else - { - $uri .= '?'.$_SERVER['QUERY_STRING']; - } - } - - $cache_path .= md5($uri); - - if ( ! $fp = @fopen($cache_path, 'w+b')) - { - log_message('error', 'Unable to write cache file: '.$cache_path); - return; - } - - if ( ! flock($fp, LOCK_EX)) - { - log_message('error', 'Unable to secure a file lock for file at: '.$cache_path); - fclose($fp); - return; - } - - // If output compression is enabled, compress the cache - // itself, so that we don't have to do that each time - // we're serving it - if ($this->_compress_output === TRUE) - { - $output = gzencode($output); - - if ($this->get_header('content-type') === NULL) - { - $this->set_content_type($this->mime_type); - } - } - - $expire = time() + ($this->cache_expiration * 60); - - // Put together our serialized info. - $cache_info = serialize(array( - 'expire' => $expire, - 'headers' => $this->headers - )); - - $output = $cache_info.'ENDCI--->'.$output; - - for ($written = 0, $length = self::strlen($output); $written < $length; $written += $result) - { - if (($result = fwrite($fp, self::substr($output, $written))) === FALSE) - { - break; - } - } - - flock($fp, LOCK_UN); - fclose($fp); - - if ( ! is_int($result)) - { - @unlink($cache_path); - log_message('error', 'Unable to write the complete cache content at: '.$cache_path); - return; - } - - chmod($cache_path, 0640); - log_message('debug', 'Cache file written: '.$cache_path); - - // Send HTTP cache-control headers to browser to match file cache settings. - $this->set_cache_header($_SERVER['REQUEST_TIME'], $expire); - } - - // -------------------------------------------------------------------- - - /** - * Update/serve cached output - * - * @uses CI_Config - * @uses CI_URI - * - * @param object &$CFG CI_Config class instance - * @param object &$URI CI_URI class instance - * @return bool TRUE on success or FALSE on failure - */ - public function _display_cache(&$CFG, &$URI) - { - $cache_path = ($CFG->item('cache_path') === '') ? APPPATH.'cache/' : $CFG->item('cache_path'); - - // Build the file path. The file name is an MD5 hash of the full URI - $uri = $CFG->item('base_url').$CFG->item('index_page').$URI->uri_string; - - if (($cache_query_string = $CFG->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING'])) - { - if (is_array($cache_query_string)) - { - $uri .= '?'.http_build_query(array_intersect_key($_GET, array_flip($cache_query_string))); - } - else - { - $uri .= '?'.$_SERVER['QUERY_STRING']; - } - } - - $filepath = $cache_path.md5($uri); - - if ( ! file_exists($filepath) OR ! $fp = @fopen($filepath, 'rb')) - { - return FALSE; - } - - flock($fp, LOCK_SH); - - $cache = (filesize($filepath) > 0) ? fread($fp, filesize($filepath)) : ''; - - flock($fp, LOCK_UN); - fclose($fp); - - // Look for embedded serialized file info. - if ( ! preg_match('/^(.*)ENDCI--->/', $cache, $match)) - { - return FALSE; - } - - $cache_info = unserialize($match[1]); - $expire = $cache_info['expire']; - - $last_modified = filemtime($filepath); - - // Has the file expired? - if ($_SERVER['REQUEST_TIME'] >= $expire && is_really_writable($cache_path)) - { - // If so we'll delete it. - @unlink($filepath); - log_message('debug', 'Cache file has expired. File deleted.'); - return FALSE; - } - - // Send the HTTP cache control headers - $this->set_cache_header($last_modified, $expire); - - // Add headers from cache file. - foreach ($cache_info['headers'] as $header) - { - $this->set_header($header[0], $header[1]); - } - - // Display the cache - $this->_display(self::substr($cache, self::strlen($match[0]))); - log_message('debug', 'Cache file is current. Sending it to browser.'); - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Delete cache - * - * @param string $uri URI string - * @return bool - */ - public function delete_cache($uri = '') - { - $CI =& get_instance(); - $cache_path = $CI->config->item('cache_path'); - if ($cache_path === '') - { - $cache_path = APPPATH.'cache/'; - } - - if ( ! is_dir($cache_path)) - { - log_message('error', 'Unable to find cache path: '.$cache_path); - return FALSE; - } - - if (empty($uri)) - { - $uri = $CI->uri->uri_string(); - - if (($cache_query_string = $CI->config->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING'])) - { - if (is_array($cache_query_string)) - { - $uri .= '?'.http_build_query(array_intersect_key($_GET, array_flip($cache_query_string))); - } - else - { - $uri .= '?'.$_SERVER['QUERY_STRING']; - } - } - } - - $cache_path .= md5($CI->config->item('base_url').$CI->config->item('index_page').ltrim($uri, '/')); - - if ( ! @unlink($cache_path)) - { - log_message('error', 'Unable to delete cache file for '.$uri); - return FALSE; - } - - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Set Cache Header - * - * Set the HTTP headers to match the server-side file cache settings - * in order to reduce bandwidth. - * - * @param int $last_modified Timestamp of when the page was last modified - * @param int $expiration Timestamp of when should the requested page expire from cache - * @return void - */ - public function set_cache_header($last_modified, $expiration) - { - $max_age = $expiration - $_SERVER['REQUEST_TIME']; - - if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $last_modified <= strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])) - { - $this->set_status_header(304); - exit; - } - - header('Pragma: public'); - header('Cache-Control: max-age='.$max_age.', public'); - header('Expires: '.gmdate('D, d M Y H:i:s', $expiration).' GMT'); - header('Last-modified: '.gmdate('D, d M Y H:i:s', $last_modified).' GMT'); - } - - // -------------------------------------------------------------------- - - /** - * Byte-safe strlen() - * - * @param string $str - * @return int - */ - protected static function strlen($str) - { - return (self::$func_overload) - ? mb_strlen($str, '8bit') - : strlen($str); - } - - // -------------------------------------------------------------------- - - /** - * Byte-safe substr() - * - * @param string $str - * @param int $start - * @param int $length - * @return string - */ - protected static function substr($str, $start, $length = NULL) - { - if (self::$func_overload) - { - // mb_substr($str, $start, null, '8bit') returns an empty - // string on PHP 5.3 - isset($length) OR $length = ($start >= 0 ? self::strlen($str) - $start : -$start); - return mb_substr($str, $start, $length, '8bit'); - } - - return isset($length) - ? substr($str, $start, $length) - : substr($str, $start); - } -} diff --git a/system/core/Router.php b/system/core/Router.php deleted file mode 100644 index 7b92f70..0000000 --- a/system/core/Router.php +++ /dev/null @@ -1,515 +0,0 @@ -config =& load_class('Config', 'core'); - $this->uri =& load_class('URI', 'core'); - - $this->enable_query_strings = ( ! is_cli() && $this->config->item('enable_query_strings') === TRUE); - - // If a directory override is configured, it has to be set before any dynamic routing logic - is_array($routing) && isset($routing['directory']) && $this->set_directory($routing['directory']); - $this->_set_routing(); - - // Set any routing overrides that may exist in the main index file - if (is_array($routing)) - { - empty($routing['controller']) OR $this->set_class($routing['controller']); - empty($routing['function']) OR $this->set_method($routing['function']); - } - - log_message('info', 'Router Class Initialized'); - } - - // -------------------------------------------------------------------- - - /** - * Set route mapping - * - * Determines what should be served based on the URI request, - * as well as any "routes" that have been set in the routing config file. - * - * @return void - */ - protected function _set_routing() - { - // Load the routes.php file. It would be great if we could - // skip this for enable_query_strings = TRUE, but then - // default_controller would be empty ... - if (file_exists(APPPATH.'config/routes.php')) - { - include(APPPATH.'config/routes.php'); - } - - if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/routes.php')) - { - include(APPPATH.'config/'.ENVIRONMENT.'/routes.php'); - } - - // Validate & get reserved routes - if (isset($route) && is_array($route)) - { - isset($route['default_controller']) && $this->default_controller = $route['default_controller']; - isset($route['translate_uri_dashes']) && $this->translate_uri_dashes = $route['translate_uri_dashes']; - unset($route['default_controller'], $route['translate_uri_dashes']); - $this->routes = $route; - } - - // Are query strings enabled in the config file? Normally CI doesn't utilize query strings - // since URI segments are more search-engine friendly, but they can optionally be used. - // If this feature is enabled, we will gather the directory/class/method a little differently - if ($this->enable_query_strings) - { - // If the directory is set at this time, it means an override exists, so skip the checks - if ( ! isset($this->directory)) - { - $_d = $this->config->item('directory_trigger'); - $_d = isset($_GET[$_d]) ? trim($_GET[$_d], " \t\n\r\0\x0B/") : ''; - - if ($_d !== '') - { - $this->uri->filter_uri($_d); - $this->set_directory($_d); - } - } - - $_c = trim($this->config->item('controller_trigger')); - if ( ! empty($_GET[$_c])) - { - $this->uri->filter_uri($_GET[$_c]); - $this->set_class($_GET[$_c]); - - $_f = trim($this->config->item('function_trigger')); - if ( ! empty($_GET[$_f])) - { - $this->uri->filter_uri($_GET[$_f]); - $this->set_method($_GET[$_f]); - } - - $this->uri->rsegments = array( - 1 => $this->class, - 2 => $this->method - ); - } - else - { - $this->_set_default_controller(); - } - - // Routing rules don't apply to query strings and we don't need to detect - // directories, so we're done here - return; - } - - // Is there anything to parse? - if ($this->uri->uri_string !== '') - { - $this->_parse_routes(); - } - else - { - $this->_set_default_controller(); - } - } - - // -------------------------------------------------------------------- - - /** - * Set request route - * - * Takes an array of URI segments as input and sets the class/method - * to be called. - * - * @used-by CI_Router::_parse_routes() - * @param array $segments URI segments - * @return void - */ - protected function _set_request($segments = array()) - { - $segments = $this->_validate_request($segments); - // If we don't have any segments left - try the default controller; - // WARNING: Directories get shifted out of the segments array! - if (empty($segments)) - { - $this->_set_default_controller(); - return; - } - - if ($this->translate_uri_dashes === TRUE) - { - $segments[0] = str_replace('-', '_', $segments[0]); - if (isset($segments[1])) - { - $segments[1] = str_replace('-', '_', $segments[1]); - } - } - - $this->set_class($segments[0]); - if (isset($segments[1])) - { - $this->set_method($segments[1]); - } - else - { - $segments[1] = 'index'; - } - - array_unshift($segments, NULL); - unset($segments[0]); - $this->uri->rsegments = $segments; - } - - // -------------------------------------------------------------------- - - /** - * Set default controller - * - * @return void - */ - protected function _set_default_controller() - { - if (empty($this->default_controller)) - { - show_error('Unable to determine what should be displayed. A default route has not been specified in the routing file.'); - } - - // Is the method being specified? - if (sscanf($this->default_controller, '%[^/]/%s', $class, $method) !== 2) - { - $method = 'index'; - } - - if ( ! file_exists(APPPATH.'controllers/'.$this->directory.ucfirst($class).'.php')) - { - // This will trigger 404 later - return; - } - - $this->set_class($class); - $this->set_method($method); - - // Assign routed segments, index starting from 1 - $this->uri->rsegments = array( - 1 => $class, - 2 => $method - ); - - log_message('debug', 'No URI present. Default controller set.'); - } - - // -------------------------------------------------------------------- - - /** - * Validate request - * - * Attempts validate the URI request and determine the controller path. - * - * @used-by CI_Router::_set_request() - * @param array $segments URI segments - * @return mixed URI segments - */ - protected function _validate_request($segments) - { - $c = count($segments); - $directory_override = isset($this->directory); - - // Loop through our segments and return as soon as a controller - // is found or when such a directory doesn't exist - while ($c-- > 0) - { - $test = $this->directory - .ucfirst($this->translate_uri_dashes === TRUE ? str_replace('-', '_', $segments[0]) : $segments[0]); - - if ( ! file_exists(APPPATH.'controllers/'.$test.'.php') - && $directory_override === FALSE - && is_dir(APPPATH.'controllers/'.$this->directory.$segments[0]) - ) - { - $this->set_directory(array_shift($segments), TRUE); - continue; - } - - return $segments; - } - - // This means that all segments were actually directories - return $segments; - } - - // -------------------------------------------------------------------- - - /** - * Parse Routes - * - * Matches any routes that may exist in the config/routes.php file - * against the URI to determine if the class/method need to be remapped. - * - * @return void - */ - protected function _parse_routes() - { - // Turn the segment array into a URI string - $uri = implode('/', $this->uri->segments); - - // Get HTTP verb - $http_verb = isset($_SERVER['REQUEST_METHOD']) ? strtolower($_SERVER['REQUEST_METHOD']) : 'cli'; - - // Loop through the route array looking for wildcards - foreach ($this->routes as $key => $val) - { - // Check if route format is using HTTP verbs - if (is_array($val)) - { - $val = array_change_key_case($val, CASE_LOWER); - if (isset($val[$http_verb])) - { - $val = $val[$http_verb]; - } - else - { - continue; - } - } - - // Convert wildcards to RegEx - $key = str_replace(array(':any', ':num'), array('[^/]+', '[0-9]+'), $key); - - // Does the RegEx match? - if (preg_match('#^'.$key.'$#', $uri, $matches)) - { - // Are we using callbacks to process back-references? - if ( ! is_string($val) && is_callable($val)) - { - // Remove the original string from the matches array. - array_shift($matches); - - // Execute the callback using the values in matches as its parameters. - $val = call_user_func_array($val, $matches); - } - // Are we using the default routing method for back-references? - elseif (strpos($val, '$') !== FALSE && strpos($key, '(') !== FALSE) - { - $val = preg_replace('#^'.$key.'$#', $val, $uri); - } - - $this->_set_request(explode('/', $val)); - return; - } - } - - // If we got this far it means we didn't encounter a - // matching route so we'll set the site default route - $this->_set_request(array_values($this->uri->segments)); - } - - // -------------------------------------------------------------------- - - /** - * Set class name - * - * @param string $class Class name - * @return void - */ - public function set_class($class) - { - $this->class = str_replace(array('/', '.'), '', $class); - } - - // -------------------------------------------------------------------- - - /** - * Fetch the current class - * - * @deprecated 3.0.0 Read the 'class' property instead - * @return string - */ - public function fetch_class() - { - return $this->class; - } - - // -------------------------------------------------------------------- - - /** - * Set method name - * - * @param string $method Method name - * @return void - */ - public function set_method($method) - { - $this->method = $method; - } - - // -------------------------------------------------------------------- - - /** - * Fetch the current method - * - * @deprecated 3.0.0 Read the 'method' property instead - * @return string - */ - public function fetch_method() - { - return $this->method; - } - - // -------------------------------------------------------------------- - - /** - * Set directory name - * - * @param string $dir Directory name - * @param bool $append Whether we're appending rather than setting the full value - * @return void - */ - public function set_directory($dir, $append = FALSE) - { - if ($append !== TRUE OR empty($this->directory)) - { - $this->directory = str_replace('.', '', trim($dir, '/')).'/'; - } - else - { - $this->directory .= str_replace('.', '', trim($dir, '/')).'/'; - } - } - - // -------------------------------------------------------------------- - - /** - * Fetch directory - * - * Feches the sub-directory (if any) that contains the requested - * controller class. - * - * @deprecated 3.0.0 Read the 'directory' property instead - * @return string - */ - public function fetch_directory() - { - return $this->directory; - } - -} diff --git a/system/core/Security.php b/system/core/Security.php deleted file mode 100644 index 31926b4..0000000 --- a/system/core/Security.php +++ /dev/null @@ -1,1090 +0,0 @@ -', '<', '>', - "'", '"', '&', '$', '#', - '{', '}', '[', ']', '=', - ';', '?', '%20', '%22', - '%3c', // < - '%253c', // < - '%3e', // > - '%0e', // > - '%28', // ( - '%29', // ) - '%2528', // ( - '%26', // & - '%24', // $ - '%3f', // ? - '%3b', // ; - '%3d' // = - ); - - /** - * Character set - * - * Will be overridden by the constructor. - * - * @var string - */ - public $charset = 'UTF-8'; - - /** - * XSS Hash - * - * Random Hash for protecting URLs. - * - * @var string - */ - protected $_xss_hash; - - /** - * CSRF Hash - * - * Random hash for Cross Site Request Forgery protection cookie - * - * @var string - */ - protected $_csrf_hash; - - /** - * CSRF Expire time - * - * Expiration time for Cross Site Request Forgery protection cookie. - * Defaults to two hours (in seconds). - * - * @var int - */ - protected $_csrf_expire = 7200; - - /** - * CSRF Token name - * - * Token name for Cross Site Request Forgery protection cookie. - * - * @var string - */ - protected $_csrf_token_name = 'ci_csrf_token'; - - /** - * CSRF Cookie name - * - * Cookie name for Cross Site Request Forgery protection cookie. - * - * @var string - */ - protected $_csrf_cookie_name = 'ci_csrf_token'; - - /** - * List of never allowed strings - * - * @var array - */ - protected $_never_allowed_str = array( - 'document.cookie' => '[removed]', - '(document).cookie' => '[removed]', - 'document.write' => '[removed]', - '(document).write' => '[removed]', - '.parentNode' => '[removed]', - '.innerHTML' => '[removed]', - '-moz-binding' => '[removed]', - '' => '-->', - ' '<![CDATA[', - '' => '<comment>', - '<%' => '<%' - ); - - /** - * List of never allowed regex replacements - * - * @var array - */ - protected $_never_allowed_regex = array( - 'javascript\s*:', - '(\(?document\)?|\(?window\)?(\.document)?)\.(location|on\w*)', - 'expression\s*(\(|&\#40;)', // CSS and IE - 'vbscript\s*:', // IE, surprise! - 'wscript\s*:', // IE - 'jscript\s*:', // IE - 'vbs\s*:', // IE - 'Redirect\s+30\d', - "([\"'])?data\s*:[^\\1]*?base64[^\\1]*?,[^\\1]*?\\1?" - ); - - /** - * Class constructor - * - * @return void - */ - public function __construct() - { - // Is CSRF protection enabled? - if (config_item('csrf_protection')) - { - // CSRF config - foreach (array('csrf_expire', 'csrf_token_name', 'csrf_cookie_name') as $key) - { - if (NULL !== ($val = config_item($key))) - { - $this->{'_'.$key} = $val; - } - } - - // Append application specific cookie prefix - if ($cookie_prefix = config_item('cookie_prefix')) - { - $this->_csrf_cookie_name = $cookie_prefix.$this->_csrf_cookie_name; - } - - // Set the CSRF hash - $this->_csrf_set_hash(); - } - - $this->charset = strtoupper(config_item('charset')); - - log_message('info', 'Security Class Initialized'); - } - - // -------------------------------------------------------------------- - - /** - * CSRF Verify - * - * @return CI_Security - */ - public function csrf_verify() - { - // If it's not a POST request we will set the CSRF cookie - if (strtoupper($_SERVER['REQUEST_METHOD']) !== 'POST') - { - return $this->csrf_set_cookie(); - } - - // Check if URI has been whitelisted from CSRF checks - if ($exclude_uris = config_item('csrf_exclude_uris')) - { - $uri = load_class('URI', 'core'); - foreach ($exclude_uris as $excluded) - { - if (preg_match('#^'.$excluded.'$#i'.(UTF8_ENABLED ? 'u' : ''), $uri->uri_string())) - { - return $this; - } - } - } - - // Check CSRF token validity, but don't error on mismatch just yet - we'll want to regenerate - $valid = isset($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name]) - && hash_equals($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name]); - - // We kill this since we're done and we don't want to pollute the _POST array - unset($_POST[$this->_csrf_token_name]); - - // Regenerate on every submission? - if (config_item('csrf_regenerate')) - { - // Nothing should last forever - unset($_COOKIE[$this->_csrf_cookie_name]); - $this->_csrf_hash = NULL; - } - - $this->_csrf_set_hash(); - $this->csrf_set_cookie(); - - if ($valid !== TRUE) - { - $this->csrf_show_error(); - } - - log_message('info', 'CSRF token verified'); - return $this; - } - - // -------------------------------------------------------------------- - - /** - * CSRF Set Cookie - * - * @codeCoverageIgnore - * @return CI_Security - */ - public function csrf_set_cookie() - { - $expire = time() + $this->_csrf_expire; - $secure_cookie = (bool) config_item('cookie_secure'); - - if ($secure_cookie && ! is_https()) - { - return FALSE; - } - - setcookie( - $this->_csrf_cookie_name, - $this->_csrf_hash, - $expire, - config_item('cookie_path'), - config_item('cookie_domain'), - $secure_cookie, - config_item('cookie_httponly') - ); - log_message('info', 'CSRF cookie sent'); - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Show CSRF Error - * - * @return void - */ - public function csrf_show_error() - { - show_error('The action you have requested is not allowed.', 403); - } - - // -------------------------------------------------------------------- - - /** - * Get CSRF Hash - * - * @see CI_Security::$_csrf_hash - * @return string CSRF hash - */ - public function get_csrf_hash() - { - return $this->_csrf_hash; - } - - // -------------------------------------------------------------------- - - /** - * Get CSRF Token Name - * - * @see CI_Security::$_csrf_token_name - * @return string CSRF token name - */ - public function get_csrf_token_name() - { - return $this->_csrf_token_name; - } - - // -------------------------------------------------------------------- - - /** - * XSS Clean - * - * Sanitizes data so that Cross Site Scripting Hacks can be - * prevented. This method does a fair amount of work but - * it is extremely thorough, designed to prevent even the - * most obscure XSS attempts. Nothing is ever 100% foolproof, - * of course, but I haven't been able to get anything passed - * the filter. - * - * Note: Should only be used to deal with data upon submission. - * It's not something that should be used for general - * runtime processing. - * - * @link http://channel.bitflux.ch/wiki/XSS_Prevention - * Based in part on some code and ideas from Bitflux. - * - * @link http://ha.ckers.org/xss.html - * To help develop this script I used this great list of - * vulnerabilities along with a few other hacks I've - * harvested from examining vulnerabilities in other programs. - * - * @param string|string[] $str Input data - * @param bool $is_image Whether the input is an image - * @return string - */ - public function xss_clean($str, $is_image = FALSE) - { - // Is the string an array? - if (is_array($str)) - { - foreach ($str as $key => &$value) - { - $str[$key] = $this->xss_clean($value); - } - - return $str; - } - - // Remove Invisible Characters - $str = remove_invisible_characters($str); - - /* - * URL Decode - * - * Just in case stuff like this is submitted: - * - * Google - * - * Note: Use rawurldecode() so it does not remove plus signs - */ - if (stripos($str, '%') !== false) - { - do - { - $oldstr = $str; - $str = rawurldecode($str); - $str = preg_replace_callback('#%(?:\s*[0-9a-f]){2,}#i', array($this, '_urldecodespaces'), $str); - } - while ($oldstr !== $str); - unset($oldstr); - } - - /* - * Convert character entities to ASCII - * - * This permits our tests below to work reliably. - * We only convert entities that are within tags since - * these are the ones that will pose security problems. - */ - $str = preg_replace_callback("/[^a-z0-9>]+[a-z0-9]+=([\'\"]).*?\\1/si", array($this, '_convert_attribute'), $str); - $str = preg_replace_callback('/<\w+.*/si', array($this, '_decode_entity'), $str); - - // Remove Invisible Characters Again! - $str = remove_invisible_characters($str); - - /* - * Convert all tabs to spaces - * - * This prevents strings like this: ja vascript - * NOTE: we deal with spaces between characters later. - * NOTE: preg_replace was found to be amazingly slow here on - * large blocks of data, so we use str_replace. - */ - $str = str_replace("\t", ' ', $str); - - // Capture converted string for later comparison - $converted_string = $str; - - // Remove Strings that are never allowed - $str = $this->_do_never_allowed($str); - - /* - * Makes PHP tags safe - * - * Note: XML tags are inadvertently replaced too: - * - * '), array('<?', '?>'), $str); - } - - /* - * Compact any exploded words - * - * This corrects words like: j a v a s c r i p t - * These words are compacted back to their correct state. - */ - $words = array( - 'javascript', 'expression', 'vbscript', 'jscript', 'wscript', - 'vbs', 'script', 'base64', 'applet', 'alert', 'document', - 'write', 'cookie', 'window', 'confirm', 'prompt', 'eval' - ); - - foreach ($words as $word) - { - $word = implode('\s*', str_split($word)).'\s*'; - - // We only want to do this when it is followed by a non-word character - // That way valid stuff like "dealer to" does not become "dealerto" - $str = preg_replace_callback('#('.substr($word, 0, -3).')(\W)#is', array($this, '_compact_exploded_words'), $str); - } - - /* - * Remove disallowed Javascript in links or img tags - * We used to do some version comparisons and use of stripos(), - * but it is dog slow compared to these simplified non-capturing - * preg_match(), especially if the pattern exists in the string - * - * Note: It was reported that not only space characters, but all in - * the following pattern can be parsed as separators between a tag name - * and its attributes: [\d\s"\'`;,\/\=\(\x00\x0B\x09\x0C] - * ... however, remove_invisible_characters() above already strips the - * hex-encoded ones, so we'll skip them below. - */ - do - { - $original = $str; - - if (preg_match('/]+([^>]*?)(?:>|$)#si', array($this, '_js_link_removal'), $str); - } - - if (preg_match('/]*?)(?:\s?/?>|$)#si', array($this, '_js_img_removal'), $str); - } - - if (preg_match('/script|xss/i', $str)) - { - $str = preg_replace('##si', '[removed]', $str); - } - } - while ($original !== $str); - unset($original); - - /* - * Sanitize naughty HTML elements - * - * If a tag containing any of the words in the list - * below is found, the tag gets converted to entities. - * - * So this: - * Becomes: <blink> - */ - $pattern = '#' - .'<((?/*\s*)((?[a-z0-9]+)(?=[^a-z0-9]|$)|.+)' // tag start and name, followed by a non-tag character - .'[^\s\042\047a-z0-9>/=]*' // a valid attribute character immediately after the tag would count as a separator - // optional attributes - .'(?(?:[\s\042\047/=]*' // non-attribute characters, excluding > (tag close) for obvious reasons - .'[^\s\042\047>/=]+' // attribute characters - // optional attribute-value - .'(?:\s*=' // attribute-value separator - .'(?:[^\s\042\047=><`]+|\s*\042[^\042]*\042|\s*\047[^\047]*\047|\s*(?U:[^\s\042\047=><`]*))' // single, double or non-quoted value - .')?' // end optional attribute-value group - .')*)' // end optional attributes group - .'[^>]*)(?\>)?#isS'; - - // Note: It would be nice to optimize this for speed, BUT - // only matching the naughty elements here results in - // false positives and in turn - vulnerabilities! - do - { - $old_str = $str; - $str = preg_replace_callback($pattern, array($this, '_sanitize_naughty_html'), $str); - } - while ($old_str !== $str); - unset($old_str); - - /* - * Sanitize naughty scripting elements - * - * Similar to above, only instead of looking for - * tags it looks for PHP and JavaScript commands - * that are disallowed. Rather than removing the - * code, it simply converts the parenthesis to entities - * rendering the code un-executable. - * - * For example: eval('some code') - * Becomes: eval('some code') - */ - $str = preg_replace( - '#(alert|prompt|confirm|cmd|passthru|eval|exec|expression|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(\s*)\((.*?)\)#si', - '\\1\\2(\\3)', - $str - ); - - // Same thing, but for "tag functions" (e.g. eval`some code`) - // See https://github.com/bcit-ci/CodeIgniter/issues/5420 - $str = preg_replace( - '#(alert|prompt|confirm|cmd|passthru|eval|exec|expression|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(\s*)`(.*?)`#si', - '\\1\\2`\\3`', - $str - ); - - // Final clean up - // This adds a bit of extra precaution in case - // something got through the above filters - $str = $this->_do_never_allowed($str); - - /* - * Images are Handled in a Special Way - * - Essentially, we want to know that after all of the character - * conversion is done whether any unwanted, likely XSS, code was found. - * If not, we return TRUE, as the image is clean. - * However, if the string post-conversion does not matched the - * string post-removal of XSS, then it fails, as there was unwanted XSS - * code found and removed/changed during processing. - */ - if ($is_image === TRUE) - { - return ($str === $converted_string); - } - - return $str; - } - - // -------------------------------------------------------------------- - - /** - * XSS Hash - * - * Generates the XSS hash if needed and returns it. - * - * @see CI_Security::$_xss_hash - * @return string XSS hash - */ - public function xss_hash() - { - if ($this->_xss_hash === NULL) - { - $rand = $this->get_random_bytes(16); - $this->_xss_hash = ($rand === FALSE) - ? md5(uniqid(mt_rand(), TRUE)) - : bin2hex($rand); - } - - return $this->_xss_hash; - } - - // -------------------------------------------------------------------- - - /** - * Get random bytes - * - * @param int $length Output length - * @return string - */ - public function get_random_bytes($length) - { - if (empty($length) OR ! ctype_digit((string) $length)) - { - return FALSE; - } - - if (function_exists('random_bytes')) - { - try - { - // The cast is required to avoid TypeError - return random_bytes((int) $length); - } - catch (Exception $e) - { - // If random_bytes() can't do the job, we can't either ... - // There's no point in using fallbacks. - log_message('error', $e->getMessage()); - return FALSE; - } - } - - // Unfortunately, none of the following PRNGs is guaranteed to exist ... - if (defined('MCRYPT_DEV_URANDOM') && ($output = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM)) !== FALSE) - { - return $output; - } - - - if (is_readable('/dev/urandom') && ($fp = fopen('/dev/urandom', 'rb')) !== FALSE) - { - // Try not to waste entropy ... - is_php('5.4') && stream_set_chunk_size($fp, $length); - $output = fread($fp, $length); - fclose($fp); - if ($output !== FALSE) - { - return $output; - } - } - - if (function_exists('openssl_random_pseudo_bytes')) - { - return openssl_random_pseudo_bytes($length); - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * HTML Entities Decode - * - * A replacement for html_entity_decode() - * - * The reason we are not using html_entity_decode() by itself is because - * while it is not technically correct to leave out the semicolon - * at the end of an entity most browsers will still interpret the entity - * correctly. html_entity_decode() does not convert entities without - * semicolons, so we are left with our own little solution here. Bummer. - * - * @link http://php.net/html-entity-decode - * - * @param string $str Input - * @param string $charset Character set - * @return string - */ - public function entity_decode($str, $charset = NULL) - { - if (strpos($str, '&') === FALSE) - { - return $str; - } - - static $_entities; - - isset($charset) OR $charset = $this->charset; - $flag = is_php('5.4') - ? ENT_COMPAT | ENT_HTML5 - : ENT_COMPAT; - - if ( ! isset($_entities)) - { - $_entities = array_map('strtolower', get_html_translation_table(HTML_ENTITIES, $flag, $charset)); - - // If we're not on PHP 5.4+, add the possibly dangerous HTML 5 - // entities to the array manually - if ($flag === ENT_COMPAT) - { - $_entities[':'] = ':'; - $_entities['('] = '('; - $_entities[')'] = ')'; - $_entities["\n"] = ' '; - $_entities["\t"] = ' '; - } - } - - do - { - $str_compare = $str; - - // Decode standard entities, avoiding false positives - if (preg_match_all('/&[a-z]{2,}(?![a-z;])/i', $str, $matches)) - { - $replace = array(); - $matches = array_unique(array_map('strtolower', $matches[0])); - foreach ($matches as &$match) - { - if (($char = array_search($match.';', $_entities, TRUE)) !== FALSE) - { - $replace[$match] = $char; - } - } - - $str = str_replace(array_keys($replace), array_values($replace), $str); - } - - // Decode numeric & UTF16 two byte entities - $str = html_entity_decode( - preg_replace('/(&#(?:x0*[0-9a-f]{2,5}(?![0-9a-f;])|(?:0*\d{2,4}(?![0-9;]))))/iS', '$1;', $str), - $flag, - $charset - ); - - if ($flag === ENT_COMPAT) - { - $str = str_replace(array_values($_entities), array_keys($_entities), $str); - } - } - while ($str_compare !== $str); - return $str; - } - - // -------------------------------------------------------------------- - - /** - * Sanitize Filename - * - * @param string $str Input file name - * @param bool $relative_path Whether to preserve paths - * @return string - */ - public function sanitize_filename($str, $relative_path = FALSE) - { - $bad = $this->filename_bad_chars; - - if ( ! $relative_path) - { - $bad[] = './'; - $bad[] = '/'; - } - - $str = remove_invisible_characters($str, FALSE); - - do - { - $old = $str; - $str = str_replace($bad, '', $str); - } - while ($old !== $str); - - return stripslashes($str); - } - - // ---------------------------------------------------------------- - - /** - * Strip Image Tags - * - * @param string $str - * @return string - */ - public function strip_image_tags($str) - { - return preg_replace( - array( - '##i', - '#`]+)).*?\>#i' - ), - '\\2', - $str - ); - } - - // ---------------------------------------------------------------- - - /** - * URL-decode taking spaces into account - * - * @see https://github.com/bcit-ci/CodeIgniter/issues/4877 - * @param array $matches - * @return string - */ - protected function _urldecodespaces($matches) - { - $input = $matches[0]; - $nospaces = preg_replace('#\s+#', '', $input); - return ($nospaces === $input) - ? $input - : rawurldecode($nospaces); - } - - // ---------------------------------------------------------------- - - /** - * Compact Exploded Words - * - * Callback method for xss_clean() to remove whitespace from - * things like 'j a v a s c r i p t'. - * - * @used-by CI_Security::xss_clean() - * @param array $matches - * @return string - */ - protected function _compact_exploded_words($matches) - { - return preg_replace('/\s+/s', '', $matches[1]).$matches[2]; - } - - // -------------------------------------------------------------------- - - /** - * Sanitize Naughty HTML - * - * Callback method for xss_clean() to remove naughty HTML elements. - * - * @used-by CI_Security::xss_clean() - * @param array $matches - * @return string - */ - protected function _sanitize_naughty_html($matches) - { - static $naughty_tags = array( - 'alert', 'area', 'prompt', 'confirm', 'applet', 'audio', 'basefont', 'base', 'behavior', 'bgsound', - 'blink', 'body', 'embed', 'expression', 'form', 'frameset', 'frame', 'head', 'html', 'ilayer', - 'iframe', 'input', 'button', 'select', 'isindex', 'layer', 'link', 'meta', 'keygen', 'object', - 'plaintext', 'style', 'script', 'textarea', 'title', 'math', 'video', 'svg', 'xml', 'xss' - ); - - static $evil_attributes = array( - 'on\w+', 'style', 'xmlns', 'formaction', 'form', 'xlink:href', 'FSCommand', 'seekSegmentTime' - ); - - // First, escape unclosed tags - if (empty($matches['closeTag'])) - { - return '<'.$matches[1]; - } - // Is the element that we caught naughty? If so, escape it - elseif (in_array(strtolower($matches['tagName']), $naughty_tags, TRUE)) - { - return '<'.$matches[1].'>'; - } - // For other tags, see if their attributes are "evil" and strip those - elseif (isset($matches['attributes'])) - { - // We'll store the already filtered attributes here - $attributes = array(); - - // Attribute-catching pattern - $attributes_pattern = '#' - .'(?[^\s\042\047>/=]+)' // attribute characters - // optional attribute-value - .'(?:\s*=(?[^\s\042\047=><`]+|\s*\042[^\042]*\042|\s*\047[^\047]*\047|\s*(?U:[^\s\042\047=><`]*)))' // attribute-value separator - .'#i'; - - // Blacklist pattern for evil attribute names - $is_evil_pattern = '#^('.implode('|', $evil_attributes).')$#i'; - - // Each iteration filters a single attribute - do - { - // Strip any non-alpha characters that may precede an attribute. - // Browsers often parse these incorrectly and that has been a - // of numerous XSS issues we've had. - $matches['attributes'] = preg_replace('#^[^a-z]+#i', '', $matches['attributes']); - - if ( ! preg_match($attributes_pattern, $matches['attributes'], $attribute, PREG_OFFSET_CAPTURE)) - { - // No (valid) attribute found? Discard everything else inside the tag - break; - } - - if ( - // Is it indeed an "evil" attribute? - preg_match($is_evil_pattern, $attribute['name'][0]) - // Or does it have an equals sign, but no value and not quoted? Strip that too! - OR (trim($attribute['value'][0]) === '') - ) - { - $attributes[] = 'xss=removed'; - } - else - { - $attributes[] = $attribute[0][0]; - } - - $matches['attributes'] = substr($matches['attributes'], $attribute[0][1] + strlen($attribute[0][0])); - } - while ($matches['attributes'] !== ''); - - $attributes = empty($attributes) - ? '' - : ' '.implode(' ', $attributes); - return '<'.$matches['slash'].$matches['tagName'].$attributes.'>'; - } - - return $matches[0]; - } - - // -------------------------------------------------------------------- - - /** - * JS Link Removal - * - * Callback method for xss_clean() to sanitize links. - * - * This limits the PCRE backtracks, making it more performance friendly - * and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in - * PHP 5.2+ on link-heavy strings. - * - * @used-by CI_Security::xss_clean() - * @param array $match - * @return string - */ - protected function _js_link_removal($match) - { - return str_replace( - $match[1], - preg_replace( - '#href=.*?(?:(?:alert|prompt|confirm)(?:\(|&\#40;|`|&\#96;)|javascript:|livescript:|mocha:|charset=|window\.|\(?document\)?\.|\.cookie|_filter_attributes($match[1]) - ), - $match[0] - ); - } - - // -------------------------------------------------------------------- - - /** - * JS Image Removal - * - * Callback method for xss_clean() to sanitize image tags. - * - * This limits the PCRE backtracks, making it more performance friendly - * and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in - * PHP 5.2+ on image tag heavy strings. - * - * @used-by CI_Security::xss_clean() - * @param array $match - * @return string - */ - protected function _js_img_removal($match) - { - return str_replace( - $match[1], - preg_replace( - '#src=.*?(?:(?:alert|prompt|confirm|eval)(?:\(|&\#40;|`|&\#96;)|javascript:|livescript:|mocha:|charset=|window\.|\(?document\)?\.|\.cookie|_filter_attributes($match[1]) - ), - $match[0] - ); - } - - // -------------------------------------------------------------------- - - /** - * Attribute Conversion - * - * @used-by CI_Security::xss_clean() - * @param array $match - * @return string - */ - protected function _convert_attribute($match) - { - return str_replace(array('>', '<', '\\'), array('>', '<', '\\\\'), $match[0]); - } - - // -------------------------------------------------------------------- - - /** - * Filter Attributes - * - * Filters tag attributes for consistency and safety. - * - * @used-by CI_Security::_js_img_removal() - * @used-by CI_Security::_js_link_removal() - * @param string $str - * @return string - */ - protected function _filter_attributes($str) - { - $out = ''; - if (preg_match_all('#\s*[a-z\-]+\s*=\s*(\042|\047)([^\\1]*?)\\1#is', $str, $matches)) - { - foreach ($matches[0] as $match) - { - $out .= preg_replace('#/\*.*?\*/#s', '', $match); - } - } - - return $out; - } - - // -------------------------------------------------------------------- - - /** - * HTML Entity Decode Callback - * - * @used-by CI_Security::xss_clean() - * @param array $match - * @return string - */ - protected function _decode_entity($match) - { - // Protect GET variables in URLs - // 901119URL5918AMP18930PROTECT8198 - $match = preg_replace('|\&([a-z\_0-9\-]+)\=([a-z\_0-9\-/]+)|i', $this->xss_hash().'\\1=\\2', $match[0]); - - // Decode, then un-protect URL GET vars - return str_replace( - $this->xss_hash(), - '&', - $this->entity_decode($match, $this->charset) - ); - } - - // -------------------------------------------------------------------- - - /** - * Do Never Allowed - * - * @used-by CI_Security::xss_clean() - * @param string - * @return string - */ - protected function _do_never_allowed($str) - { - $str = str_replace(array_keys($this->_never_allowed_str), $this->_never_allowed_str, $str); - - foreach ($this->_never_allowed_regex as $regex) - { - $str = preg_replace('#'.$regex.'#is', '[removed]', $str); - } - - return $str; - } - - // -------------------------------------------------------------------- - - /** - * Set CSRF Hash and Cookie - * - * @return string - */ - protected function _csrf_set_hash() - { - if ($this->_csrf_hash === NULL) - { - // If the cookie exists we will use its value. - // We don't necessarily want to regenerate it with - // each page load since a page could contain embedded - // sub-pages causing this feature to fail - if (isset($_COOKIE[$this->_csrf_cookie_name]) && is_string($_COOKIE[$this->_csrf_cookie_name]) - && preg_match('#^[0-9a-f]{32}$#iS', $_COOKIE[$this->_csrf_cookie_name]) === 1) - { - return $this->_csrf_hash = $_COOKIE[$this->_csrf_cookie_name]; - } - - $rand = $this->get_random_bytes(16); - $this->_csrf_hash = ($rand === FALSE) - ? md5(uniqid(mt_rand(), TRUE)) - : bin2hex($rand); - } - - return $this->_csrf_hash; - } - -} diff --git a/system/core/URI.php b/system/core/URI.php deleted file mode 100644 index 574ade6..0000000 --- a/system/core/URI.php +++ /dev/null @@ -1,643 +0,0 @@ -config =& load_class('Config', 'core'); - - // If query strings are enabled, we don't need to parse any segments. - // However, they don't make sense under CLI. - if (is_cli() OR $this->config->item('enable_query_strings') !== TRUE) - { - $this->_permitted_uri_chars = $this->config->item('permitted_uri_chars'); - - // If it's a CLI request, ignore the configuration - if (is_cli()) - { - $uri = $this->_parse_argv(); - } - else - { - $protocol = $this->config->item('uri_protocol'); - empty($protocol) && $protocol = 'REQUEST_URI'; - - switch ($protocol) - { - case 'AUTO': // For BC purposes only - case 'REQUEST_URI': - $uri = $this->_parse_request_uri(); - break; - case 'QUERY_STRING': - $uri = $this->_parse_query_string(); - break; - case 'PATH_INFO': - default: - $uri = isset($_SERVER[$protocol]) - ? $_SERVER[$protocol] - : $this->_parse_request_uri(); - break; - } - } - - $this->_set_uri_string($uri); - } - - log_message('info', 'URI Class Initialized'); - } - - // -------------------------------------------------------------------- - - /** - * Set URI String - * - * @param string $str - * @return void - */ - protected function _set_uri_string($str) - { - // Filter out control characters and trim slashes - $this->uri_string = trim(remove_invisible_characters($str, FALSE), '/'); - - if ($this->uri_string !== '') - { - // Remove the URL suffix, if present - if (($suffix = (string) $this->config->item('url_suffix')) !== '') - { - $slen = strlen($suffix); - - if (substr($this->uri_string, -$slen) === $suffix) - { - $this->uri_string = substr($this->uri_string, 0, -$slen); - } - } - - $this->segments[0] = NULL; - // Populate the segments array - foreach (explode('/', trim($this->uri_string, '/')) as $val) - { - $val = trim($val); - // Filter segments for security - $this->filter_uri($val); - - if ($val !== '') - { - $this->segments[] = $val; - } - } - - unset($this->segments[0]); - } - } - - // -------------------------------------------------------------------- - - /** - * Parse REQUEST_URI - * - * Will parse REQUEST_URI and automatically detect the URI from it, - * while fixing the query string if necessary. - * - * @return string - */ - protected function _parse_request_uri() - { - if ( ! isset($_SERVER['REQUEST_URI'], $_SERVER['SCRIPT_NAME'])) - { - return ''; - } - - // parse_url() returns false if no host is present, but the path or query string - // contains a colon followed by a number - $uri = parse_url('http://dummy'.$_SERVER['REQUEST_URI']); - $query = isset($uri['query']) ? $uri['query'] : ''; - $uri = isset($uri['path']) ? $uri['path'] : ''; - - if (isset($_SERVER['SCRIPT_NAME'][0])) - { - if (strpos($uri, $_SERVER['SCRIPT_NAME']) === 0) - { - $uri = (string) substr($uri, strlen($_SERVER['SCRIPT_NAME'])); - } - elseif (strpos($uri, dirname($_SERVER['SCRIPT_NAME'])) === 0) - { - $uri = (string) substr($uri, strlen(dirname($_SERVER['SCRIPT_NAME']))); - } - } - - // This section ensures that even on servers that require the URI to be in the query string (Nginx) a correct - // URI is found, and also fixes the QUERY_STRING server var and $_GET array. - if (trim($uri, '/') === '' && strncmp($query, '/', 1) === 0) - { - $query = explode('?', $query, 2); - $uri = $query[0]; - $_SERVER['QUERY_STRING'] = isset($query[1]) ? $query[1] : ''; - } - else - { - $_SERVER['QUERY_STRING'] = $query; - } - - parse_str($_SERVER['QUERY_STRING'], $_GET); - - if ($uri === '/' OR $uri === '') - { - return '/'; - } - - // Do some final cleaning of the URI and return it - return $this->_remove_relative_directory($uri); - } - - // -------------------------------------------------------------------- - - /** - * Parse QUERY_STRING - * - * Will parse QUERY_STRING and automatically detect the URI from it. - * - * @return string - */ - protected function _parse_query_string() - { - $uri = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING'); - - if (trim($uri, '/') === '') - { - return ''; - } - elseif (strncmp($uri, '/', 1) === 0) - { - $uri = explode('?', $uri, 2); - $_SERVER['QUERY_STRING'] = isset($uri[1]) ? $uri[1] : ''; - $uri = $uri[0]; - } - - parse_str($_SERVER['QUERY_STRING'], $_GET); - - return $this->_remove_relative_directory($uri); - } - - // -------------------------------------------------------------------- - - /** - * Parse CLI arguments - * - * Take each command line argument and assume it is a URI segment. - * - * @return string - */ - protected function _parse_argv() - { - $args = array_slice($_SERVER['argv'], 1); - return $args ? implode('/', $args) : ''; - } - - // -------------------------------------------------------------------- - - /** - * Remove relative directory (../) and multi slashes (///) - * - * Do some final cleaning of the URI and return it, currently only used in self::_parse_request_uri() - * - * @param string $uri - * @return string - */ - protected function _remove_relative_directory($uri) - { - $uris = array(); - $tok = strtok($uri, '/'); - while ($tok !== FALSE) - { - if (( ! empty($tok) OR $tok === '0') && $tok !== '..') - { - $uris[] = $tok; - } - $tok = strtok('/'); - } - - return implode('/', $uris); - } - - // -------------------------------------------------------------------- - - /** - * Filter URI - * - * Filters segments for malicious characters. - * - * @param string $str - * @return void - */ - public function filter_uri(&$str) - { - if ( ! empty($str) && ! empty($this->_permitted_uri_chars) && ! preg_match('/^['.$this->_permitted_uri_chars.']+$/i'.(UTF8_ENABLED ? 'u' : ''), $str)) - { - show_error('The URI you submitted has disallowed characters.', 400); - } - } - - // -------------------------------------------------------------------- - - /** - * Fetch URI Segment - * - * @see CI_URI::$segments - * @param int $n Index - * @param mixed $no_result What to return if the segment index is not found - * @return mixed - */ - public function segment($n, $no_result = NULL) - { - return isset($this->segments[$n]) ? $this->segments[$n] : $no_result; - } - - // -------------------------------------------------------------------- - - /** - * Fetch URI "routed" Segment - * - * Returns the re-routed URI segment (assuming routing rules are used) - * based on the index provided. If there is no routing, will return - * the same result as CI_URI::segment(). - * - * @see CI_URI::$rsegments - * @see CI_URI::segment() - * @param int $n Index - * @param mixed $no_result What to return if the segment index is not found - * @return mixed - */ - public function rsegment($n, $no_result = NULL) - { - return isset($this->rsegments[$n]) ? $this->rsegments[$n] : $no_result; - } - - // -------------------------------------------------------------------- - - /** - * URI to assoc - * - * Generates an associative array of URI data starting at the supplied - * segment index. For example, if this is your URI: - * - * example.com/user/search/name/joe/location/UK/gender/male - * - * You can use this method to generate an array with this prototype: - * - * array ( - * name => joe - * location => UK - * gender => male - * ) - * - * @param int $n Index (default: 3) - * @param array $default Default values - * @return array - */ - public function uri_to_assoc($n = 3, $default = array()) - { - return $this->_uri_to_assoc($n, $default, 'segment'); - } - - // -------------------------------------------------------------------- - - /** - * Routed URI to assoc - * - * Identical to CI_URI::uri_to_assoc(), only it uses the re-routed - * segment array. - * - * @see CI_URI::uri_to_assoc() - * @param int $n Index (default: 3) - * @param array $default Default values - * @return array - */ - public function ruri_to_assoc($n = 3, $default = array()) - { - return $this->_uri_to_assoc($n, $default, 'rsegment'); - } - - // -------------------------------------------------------------------- - - /** - * Internal URI-to-assoc - * - * Generates a key/value pair from the URI string or re-routed URI string. - * - * @used-by CI_URI::uri_to_assoc() - * @used-by CI_URI::ruri_to_assoc() - * @param int $n Index (default: 3) - * @param array $default Default values - * @param string $which Array name ('segment' or 'rsegment') - * @return array - */ - protected function _uri_to_assoc($n = 3, $default = array(), $which = 'segment') - { - if ( ! is_numeric($n)) - { - return $default; - } - - if (isset($this->keyval[$which], $this->keyval[$which][$n])) - { - return $this->keyval[$which][$n]; - } - - $total_segments = "total_{$which}s"; - $segment_array = "{$which}_array"; - - if ($this->$total_segments() < $n) - { - return (count($default) === 0) - ? array() - : array_fill_keys($default, NULL); - } - - $segments = array_slice($this->$segment_array(), ($n - 1)); - $i = 0; - $lastval = ''; - $retval = array(); - foreach ($segments as $seg) - { - if ($i % 2) - { - $retval[$lastval] = $seg; - } - else - { - $retval[$seg] = NULL; - $lastval = $seg; - } - - $i++; - } - - if (count($default) > 0) - { - foreach ($default as $val) - { - if ( ! array_key_exists($val, $retval)) - { - $retval[$val] = NULL; - } - } - } - - // Cache the array for reuse - isset($this->keyval[$which]) OR $this->keyval[$which] = array(); - $this->keyval[$which][$n] = $retval; - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Assoc to URI - * - * Generates a URI string from an associative array. - * - * @param array $array Input array of key/value pairs - * @return string URI string - */ - public function assoc_to_uri($array) - { - $temp = array(); - foreach ((array) $array as $key => $val) - { - $temp[] = $key; - $temp[] = $val; - } - - return implode('/', $temp); - } - - // -------------------------------------------------------------------- - - /** - * Slash segment - * - * Fetches an URI segment with a slash. - * - * @param int $n Index - * @param string $where Where to add the slash ('trailing' or 'leading') - * @return string - */ - public function slash_segment($n, $where = 'trailing') - { - return $this->_slash_segment($n, $where, 'segment'); - } - - // -------------------------------------------------------------------- - - /** - * Slash routed segment - * - * Fetches an URI routed segment with a slash. - * - * @param int $n Index - * @param string $where Where to add the slash ('trailing' or 'leading') - * @return string - */ - public function slash_rsegment($n, $where = 'trailing') - { - return $this->_slash_segment($n, $where, 'rsegment'); - } - - // -------------------------------------------------------------------- - - /** - * Internal Slash segment - * - * Fetches an URI Segment and adds a slash to it. - * - * @used-by CI_URI::slash_segment() - * @used-by CI_URI::slash_rsegment() - * - * @param int $n Index - * @param string $where Where to add the slash ('trailing' or 'leading') - * @param string $which Array name ('segment' or 'rsegment') - * @return string - */ - protected function _slash_segment($n, $where = 'trailing', $which = 'segment') - { - $leading = $trailing = '/'; - - if ($where === 'trailing') - { - $leading = ''; - } - elseif ($where === 'leading') - { - $trailing = ''; - } - - return $leading.$this->$which($n).$trailing; - } - - // -------------------------------------------------------------------- - - /** - * Segment Array - * - * @return array CI_URI::$segments - */ - public function segment_array() - { - return $this->segments; - } - - // -------------------------------------------------------------------- - - /** - * Routed Segment Array - * - * @return array CI_URI::$rsegments - */ - public function rsegment_array() - { - return $this->rsegments; - } - - // -------------------------------------------------------------------- - - /** - * Total number of segments - * - * @return int - */ - public function total_segments() - { - return count($this->segments); - } - - // -------------------------------------------------------------------- - - /** - * Total number of routed segments - * - * @return int - */ - public function total_rsegments() - { - return count($this->rsegments); - } - - // -------------------------------------------------------------------- - - /** - * Fetch URI string - * - * @return string CI_URI::$uri_string - */ - public function uri_string() - { - return $this->uri_string; - } - - // -------------------------------------------------------------------- - - /** - * Fetch Re-routed URI string - * - * @return string - */ - public function ruri_string() - { - return ltrim(load_class('Router', 'core')->directory, '/').implode('/', $this->rsegments); - } - -} diff --git a/system/core/Utf8.php b/system/core/Utf8.php deleted file mode 100644 index 7e02177..0000000 --- a/system/core/Utf8.php +++ /dev/null @@ -1,164 +0,0 @@ -is_ascii($str) === FALSE) - { - if (MB_ENABLED) - { - $str = mb_convert_encoding($str, 'UTF-8', 'UTF-8'); - } - elseif (ICONV_ENABLED) - { - $str = @iconv('UTF-8', 'UTF-8//IGNORE', $str); - } - } - - return $str; - } - - // -------------------------------------------------------------------- - - /** - * Remove ASCII control characters - * - * Removes all ASCII control characters except horizontal tabs, - * line feeds, and carriage returns, as all others can cause - * problems in XML. - * - * @param string $str String to clean - * @return string - */ - public function safe_ascii_for_xml($str) - { - return remove_invisible_characters($str, FALSE); - } - - // -------------------------------------------------------------------- - - /** - * Convert to UTF-8 - * - * Attempts to convert a string to UTF-8. - * - * @param string $str Input string - * @param string $encoding Input encoding - * @return string $str encoded in UTF-8 or FALSE on failure - */ - public function convert_to_utf8($str, $encoding) - { - if (MB_ENABLED) - { - return mb_convert_encoding($str, 'UTF-8', $encoding); - } - elseif (ICONV_ENABLED) - { - return @iconv($encoding, 'UTF-8', $str); - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Is ASCII? - * - * Tests if a string is standard 7-bit ASCII or not. - * - * @param string $str String to check - * @return bool - */ - public function is_ascii($str) - { - return (preg_match('/[^\x00-\x7F]/S', $str) === 0); - } - -} diff --git a/system/core/compat/hash.php b/system/core/compat/hash.php deleted file mode 100644 index 68a8129..0000000 --- a/system/core/compat/hash.php +++ /dev/null @@ -1,254 +0,0 @@ - 32, - 'haval128,3' => 128, - 'haval160,3' => 128, - 'haval192,3' => 128, - 'haval224,3' => 128, - 'haval256,3' => 128, - 'haval128,4' => 128, - 'haval160,4' => 128, - 'haval192,4' => 128, - 'haval224,4' => 128, - 'haval256,4' => 128, - 'haval128,5' => 128, - 'haval160,5' => 128, - 'haval192,5' => 128, - 'haval224,5' => 128, - 'haval256,5' => 128, - 'md2' => 16, - 'md4' => 64, - 'md5' => 64, - 'ripemd128' => 64, - 'ripemd160' => 64, - 'ripemd256' => 64, - 'ripemd320' => 64, - 'salsa10' => 64, - 'salsa20' => 64, - 'sha1' => 64, - 'sha224' => 64, - 'sha256' => 64, - 'sha384' => 128, - 'sha512' => 128, - 'snefru' => 32, - 'snefru256' => 32, - 'tiger128,3' => 64, - 'tiger160,3' => 64, - 'tiger192,3' => 64, - 'tiger128,4' => 64, - 'tiger160,4' => 64, - 'tiger192,4' => 64, - 'whirlpool' => 64 - ); - - if (isset($block_sizes[$algo], $password[$block_sizes[$algo]])) - { - $password = hash($algo, $password, TRUE); - } - - $hash = ''; - // Note: Blocks are NOT 0-indexed - for ($bc = (int) ceil($length / $hash_length), $bi = 1; $bi <= $bc; $bi++) - { - $key = $derived_key = hash_hmac($algo, $salt.pack('N', $bi), $password, TRUE); - for ($i = 1; $i < $iterations; $i++) - { - $derived_key ^= $key = hash_hmac($algo, $key, $password, TRUE); - } - - $hash .= $derived_key; - } - - // This is not RFC-compatible, but we're aiming for natural PHP compatibility - if ( ! $raw_output) - { - $hash = bin2hex($hash); - } - - return defined('MB_OVERLOAD_STRING') - ? mb_substr($hash, 0, $length, '8bit') - : substr($hash, 0, $length); - } -} diff --git a/system/core/compat/index.html b/system/core/compat/index.html deleted file mode 100644 index b702fbc..0000000 --- a/system/core/compat/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - 403 Forbidden - - - -

Directory access is forbidden.

- - - diff --git a/system/core/compat/mbstring.php b/system/core/compat/mbstring.php deleted file mode 100644 index 9f6c24e..0000000 --- a/system/core/compat/mbstring.php +++ /dev/null @@ -1,149 +0,0 @@ - 0, 'algoName' => 'unknown', 'options' => array()) - : array('algo' => 1, 'algoName' => 'bcrypt', 'options' => array('cost' => $hash)); - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('password_hash')) -{ - /** - * password_hash() - * - * @link http://php.net/password_hash - * @param string $password - * @param int $algo - * @param array $options - * @return mixed - */ - function password_hash($password, $algo, array $options = array()) - { - static $func_overload; - isset($func_overload) OR $func_overload = (extension_loaded('mbstring') && ini_get('mbstring.func_overload')); - - if ($algo !== 1) - { - trigger_error('password_hash(): Unknown hashing algorithm: '.(int) $algo, E_USER_WARNING); - return NULL; - } - - if (isset($options['cost']) && ($options['cost'] < 4 OR $options['cost'] > 31)) - { - trigger_error('password_hash(): Invalid bcrypt cost parameter specified: '.(int) $options['cost'], E_USER_WARNING); - return NULL; - } - - if (isset($options['salt']) && ($saltlen = ($func_overload ? mb_strlen($options['salt'], '8bit') : strlen($options['salt']))) < 22) - { - trigger_error('password_hash(): Provided salt is too short: '.$saltlen.' expecting 22', E_USER_WARNING); - return NULL; - } - elseif ( ! isset($options['salt'])) - { - if (function_exists('random_bytes')) - { - try - { - $options['salt'] = random_bytes(16); - } - catch (Exception $e) - { - log_message('error', 'compat/password: Error while trying to use random_bytes(): '.$e->getMessage()); - return FALSE; - } - } - elseif (defined('MCRYPT_DEV_URANDOM')) - { - $options['salt'] = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM); - } - elseif (DIRECTORY_SEPARATOR === '/' && (is_readable($dev = '/dev/arandom') OR is_readable($dev = '/dev/urandom'))) - { - if (($fp = fopen($dev, 'rb')) === FALSE) - { - log_message('error', 'compat/password: Unable to open '.$dev.' for reading.'); - return FALSE; - } - - // Try not to waste entropy ... - is_php('5.4') && stream_set_chunk_size($fp, 16); - - $options['salt'] = ''; - for ($read = 0; $read < 16; $read = ($func_overload) ? mb_strlen($options['salt'], '8bit') : strlen($options['salt'])) - { - if (($read = fread($fp, 16 - $read)) === FALSE) - { - log_message('error', 'compat/password: Error while reading from '.$dev.'.'); - return FALSE; - } - $options['salt'] .= $read; - } - - fclose($fp); - } - elseif (function_exists('openssl_random_pseudo_bytes')) - { - $is_secure = NULL; - $options['salt'] = openssl_random_pseudo_bytes(16, $is_secure); - if ($is_secure !== TRUE) - { - log_message('error', 'compat/password: openssl_random_pseudo_bytes() set the $cryto_strong flag to FALSE'); - return FALSE; - } - } - else - { - log_message('error', 'compat/password: No CSPRNG available.'); - return FALSE; - } - - $options['salt'] = str_replace('+', '.', rtrim(base64_encode($options['salt']), '=')); - } - elseif ( ! preg_match('#^[a-zA-Z0-9./]+$#D', $options['salt'])) - { - $options['salt'] = str_replace('+', '.', rtrim(base64_encode($options['salt']), '=')); - } - - isset($options['cost']) OR $options['cost'] = 10; - - return (strlen($password = crypt($password, sprintf('$2y$%02d$%s', $options['cost'], $options['salt']))) === 60) - ? $password - : FALSE; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('password_needs_rehash')) -{ - /** - * password_needs_rehash() - * - * @link http://php.net/password_needs_rehash - * @param string $hash - * @param int $algo - * @param array $options - * @return bool - */ - function password_needs_rehash($hash, $algo, array $options = array()) - { - $info = password_get_info($hash); - - if ($algo !== $info['algo']) - { - return TRUE; - } - elseif ($algo === 1) - { - $options['cost'] = isset($options['cost']) ? (int) $options['cost'] : 10; - return ($info['options']['cost'] !== $options['cost']); - } - - // Odd at first glance, but according to a comment in PHP's own unit tests, - // because it is an unknown algorithm - it's valid and therefore doesn't - // need rehashing. - return FALSE; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('password_verify')) -{ - /** - * password_verify() - * - * @link http://php.net/password_verify - * @param string $password - * @param string $hash - * @return bool - */ - function password_verify($password, $hash) - { - if (strlen($hash) !== 60 OR strlen($password = crypt($password, $hash)) !== 60) - { - return FALSE; - } - - $compare = 0; - for ($i = 0; $i < 60; $i++) - { - $compare |= (ord($password[$i]) ^ ord($hash[$i])); - } - - return ($compare === 0); - } -} diff --git a/system/core/compat/standard.php b/system/core/compat/standard.php deleted file mode 100644 index 24f3abc..0000000 --- a/system/core/compat/standard.php +++ /dev/null @@ -1,182 +0,0 @@ - - - - 403 Forbidden - - - -

Directory access is forbidden.

- - - diff --git a/system/database/DB.php b/system/database/DB.php deleted file mode 100644 index f58c2e8..0000000 --- a/system/database/DB.php +++ /dev/null @@ -1,218 +0,0 @@ -load->get_package_paths() as $path) - { - if ($path !== APPPATH) - { - if (file_exists($file_path = $path.'config/'.ENVIRONMENT.'/database.php')) - { - include($file_path); - } - elseif (file_exists($file_path = $path.'config/database.php')) - { - include($file_path); - } - } - } - } - - if ( ! isset($db) OR count($db) === 0) - { - show_error('No database connection settings were found in the database config file.'); - } - - if ($params !== '') - { - $active_group = $params; - } - - if ( ! isset($active_group)) - { - show_error('You have not specified a database connection group via $active_group in your config/database.php file.'); - } - elseif ( ! isset($db[$active_group])) - { - show_error('You have specified an invalid database connection group ('.$active_group.') in your config/database.php file.'); - } - - $params = $db[$active_group]; - } - elseif (is_string($params)) - { - /** - * Parse the URL from the DSN string - * Database settings can be passed as discreet - * parameters or as a data source name in the first - * parameter. DSNs must have this prototype: - * $dsn = 'driver://username:password@hostname/database'; - */ - if (($dsn = @parse_url($params)) === FALSE) - { - show_error('Invalid DB Connection String'); - } - - $params = array( - 'dbdriver' => $dsn['scheme'], - 'hostname' => isset($dsn['host']) ? rawurldecode($dsn['host']) : '', - 'port' => isset($dsn['port']) ? rawurldecode($dsn['port']) : '', - 'username' => isset($dsn['user']) ? rawurldecode($dsn['user']) : '', - 'password' => isset($dsn['pass']) ? rawurldecode($dsn['pass']) : '', - 'database' => isset($dsn['path']) ? rawurldecode(substr($dsn['path'], 1)) : '' - ); - - // Were additional config items set? - if (isset($dsn['query'])) - { - parse_str($dsn['query'], $extra); - - foreach ($extra as $key => $val) - { - if (is_string($val) && in_array(strtoupper($val), array('TRUE', 'FALSE', 'NULL'))) - { - $val = var_export($val, TRUE); - } - - $params[$key] = $val; - } - } - } - - // No DB specified yet? Beat them senseless... - if (empty($params['dbdriver'])) - { - show_error('You have not selected a database type to connect to.'); - } - - // Load the DB classes. Note: Since the query builder class is optional - // we need to dynamically create a class that extends proper parent class - // based on whether we're using the query builder class or not. - if ($query_builder_override !== NULL) - { - $query_builder = $query_builder_override; - } - // Backwards compatibility work-around for keeping the - // $active_record config variable working. Should be - // removed in v3.1 - elseif ( ! isset($query_builder) && isset($active_record)) - { - $query_builder = $active_record; - } - - require_once(BASEPATH.'database/DB_driver.php'); - - if ( ! isset($query_builder) OR $query_builder === TRUE) - { - require_once(BASEPATH.'database/DB_query_builder.php'); - if ( ! class_exists('CI_DB', FALSE)) - { - /** - * CI_DB - * - * Acts as an alias for both CI_DB_driver and CI_DB_query_builder. - * - * @see CI_DB_query_builder - * @see CI_DB_driver - */ - class CI_DB extends CI_DB_query_builder { } - } - } - elseif ( ! class_exists('CI_DB', FALSE)) - { - /** - * @ignore - */ - class CI_DB extends CI_DB_driver { } - } - - // Load the DB driver - $driver_file = BASEPATH.'database/drivers/'.$params['dbdriver'].'/'.$params['dbdriver'].'_driver.php'; - - file_exists($driver_file) OR show_error('Invalid DB driver'); - require_once($driver_file); - - // Instantiate the DB adapter - $driver = 'CI_DB_'.$params['dbdriver'].'_driver'; - $DB = new $driver($params); - - // Check for a subdriver - if ( ! empty($DB->subdriver)) - { - $driver_file = BASEPATH.'database/drivers/'.$DB->dbdriver.'/subdrivers/'.$DB->dbdriver.'_'.$DB->subdriver.'_driver.php'; - - if (file_exists($driver_file)) - { - require_once($driver_file); - $driver = 'CI_DB_'.$DB->dbdriver.'_'.$DB->subdriver.'_driver'; - $DB = new $driver($params); - } - } - - $DB->initialize(); - return $DB; -} diff --git a/system/database/DB_cache.php b/system/database/DB_cache.php deleted file mode 100644 index 56b7356..0000000 --- a/system/database/DB_cache.php +++ /dev/null @@ -1,221 +0,0 @@ -CI and load the file helper since we use it a lot - $this->CI =& get_instance(); - $this->db =& $db; - $this->CI->load->helper('file'); - - $this->check_path(); - } - - // -------------------------------------------------------------------- - - /** - * Set Cache Directory Path - * - * @param string $path Path to the cache directory - * @return bool - */ - public function check_path($path = '') - { - if ($path === '') - { - if ($this->db->cachedir === '') - { - return $this->db->cache_off(); - } - - $path = $this->db->cachedir; - } - - // Add a trailing slash to the path if needed - $path = realpath($path) - ? rtrim(realpath($path), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR - : rtrim($path, '/').'/'; - - if ( ! is_dir($path)) - { - log_message('debug', 'DB cache path error: '.$path); - - // If the path is wrong we'll turn off caching - return $this->db->cache_off(); - } - - if ( ! is_really_writable($path)) - { - log_message('debug', 'DB cache dir not writable: '.$path); - - // If the path is not really writable we'll turn off caching - return $this->db->cache_off(); - } - - $this->db->cachedir = $path; - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Retrieve a cached query - * - * The URI being requested will become the name of the cache sub-folder. - * An MD5 hash of the SQL statement will become the cache file name. - * - * @param string $sql - * @return string - */ - public function read($sql) - { - $segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1); - $segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2); - $filepath = $this->db->cachedir.$segment_one.'+'.$segment_two.'/'.md5($sql); - - if ( ! is_file($filepath) OR FALSE === ($cachedata = file_get_contents($filepath))) - { - return FALSE; - } - - return unserialize($cachedata); - } - - // -------------------------------------------------------------------- - - /** - * Write a query to a cache file - * - * @param string $sql - * @param object $object - * @return bool - */ - public function write($sql, $object) - { - $segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1); - $segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2); - $dir_path = $this->db->cachedir.$segment_one.'+'.$segment_two.'/'; - $filename = md5($sql); - - if ( ! is_dir($dir_path) && ! @mkdir($dir_path, 0750)) - { - return FALSE; - } - - if (write_file($dir_path.$filename, serialize($object)) === FALSE) - { - return FALSE; - } - - chmod($dir_path.$filename, 0640); - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Delete cache files within a particular directory - * - * @param string $segment_one - * @param string $segment_two - * @return void - */ - public function delete($segment_one = '', $segment_two = '') - { - if ($segment_one === '') - { - $segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1); - } - - if ($segment_two === '') - { - $segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2); - } - - $dir_path = $this->db->cachedir.$segment_one.'+'.$segment_two.'/'; - delete_files($dir_path, TRUE); - } - - // -------------------------------------------------------------------- - - /** - * Delete all existing cache files - * - * @return void - */ - public function delete_all() - { - delete_files($this->db->cachedir, TRUE, TRUE); - } - -} diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php deleted file mode 100644 index f8956f0..0000000 --- a/system/database/DB_driver.php +++ /dev/null @@ -1,1991 +0,0 @@ - $val) - { - $this->$key = $val; - } - } - - log_message('info', 'Database Driver Class Initialized'); - } - - // -------------------------------------------------------------------- - - /** - * Initialize Database Settings - * - * @return bool - */ - public function initialize() - { - /* If an established connection is available, then there's - * no need to connect and select the database. - * - * Depending on the database driver, conn_id can be either - * boolean TRUE, a resource or an object. - */ - if ($this->conn_id) - { - return TRUE; - } - - // ---------------------------------------------------------------- - - // Connect to the database and set the connection ID - $this->conn_id = $this->db_connect($this->pconnect); - - // No connection resource? Check if there is a failover else throw an error - if ( ! $this->conn_id) - { - // Check if there is a failover set - if ( ! empty($this->failover) && is_array($this->failover)) - { - // Go over all the failovers - foreach ($this->failover as $failover) - { - // Replace the current settings with those of the failover - foreach ($failover as $key => $val) - { - $this->$key = $val; - } - - // Try to connect - $this->conn_id = $this->db_connect($this->pconnect); - - // If a connection is made break the foreach loop - if ($this->conn_id) - { - break; - } - } - } - - // We still don't have a connection? - if ( ! $this->conn_id) - { - log_message('error', 'Unable to connect to the database'); - - if ($this->db_debug) - { - $this->display_error('db_unable_to_connect'); - } - - return FALSE; - } - } - - // Now we set the character set and that's all - return $this->db_set_charset($this->char_set); - } - - // -------------------------------------------------------------------- - - /** - * DB connect - * - * This is just a dummy method that all drivers will override. - * - * @return mixed - */ - public function db_connect() - { - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Persistent database connection - * - * @return mixed - */ - public function db_pconnect() - { - return $this->db_connect(TRUE); - } - - // -------------------------------------------------------------------- - - /** - * Reconnect - * - * Keep / reestablish the db connection if no queries have been - * sent for a length of time exceeding the server's idle timeout. - * - * This is just a dummy method to allow drivers without such - * functionality to not declare it, while others will override it. - * - * @return void - */ - public function reconnect() - { - } - - // -------------------------------------------------------------------- - - /** - * Select database - * - * This is just a dummy method to allow drivers without such - * functionality to not declare it, while others will override it. - * - * @return bool - */ - public function db_select() - { - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Last error - * - * @return array - */ - public function error() - { - return array('code' => NULL, 'message' => NULL); - } - - // -------------------------------------------------------------------- - - /** - * Set client character set - * - * @param string - * @return bool - */ - public function db_set_charset($charset) - { - if (method_exists($this, '_db_set_charset') && ! $this->_db_set_charset($charset)) - { - log_message('error', 'Unable to set database connection charset: '.$charset); - - if ($this->db_debug) - { - $this->display_error('db_unable_to_set_charset', $charset); - } - - return FALSE; - } - - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * The name of the platform in use (mysql, mssql, etc...) - * - * @return string - */ - public function platform() - { - return $this->dbdriver; - } - - // -------------------------------------------------------------------- - - /** - * Database version number - * - * Returns a string containing the version of the database being used. - * Most drivers will override this method. - * - * @return string - */ - public function version() - { - if (isset($this->data_cache['version'])) - { - return $this->data_cache['version']; - } - - if (FALSE === ($sql = $this->_version())) - { - return ($this->db_debug) ? $this->display_error('db_unsupported_function') : FALSE; - } - - $query = $this->query($sql)->row(); - return $this->data_cache['version'] = $query->ver; - } - - // -------------------------------------------------------------------- - - /** - * Version number query string - * - * @return string - */ - protected function _version() - { - return 'SELECT VERSION() AS ver'; - } - - // -------------------------------------------------------------------- - - /** - * Execute the query - * - * Accepts an SQL string as input and returns a result object upon - * successful execution of a "read" type query. Returns boolean TRUE - * upon successful execution of a "write" type query. Returns boolean - * FALSE upon failure, and if the $db_debug variable is set to TRUE - * will raise an error. - * - * @param string $sql - * @param array $binds = FALSE An array of binding data - * @param bool $return_object = NULL - * @return mixed - */ - public function query($sql, $binds = FALSE, $return_object = NULL) - { - if ($sql === '') - { - log_message('error', 'Invalid query: '.$sql); - return ($this->db_debug) ? $this->display_error('db_invalid_query') : FALSE; - } - elseif ( ! is_bool($return_object)) - { - $return_object = ! $this->is_write_type($sql); - } - - // Verify table prefix and replace if necessary - if ($this->dbprefix !== '' && $this->swap_pre !== '' && $this->dbprefix !== $this->swap_pre) - { - $sql = preg_replace('/(\W)'.$this->swap_pre.'(\S+?)/', '\\1'.$this->dbprefix.'\\2', $sql); - } - - // Compile binds if needed - if ($binds !== FALSE) - { - $sql = $this->compile_binds($sql, $binds); - } - - // Is query caching enabled? If the query is a "read type" - // we will load the caching class and return the previously - // cached query if it exists - if ($this->cache_on === TRUE && $return_object === TRUE && $this->_cache_init()) - { - $this->load_rdriver(); - if (FALSE !== ($cache = $this->CACHE->read($sql))) - { - return $cache; - } - } - - // Save the query for debugging - if ($this->save_queries === TRUE) - { - $this->queries[] = $sql; - } - - // Start the Query Timer - $time_start = microtime(TRUE); - - // Run the Query - if (FALSE === ($this->result_id = $this->simple_query($sql))) - { - if ($this->save_queries === TRUE) - { - $this->query_times[] = 0; - } - - // This will trigger a rollback if transactions are being used - if ($this->_trans_depth !== 0) - { - $this->_trans_status = FALSE; - } - - // Grab the error now, as we might run some additional queries before displaying the error - $error = $this->error(); - - // Log errors - log_message('error', 'Query error: '.$error['message'].' - Invalid query: '.$sql); - - if ($this->db_debug) - { - // We call this function in order to roll-back queries - // if transactions are enabled. If we don't call this here - // the error message will trigger an exit, causing the - // transactions to remain in limbo. - while ($this->_trans_depth !== 0) - { - $trans_depth = $this->_trans_depth; - $this->trans_complete(); - if ($trans_depth === $this->_trans_depth) - { - log_message('error', 'Database: Failure during an automated transaction commit/rollback!'); - break; - } - } - - // Display errors - return $this->display_error(array('Error Number: '.$error['code'], $error['message'], $sql)); - } - - return FALSE; - } - - // Stop and aggregate the query time results - $time_end = microtime(TRUE); - $this->benchmark += $time_end - $time_start; - - if ($this->save_queries === TRUE) - { - $this->query_times[] = $time_end - $time_start; - } - - // Increment the query counter - $this->query_count++; - - // Will we have a result object instantiated? If not - we'll simply return TRUE - if ($return_object !== TRUE) - { - // If caching is enabled we'll auto-cleanup any existing files related to this particular URI - if ($this->cache_on === TRUE && $this->cache_autodel === TRUE && $this->_cache_init()) - { - $this->CACHE->delete(); - } - - return TRUE; - } - - // Load and instantiate the result driver - $driver = $this->load_rdriver(); - $RES = new $driver($this); - - // Is query caching enabled? If so, we'll serialize the - // result object and save it to a cache file. - if ($this->cache_on === TRUE && $this->_cache_init()) - { - // We'll create a new instance of the result object - // only without the platform specific driver since - // we can't use it with cached data (the query result - // resource ID won't be any good once we've cached the - // result object, so we'll have to compile the data - // and save it) - $CR = new CI_DB_result($this); - $CR->result_object = $RES->result_object(); - $CR->result_array = $RES->result_array(); - $CR->num_rows = $RES->num_rows(); - - // Reset these since cached objects can not utilize resource IDs. - $CR->conn_id = NULL; - $CR->result_id = NULL; - - $this->CACHE->write($sql, $CR); - } - - return $RES; - } - - // -------------------------------------------------------------------- - - /** - * Load the result drivers - * - * @return string the name of the result class - */ - public function load_rdriver() - { - $driver = 'CI_DB_'.$this->dbdriver.'_result'; - - if ( ! class_exists($driver, FALSE)) - { - require_once(BASEPATH.'database/DB_result.php'); - require_once(BASEPATH.'database/drivers/'.$this->dbdriver.'/'.$this->dbdriver.'_result.php'); - } - - return $driver; - } - - // -------------------------------------------------------------------- - - /** - * Simple Query - * This is a simplified version of the query() function. Internally - * we only use it when running transaction commands since they do - * not require all the features of the main query() function. - * - * @param string the sql query - * @return mixed - */ - public function simple_query($sql) - { - if ( ! $this->conn_id) - { - if ( ! $this->initialize()) - { - return FALSE; - } - } - - return $this->_execute($sql); - } - - // -------------------------------------------------------------------- - - /** - * Disable Transactions - * This permits transactions to be disabled at run-time. - * - * @return void - */ - public function trans_off() - { - $this->trans_enabled = FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Enable/disable Transaction Strict Mode - * - * When strict mode is enabled, if you are running multiple groups of - * transactions, if one group fails all subsequent groups will be - * rolled back. - * - * If strict mode is disabled, each group is treated autonomously, - * meaning a failure of one group will not affect any others - * - * @param bool $mode = TRUE - * @return void - */ - public function trans_strict($mode = TRUE) - { - $this->trans_strict = is_bool($mode) ? $mode : TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Start Transaction - * - * @param bool $test_mode = FALSE - * @return bool - */ - public function trans_start($test_mode = FALSE) - { - if ( ! $this->trans_enabled) - { - return FALSE; - } - - return $this->trans_begin($test_mode); - } - - // -------------------------------------------------------------------- - - /** - * Complete Transaction - * - * @return bool - */ - public function trans_complete() - { - if ( ! $this->trans_enabled) - { - return FALSE; - } - - // The query() function will set this flag to FALSE in the event that a query failed - if ($this->_trans_status === FALSE OR $this->_trans_failure === TRUE) - { - $this->trans_rollback(); - - // If we are NOT running in strict mode, we will reset - // the _trans_status flag so that subsequent groups of - // transactions will be permitted. - if ($this->trans_strict === FALSE) - { - $this->_trans_status = TRUE; - } - - log_message('debug', 'DB Transaction Failure'); - return FALSE; - } - - return $this->trans_commit(); - } - - // -------------------------------------------------------------------- - - /** - * Lets you retrieve the transaction flag to determine if it has failed - * - * @return bool - */ - public function trans_status() - { - return $this->_trans_status; - } - - // -------------------------------------------------------------------- - - /** - * Begin Transaction - * - * @param bool $test_mode - * @return bool - */ - public function trans_begin($test_mode = FALSE) - { - if ( ! $this->trans_enabled) - { - return FALSE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - elseif ($this->_trans_depth > 0) - { - $this->_trans_depth++; - return TRUE; - } - - // Reset the transaction failure flag. - // If the $test_mode flag is set to TRUE transactions will be rolled back - // even if the queries produce a successful result. - $this->_trans_failure = ($test_mode === TRUE); - - if ($this->_trans_begin()) - { - $this->_trans_status = TRUE; - $this->_trans_depth++; - return TRUE; - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Commit Transaction - * - * @return bool - */ - public function trans_commit() - { - if ( ! $this->trans_enabled OR $this->_trans_depth === 0) - { - return FALSE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - elseif ($this->_trans_depth > 1 OR $this->_trans_commit()) - { - $this->_trans_depth--; - return TRUE; - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Rollback Transaction - * - * @return bool - */ - public function trans_rollback() - { - if ( ! $this->trans_enabled OR $this->_trans_depth === 0) - { - return FALSE; - } - // When transactions are nested we only begin/commit/rollback the outermost ones - elseif ($this->_trans_depth > 1 OR $this->_trans_rollback()) - { - $this->_trans_depth--; - return TRUE; - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Compile Bindings - * - * @param string the sql statement - * @param array an array of bind data - * @return string - */ - public function compile_binds($sql, $binds) - { - if (empty($this->bind_marker) OR strpos($sql, $this->bind_marker) === FALSE) - { - return $sql; - } - elseif ( ! is_array($binds)) - { - $binds = array($binds); - $bind_count = 1; - } - else - { - // Make sure we're using numeric keys - $binds = array_values($binds); - $bind_count = count($binds); - } - - // We'll need the marker length later - $ml = strlen($this->bind_marker); - - // Make sure not to replace a chunk inside a string that happens to match the bind marker - if ($c = preg_match_all("/'[^']*'|\"[^\"]*\"/i", $sql, $matches)) - { - $c = preg_match_all('/'.preg_quote($this->bind_marker, '/').'/i', - str_replace($matches[0], - str_replace($this->bind_marker, str_repeat(' ', $ml), $matches[0]), - $sql, $c), - $matches, PREG_OFFSET_CAPTURE); - - // Bind values' count must match the count of markers in the query - if ($bind_count !== $c) - { - return $sql; - } - } - elseif (($c = preg_match_all('/'.preg_quote($this->bind_marker, '/').'/i', $sql, $matches, PREG_OFFSET_CAPTURE)) !== $bind_count) - { - return $sql; - } - - do - { - $c--; - $escaped_value = $this->escape($binds[$c]); - if (is_array($escaped_value)) - { - $escaped_value = '('.implode(',', $escaped_value).')'; - } - $sql = substr_replace($sql, $escaped_value, $matches[0][$c][1], $ml); - } - while ($c !== 0); - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Determines if a query is a "write" type. - * - * @param string An SQL query string - * @return bool - */ - public function is_write_type($sql) - { - return (bool) preg_match('/^\s*"?(SET|INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX|MERGE)\s/i', $sql); - } - - // -------------------------------------------------------------------- - - /** - * Calculate the aggregate query elapsed time - * - * @param int The number of decimal places - * @return string - */ - public function elapsed_time($decimals = 6) - { - return number_format($this->benchmark, $decimals); - } - - // -------------------------------------------------------------------- - - /** - * Returns the total number of queries - * - * @return int - */ - public function total_queries() - { - return $this->query_count; - } - - // -------------------------------------------------------------------- - - /** - * Returns the last query that was executed - * - * @return string - */ - public function last_query() - { - return end($this->queries); - } - - // -------------------------------------------------------------------- - - /** - * "Smart" Escape String - * - * Escapes data based on type - * Sets boolean and null types - * - * @param string - * @return mixed - */ - public function escape($str) - { - if (is_array($str)) - { - $str = array_map(array(&$this, 'escape'), $str); - return $str; - } - elseif (is_string($str) OR (is_object($str) && method_exists($str, '__toString'))) - { - return "'".$this->escape_str($str)."'"; - } - elseif (is_bool($str)) - { - return ($str === FALSE) ? 0 : 1; - } - elseif ($str === NULL) - { - return 'NULL'; - } - - return $str; - } - - // -------------------------------------------------------------------- - - /** - * Escape String - * - * @param string|string[] $str Input string - * @param bool $like Whether or not the string will be used in a LIKE condition - * @return string - */ - public function escape_str($str, $like = FALSE) - { - if (is_array($str)) - { - foreach ($str as $key => $val) - { - $str[$key] = $this->escape_str($val, $like); - } - - return $str; - } - - $str = $this->_escape_str($str); - - // escape LIKE condition wildcards - if ($like === TRUE) - { - return str_replace( - array($this->_like_escape_chr, '%', '_'), - array($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'), - $str - ); - } - - return $str; - } - - // -------------------------------------------------------------------- - - /** - * Escape LIKE String - * - * Calls the individual driver for platform - * specific escaping for LIKE conditions - * - * @param string|string[] - * @return mixed - */ - public function escape_like_str($str) - { - return $this->escape_str($str, TRUE); - } - - // -------------------------------------------------------------------- - - /** - * Platform-dependent string escape - * - * @param string - * @return string - */ - protected function _escape_str($str) - { - return str_replace("'", "''", remove_invisible_characters($str, FALSE)); - } - - // -------------------------------------------------------------------- - - /** - * Primary - * - * Retrieves the primary key. It assumes that the row in the first - * position is the primary key - * - * @param string $table Table name - * @return string - */ - public function primary($table) - { - $fields = $this->list_fields($table); - return is_array($fields) ? current($fields) : FALSE; - } - - // -------------------------------------------------------------------- - - /** - * "Count All" query - * - * Generates a platform-specific query string that counts all records in - * the specified database - * - * @param string - * @return int - */ - public function count_all($table = '') - { - if ($table === '') - { - return 0; - } - - $query = $this->query($this->_count_string.$this->escape_identifiers('numrows').' FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE)); - if ($query->num_rows() === 0) - { - return 0; - } - - $query = $query->row(); - $this->_reset_select(); - return (int) $query->numrows; - } - - // -------------------------------------------------------------------- - - /** - * Returns an array of table names - * - * @param string $constrain_by_prefix = FALSE - * @return array - */ - public function list_tables($constrain_by_prefix = FALSE) - { - // Is there a cached result? - if (isset($this->data_cache['table_names'])) - { - return $this->data_cache['table_names']; - } - - if (FALSE === ($sql = $this->_list_tables($constrain_by_prefix))) - { - return ($this->db_debug) ? $this->display_error('db_unsupported_function') : FALSE; - } - - $this->data_cache['table_names'] = array(); - $query = $this->query($sql); - - foreach ($query->result_array() as $row) - { - // Do we know from which column to get the table name? - if ( ! isset($key)) - { - if (isset($row['table_name'])) - { - $key = 'table_name'; - } - elseif (isset($row['TABLE_NAME'])) - { - $key = 'TABLE_NAME'; - } - else - { - /* We have no other choice but to just get the first element's key. - * Due to array_shift() accepting its argument by reference, if - * E_STRICT is on, this would trigger a warning. So we'll have to - * assign it first. - */ - $key = array_keys($row); - $key = array_shift($key); - } - } - - $this->data_cache['table_names'][] = $row[$key]; - } - - return $this->data_cache['table_names']; - } - - // -------------------------------------------------------------------- - - /** - * Determine if a particular table exists - * - * @param string $table_name - * @return bool - */ - public function table_exists($table_name) - { - return in_array($this->protect_identifiers($table_name, TRUE, FALSE, FALSE), $this->list_tables()); - } - - // -------------------------------------------------------------------- - - /** - * Fetch Field Names - * - * @param string $table Table name - * @return array - */ - public function list_fields($table) - { - // Is there a cached result? - if (isset($this->data_cache['field_names'][$table])) - { - return $this->data_cache['field_names'][$table]; - } - - if (FALSE === ($sql = $this->_list_columns($table))) - { - return ($this->db_debug) ? $this->display_error('db_unsupported_function') : FALSE; - } - - $query = $this->query($sql); - $this->data_cache['field_names'][$table] = array(); - - foreach ($query->result_array() as $row) - { - // Do we know from where to get the column's name? - if ( ! isset($key)) - { - if (isset($row['column_name'])) - { - $key = 'column_name'; - } - elseif (isset($row['COLUMN_NAME'])) - { - $key = 'COLUMN_NAME'; - } - else - { - // We have no other choice but to just get the first element's key. - $key = key($row); - } - } - - $this->data_cache['field_names'][$table][] = $row[$key]; - } - - return $this->data_cache['field_names'][$table]; - } - - // -------------------------------------------------------------------- - - /** - * Determine if a particular field exists - * - * @param string - * @param string - * @return bool - */ - public function field_exists($field_name, $table_name) - { - return in_array($field_name, $this->list_fields($table_name)); - } - - // -------------------------------------------------------------------- - - /** - * Returns an object with field data - * - * @param string $table the table name - * @return array - */ - public function field_data($table) - { - $query = $this->query($this->_field_data($this->protect_identifiers($table, TRUE, NULL, FALSE))); - return ($query) ? $query->field_data() : FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Escape the SQL Identifiers - * - * This function escapes column and table names - * - * @param mixed - * @return mixed - */ - public function escape_identifiers($item) - { - if ($this->_escape_char === '' OR empty($item) OR in_array($item, $this->_reserved_identifiers)) - { - return $item; - } - elseif (is_array($item)) - { - foreach ($item as $key => $value) - { - $item[$key] = $this->escape_identifiers($value); - } - - return $item; - } - // Avoid breaking functions and literal values inside queries - elseif (ctype_digit($item) OR $item[0] === "'" OR ($this->_escape_char !== '"' && $item[0] === '"') OR strpos($item, '(') !== FALSE) - { - return $item; - } - - static $preg_ec = array(); - - if (empty($preg_ec)) - { - if (is_array($this->_escape_char)) - { - $preg_ec = array( - preg_quote($this->_escape_char[0], '/'), - preg_quote($this->_escape_char[1], '/'), - $this->_escape_char[0], - $this->_escape_char[1] - ); - } - else - { - $preg_ec[0] = $preg_ec[1] = preg_quote($this->_escape_char, '/'); - $preg_ec[2] = $preg_ec[3] = $this->_escape_char; - } - } - - foreach ($this->_reserved_identifiers as $id) - { - if (strpos($item, '.'.$id) !== FALSE) - { - return preg_replace('/'.$preg_ec[0].'?([^'.$preg_ec[1].'\.]+)'.$preg_ec[1].'?\./i', $preg_ec[2].'$1'.$preg_ec[3].'.', $item); - } - } - - return preg_replace('/'.$preg_ec[0].'?([^'.$preg_ec[1].'\.]+)'.$preg_ec[1].'?(\.)?/i', $preg_ec[2].'$1'.$preg_ec[3].'$2', $item); - } - - // -------------------------------------------------------------------- - - /** - * Generate an insert string - * - * @param string the table upon which the query will be performed - * @param array an associative array data of key/values - * @return string - */ - public function insert_string($table, $data) - { - $fields = $values = array(); - - foreach ($data as $key => $val) - { - $fields[] = $this->escape_identifiers($key); - $values[] = $this->escape($val); - } - - return $this->_insert($this->protect_identifiers($table, TRUE, NULL, FALSE), $fields, $values); - } - - // -------------------------------------------------------------------- - - /** - * Insert statement - * - * Generates a platform-specific insert string from the supplied data - * - * @param string the table name - * @param array the insert keys - * @param array the insert values - * @return string - */ - protected function _insert($table, $keys, $values) - { - return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')'; - } - - // -------------------------------------------------------------------- - - /** - * Generate an update string - * - * @param string the table upon which the query will be performed - * @param array an associative array data of key/values - * @param mixed the "where" statement - * @return string - */ - public function update_string($table, $data, $where) - { - if (empty($where)) - { - return FALSE; - } - - $this->where($where); - - $fields = array(); - foreach ($data as $key => $val) - { - $fields[$this->protect_identifiers($key)] = $this->escape($val); - } - - $sql = $this->_update($this->protect_identifiers($table, TRUE, NULL, FALSE), $fields); - $this->_reset_write(); - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Update statement - * - * Generates a platform-specific update string from the supplied data - * - * @param string the table name - * @param array the update data - * @return string - */ - protected function _update($table, $values) - { - foreach ($values as $key => $val) - { - $valstr[] = $key.' = '.$val; - } - - return 'UPDATE '.$table.' SET '.implode(', ', $valstr) - .$this->_compile_wh('qb_where') - .$this->_compile_order_by() - .($this->qb_limit !== FALSE ? ' LIMIT '.$this->qb_limit : ''); - } - - // -------------------------------------------------------------------- - - /** - * Tests whether the string has an SQL operator - * - * @param string - * @return bool - */ - protected function _has_operator($str) - { - return (bool) preg_match('/(<|>|!|=|\sIS NULL|\sIS NOT NULL|\sEXISTS|\sBETWEEN|\sLIKE|\sIN\s*\(|\s)/i', trim($str)); - } - - // -------------------------------------------------------------------- - - /** - * Returns the SQL string operator - * - * @param string - * @return string - */ - protected function _get_operator($str) - { - static $_operators; - - if (empty($_operators)) - { - $_les = ($this->_like_escape_str !== '') - ? '\s+'.preg_quote(trim(sprintf($this->_like_escape_str, $this->_like_escape_chr)), '/') - : ''; - $_operators = array( - '\s*(?:<|>|!)?=\s*', // =, <=, >=, != - '\s*<>?\s*', // <, <> - '\s*>\s*', // > - '\s+IS NULL', // IS NULL - '\s+IS NOT NULL', // IS NOT NULL - '\s+EXISTS\s*\(.*\)', // EXISTS(sql) - '\s+NOT EXISTS\s*\(.*\)', // NOT EXISTS(sql) - '\s+BETWEEN\s+', // BETWEEN value AND value - '\s+IN\s*\(.*\)', // IN(list) - '\s+NOT IN\s*\(.*\)', // NOT IN (list) - '\s+LIKE\s+\S.*('.$_les.')?', // LIKE 'expr'[ ESCAPE '%s'] - '\s+NOT LIKE\s+\S.*('.$_les.')?' // NOT LIKE 'expr'[ ESCAPE '%s'] - ); - - } - - return preg_match('/'.implode('|', $_operators).'/i', $str, $match) - ? $match[0] : FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Enables a native PHP function to be run, using a platform agnostic wrapper. - * - * @param string $function Function name - * @return mixed - */ - public function call_function($function) - { - $driver = ($this->dbdriver === 'postgre') ? 'pg_' : $this->dbdriver.'_'; - - if (FALSE === strpos($driver, $function)) - { - $function = $driver.$function; - } - - if ( ! function_exists($function)) - { - return ($this->db_debug) ? $this->display_error('db_unsupported_function') : FALSE; - } - - return (func_num_args() > 1) - ? call_user_func_array($function, array_slice(func_get_args(), 1)) - : call_user_func($function); - } - - // -------------------------------------------------------------------- - - /** - * Set Cache Directory Path - * - * @param string the path to the cache directory - * @return void - */ - public function cache_set_path($path = '') - { - $this->cachedir = $path; - } - - // -------------------------------------------------------------------- - - /** - * Enable Query Caching - * - * @return bool cache_on value - */ - public function cache_on() - { - return $this->cache_on = TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Disable Query Caching - * - * @return bool cache_on value - */ - public function cache_off() - { - return $this->cache_on = FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Delete the cache files associated with a particular URI - * - * @param string $segment_one = '' - * @param string $segment_two = '' - * @return bool - */ - public function cache_delete($segment_one = '', $segment_two = '') - { - return $this->_cache_init() - ? $this->CACHE->delete($segment_one, $segment_two) - : FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Delete All cache files - * - * @return bool - */ - public function cache_delete_all() - { - return $this->_cache_init() - ? $this->CACHE->delete_all() - : FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Initialize the Cache Class - * - * @return bool - */ - protected function _cache_init() - { - if ( ! class_exists('CI_DB_Cache', FALSE)) - { - require_once(BASEPATH.'database/DB_cache.php'); - } - elseif (is_object($this->CACHE)) - { - return TRUE; - } - - $this->CACHE = new CI_DB_Cache($this); // pass db object to support multiple db connections and returned db objects - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Close DB Connection - * - * @return void - */ - public function close() - { - if ($this->conn_id) - { - $this->_close(); - $this->conn_id = FALSE; - } - } - - // -------------------------------------------------------------------- - - /** - * Close DB Connection - * - * This method would be overridden by most of the drivers. - * - * @return void - */ - protected function _close() - { - $this->conn_id = FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Display an error message - * - * @param string the error message - * @param string any "swap" values - * @param bool whether to localize the message - * @return string sends the application/views/errors/error_db.php template - */ - public function display_error($error = '', $swap = '', $native = FALSE) - { - $LANG =& load_class('Lang', 'core'); - $LANG->load('db'); - - $heading = $LANG->line('db_error_heading'); - - if ($native === TRUE) - { - $message = (array) $error; - } - else - { - $message = is_array($error) ? $error : array(str_replace('%s', $swap, $LANG->line($error))); - } - - // Find the most likely culprit of the error by going through - // the backtrace until the source file is no longer in the - // database folder. - $trace = debug_backtrace(); - foreach ($trace as $call) - { - if (isset($call['file'], $call['class'])) - { - // We'll need this on Windows, as APPPATH and BASEPATH will always use forward slashes - if (DIRECTORY_SEPARATOR !== '/') - { - $call['file'] = str_replace('\\', '/', $call['file']); - } - - if (strpos($call['file'], BASEPATH.'database') === FALSE && strpos($call['class'], 'Loader') === FALSE) - { - // Found it - use a relative path for safety - $message[] = 'Filename: '.str_replace(array(APPPATH, BASEPATH), '', $call['file']); - $message[] = 'Line Number: '.$call['line']; - break; - } - } - } - - $error =& load_class('Exceptions', 'core'); - echo $error->show_error($heading, $message, 'error_db'); - exit(8); // EXIT_DATABASE - } - - // -------------------------------------------------------------------- - - /** - * Protect Identifiers - * - * This function is used extensively by the Query Builder class, and by - * a couple functions in this class. - * It takes a column or table name (optionally with an alias) and inserts - * the table prefix onto it. Some logic is necessary in order to deal with - * column names that include the path. Consider a query like this: - * - * SELECT hostname.database.table.column AS c FROM hostname.database.table - * - * Or a query with aliasing: - * - * SELECT m.member_id, m.member_name FROM members AS m - * - * Since the column name can include up to four segments (host, DB, table, column) - * or also have an alias prefix, we need to do a bit of work to figure this out and - * insert the table prefix (if it exists) in the proper position, and escape only - * the correct identifiers. - * - * @param string - * @param bool - * @param mixed - * @param bool - * @return string - */ - public function protect_identifiers($item, $prefix_single = FALSE, $protect_identifiers = NULL, $field_exists = TRUE) - { - if ( ! is_bool($protect_identifiers)) - { - $protect_identifiers = $this->_protect_identifiers; - } - - if (is_array($item)) - { - $escaped_array = array(); - foreach ($item as $k => $v) - { - $escaped_array[$this->protect_identifiers($k)] = $this->protect_identifiers($v, $prefix_single, $protect_identifiers, $field_exists); - } - - return $escaped_array; - } - - // This is basically a bug fix for queries that use MAX, MIN, etc. - // If a parenthesis is found we know that we do not need to - // escape the data or add a prefix. There's probably a more graceful - // way to deal with this, but I'm not thinking of it -- Rick - // - // Added exception for single quotes as well, we don't want to alter - // literal strings. -- Narf - if (strcspn($item, "()'") !== strlen($item)) - { - return $item; - } - - // Convert tabs or multiple spaces into single spaces - $item = preg_replace('/\s+/', ' ', trim($item)); - - // If the item has an alias declaration we remove it and set it aside. - // Note: strripos() is used in order to support spaces in table names - if ($offset = strripos($item, ' AS ')) - { - $alias = ($protect_identifiers) - ? substr($item, $offset, 4).$this->escape_identifiers(substr($item, $offset + 4)) - : substr($item, $offset); - $item = substr($item, 0, $offset); - } - elseif ($offset = strrpos($item, ' ')) - { - $alias = ($protect_identifiers) - ? ' '.$this->escape_identifiers(substr($item, $offset + 1)) - : substr($item, $offset); - $item = substr($item, 0, $offset); - } - else - { - $alias = ''; - } - - // Break the string apart if it contains periods, then insert the table prefix - // in the correct location, assuming the period doesn't indicate that we're dealing - // with an alias. While we're at it, we will escape the components - if (strpos($item, '.') !== FALSE) - { - $parts = explode('.', $item); - - // Does the first segment of the exploded item match - // one of the aliases previously identified? If so, - // we have nothing more to do other than escape the item - // - // NOTE: The ! empty() condition prevents this method - // from breaking when QB isn't enabled. - if ( ! empty($this->qb_aliased_tables) && in_array($parts[0], $this->qb_aliased_tables)) - { - if ($protect_identifiers === TRUE) - { - foreach ($parts as $key => $val) - { - if ( ! in_array($val, $this->_reserved_identifiers)) - { - $parts[$key] = $this->escape_identifiers($val); - } - } - - $item = implode('.', $parts); - } - - return $item.$alias; - } - - // Is there a table prefix defined in the config file? If not, no need to do anything - if ($this->dbprefix !== '') - { - // We now add the table prefix based on some logic. - // Do we have 4 segments (hostname.database.table.column)? - // If so, we add the table prefix to the column name in the 3rd segment. - if (isset($parts[3])) - { - $i = 2; - } - // Do we have 3 segments (database.table.column)? - // If so, we add the table prefix to the column name in 2nd position - elseif (isset($parts[2])) - { - $i = 1; - } - // Do we have 2 segments (table.column)? - // If so, we add the table prefix to the column name in 1st segment - else - { - $i = 0; - } - - // This flag is set when the supplied $item does not contain a field name. - // This can happen when this function is being called from a JOIN. - if ($field_exists === FALSE) - { - $i++; - } - - // dbprefix may've already been applied, with or without the identifier escaped - $ec = '(?'.preg_quote(is_array($this->_escape_char) ? $this->_escape_char[0] : $this->_escape_char).')?'; - isset($ec[0]) && $ec .= '?'; // Just in case someone has disabled escaping by forcing an empty escape character - - // Verify table prefix and replace if necessary - if ($this->swap_pre !== '' && preg_match('#^'.$ec.preg_quote($this->swap_pre).'#', $parts[$i])) - { - $parts[$i] = preg_replace('#^'.$ec.preg_quote($this->swap_pre).'(\S+?)#', '\\1'.$this->dbprefix.'\\2', $parts[$i]); - } - // We only add the table prefix if it does not already exist - else - { - preg_match('#^'.$ec.preg_quote($this->dbprefix).'#', $parts[$i]) OR $parts[$i] = $this->dbprefix.$parts[$i]; - } - - // Put the parts back together - $item = implode('.', $parts); - } - - if ($protect_identifiers === TRUE) - { - $item = $this->escape_identifiers($item); - } - - return $item.$alias; - } - - // Is there a table prefix? If not, no need to insert it - if ($this->dbprefix !== '') - { - // Verify table prefix and replace if necessary - if ($this->swap_pre !== '' && strpos($item, $this->swap_pre) === 0) - { - $item = preg_replace('/^'.$this->swap_pre.'(\S+?)/', $this->dbprefix.'\\1', $item); - } - // Do we prefix an item with no segments? - elseif ($prefix_single === TRUE && strpos($item, $this->dbprefix) !== 0) - { - $item = $this->dbprefix.$item; - } - } - - if ($protect_identifiers === TRUE && ! in_array($item, $this->_reserved_identifiers)) - { - $item = $this->escape_identifiers($item); - } - - return $item.$alias; - } - - // -------------------------------------------------------------------- - - /** - * Dummy method that allows Query Builder class to be disabled - * and keep count_all() working. - * - * @return void - */ - protected function _reset_select() - { - } - -} diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php deleted file mode 100644 index d3057dc..0000000 --- a/system/database/DB_forge.php +++ /dev/null @@ -1,1030 +0,0 @@ -db =& $db; - log_message('info', 'Database Forge Class Initialized'); - } - - // -------------------------------------------------------------------- - - /** - * Create database - * - * @param string $db_name - * @return bool - */ - public function create_database($db_name) - { - if ($this->_create_database === FALSE) - { - return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE; - } - elseif ( ! $this->db->query(sprintf($this->_create_database, $this->db->escape_identifiers($db_name), $this->db->char_set, $this->db->dbcollat))) - { - return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE; - } - - if ( ! empty($this->db->data_cache['db_names'])) - { - $this->db->data_cache['db_names'][] = $db_name; - } - - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Drop database - * - * @param string $db_name - * @return bool - */ - public function drop_database($db_name) - { - if ($this->_drop_database === FALSE) - { - return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE; - } - elseif ( ! $this->db->query(sprintf($this->_drop_database, $this->db->escape_identifiers($db_name)))) - { - return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE; - } - - if ( ! empty($this->db->data_cache['db_names'])) - { - $key = array_search(strtolower($db_name), array_map('strtolower', $this->db->data_cache['db_names']), TRUE); - if ($key !== FALSE) - { - unset($this->db->data_cache['db_names'][$key]); - } - } - - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Add Key - * - * @param string $key - * @param bool $primary - * @return CI_DB_forge - */ - public function add_key($key, $primary = FALSE) - { - // DO NOT change this! This condition is only applicable - // for PRIMARY keys because you can only have one such, - // and therefore all fields you add to it will be included - // in the same, composite PRIMARY KEY. - // - // It's not the same for regular indexes. - if ($primary === TRUE && is_array($key)) - { - foreach ($key as $one) - { - $this->add_key($one, $primary); - } - - return $this; - } - - if ($primary === TRUE) - { - $this->primary_keys[] = $key; - } - else - { - $this->keys[] = $key; - } - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Add Field - * - * @param array $field - * @return CI_DB_forge - */ - public function add_field($field) - { - if (is_string($field)) - { - if ($field === 'id') - { - $this->add_field(array( - 'id' => array( - 'type' => 'INT', - 'constraint' => 9, - 'auto_increment' => TRUE - ) - )); - $this->add_key('id', TRUE); - } - else - { - if (strpos($field, ' ') === FALSE) - { - show_error('Field information is required for that operation.'); - } - - $this->fields[] = $field; - } - } - - if (is_array($field)) - { - $this->fields = array_merge($this->fields, $field); - } - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Create Table - * - * @param string $table Table name - * @param bool $if_not_exists Whether to add IF NOT EXISTS condition - * @param array $attributes Associative array of table attributes - * @return bool - */ - public function create_table($table, $if_not_exists = FALSE, array $attributes = array()) - { - if ($table === '') - { - show_error('A table name is required for that operation.'); - } - else - { - $table = $this->db->dbprefix.$table; - } - - if (count($this->fields) === 0) - { - show_error('Field information is required.'); - } - - $sql = $this->_create_table($table, $if_not_exists, $attributes); - - if (is_bool($sql)) - { - $this->_reset(); - if ($sql === FALSE) - { - return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE; - } - } - - if (($result = $this->db->query($sql)) !== FALSE) - { - isset($this->db->data_cache['table_names']) && $this->db->data_cache['table_names'][] = $table; - - // Most databases don't support creating indexes from within the CREATE TABLE statement - if ( ! empty($this->keys)) - { - for ($i = 0, $sqls = $this->_process_indexes($table), $c = count($sqls); $i < $c; $i++) - { - $this->db->query($sqls[$i]); - } - } - } - - $this->_reset(); - return $result; - } - - // -------------------------------------------------------------------- - - /** - * Create Table - * - * @param string $table Table name - * @param bool $if_not_exists Whether to add 'IF NOT EXISTS' condition - * @param array $attributes Associative array of table attributes - * @return mixed - */ - protected function _create_table($table, $if_not_exists, $attributes) - { - if ($if_not_exists === TRUE && $this->_create_table_if === FALSE) - { - if ($this->db->table_exists($table)) - { - return TRUE; - } - - $if_not_exists = FALSE; - } - - $sql = ($if_not_exists) - ? sprintf($this->_create_table_if, $this->db->escape_identifiers($table)) - : 'CREATE TABLE'; - - $columns = $this->_process_fields(TRUE); - for ($i = 0, $c = count($columns); $i < $c; $i++) - { - $columns[$i] = ($columns[$i]['_literal'] !== FALSE) - ? "\n\t".$columns[$i]['_literal'] - : "\n\t".$this->_process_column($columns[$i]); - } - - $columns = implode(',', $columns) - .$this->_process_primary_keys($table); - - // Are indexes created from within the CREATE TABLE statement? (e.g. in MySQL) - if ($this->_create_table_keys === TRUE) - { - $columns .= $this->_process_indexes($table); - } - - // _create_table will usually have the following format: "%s %s (%s\n)" - $sql = sprintf($this->_create_table.'%s', - $sql, - $this->db->escape_identifiers($table), - $columns, - $this->_create_table_attr($attributes) - ); - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * CREATE TABLE attributes - * - * @param array $attributes Associative array of table attributes - * @return string - */ - protected function _create_table_attr($attributes) - { - $sql = ''; - - foreach (array_keys($attributes) as $key) - { - if (is_string($key)) - { - $sql .= ' '.strtoupper($key).' '.$attributes[$key]; - } - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Drop Table - * - * @param string $table_name Table name - * @param bool $if_exists Whether to add an IF EXISTS condition - * @return bool - */ - public function drop_table($table_name, $if_exists = FALSE) - { - if ($table_name === '') - { - return ($this->db->db_debug) ? $this->db->display_error('db_table_name_required') : FALSE; - } - - if (($query = $this->_drop_table($this->db->dbprefix.$table_name, $if_exists)) === TRUE) - { - return TRUE; - } - - $query = $this->db->query($query); - - // Update table list cache - if ($query && ! empty($this->db->data_cache['table_names'])) - { - $key = array_search(strtolower($this->db->dbprefix.$table_name), array_map('strtolower', $this->db->data_cache['table_names']), TRUE); - if ($key !== FALSE) - { - unset($this->db->data_cache['table_names'][$key]); - } - } - - return $query; - } - - // -------------------------------------------------------------------- - - /** - * Drop Table - * - * Generates a platform-specific DROP TABLE string - * - * @param string $table Table name - * @param bool $if_exists Whether to add an IF EXISTS condition - * @return mixed (Returns a platform-specific DROP table string, or TRUE to indicate there's nothing to do) - */ - protected function _drop_table($table, $if_exists) - { - $sql = 'DROP TABLE'; - - if ($if_exists) - { - if ($this->_drop_table_if === FALSE) - { - if ( ! $this->db->table_exists($table)) - { - return TRUE; - } - } - else - { - $sql = sprintf($this->_drop_table_if, $this->db->escape_identifiers($table)); - } - } - - return $sql.' '.$this->db->escape_identifiers($table); - } - - // -------------------------------------------------------------------- - - /** - * Rename Table - * - * @param string $table_name Old table name - * @param string $new_table_name New table name - * @return bool - */ - public function rename_table($table_name, $new_table_name) - { - if ($table_name === '' OR $new_table_name === '') - { - show_error('A table name is required for that operation.'); - return FALSE; - } - elseif ($this->_rename_table === FALSE) - { - return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE; - } - - $result = $this->db->query(sprintf($this->_rename_table, - $this->db->escape_identifiers($this->db->dbprefix.$table_name), - $this->db->escape_identifiers($this->db->dbprefix.$new_table_name)) - ); - - if ($result && ! empty($this->db->data_cache['table_names'])) - { - $key = array_search(strtolower($this->db->dbprefix.$table_name), array_map('strtolower', $this->db->data_cache['table_names']), TRUE); - if ($key !== FALSE) - { - $this->db->data_cache['table_names'][$key] = $this->db->dbprefix.$new_table_name; - } - } - - return $result; - } - - // -------------------------------------------------------------------- - - /** - * Column Add - * - * @todo Remove deprecated $_after option in 3.1+ - * @param string $table Table name - * @param array $field Column definition - * @param string $_after Column for AFTER clause (deprecated) - * @return bool - */ - public function add_column($table, $field, $_after = NULL) - { - // Work-around for literal column definitions - is_array($field) OR $field = array($field); - - foreach (array_keys($field) as $k) - { - // Backwards-compatibility work-around for MySQL/CUBRID AFTER clause (remove in 3.1+) - if ($_after !== NULL && is_array($field[$k]) && ! isset($field[$k]['after'])) - { - $field[$k]['after'] = $_after; - } - - $this->add_field(array($k => $field[$k])); - } - - $sqls = $this->_alter_table('ADD', $this->db->dbprefix.$table, $this->_process_fields()); - $this->_reset(); - if ($sqls === FALSE) - { - return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE; - } - - for ($i = 0, $c = count($sqls); $i < $c; $i++) - { - if ($this->db->query($sqls[$i]) === FALSE) - { - return FALSE; - } - } - - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Column Drop - * - * @param string $table Table name - * @param string $column_name Column name - * @return bool - */ - public function drop_column($table, $column_name) - { - $sql = $this->_alter_table('DROP', $this->db->dbprefix.$table, $column_name); - if ($sql === FALSE) - { - return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE; - } - - return $this->db->query($sql); - } - - // -------------------------------------------------------------------- - - /** - * Column Modify - * - * @param string $table Table name - * @param string $field Column definition - * @return bool - */ - public function modify_column($table, $field) - { - // Work-around for literal column definitions - is_array($field) OR $field = array($field); - - foreach (array_keys($field) as $k) - { - $this->add_field(array($k => $field[$k])); - } - - if (count($this->fields) === 0) - { - show_error('Field information is required.'); - } - - $sqls = $this->_alter_table('CHANGE', $this->db->dbprefix.$table, $this->_process_fields()); - $this->_reset(); - if ($sqls === FALSE) - { - return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE; - } - - for ($i = 0, $c = count($sqls); $i < $c; $i++) - { - if ($this->db->query($sqls[$i]) === FALSE) - { - return FALSE; - } - } - - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * ALTER TABLE - * - * @param string $alter_type ALTER type - * @param string $table Table name - * @param mixed $field Column definition - * @return string|string[] - */ - protected function _alter_table($alter_type, $table, $field) - { - $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' '; - - // DROP has everything it needs now. - if ($alter_type === 'DROP') - { - return $sql.'DROP COLUMN '.$this->db->escape_identifiers($field); - } - - $sql .= ($alter_type === 'ADD') - ? 'ADD ' - : $alter_type.' COLUMN '; - - $sqls = array(); - for ($i = 0, $c = count($field); $i < $c; $i++) - { - $sqls[] = $sql - .($field[$i]['_literal'] !== FALSE ? $field[$i]['_literal'] : $this->_process_column($field[$i])); - } - - return $sqls; - } - - // -------------------------------------------------------------------- - - /** - * Process fields - * - * @param bool $create_table - * @return array - */ - protected function _process_fields($create_table = FALSE) - { - $fields = array(); - - foreach ($this->fields as $key => $attributes) - { - if (is_int($key) && ! is_array($attributes)) - { - $fields[] = array('_literal' => $attributes); - continue; - } - - $attributes = array_change_key_case($attributes, CASE_UPPER); - - if ($create_table === TRUE && empty($attributes['TYPE'])) - { - continue; - } - - isset($attributes['TYPE']) && $this->_attr_type($attributes); - - $field = array( - 'name' => $key, - 'new_name' => isset($attributes['NAME']) ? $attributes['NAME'] : NULL, - 'type' => isset($attributes['TYPE']) ? $attributes['TYPE'] : NULL, - 'length' => '', - 'unsigned' => '', - 'null' => '', - 'unique' => '', - 'default' => '', - 'auto_increment' => '', - '_literal' => FALSE - ); - - isset($attributes['TYPE']) && $this->_attr_unsigned($attributes, $field); - - if ($create_table === FALSE) - { - if (isset($attributes['AFTER'])) - { - $field['after'] = $attributes['AFTER']; - } - elseif (isset($attributes['FIRST'])) - { - $field['first'] = (bool) $attributes['FIRST']; - } - } - - $this->_attr_default($attributes, $field); - - if (isset($attributes['NULL'])) - { - if ($attributes['NULL'] === TRUE) - { - $field['null'] = empty($this->_null) ? '' : ' '.$this->_null; - } - else - { - $field['null'] = ' NOT NULL'; - } - } - elseif ($create_table === TRUE) - { - $field['null'] = ' NOT NULL'; - } - - $this->_attr_auto_increment($attributes, $field); - $this->_attr_unique($attributes, $field); - - if (isset($attributes['COMMENT'])) - { - $field['comment'] = $this->db->escape($attributes['COMMENT']); - } - - if (isset($attributes['TYPE']) && ! empty($attributes['CONSTRAINT'])) - { - switch (strtoupper($attributes['TYPE'])) - { - case 'ENUM': - case 'SET': - $attributes['CONSTRAINT'] = $this->db->escape($attributes['CONSTRAINT']); - default: - $field['length'] = is_array($attributes['CONSTRAINT']) - ? '('.implode(',', $attributes['CONSTRAINT']).')' - : '('.$attributes['CONSTRAINT'].')'; - break; - } - } - - $fields[] = $field; - } - - return $fields; - } - - // -------------------------------------------------------------------- - - /** - * Process column - * - * @param array $field - * @return string - */ - protected function _process_column($field) - { - return $this->db->escape_identifiers($field['name']) - .' '.$field['type'].$field['length'] - .$field['unsigned'] - .$field['default'] - .$field['null'] - .$field['auto_increment'] - .$field['unique']; - } - - // -------------------------------------------------------------------- - - /** - * Field attribute TYPE - * - * Performs a data type mapping between different databases. - * - * @param array &$attributes - * @return void - */ - protected function _attr_type(&$attributes) - { - // Usually overridden by drivers - } - - // -------------------------------------------------------------------- - - /** - * Field attribute UNSIGNED - * - * Depending on the _unsigned property value: - * - * - TRUE will always set $field['unsigned'] to 'UNSIGNED' - * - FALSE will always set $field['unsigned'] to '' - * - array(TYPE) will set $field['unsigned'] to 'UNSIGNED', - * if $attributes['TYPE'] is found in the array - * - array(TYPE => UTYPE) will change $field['type'], - * from TYPE to UTYPE in case of a match - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_unsigned(&$attributes, &$field) - { - if (empty($attributes['UNSIGNED']) OR $attributes['UNSIGNED'] !== TRUE) - { - return; - } - - // Reset the attribute in order to avoid issues if we do type conversion - $attributes['UNSIGNED'] = FALSE; - - if (is_array($this->_unsigned)) - { - foreach (array_keys($this->_unsigned) as $key) - { - if (is_int($key) && strcasecmp($attributes['TYPE'], $this->_unsigned[$key]) === 0) - { - $field['unsigned'] = ' UNSIGNED'; - return; - } - elseif (is_string($key) && strcasecmp($attributes['TYPE'], $key) === 0) - { - $field['type'] = $key; - return; - } - } - - return; - } - - $field['unsigned'] = ($this->_unsigned === TRUE) ? ' UNSIGNED' : ''; - } - - // -------------------------------------------------------------------- - - /** - * Field attribute DEFAULT - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_default(&$attributes, &$field) - { - if ($this->_default === FALSE) - { - return; - } - - if (array_key_exists('DEFAULT', $attributes)) - { - if ($attributes['DEFAULT'] === NULL) - { - $field['default'] = empty($this->_null) ? '' : $this->_default.$this->_null; - - // Override the NULL attribute if that's our default - $attributes['NULL'] = TRUE; - $field['null'] = empty($this->_null) ? '' : ' '.$this->_null; - } - else - { - $field['default'] = $this->_default.$this->db->escape($attributes['DEFAULT']); - } - } - } - - // -------------------------------------------------------------------- - - /** - * Field attribute UNIQUE - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_unique(&$attributes, &$field) - { - if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE) - { - $field['unique'] = ' UNIQUE'; - } - } - - // -------------------------------------------------------------------- - - /** - * Field attribute AUTO_INCREMENT - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_auto_increment(&$attributes, &$field) - { - if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE) - { - $field['auto_increment'] = ' AUTO_INCREMENT'; - } - } - - // -------------------------------------------------------------------- - - /** - * Process primary keys - * - * @param string $table Table name - * @return string - */ - protected function _process_primary_keys($table) - { - $sql = ''; - - for ($i = 0, $c = count($this->primary_keys); $i < $c; $i++) - { - if ( ! isset($this->fields[$this->primary_keys[$i]])) - { - unset($this->primary_keys[$i]); - } - } - - if (count($this->primary_keys) > 0) - { - $sql .= ",\n\tCONSTRAINT ".$this->db->escape_identifiers('pk_'.$table) - .' PRIMARY KEY('.implode(', ', $this->db->escape_identifiers($this->primary_keys)).')'; - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Process indexes - * - * @param string $table Table name - * @return string[] list of SQL statements - */ - protected function _process_indexes($table) - { - $sqls = array(); - - for ($i = 0, $c = count($this->keys); $i < $c; $i++) - { - if (is_array($this->keys[$i])) - { - for ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++) - { - if ( ! isset($this->fields[$this->keys[$i][$i2]])) - { - unset($this->keys[$i][$i2]); - continue; - } - } - } - elseif ( ! isset($this->fields[$this->keys[$i]])) - { - unset($this->keys[$i]); - continue; - } - - is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]); - - $sqls[] = 'CREATE INDEX '.$this->db->escape_identifiers($table.'_'.implode('_', $this->keys[$i])) - .' ON '.$this->db->escape_identifiers($table) - .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).');'; - } - - return $sqls; - } - - // -------------------------------------------------------------------- - - /** - * Reset - * - * Resets table creation vars - * - * @return void - */ - protected function _reset() - { - $this->fields = $this->keys = $this->primary_keys = array(); - } - -} diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php deleted file mode 100644 index 3d0c329..0000000 --- a/system/database/DB_query_builder.php +++ /dev/null @@ -1,2808 +0,0 @@ -_protect_identifiers; - - foreach ($select as $val) - { - $val = trim($val); - - if ($val !== '') - { - $this->qb_select[] = $val; - $this->qb_no_escape[] = $escape; - - if ($this->qb_caching === TRUE) - { - $this->qb_cache_select[] = $val; - $this->qb_cache_exists[] = 'select'; - $this->qb_cache_no_escape[] = $escape; - } - } - } - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Select Max - * - * Generates a SELECT MAX(field) portion of a query - * - * @param string the field - * @param string an alias - * @return CI_DB_query_builder - */ - public function select_max($select = '', $alias = '') - { - return $this->_max_min_avg_sum($select, $alias, 'MAX'); - } - - // -------------------------------------------------------------------- - - /** - * Select Min - * - * Generates a SELECT MIN(field) portion of a query - * - * @param string the field - * @param string an alias - * @return CI_DB_query_builder - */ - public function select_min($select = '', $alias = '') - { - return $this->_max_min_avg_sum($select, $alias, 'MIN'); - } - - // -------------------------------------------------------------------- - - /** - * Select Average - * - * Generates a SELECT AVG(field) portion of a query - * - * @param string the field - * @param string an alias - * @return CI_DB_query_builder - */ - public function select_avg($select = '', $alias = '') - { - return $this->_max_min_avg_sum($select, $alias, 'AVG'); - } - - // -------------------------------------------------------------------- - - /** - * Select Sum - * - * Generates a SELECT SUM(field) portion of a query - * - * @param string the field - * @param string an alias - * @return CI_DB_query_builder - */ - public function select_sum($select = '', $alias = '') - { - return $this->_max_min_avg_sum($select, $alias, 'SUM'); - } - - // -------------------------------------------------------------------- - - /** - * SELECT [MAX|MIN|AVG|SUM]() - * - * @used-by select_max() - * @used-by select_min() - * @used-by select_avg() - * @used-by select_sum() - * - * @param string $select Field name - * @param string $alias - * @param string $type - * @return CI_DB_query_builder - */ - protected function _max_min_avg_sum($select = '', $alias = '', $type = 'MAX') - { - if ( ! is_string($select) OR $select === '') - { - $this->display_error('db_invalid_query'); - } - - $type = strtoupper($type); - - if ( ! in_array($type, array('MAX', 'MIN', 'AVG', 'SUM'))) - { - show_error('Invalid function type: '.$type); - } - - if ($alias === '') - { - $alias = $this->_create_alias_from_table(trim($select)); - } - - $sql = $type.'('.$this->protect_identifiers(trim($select)).') AS '.$this->escape_identifiers(trim($alias)); - - $this->qb_select[] = $sql; - $this->qb_no_escape[] = NULL; - - if ($this->qb_caching === TRUE) - { - $this->qb_cache_select[] = $sql; - $this->qb_cache_exists[] = 'select'; - } - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Determines the alias name based on the table - * - * @param string $item - * @return string - */ - protected function _create_alias_from_table($item) - { - if (strpos($item, '.') !== FALSE) - { - $item = explode('.', $item); - return end($item); - } - - return $item; - } - - // -------------------------------------------------------------------- - - /** - * DISTINCT - * - * Sets a flag which tells the query string compiler to add DISTINCT - * - * @param bool $val - * @return CI_DB_query_builder - */ - public function distinct($val = TRUE) - { - $this->qb_distinct = is_bool($val) ? $val : TRUE; - return $this; - } - - // -------------------------------------------------------------------- - - /** - * From - * - * Generates the FROM portion of the query - * - * @param mixed $from can be a string or array - * @return CI_DB_query_builder - */ - public function from($from) - { - foreach ((array) $from as $val) - { - if (strpos($val, ',') !== FALSE) - { - foreach (explode(',', $val) as $v) - { - $v = trim($v); - $this->_track_aliases($v); - - $this->qb_from[] = $v = $this->protect_identifiers($v, TRUE, NULL, FALSE); - - if ($this->qb_caching === TRUE) - { - $this->qb_cache_from[] = $v; - $this->qb_cache_exists[] = 'from'; - } - } - } - else - { - $val = trim($val); - - // Extract any aliases that might exist. We use this information - // in the protect_identifiers to know whether to add a table prefix - $this->_track_aliases($val); - - $this->qb_from[] = $val = $this->protect_identifiers($val, TRUE, NULL, FALSE); - - if ($this->qb_caching === TRUE) - { - $this->qb_cache_from[] = $val; - $this->qb_cache_exists[] = 'from'; - } - } - } - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * JOIN - * - * Generates the JOIN portion of the query - * - * @param string - * @param string the join condition - * @param string the type of join - * @param string whether not to try to escape identifiers - * @return CI_DB_query_builder - */ - public function join($table, $cond, $type = '', $escape = NULL) - { - if ($type !== '') - { - $type = strtoupper(trim($type)); - - if ( ! in_array($type, array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER'), TRUE)) - { - $type = ''; - } - else - { - $type .= ' '; - } - } - - // Extract any aliases that might exist. We use this information - // in the protect_identifiers to know whether to add a table prefix - $this->_track_aliases($table); - - is_bool($escape) OR $escape = $this->_protect_identifiers; - - if ( ! $this->_has_operator($cond)) - { - $cond = ' USING ('.($escape ? $this->escape_identifiers($cond) : $cond).')'; - } - elseif ($escape === FALSE) - { - $cond = ' ON '.$cond; - } - else - { - // Split multiple conditions - if (preg_match_all('/\sAND\s|\sOR\s/i', $cond, $joints, PREG_OFFSET_CAPTURE)) - { - $conditions = array(); - $joints = $joints[0]; - array_unshift($joints, array('', 0)); - - for ($i = count($joints) - 1, $pos = strlen($cond); $i >= 0; $i--) - { - $joints[$i][1] += strlen($joints[$i][0]); // offset - $conditions[$i] = substr($cond, $joints[$i][1], $pos - $joints[$i][1]); - $pos = $joints[$i][1] - strlen($joints[$i][0]); - $joints[$i] = $joints[$i][0]; - } - } - else - { - $conditions = array($cond); - $joints = array(''); - } - - $cond = ' ON '; - for ($i = 0, $c = count($conditions); $i < $c; $i++) - { - $operator = $this->_get_operator($conditions[$i]); - $cond .= $joints[$i]; - $cond .= preg_match("/(\(*)?([\[\]\w\.'-]+)".preg_quote($operator)."(.*)/i", $conditions[$i], $match) - ? $match[1].$this->protect_identifiers($match[2]).$operator.$this->protect_identifiers($match[3]) - : $conditions[$i]; - } - } - - // Do we want to escape the table name? - if ($escape === TRUE) - { - $table = $this->protect_identifiers($table, TRUE, NULL, FALSE); - } - - // Assemble the JOIN statement - $this->qb_join[] = $join = $type.'JOIN '.$table.$cond; - - if ($this->qb_caching === TRUE) - { - $this->qb_cache_join[] = $join; - $this->qb_cache_exists[] = 'join'; - } - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * WHERE - * - * Generates the WHERE portion of the query. - * Separates multiple calls with 'AND'. - * - * @param mixed - * @param mixed - * @param bool - * @return CI_DB_query_builder - */ - public function where($key, $value = NULL, $escape = NULL) - { - return $this->_wh('qb_where', $key, $value, 'AND ', $escape); - } - - // -------------------------------------------------------------------- - - /** - * OR WHERE - * - * Generates the WHERE portion of the query. - * Separates multiple calls with 'OR'. - * - * @param mixed - * @param mixed - * @param bool - * @return CI_DB_query_builder - */ - public function or_where($key, $value = NULL, $escape = NULL) - { - return $this->_wh('qb_where', $key, $value, 'OR ', $escape); - } - - // -------------------------------------------------------------------- - - /** - * WHERE, HAVING - * - * @used-by where() - * @used-by or_where() - * @used-by having() - * @used-by or_having() - * - * @param string $qb_key 'qb_where' or 'qb_having' - * @param mixed $key - * @param mixed $value - * @param string $type - * @param bool $escape - * @return CI_DB_query_builder - */ - protected function _wh($qb_key, $key, $value = NULL, $type = 'AND ', $escape = NULL) - { - $qb_cache_key = ($qb_key === 'qb_having') ? 'qb_cache_having' : 'qb_cache_where'; - - if ( ! is_array($key)) - { - $key = array($key => $value); - } - - // If the escape value was not set will base it on the global setting - is_bool($escape) OR $escape = $this->_protect_identifiers; - - foreach ($key as $k => $v) - { - $prefix = (count($this->$qb_key) === 0 && count($this->$qb_cache_key) === 0) - ? $this->_group_get_type('') - : $this->_group_get_type($type); - - if ($v !== NULL) - { - if ($escape === TRUE) - { - $v = $this->escape($v); - } - - if ( ! $this->_has_operator($k)) - { - $k .= ' = '; - } - } - elseif ( ! $this->_has_operator($k)) - { - // value appears not to have been set, assign the test to IS NULL - $k .= ' IS NULL'; - } - elseif (preg_match('/\s*(!?=|<>|\sIS(?:\s+NOT)?\s)\s*$/i', $k, $match, PREG_OFFSET_CAPTURE)) - { - $k = substr($k, 0, $match[0][1]).($match[1][0] === '=' ? ' IS NULL' : ' IS NOT NULL'); - } - - ${$qb_key} = array('condition' => $prefix.$k, 'value' => $v, 'escape' => $escape); - $this->{$qb_key}[] = ${$qb_key}; - if ($this->qb_caching === TRUE) - { - $this->{$qb_cache_key}[] = ${$qb_key}; - $this->qb_cache_exists[] = substr($qb_key, 3); - } - - } - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * WHERE IN - * - * Generates a WHERE field IN('item', 'item') SQL query, - * joined with 'AND' if appropriate. - * - * @param string $key The field to search - * @param array $values The values searched on - * @param bool $escape - * @return CI_DB_query_builder - */ - public function where_in($key = NULL, $values = NULL, $escape = NULL) - { - return $this->_where_in($key, $values, FALSE, 'AND ', $escape); - } - - // -------------------------------------------------------------------- - - /** - * OR WHERE IN - * - * Generates a WHERE field IN('item', 'item') SQL query, - * joined with 'OR' if appropriate. - * - * @param string $key The field to search - * @param array $values The values searched on - * @param bool $escape - * @return CI_DB_query_builder - */ - public function or_where_in($key = NULL, $values = NULL, $escape = NULL) - { - return $this->_where_in($key, $values, FALSE, 'OR ', $escape); - } - - // -------------------------------------------------------------------- - - /** - * WHERE NOT IN - * - * Generates a WHERE field NOT IN('item', 'item') SQL query, - * joined with 'AND' if appropriate. - * - * @param string $key The field to search - * @param array $values The values searched on - * @param bool $escape - * @return CI_DB_query_builder - */ - public function where_not_in($key = NULL, $values = NULL, $escape = NULL) - { - return $this->_where_in($key, $values, TRUE, 'AND ', $escape); - } - - // -------------------------------------------------------------------- - - /** - * OR WHERE NOT IN - * - * Generates a WHERE field NOT IN('item', 'item') SQL query, - * joined with 'OR' if appropriate. - * - * @param string $key The field to search - * @param array $values The values searched on - * @param bool $escape - * @return CI_DB_query_builder - */ - public function or_where_not_in($key = NULL, $values = NULL, $escape = NULL) - { - return $this->_where_in($key, $values, TRUE, 'OR ', $escape); - } - - // -------------------------------------------------------------------- - - /** - * Internal WHERE IN - * - * @used-by where_in() - * @used-by or_where_in() - * @used-by where_not_in() - * @used-by or_where_not_in() - * - * @param string $key The field to search - * @param array $values The values searched on - * @param bool $not If the statement would be IN or NOT IN - * @param string $type - * @param bool $escape - * @return CI_DB_query_builder - */ - protected function _where_in($key = NULL, $values = NULL, $not = FALSE, $type = 'AND ', $escape = NULL) - { - if ($key === NULL OR $values === NULL) - { - return $this; - } - - if ( ! is_array($values)) - { - $values = array($values); - } - - is_bool($escape) OR $escape = $this->_protect_identifiers; - - $not = ($not) ? ' NOT' : ''; - - if ($escape === TRUE) - { - $where_in = array(); - foreach ($values as $value) - { - $where_in[] = $this->escape($value); - } - } - else - { - $where_in = array_values($values); - } - - $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) - ? $this->_group_get_type('') - : $this->_group_get_type($type); - - $where_in = array( - 'condition' => $prefix.$key.$not.' IN('.implode(', ', $where_in).')', - 'value' => NULL, - 'escape' => $escape - ); - - $this->qb_where[] = $where_in; - if ($this->qb_caching === TRUE) - { - $this->qb_cache_where[] = $where_in; - $this->qb_cache_exists[] = 'where'; - } - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * LIKE - * - * Generates a %LIKE% portion of the query. - * Separates multiple calls with 'AND'. - * - * @param mixed $field - * @param string $match - * @param string $side - * @param bool $escape - * @return CI_DB_query_builder - */ - public function like($field, $match = '', $side = 'both', $escape = NULL) - { - return $this->_like($field, $match, 'AND ', $side, '', $escape); - } - - // -------------------------------------------------------------------- - - /** - * NOT LIKE - * - * Generates a NOT LIKE portion of the query. - * Separates multiple calls with 'AND'. - * - * @param mixed $field - * @param string $match - * @param string $side - * @param bool $escape - * @return CI_DB_query_builder - */ - public function not_like($field, $match = '', $side = 'both', $escape = NULL) - { - return $this->_like($field, $match, 'AND ', $side, 'NOT', $escape); - } - - // -------------------------------------------------------------------- - - /** - * OR LIKE - * - * Generates a %LIKE% portion of the query. - * Separates multiple calls with 'OR'. - * - * @param mixed $field - * @param string $match - * @param string $side - * @param bool $escape - * @return CI_DB_query_builder - */ - public function or_like($field, $match = '', $side = 'both', $escape = NULL) - { - return $this->_like($field, $match, 'OR ', $side, '', $escape); - } - - // -------------------------------------------------------------------- - - /** - * OR NOT LIKE - * - * Generates a NOT LIKE portion of the query. - * Separates multiple calls with 'OR'. - * - * @param mixed $field - * @param string $match - * @param string $side - * @param bool $escape - * @return CI_DB_query_builder - */ - public function or_not_like($field, $match = '', $side = 'both', $escape = NULL) - { - return $this->_like($field, $match, 'OR ', $side, 'NOT', $escape); - } - - // -------------------------------------------------------------------- - - /** - * Internal LIKE - * - * @used-by like() - * @used-by or_like() - * @used-by not_like() - * @used-by or_not_like() - * - * @param mixed $field - * @param string $match - * @param string $type - * @param string $side - * @param string $not - * @param bool $escape - * @return CI_DB_query_builder - */ - protected function _like($field, $match = '', $type = 'AND ', $side = 'both', $not = '', $escape = NULL) - { - if ( ! is_array($field)) - { - $field = array($field => $match); - } - - is_bool($escape) OR $escape = $this->_protect_identifiers; - // lowercase $side in case somebody writes e.g. 'BEFORE' instead of 'before' (doh) - $side = strtolower($side); - - foreach ($field as $k => $v) - { - $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) - ? $this->_group_get_type('') : $this->_group_get_type($type); - - if ($escape === TRUE) - { - $v = $this->escape_like_str($v); - } - - switch ($side) - { - case 'none': - $v = "'{$v}'"; - break; - case 'before': - $v = "'%{$v}'"; - break; - case 'after': - $v = "'{$v}%'"; - break; - case 'both': - default: - $v = "'%{$v}%'"; - break; - } - - // some platforms require an escape sequence definition for LIKE wildcards - if ($escape === TRUE && $this->_like_escape_str !== '') - { - $v .= sprintf($this->_like_escape_str, $this->_like_escape_chr); - } - - $qb_where = array('condition' => "{$prefix} {$k} {$not} LIKE {$v}", 'value' => NULL, 'escape' => $escape); - $this->qb_where[] = $qb_where; - if ($this->qb_caching === TRUE) - { - $this->qb_cache_where[] = $qb_where; - $this->qb_cache_exists[] = 'where'; - } - } - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Starts a query group. - * - * @param string $not (Internal use only) - * @param string $type (Internal use only) - * @return CI_DB_query_builder - */ - public function group_start($not = '', $type = 'AND ') - { - $type = $this->_group_get_type($type); - - $this->qb_where_group_started = TRUE; - $prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) ? '' : $type; - $where = array( - 'condition' => $prefix.$not.str_repeat(' ', ++$this->qb_where_group_count).' (', - 'value' => NULL, - 'escape' => FALSE - ); - - $this->qb_where[] = $where; - if ($this->qb_caching) - { - $this->qb_cache_where[] = $where; - } - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Starts a query group, but ORs the group - * - * @return CI_DB_query_builder - */ - public function or_group_start() - { - return $this->group_start('', 'OR '); - } - - // -------------------------------------------------------------------- - - /** - * Starts a query group, but NOTs the group - * - * @return CI_DB_query_builder - */ - public function not_group_start() - { - return $this->group_start('NOT ', 'AND '); - } - - // -------------------------------------------------------------------- - - /** - * Starts a query group, but OR NOTs the group - * - * @return CI_DB_query_builder - */ - public function or_not_group_start() - { - return $this->group_start('NOT ', 'OR '); - } - - // -------------------------------------------------------------------- - - /** - * Ends a query group - * - * @return CI_DB_query_builder - */ - public function group_end() - { - $this->qb_where_group_started = FALSE; - $where = array( - 'condition' => str_repeat(' ', $this->qb_where_group_count--).')', - 'value' => NULL, - 'escape' => FALSE - ); - - $this->qb_where[] = $where; - if ($this->qb_caching) - { - $this->qb_cache_where[] = $where; - } - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Group_get_type - * - * @used-by group_start() - * @used-by _like() - * @used-by _wh() - * @used-by _where_in() - * - * @param string $type - * @return string - */ - protected function _group_get_type($type) - { - if ($this->qb_where_group_started) - { - $type = ''; - $this->qb_where_group_started = FALSE; - } - - return $type; - } - - // -------------------------------------------------------------------- - - /** - * GROUP BY - * - * @param string $by - * @param bool $escape - * @return CI_DB_query_builder - */ - public function group_by($by, $escape = NULL) - { - is_bool($escape) OR $escape = $this->_protect_identifiers; - - if (is_string($by)) - { - $by = ($escape === TRUE) - ? explode(',', $by) - : array($by); - } - - foreach ($by as $val) - { - $val = trim($val); - - if ($val !== '') - { - $val = array('field' => $val, 'escape' => $escape); - - $this->qb_groupby[] = $val; - if ($this->qb_caching === TRUE) - { - $this->qb_cache_groupby[] = $val; - $this->qb_cache_exists[] = 'groupby'; - } - } - } - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * HAVING - * - * Separates multiple calls with 'AND'. - * - * @param string $key - * @param string $value - * @param bool $escape - * @return CI_DB_query_builder - */ - public function having($key, $value = NULL, $escape = NULL) - { - return $this->_wh('qb_having', $key, $value, 'AND ', $escape); - } - - // -------------------------------------------------------------------- - - /** - * OR HAVING - * - * Separates multiple calls with 'OR'. - * - * @param string $key - * @param string $value - * @param bool $escape - * @return CI_DB_query_builder - */ - public function or_having($key, $value = NULL, $escape = NULL) - { - return $this->_wh('qb_having', $key, $value, 'OR ', $escape); - } - - // -------------------------------------------------------------------- - - /** - * ORDER BY - * - * @param string $orderby - * @param string $direction ASC, DESC or RANDOM - * @param bool $escape - * @return CI_DB_query_builder - */ - public function order_by($orderby, $direction = '', $escape = NULL) - { - $direction = strtoupper(trim($direction)); - - if ($direction === 'RANDOM') - { - $direction = ''; - - // Do we have a seed value? - $orderby = ctype_digit((string) $orderby) - ? sprintf($this->_random_keyword[1], $orderby) - : $this->_random_keyword[0]; - } - elseif (empty($orderby)) - { - return $this; - } - elseif ($direction !== '') - { - $direction = in_array($direction, array('ASC', 'DESC'), TRUE) ? ' '.$direction : ''; - } - - is_bool($escape) OR $escape = $this->_protect_identifiers; - - if ($escape === FALSE) - { - $qb_orderby[] = array('field' => $orderby, 'direction' => $direction, 'escape' => FALSE); - } - else - { - $qb_orderby = array(); - foreach (explode(',', $orderby) as $field) - { - $qb_orderby[] = ($direction === '' && preg_match('/\s+(ASC|DESC)$/i', rtrim($field), $match, PREG_OFFSET_CAPTURE)) - ? array('field' => ltrim(substr($field, 0, $match[0][1])), 'direction' => ' '.$match[1][0], 'escape' => TRUE) - : array('field' => trim($field), 'direction' => $direction, 'escape' => TRUE); - } - } - - $this->qb_orderby = array_merge($this->qb_orderby, $qb_orderby); - if ($this->qb_caching === TRUE) - { - $this->qb_cache_orderby = array_merge($this->qb_cache_orderby, $qb_orderby); - $this->qb_cache_exists[] = 'orderby'; - } - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * LIMIT - * - * @param int $value LIMIT value - * @param int $offset OFFSET value - * @return CI_DB_query_builder - */ - public function limit($value, $offset = 0) - { - is_null($value) OR $this->qb_limit = (int) $value; - empty($offset) OR $this->qb_offset = (int) $offset; - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Sets the OFFSET value - * - * @param int $offset OFFSET value - * @return CI_DB_query_builder - */ - public function offset($offset) - { - empty($offset) OR $this->qb_offset = (int) $offset; - return $this; - } - - // -------------------------------------------------------------------- - - /** - * LIMIT string - * - * Generates a platform-specific LIMIT clause. - * - * @param string $sql SQL Query - * @return string - */ - protected function _limit($sql) - { - return $sql.' LIMIT '.($this->qb_offset ? $this->qb_offset.', ' : '').(int) $this->qb_limit; - } - - // -------------------------------------------------------------------- - - /** - * The "set" function. - * - * Allows key/value pairs to be set for inserting or updating - * - * @param mixed - * @param string - * @param bool - * @return CI_DB_query_builder - */ - public function set($key, $value = '', $escape = NULL) - { - $key = $this->_object_to_array($key); - - if ( ! is_array($key)) - { - $key = array($key => $value); - } - - is_bool($escape) OR $escape = $this->_protect_identifiers; - - foreach ($key as $k => $v) - { - $this->qb_set[$this->protect_identifiers($k, FALSE, $escape)] = ($escape) - ? $this->escape($v) : $v; - } - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Get SELECT query string - * - * Compiles a SELECT query string and returns the sql. - * - * @param string the table name to select from (optional) - * @param bool TRUE: resets QB values; FALSE: leave QB values alone - * @return string - */ - public function get_compiled_select($table = '', $reset = TRUE) - { - if ($table !== '') - { - $this->_track_aliases($table); - $this->from($table); - } - - $select = $this->_compile_select(); - - if ($reset === TRUE) - { - $this->_reset_select(); - } - - return $select; - } - - // -------------------------------------------------------------------- - - /** - * Get - * - * Compiles the select statement based on the other functions called - * and runs the query - * - * @param string the table - * @param string the limit clause - * @param string the offset clause - * @return CI_DB_result - */ - public function get($table = '', $limit = NULL, $offset = NULL) - { - if ($table !== '') - { - $this->_track_aliases($table); - $this->from($table); - } - - if ( ! empty($limit)) - { - $this->limit($limit, $offset); - } - - $result = $this->query($this->_compile_select()); - $this->_reset_select(); - return $result; - } - - // -------------------------------------------------------------------- - - /** - * "Count All Results" query - * - * Generates a platform-specific query string that counts all records - * returned by an Query Builder query. - * - * @param string - * @param bool the reset clause - * @return int - */ - public function count_all_results($table = '', $reset = TRUE) - { - if ($table !== '') - { - $this->_track_aliases($table); - $this->from($table); - } - - // ORDER BY usage is often problematic here (most notably - // on Microsoft SQL Server) and ultimately unnecessary - // for selecting COUNT(*) ... - $qb_orderby = $this->qb_orderby; - $qb_cache_orderby = $this->qb_cache_orderby; - $this->qb_orderby = $this->qb_cache_orderby = array(); - - $result = ($this->qb_distinct === TRUE OR ! empty($this->qb_groupby) OR ! empty($this->qb_cache_groupby) OR $this->qb_limit OR $this->qb_offset) - ? $this->query($this->_count_string.$this->protect_identifiers('numrows')."\nFROM (\n".$this->_compile_select()."\n) CI_count_all_results") - : $this->query($this->_compile_select($this->_count_string.$this->protect_identifiers('numrows'))); - - if ($reset === TRUE) - { - $this->_reset_select(); - } - else - { - $this->qb_orderby = $qb_orderby; - $this->qb_cache_orderby = $qb_cache_orderby; - } - - if ($result->num_rows() === 0) - { - return 0; - } - - $row = $result->row(); - return (int) $row->numrows; - } - - // -------------------------------------------------------------------- - - /** - * get_where() - * - * Allows the where clause, limit and offset to be added directly - * - * @param string $table - * @param string $where - * @param int $limit - * @param int $offset - * @return CI_DB_result - */ - public function get_where($table = '', $where = NULL, $limit = NULL, $offset = NULL) - { - if ($table !== '') - { - $this->from($table); - } - - if ($where !== NULL) - { - $this->where($where); - } - - if ( ! empty($limit)) - { - $this->limit($limit, $offset); - } - - $result = $this->query($this->_compile_select()); - $this->_reset_select(); - return $result; - } - - // -------------------------------------------------------------------- - - /** - * Insert_Batch - * - * Compiles batch insert strings and runs the queries - * - * @param string $table Table to insert into - * @param array $set An associative array of insert values - * @param bool $escape Whether to escape values and identifiers - * @return int Number of rows inserted or FALSE on failure - */ - public function insert_batch($table, $set = NULL, $escape = NULL, $batch_size = 100) - { - if ($set === NULL) - { - if (empty($this->qb_set)) - { - return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE; - } - } - else - { - if (empty($set)) - { - return ($this->db_debug) ? $this->display_error('insert_batch() called with no data') : FALSE; - } - - $this->set_insert_batch($set, '', $escape); - } - - if (strlen($table) === 0) - { - if ( ! isset($this->qb_from[0])) - { - return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE; - } - - $table = $this->qb_from[0]; - } - - // Batch this baby - $affected_rows = 0; - for ($i = 0, $total = count($this->qb_set); $i < $total; $i += $batch_size) - { - if ($this->query($this->_insert_batch($this->protect_identifiers($table, TRUE, $escape, FALSE), $this->qb_keys, array_slice($this->qb_set, $i, $batch_size)))) - { - $affected_rows += $this->affected_rows(); - } - } - - $this->_reset_write(); - return $affected_rows; - } - - // -------------------------------------------------------------------- - - /** - * Insert batch statement - * - * Generates a platform-specific insert string from the supplied data. - * - * @param string $table Table name - * @param array $keys INSERT keys - * @param array $values INSERT values - * @return string - */ - protected function _insert_batch($table, $keys, $values) - { - return 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES '.implode(', ', $values); - } - - // -------------------------------------------------------------------- - - /** - * The "set_insert_batch" function. Allows key/value pairs to be set for batch inserts - * - * @param mixed - * @param string - * @param bool - * @return CI_DB_query_builder - */ - public function set_insert_batch($key, $value = '', $escape = NULL) - { - $key = $this->_object_to_array_batch($key); - - if ( ! is_array($key)) - { - $key = array($key => $value); - } - - is_bool($escape) OR $escape = $this->_protect_identifiers; - - $keys = array_keys($this->_object_to_array(reset($key))); - sort($keys); - - foreach ($key as $row) - { - $row = $this->_object_to_array($row); - if (count(array_diff($keys, array_keys($row))) > 0 OR count(array_diff(array_keys($row), $keys)) > 0) - { - // batch function above returns an error on an empty array - $this->qb_set[] = array(); - return; - } - - ksort($row); // puts $row in the same order as our keys - - if ($escape !== FALSE) - { - $clean = array(); - foreach ($row as $value) - { - $clean[] = $this->escape($value); - } - - $row = $clean; - } - - $this->qb_set[] = '('.implode(',', $row).')'; - } - - foreach ($keys as $k) - { - $this->qb_keys[] = $this->protect_identifiers($k, FALSE, $escape); - } - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Get INSERT query string - * - * Compiles an insert query and returns the sql - * - * @param string the table to insert into - * @param bool TRUE: reset QB values; FALSE: leave QB values alone - * @return string - */ - public function get_compiled_insert($table = '', $reset = TRUE) - { - if ($this->_validate_insert($table) === FALSE) - { - return FALSE; - } - - $sql = $this->_insert( - $this->protect_identifiers( - $this->qb_from[0], TRUE, NULL, FALSE - ), - array_keys($this->qb_set), - array_values($this->qb_set) - ); - - if ($reset === TRUE) - { - $this->_reset_write(); - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Insert - * - * Compiles an insert string and runs the query - * - * @param string the table to insert data into - * @param array an associative array of insert values - * @param bool $escape Whether to escape values and identifiers - * @return bool TRUE on success, FALSE on failure - */ - public function insert($table = '', $set = NULL, $escape = NULL) - { - if ($set !== NULL) - { - $this->set($set, '', $escape); - } - - if ($this->_validate_insert($table) === FALSE) - { - return FALSE; - } - - $sql = $this->_insert( - $this->protect_identifiers( - $this->qb_from[0], TRUE, $escape, FALSE - ), - array_keys($this->qb_set), - array_values($this->qb_set) - ); - - $this->_reset_write(); - return $this->query($sql); - } - - // -------------------------------------------------------------------- - - /** - * Validate Insert - * - * This method is used by both insert() and get_compiled_insert() to - * validate that the there data is actually being set and that table - * has been chosen to be inserted into. - * - * @param string the table to insert data into - * @return string - */ - protected function _validate_insert($table = '') - { - if (count($this->qb_set) === 0) - { - return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE; - } - - if ($table !== '') - { - $this->qb_from[0] = $table; - } - elseif ( ! isset($this->qb_from[0])) - { - return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE; - } - - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Replace - * - * Compiles an replace into string and runs the query - * - * @param string the table to replace data into - * @param array an associative array of insert values - * @return bool TRUE on success, FALSE on failure - */ - public function replace($table = '', $set = NULL) - { - if ($set !== NULL) - { - $this->set($set); - } - - if (count($this->qb_set) === 0) - { - return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE; - } - - if ($table === '') - { - if ( ! isset($this->qb_from[0])) - { - return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE; - } - - $table = $this->qb_from[0]; - } - - $sql = $this->_replace($this->protect_identifiers($table, TRUE, NULL, FALSE), array_keys($this->qb_set), array_values($this->qb_set)); - - $this->_reset_write(); - return $this->query($sql); - } - - // -------------------------------------------------------------------- - - /** - * Replace statement - * - * Generates a platform-specific replace string from the supplied data - * - * @param string the table name - * @param array the insert keys - * @param array the insert values - * @return string - */ - protected function _replace($table, $keys, $values) - { - return 'REPLACE INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')'; - } - - // -------------------------------------------------------------------- - - /** - * FROM tables - * - * Groups tables in FROM clauses if needed, so there is no confusion - * about operator precedence. - * - * Note: This is only used (and overridden) by MySQL and CUBRID. - * - * @return string - */ - protected function _from_tables() - { - return implode(', ', $this->qb_from); - } - - // -------------------------------------------------------------------- - - /** - * Get UPDATE query string - * - * Compiles an update query and returns the sql - * - * @param string the table to update - * @param bool TRUE: reset QB values; FALSE: leave QB values alone - * @return string - */ - public function get_compiled_update($table = '', $reset = TRUE) - { - // Combine any cached components with the current statements - $this->_merge_cache(); - - if ($this->_validate_update($table) === FALSE) - { - return FALSE; - } - - $sql = $this->_update($this->qb_from[0], $this->qb_set); - - if ($reset === TRUE) - { - $this->_reset_write(); - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * UPDATE - * - * Compiles an update string and runs the query. - * - * @param string $table - * @param array $set An associative array of update values - * @param mixed $where - * @param int $limit - * @return bool TRUE on success, FALSE on failure - */ - public function update($table = '', $set = NULL, $where = NULL, $limit = NULL) - { - // Combine any cached components with the current statements - $this->_merge_cache(); - - if ($set !== NULL) - { - $this->set($set); - } - - if ($this->_validate_update($table) === FALSE) - { - return FALSE; - } - - if ($where !== NULL) - { - $this->where($where); - } - - if ( ! empty($limit)) - { - $this->limit($limit); - } - - $sql = $this->_update($this->qb_from[0], $this->qb_set); - $this->_reset_write(); - return $this->query($sql); - } - - // -------------------------------------------------------------------- - - /** - * Validate Update - * - * This method is used by both update() and get_compiled_update() to - * validate that data is actually being set and that a table has been - * chosen to be update. - * - * @param string the table to update data on - * @return bool - */ - protected function _validate_update($table) - { - if (count($this->qb_set) === 0) - { - return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE; - } - - if ($table !== '') - { - $this->qb_from = array($this->protect_identifiers($table, TRUE, NULL, FALSE)); - } - elseif ( ! isset($this->qb_from[0])) - { - return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE; - } - - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Update_Batch - * - * Compiles an update string and runs the query - * - * @param string the table to retrieve the results from - * @param array an associative array of update values - * @param string the where key - * @return int number of rows affected or FALSE on failure - */ - public function update_batch($table, $set = NULL, $index = NULL, $batch_size = 100) - { - // Combine any cached components with the current statements - $this->_merge_cache(); - - if ($index === NULL) - { - return ($this->db_debug) ? $this->display_error('db_must_use_index') : FALSE; - } - - if ($set === NULL) - { - if (empty($this->qb_set_ub)) - { - return ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE; - } - } - else - { - if (empty($set)) - { - return ($this->db_debug) ? $this->display_error('update_batch() called with no data') : FALSE; - } - - $this->set_update_batch($set, $index); - } - - if (strlen($table) === 0) - { - if ( ! isset($this->qb_from[0])) - { - return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE; - } - - $table = $this->qb_from[0]; - } - - // Batch this baby - $affected_rows = 0; - for ($i = 0, $total = count($this->qb_set_ub); $i < $total; $i += $batch_size) - { - if ($this->query($this->_update_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->qb_set_ub, $i, $batch_size), $index))) - { - $affected_rows += $this->affected_rows(); - } - - $this->qb_where = array(); - } - - $this->_reset_write(); - return $affected_rows; - } - - // -------------------------------------------------------------------- - - /** - * Update_Batch statement - * - * Generates a platform-specific batch update string from the supplied data - * - * @param string $table Table name - * @param array $values Update data - * @param string $index WHERE key - * @return string - */ - protected function _update_batch($table, $values, $index) - { - $ids = array(); - foreach ($values as $key => $val) - { - $ids[] = $val[$index]['value']; - - foreach (array_keys($val) as $field) - { - if ($field !== $index) - { - $final[$val[$field]['field']][] = 'WHEN '.$val[$index]['field'].' = '.$val[$index]['value'].' THEN '.$val[$field]['value']; - } - } - } - - $cases = ''; - foreach ($final as $k => $v) - { - $cases .= $k." = CASE \n" - .implode("\n", $v)."\n" - .'ELSE '.$k.' END, '; - } - - $this->where($val[$index]['field'].' IN('.implode(',', $ids).')', NULL, FALSE); - - return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where'); - } - - // -------------------------------------------------------------------- - - /** - * The "set_update_batch" function. Allows key/value pairs to be set for batch updating - * - * @param array - * @param string - * @param bool - * @return CI_DB_query_builder - */ - public function set_update_batch($key, $index = '', $escape = NULL) - { - $key = $this->_object_to_array_batch($key); - - if ( ! is_array($key)) - { - // @todo error - } - - is_bool($escape) OR $escape = $this->_protect_identifiers; - - foreach ($key as $k => $v) - { - $index_set = FALSE; - $clean = array(); - foreach ($v as $k2 => $v2) - { - if ($k2 === $index) - { - $index_set = TRUE; - } - - $clean[$k2] = array( - 'field' => $this->protect_identifiers($k2, FALSE, $escape), - 'value' => ($escape === FALSE ? $v2 : $this->escape($v2)) - ); - } - - if ($index_set === FALSE) - { - return $this->display_error('db_batch_missing_index'); - } - - $this->qb_set_ub[] = $clean; - } - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Empty Table - * - * Compiles a delete string and runs "DELETE FROM table" - * - * @param string the table to empty - * @return bool TRUE on success, FALSE on failure - */ - public function empty_table($table = '') - { - if ($table === '') - { - if ( ! isset($this->qb_from[0])) - { - return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE; - } - - $table = $this->qb_from[0]; - } - else - { - $table = $this->protect_identifiers($table, TRUE, NULL, FALSE); - } - - $sql = $this->_delete($table); - $this->_reset_write(); - return $this->query($sql); - } - - // -------------------------------------------------------------------- - - /** - * Truncate - * - * Compiles a truncate string and runs the query - * If the database does not support the truncate() command - * This function maps to "DELETE FROM table" - * - * @param string the table to truncate - * @return bool TRUE on success, FALSE on failure - */ - public function truncate($table = '') - { - if ($table === '') - { - if ( ! isset($this->qb_from[0])) - { - return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE; - } - - $table = $this->qb_from[0]; - } - else - { - $table = $this->protect_identifiers($table, TRUE, NULL, FALSE); - } - - $sql = $this->_truncate($table); - $this->_reset_write(); - return $this->query($sql); - } - - // -------------------------------------------------------------------- - - /** - * Truncate statement - * - * Generates a platform-specific truncate string from the supplied data - * - * If the database does not support the truncate() command, - * then this method maps to 'DELETE FROM table' - * - * @param string the table name - * @return string - */ - protected function _truncate($table) - { - return 'TRUNCATE '.$table; - } - - // -------------------------------------------------------------------- - - /** - * Get DELETE query string - * - * Compiles a delete query string and returns the sql - * - * @param string the table to delete from - * @param bool TRUE: reset QB values; FALSE: leave QB values alone - * @return string - */ - public function get_compiled_delete($table = '', $reset = TRUE) - { - $this->return_delete_sql = TRUE; - $sql = $this->delete($table, '', NULL, $reset); - $this->return_delete_sql = FALSE; - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Delete - * - * Compiles a delete string and runs the query - * - * @param mixed the table(s) to delete from. String or array - * @param mixed the where clause - * @param mixed the limit clause - * @param bool - * @return mixed - */ - public function delete($table = '', $where = '', $limit = NULL, $reset_data = TRUE) - { - // Combine any cached components with the current statements - $this->_merge_cache(); - - if ($table === '') - { - if ( ! isset($this->qb_from[0])) - { - return ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE; - } - - $table = $this->qb_from[0]; - } - elseif (is_array($table)) - { - empty($where) && $reset_data = FALSE; - - foreach ($table as $single_table) - { - $this->delete($single_table, $where, $limit, $reset_data); - } - - return; - } - else - { - $table = $this->protect_identifiers($table, TRUE, NULL, FALSE); - } - - if ($where !== '') - { - $this->where($where); - } - - if ( ! empty($limit)) - { - $this->limit($limit); - } - - if (count($this->qb_where) === 0) - { - return ($this->db_debug) ? $this->display_error('db_del_must_use_where') : FALSE; - } - - $sql = $this->_delete($table); - if ($reset_data) - { - $this->_reset_write(); - } - - return ($this->return_delete_sql === TRUE) ? $sql : $this->query($sql); - } - - // -------------------------------------------------------------------- - - /** - * Delete statement - * - * Generates a platform-specific delete string from the supplied data - * - * @param string the table name - * @return string - */ - protected function _delete($table) - { - return 'DELETE FROM '.$table.$this->_compile_wh('qb_where') - .($this->qb_limit !== FALSE ? ' LIMIT '.$this->qb_limit : ''); - } - - // -------------------------------------------------------------------- - - /** - * DB Prefix - * - * Prepends a database prefix if one exists in configuration - * - * @param string the table - * @return string - */ - public function dbprefix($table = '') - { - if ($table === '') - { - $this->display_error('db_table_name_required'); - } - - return $this->dbprefix.$table; - } - - // -------------------------------------------------------------------- - - /** - * Set DB Prefix - * - * Set's the DB Prefix to something new without needing to reconnect - * - * @param string the prefix - * @return string - */ - public function set_dbprefix($prefix = '') - { - return $this->dbprefix = $prefix; - } - - // -------------------------------------------------------------------- - - /** - * Track Aliases - * - * Used to track SQL statements written with aliased tables. - * - * @param string The table to inspect - * @return string - */ - protected function _track_aliases($table) - { - if (is_array($table)) - { - foreach ($table as $t) - { - $this->_track_aliases($t); - } - return; - } - - // Does the string contain a comma? If so, we need to separate - // the string into discreet statements - if (strpos($table, ',') !== FALSE) - { - return $this->_track_aliases(explode(',', $table)); - } - - // if a table alias is used we can recognize it by a space - if (strpos($table, ' ') !== FALSE) - { - // if the alias is written with the AS keyword, remove it - $table = preg_replace('/\s+AS\s+/i', ' ', $table); - - // Grab the alias - $table = trim(strrchr($table, ' ')); - - // Store the alias, if it doesn't already exist - if ( ! in_array($table, $this->qb_aliased_tables, TRUE)) - { - $this->qb_aliased_tables[] = $table; - if ($this->qb_caching === TRUE && ! in_array($table, $this->qb_cache_aliased_tables, TRUE)) - { - $this->qb_cache_aliased_tables[] = $table; - $this->qb_cache_exists[] = 'aliased_tables'; - } - } - } - } - - // -------------------------------------------------------------------- - - /** - * Compile the SELECT statement - * - * Generates a query string based on which functions were used. - * Should not be called directly. - * - * @param bool $select_override - * @return string - */ - protected function _compile_select($select_override = FALSE) - { - // Combine any cached components with the current statements - $this->_merge_cache(); - - // Write the "select" portion of the query - if ($select_override !== FALSE) - { - $sql = $select_override; - } - else - { - $sql = ( ! $this->qb_distinct) ? 'SELECT ' : 'SELECT DISTINCT '; - - if (count($this->qb_select) === 0) - { - $sql .= '*'; - } - else - { - // Cycle through the "select" portion of the query and prep each column name. - // The reason we protect identifiers here rather than in the select() function - // is because until the user calls the from() function we don't know if there are aliases - foreach ($this->qb_select as $key => $val) - { - $no_escape = isset($this->qb_no_escape[$key]) ? $this->qb_no_escape[$key] : NULL; - $this->qb_select[$key] = $this->protect_identifiers($val, FALSE, $no_escape); - } - - $sql .= implode(', ', $this->qb_select); - } - } - - // Write the "FROM" portion of the query - if (count($this->qb_from) > 0) - { - $sql .= "\nFROM ".$this->_from_tables(); - } - - // Write the "JOIN" portion of the query - if (count($this->qb_join) > 0) - { - $sql .= "\n".implode("\n", $this->qb_join); - } - - $sql .= $this->_compile_wh('qb_where') - .$this->_compile_group_by() - .$this->_compile_wh('qb_having') - .$this->_compile_order_by(); // ORDER BY - - // LIMIT - if ($this->qb_limit !== FALSE OR $this->qb_offset) - { - return $this->_limit($sql."\n"); - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Compile WHERE, HAVING statements - * - * Escapes identifiers in WHERE and HAVING statements at execution time. - * - * Required so that aliases are tracked properly, regardless of whether - * where(), or_where(), having(), or_having are called prior to from(), - * join() and dbprefix is added only if needed. - * - * @param string $qb_key 'qb_where' or 'qb_having' - * @return string SQL statement - */ - protected function _compile_wh($qb_key) - { - if (count($this->$qb_key) > 0) - { - for ($i = 0, $c = count($this->$qb_key); $i < $c; $i++) - { - // Is this condition already compiled? - if (is_string($this->{$qb_key}[$i])) - { - continue; - } - elseif ($this->{$qb_key}[$i]['escape'] === FALSE) - { - $this->{$qb_key}[$i] = $this->{$qb_key}[$i]['condition'].(isset($this->{$qb_key}[$i]['value']) ? ' '.$this->{$qb_key}[$i]['value'] : ''); - continue; - } - - // Split multiple conditions - $conditions = preg_split( - '/((?:^|\s+)AND\s+|(?:^|\s+)OR\s+)/i', - $this->{$qb_key}[$i]['condition'], - -1, - PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY - ); - - for ($ci = 0, $cc = count($conditions); $ci < $cc; $ci++) - { - if (($op = $this->_get_operator($conditions[$ci])) === FALSE - OR ! preg_match('/^(\(?)(.*)('.preg_quote($op, '/').')\s*(.*(? '(test <= foo)', /* the whole thing */ - // 1 => '(', /* optional */ - // 2 => 'test', /* the field name */ - // 3 => ' <= ', /* $op */ - // 4 => 'foo', /* optional, if $op is e.g. 'IS NULL' */ - // 5 => ')' /* optional */ - // ); - - if ( ! empty($matches[4])) - { - $this->_is_literal($matches[4]) OR $matches[4] = $this->protect_identifiers(trim($matches[4])); - $matches[4] = ' '.$matches[4]; - } - - $conditions[$ci] = $matches[1].$this->protect_identifiers(trim($matches[2])) - .' '.trim($matches[3]).$matches[4].$matches[5]; - } - - $this->{$qb_key}[$i] = implode('', $conditions).(isset($this->{$qb_key}[$i]['value']) ? ' '.$this->{$qb_key}[$i]['value'] : ''); - } - - return ($qb_key === 'qb_having' ? "\nHAVING " : "\nWHERE ") - .implode("\n", $this->$qb_key); - } - - return ''; - } - - // -------------------------------------------------------------------- - - /** - * Compile GROUP BY - * - * Escapes identifiers in GROUP BY statements at execution time. - * - * Required so that aliases are tracked properly, regardless of whether - * group_by() is called prior to from(), join() and dbprefix is added - * only if needed. - * - * @return string SQL statement - */ - protected function _compile_group_by() - { - if (count($this->qb_groupby) > 0) - { - for ($i = 0, $c = count($this->qb_groupby); $i < $c; $i++) - { - // Is it already compiled? - if (is_string($this->qb_groupby[$i])) - { - continue; - } - - $this->qb_groupby[$i] = ($this->qb_groupby[$i]['escape'] === FALSE OR $this->_is_literal($this->qb_groupby[$i]['field'])) - ? $this->qb_groupby[$i]['field'] - : $this->protect_identifiers($this->qb_groupby[$i]['field']); - } - - return "\nGROUP BY ".implode(', ', $this->qb_groupby); - } - - return ''; - } - - // -------------------------------------------------------------------- - - /** - * Compile ORDER BY - * - * Escapes identifiers in ORDER BY statements at execution time. - * - * Required so that aliases are tracked properly, regardless of whether - * order_by() is called prior to from(), join() and dbprefix is added - * only if needed. - * - * @return string SQL statement - */ - protected function _compile_order_by() - { - if (empty($this->qb_orderby)) - { - return ''; - } - - for ($i = 0, $c = count($this->qb_orderby); $i < $c; $i++) - { - if (is_string($this->qb_orderby[$i])) - { - continue; - } - - if ($this->qb_orderby[$i]['escape'] !== FALSE && ! $this->_is_literal($this->qb_orderby[$i]['field'])) - { - $this->qb_orderby[$i]['field'] = $this->protect_identifiers($this->qb_orderby[$i]['field']); - } - - $this->qb_orderby[$i] = $this->qb_orderby[$i]['field'].$this->qb_orderby[$i]['direction']; - } - - return "\nORDER BY ".implode(', ', $this->qb_orderby); - } - - // -------------------------------------------------------------------- - - /** - * Object to Array - * - * Takes an object as input and converts the class variables to array key/vals - * - * @param object - * @return array - */ - protected function _object_to_array($object) - { - if ( ! is_object($object)) - { - return $object; - } - - $array = array(); - foreach (get_object_vars($object) as $key => $val) - { - // There are some built in keys we need to ignore for this conversion - if ( ! is_object($val) && ! is_array($val) && $key !== '_parent_name') - { - $array[$key] = $val; - } - } - - return $array; - } - - // -------------------------------------------------------------------- - - /** - * Object to Array - * - * Takes an object as input and converts the class variables to array key/vals - * - * @param object - * @return array - */ - protected function _object_to_array_batch($object) - { - if ( ! is_object($object)) - { - return $object; - } - - $array = array(); - $out = get_object_vars($object); - $fields = array_keys($out); - - foreach ($fields as $val) - { - // There are some built in keys we need to ignore for this conversion - if ($val !== '_parent_name') - { - $i = 0; - foreach ($out[$val] as $data) - { - $array[$i++][$val] = $data; - } - } - } - - return $array; - } - - // -------------------------------------------------------------------- - - /** - * Start Cache - * - * Starts QB caching - * - * @return CI_DB_query_builder - */ - public function start_cache() - { - $this->qb_caching = TRUE; - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Stop Cache - * - * Stops QB caching - * - * @return CI_DB_query_builder - */ - public function stop_cache() - { - $this->qb_caching = FALSE; - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Flush Cache - * - * Empties the QB cache - * - * @return CI_DB_query_builder - */ - public function flush_cache() - { - $this->_reset_run(array( - 'qb_cache_select' => array(), - 'qb_cache_from' => array(), - 'qb_cache_join' => array(), - 'qb_cache_where' => array(), - 'qb_cache_groupby' => array(), - 'qb_cache_having' => array(), - 'qb_cache_orderby' => array(), - 'qb_cache_set' => array(), - 'qb_cache_exists' => array(), - 'qb_cache_no_escape' => array(), - 'qb_cache_aliased_tables' => array() - )); - - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Merge Cache - * - * When called, this function merges any cached QB arrays with - * locally called ones. - * - * @return void - */ - protected function _merge_cache() - { - if (count($this->qb_cache_exists) === 0) - { - return; - } - elseif (in_array('select', $this->qb_cache_exists, TRUE)) - { - $qb_no_escape = $this->qb_cache_no_escape; - } - - foreach (array_unique($this->qb_cache_exists) as $val) // select, from, etc. - { - $qb_variable = 'qb_'.$val; - $qb_cache_var = 'qb_cache_'.$val; - $qb_new = $this->$qb_cache_var; - - for ($i = 0, $c = count($this->$qb_variable); $i < $c; $i++) - { - if ( ! in_array($this->{$qb_variable}[$i], $qb_new, TRUE)) - { - $qb_new[] = $this->{$qb_variable}[$i]; - if ($val === 'select') - { - $qb_no_escape[] = $this->qb_no_escape[$i]; - } - } - } - - $this->$qb_variable = $qb_new; - if ($val === 'select') - { - $this->qb_no_escape = $qb_no_escape; - } - } - } - - // -------------------------------------------------------------------- - - /** - * Is literal - * - * Determines if a string represents a literal value or a field name - * - * @param string $str - * @return bool - */ - protected function _is_literal($str) - { - $str = trim($str); - - if (empty($str) OR ctype_digit($str) OR (string) (float) $str === $str OR in_array(strtoupper($str), array('TRUE', 'FALSE'), TRUE)) - { - return TRUE; - } - - static $_str; - - if (empty($_str)) - { - $_str = ($this->_escape_char !== '"') - ? array('"', "'") : array("'"); - } - - return in_array($str[0], $_str, TRUE); - } - - // -------------------------------------------------------------------- - - /** - * Reset Query Builder values. - * - * Publicly-visible method to reset the QB values. - * - * @return CI_DB_query_builder - */ - public function reset_query() - { - $this->_reset_select(); - $this->_reset_write(); - return $this; - } - - // -------------------------------------------------------------------- - - /** - * Resets the query builder values. Called by the get() function - * - * @param array An array of fields to reset - * @return void - */ - protected function _reset_run($qb_reset_items) - { - foreach ($qb_reset_items as $item => $default_value) - { - $this->$item = $default_value; - } - } - - // -------------------------------------------------------------------- - - /** - * Resets the query builder values. Called by the get() function - * - * @return void - */ - protected function _reset_select() - { - $this->_reset_run(array( - 'qb_select' => array(), - 'qb_from' => array(), - 'qb_join' => array(), - 'qb_where' => array(), - 'qb_groupby' => array(), - 'qb_having' => array(), - 'qb_orderby' => array(), - 'qb_aliased_tables' => array(), - 'qb_no_escape' => array(), - 'qb_distinct' => FALSE, - 'qb_limit' => FALSE, - 'qb_offset' => FALSE - )); - } - - // -------------------------------------------------------------------- - - /** - * Resets the query builder "write" values. - * - * Called by the insert() update() insert_batch() update_batch() and delete() functions - * - * @return void - */ - protected function _reset_write() - { - $this->_reset_run(array( - 'qb_set' => array(), - 'qb_set_ub' => array(), - 'qb_from' => array(), - 'qb_join' => array(), - 'qb_where' => array(), - 'qb_orderby' => array(), - 'qb_keys' => array(), - 'qb_limit' => FALSE - )); - } - -} diff --git a/system/database/DB_result.php b/system/database/DB_result.php deleted file mode 100644 index a5a4ca2..0000000 --- a/system/database/DB_result.php +++ /dev/null @@ -1,665 +0,0 @@ -conn_id = $driver_object->conn_id; - $this->result_id = $driver_object->result_id; - } - - // -------------------------------------------------------------------- - - /** - * Number of rows in the result set - * - * @return int - */ - public function num_rows() - { - if (is_int($this->num_rows)) - { - return $this->num_rows; - } - elseif (count($this->result_array) > 0) - { - return $this->num_rows = count($this->result_array); - } - elseif (count($this->result_object) > 0) - { - return $this->num_rows = count($this->result_object); - } - - return $this->num_rows = count($this->result_array()); - } - - // -------------------------------------------------------------------- - - /** - * Query result. Acts as a wrapper function for the following functions. - * - * @param string $type 'object', 'array' or a custom class name - * @return array - */ - public function result($type = 'object') - { - if ($type === 'array') - { - return $this->result_array(); - } - elseif ($type === 'object') - { - return $this->result_object(); - } - - return $this->custom_result_object($type); - } - - // -------------------------------------------------------------------- - - /** - * Custom query result. - * - * @param string $class_name - * @return array - */ - public function custom_result_object($class_name) - { - if (isset($this->custom_result_object[$class_name])) - { - return $this->custom_result_object[$class_name]; - } - elseif ( ! $this->result_id OR $this->num_rows === 0) - { - return array(); - } - - // Don't fetch the result set again if we already have it - $_data = NULL; - if (($c = count($this->result_array)) > 0) - { - $_data = 'result_array'; - } - elseif (($c = count($this->result_object)) > 0) - { - $_data = 'result_object'; - } - - if ($_data !== NULL) - { - for ($i = 0; $i < $c; $i++) - { - $this->custom_result_object[$class_name][$i] = new $class_name(); - - foreach ($this->{$_data}[$i] as $key => $value) - { - $this->custom_result_object[$class_name][$i]->$key = $value; - } - } - - return $this->custom_result_object[$class_name]; - } - - is_null($this->row_data) OR $this->data_seek(0); - $this->custom_result_object[$class_name] = array(); - - while ($row = $this->_fetch_object($class_name)) - { - $this->custom_result_object[$class_name][] = $row; - } - - return $this->custom_result_object[$class_name]; - } - - // -------------------------------------------------------------------- - - /** - * Query result. "object" version. - * - * @return array - */ - public function result_object() - { - if (count($this->result_object) > 0) - { - return $this->result_object; - } - - // In the event that query caching is on, the result_id variable - // will not be a valid resource so we'll simply return an empty - // array. - if ( ! $this->result_id OR $this->num_rows === 0) - { - return array(); - } - - if (($c = count($this->result_array)) > 0) - { - for ($i = 0; $i < $c; $i++) - { - $this->result_object[$i] = (object) $this->result_array[$i]; - } - - return $this->result_object; - } - - is_null($this->row_data) OR $this->data_seek(0); - while ($row = $this->_fetch_object()) - { - $this->result_object[] = $row; - } - - return $this->result_object; - } - - // -------------------------------------------------------------------- - - /** - * Query result. "array" version. - * - * @return array - */ - public function result_array() - { - if (count($this->result_array) > 0) - { - return $this->result_array; - } - - // In the event that query caching is on, the result_id variable - // will not be a valid resource so we'll simply return an empty - // array. - if ( ! $this->result_id OR $this->num_rows === 0) - { - return array(); - } - - if (($c = count($this->result_object)) > 0) - { - for ($i = 0; $i < $c; $i++) - { - $this->result_array[$i] = (array) $this->result_object[$i]; - } - - return $this->result_array; - } - - is_null($this->row_data) OR $this->data_seek(0); - while ($row = $this->_fetch_assoc()) - { - $this->result_array[] = $row; - } - - return $this->result_array; - } - - // -------------------------------------------------------------------- - - /** - * Row - * - * A wrapper method. - * - * @param mixed $n - * @param string $type 'object' or 'array' - * @return mixed - */ - public function row($n = 0, $type = 'object') - { - if ( ! is_numeric($n)) - { - // We cache the row data for subsequent uses - is_array($this->row_data) OR $this->row_data = $this->row_array(0); - - // array_key_exists() instead of isset() to allow for NULL values - if (empty($this->row_data) OR ! array_key_exists($n, $this->row_data)) - { - return NULL; - } - - return $this->row_data[$n]; - } - - if ($type === 'object') return $this->row_object($n); - elseif ($type === 'array') return $this->row_array($n); - - return $this->custom_row_object($n, $type); - } - - // -------------------------------------------------------------------- - - /** - * Assigns an item into a particular column slot - * - * @param mixed $key - * @param mixed $value - * @return void - */ - public function set_row($key, $value = NULL) - { - // We cache the row data for subsequent uses - if ( ! is_array($this->row_data)) - { - $this->row_data = $this->row_array(0); - } - - if (is_array($key)) - { - foreach ($key as $k => $v) - { - $this->row_data[$k] = $v; - } - return; - } - - if ($key !== '' && $value !== NULL) - { - $this->row_data[$key] = $value; - } - } - - // -------------------------------------------------------------------- - - /** - * Returns a single result row - custom object version - * - * @param int $n - * @param string $type - * @return object - */ - public function custom_row_object($n, $type) - { - isset($this->custom_result_object[$type]) OR $this->custom_result_object($type); - - if (count($this->custom_result_object[$type]) === 0) - { - return NULL; - } - - if ($n !== $this->current_row && isset($this->custom_result_object[$type][$n])) - { - $this->current_row = $n; - } - - return $this->custom_result_object[$type][$this->current_row]; - } - - // -------------------------------------------------------------------- - - /** - * Returns a single result row - object version - * - * @param int $n - * @return object - */ - public function row_object($n = 0) - { - $result = $this->result_object(); - if (count($result) === 0) - { - return NULL; - } - - if ($n !== $this->current_row && isset($result[$n])) - { - $this->current_row = $n; - } - - return $result[$this->current_row]; - } - - // -------------------------------------------------------------------- - - /** - * Returns a single result row - array version - * - * @param int $n - * @return array - */ - public function row_array($n = 0) - { - $result = $this->result_array(); - if (count($result) === 0) - { - return NULL; - } - - if ($n !== $this->current_row && isset($result[$n])) - { - $this->current_row = $n; - } - - return $result[$this->current_row]; - } - - // -------------------------------------------------------------------- - - /** - * Returns the "first" row - * - * @param string $type - * @return mixed - */ - public function first_row($type = 'object') - { - $result = $this->result($type); - return (count($result) === 0) ? NULL : $result[0]; - } - - // -------------------------------------------------------------------- - - /** - * Returns the "last" row - * - * @param string $type - * @return mixed - */ - public function last_row($type = 'object') - { - $result = $this->result($type); - return (count($result) === 0) ? NULL : $result[count($result) - 1]; - } - - // -------------------------------------------------------------------- - - /** - * Returns the "next" row - * - * @param string $type - * @return mixed - */ - public function next_row($type = 'object') - { - $result = $this->result($type); - if (count($result) === 0) - { - return NULL; - } - - return isset($result[$this->current_row + 1]) - ? $result[++$this->current_row] - : NULL; - } - - // -------------------------------------------------------------------- - - /** - * Returns the "previous" row - * - * @param string $type - * @return mixed - */ - public function previous_row($type = 'object') - { - $result = $this->result($type); - if (count($result) === 0) - { - return NULL; - } - - if (isset($result[$this->current_row - 1])) - { - --$this->current_row; - } - return $result[$this->current_row]; - } - - // -------------------------------------------------------------------- - - /** - * Returns an unbuffered row and move pointer to next row - * - * @param string $type 'array', 'object' or a custom class name - * @return mixed - */ - public function unbuffered_row($type = 'object') - { - if ($type === 'array') - { - return $this->_fetch_assoc(); - } - elseif ($type === 'object') - { - return $this->_fetch_object(); - } - - return $this->_fetch_object($type); - } - - // -------------------------------------------------------------------- - - /** - * The following methods are normally overloaded by the identically named - * methods in the platform-specific driver -- except when query caching - * is used. When caching is enabled we do not load the other driver. - * These functions are primarily here to prevent undefined function errors - * when a cached result object is in use. They are not otherwise fully - * operational due to the unavailability of the database resource IDs with - * cached results. - */ - - // -------------------------------------------------------------------- - - /** - * Number of fields in the result set - * - * Overridden by driver result classes. - * - * @return int - */ - public function num_fields() - { - return 0; - } - - // -------------------------------------------------------------------- - - /** - * Fetch Field Names - * - * Generates an array of column names. - * - * Overridden by driver result classes. - * - * @return array - */ - public function list_fields() - { - return array(); - } - - // -------------------------------------------------------------------- - - /** - * Field data - * - * Generates an array of objects containing field meta-data. - * - * Overridden by driver result classes. - * - * @return array - */ - public function field_data() - { - return array(); - } - - // -------------------------------------------------------------------- - - /** - * Free the result - * - * Overridden by driver result classes. - * - * @return void - */ - public function free_result() - { - $this->result_id = FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Data Seek - * - * Moves the internal pointer to the desired offset. We call - * this internally before fetching results to make sure the - * result set starts at zero. - * - * Overridden by driver result classes. - * - * @param int $n - * @return bool - */ - public function data_seek($n = 0) - { - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Result - associative array - * - * Returns the result set as an array. - * - * Overridden by driver result classes. - * - * @return array - */ - protected function _fetch_assoc() - { - return array(); - } - - // -------------------------------------------------------------------- - - /** - * Result - object - * - * Returns the result set as an object. - * - * Overridden by driver result classes. - * - * @param string $class_name - * @return object - */ - protected function _fetch_object($class_name = 'stdClass') - { - return new $class_name(); - } - -} diff --git a/system/database/DB_utility.php b/system/database/DB_utility.php deleted file mode 100644 index 8680176..0000000 --- a/system/database/DB_utility.php +++ /dev/null @@ -1,424 +0,0 @@ -db =& $db; - log_message('info', 'Database Utility Class Initialized'); - } - - // -------------------------------------------------------------------- - - /** - * List databases - * - * @return array - */ - public function list_databases() - { - // Is there a cached result? - if (isset($this->db->data_cache['db_names'])) - { - return $this->db->data_cache['db_names']; - } - elseif ($this->_list_databases === FALSE) - { - return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE; - } - - $this->db->data_cache['db_names'] = array(); - - $query = $this->db->query($this->_list_databases); - if ($query === FALSE) - { - return $this->db->data_cache['db_names']; - } - - for ($i = 0, $query = $query->result_array(), $c = count($query); $i < $c; $i++) - { - $this->db->data_cache['db_names'][] = current($query[$i]); - } - - return $this->db->data_cache['db_names']; - } - - // -------------------------------------------------------------------- - - /** - * Determine if a particular database exists - * - * @param string $database_name - * @return bool - */ - public function database_exists($database_name) - { - return in_array($database_name, $this->list_databases()); - } - - // -------------------------------------------------------------------- - - /** - * Optimize Table - * - * @param string $table_name - * @return mixed - */ - public function optimize_table($table_name) - { - if ($this->_optimize_table === FALSE) - { - return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE; - } - - $query = $this->db->query(sprintf($this->_optimize_table, $this->db->escape_identifiers($table_name))); - if ($query !== FALSE) - { - $query = $query->result_array(); - return current($query); - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Optimize Database - * - * @return mixed - */ - public function optimize_database() - { - if ($this->_optimize_table === FALSE) - { - return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE; - } - - $result = array(); - foreach ($this->db->list_tables() as $table_name) - { - $res = $this->db->query(sprintf($this->_optimize_table, $this->db->escape_identifiers($table_name))); - if (is_bool($res)) - { - return $res; - } - - // Build the result array... - $res = $res->result_array(); - $res = current($res); - $key = str_replace($this->db->database.'.', '', current($res)); - $keys = array_keys($res); - unset($res[$keys[0]]); - - $result[$key] = $res; - } - - return $result; - } - - // -------------------------------------------------------------------- - - /** - * Repair Table - * - * @param string $table_name - * @return mixed - */ - public function repair_table($table_name) - { - if ($this->_repair_table === FALSE) - { - return ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE; - } - - $query = $this->db->query(sprintf($this->_repair_table, $this->db->escape_identifiers($table_name))); - if (is_bool($query)) - { - return $query; - } - - $query = $query->result_array(); - return current($query); - } - - // -------------------------------------------------------------------- - - /** - * Generate CSV from a query result object - * - * @param object $query Query result object - * @param string $delim Delimiter (default: ,) - * @param string $newline Newline character (default: \n) - * @param string $enclosure Enclosure (default: ") - * @return string - */ - public function csv_from_result($query, $delim = ',', $newline = "\n", $enclosure = '"') - { - if ( ! is_object($query) OR ! method_exists($query, 'list_fields')) - { - show_error('You must submit a valid result object'); - } - - $out = ''; - // First generate the headings from the table column names - foreach ($query->list_fields() as $name) - { - $out .= $enclosure.str_replace($enclosure, $enclosure.$enclosure, $name).$enclosure.$delim; - } - - $out = substr($out, 0, -strlen($delim)).$newline; - - // Next blast through the result array and build out the rows - while ($row = $query->unbuffered_row('array')) - { - $line = array(); - foreach ($row as $item) - { - $line[] = $enclosure.str_replace($enclosure, $enclosure.$enclosure, $item).$enclosure; - } - $out .= implode($delim, $line).$newline; - } - - return $out; - } - - // -------------------------------------------------------------------- - - /** - * Generate XML data from a query result object - * - * @param object $query Query result object - * @param array $params Any preferences - * @return string - */ - public function xml_from_result($query, $params = array()) - { - if ( ! is_object($query) OR ! method_exists($query, 'list_fields')) - { - show_error('You must submit a valid result object'); - } - - // Set our default values - foreach (array('root' => 'root', 'element' => 'element', 'newline' => "\n", 'tab' => "\t") as $key => $val) - { - if ( ! isset($params[$key])) - { - $params[$key] = $val; - } - } - - // Create variables for convenience - extract($params); - - // Load the xml helper - get_instance()->load->helper('xml'); - - // Generate the result - $xml = '<'.$root.'>'.$newline; - while ($row = $query->unbuffered_row()) - { - $xml .= $tab.'<'.$element.'>'.$newline; - foreach ($row as $key => $val) - { - $xml .= $tab.$tab.'<'.$key.'>'.xml_convert($val).''.$newline; - } - $xml .= $tab.''.$newline; - } - - return $xml.''.$newline; - } - - // -------------------------------------------------------------------- - - /** - * Database Backup - * - * @param array $params - * @return string - */ - public function backup($params = array()) - { - // If the parameters have not been submitted as an - // array then we know that it is simply the table - // name, which is a valid short cut. - if (is_string($params)) - { - $params = array('tables' => $params); - } - - // Set up our default preferences - $prefs = array( - 'tables' => array(), - 'ignore' => array(), - 'filename' => '', - 'format' => 'gzip', // gzip, zip, txt - 'add_drop' => TRUE, - 'add_insert' => TRUE, - 'newline' => "\n", - 'foreign_key_checks' => TRUE - ); - - // Did the user submit any preferences? If so set them.... - if (count($params) > 0) - { - foreach ($prefs as $key => $val) - { - if (isset($params[$key])) - { - $prefs[$key] = $params[$key]; - } - } - } - - // Are we backing up a complete database or individual tables? - // If no table names were submitted we'll fetch the entire table list - if (count($prefs['tables']) === 0) - { - $prefs['tables'] = $this->db->list_tables(); - } - - // Validate the format - if ( ! in_array($prefs['format'], array('gzip', 'zip', 'txt'), TRUE)) - { - $prefs['format'] = 'txt'; - } - - // Is the encoder supported? If not, we'll either issue an - // error or use plain text depending on the debug settings - if (($prefs['format'] === 'gzip' && ! function_exists('gzencode')) - OR ($prefs['format'] === 'zip' && ! function_exists('gzcompress'))) - { - if ($this->db->db_debug) - { - return $this->db->display_error('db_unsupported_compression'); - } - - $prefs['format'] = 'txt'; - } - - // Was a Zip file requested? - if ($prefs['format'] === 'zip') - { - // Set the filename if not provided (only needed with Zip files) - if ($prefs['filename'] === '') - { - $prefs['filename'] = (count($prefs['tables']) === 1 ? $prefs['tables'] : $this->db->database) - .date('Y-m-d_H-i', time()).'.sql'; - } - else - { - // If they included the .zip file extension we'll remove it - if (preg_match('|.+?\.zip$|', $prefs['filename'])) - { - $prefs['filename'] = str_replace('.zip', '', $prefs['filename']); - } - - // Tack on the ".sql" file extension if needed - if ( ! preg_match('|.+?\.sql$|', $prefs['filename'])) - { - $prefs['filename'] .= '.sql'; - } - } - - // Load the Zip class and output it - $CI =& get_instance(); - $CI->load->library('zip'); - $CI->zip->add_data($prefs['filename'], $this->_backup($prefs)); - return $CI->zip->get_zip(); - } - elseif ($prefs['format'] === 'txt') // Was a text file requested? - { - return $this->_backup($prefs); - } - elseif ($prefs['format'] === 'gzip') // Was a Gzip file requested? - { - return gzencode($this->_backup($prefs)); - } - - return; - } - -} diff --git a/system/database/drivers/cubrid/cubrid_driver.php b/system/database/drivers/cubrid/cubrid_driver.php deleted file mode 100644 index 9d6afea..0000000 --- a/system/database/drivers/cubrid/cubrid_driver.php +++ /dev/null @@ -1,405 +0,0 @@ -dsn, $matches)) - { - if (stripos($matches[2], 'autocommit=off') !== FALSE) - { - $this->auto_commit = FALSE; - } - } - else - { - // If no port is defined by the user, use the default value - empty($this->port) OR $this->port = 33000; - } - } - - // -------------------------------------------------------------------- - - /** - * Non-persistent database connection - * - * @param bool $persistent - * @return resource - */ - public function db_connect($persistent = FALSE) - { - if (preg_match('/^CUBRID:[^:]+(:[0-9][1-9]{0,4})?:[^:]+:([^:]*):([^:]*):(\?.+)?$/', $this->dsn, $matches)) - { - $func = ($persistent !== TRUE) ? 'cubrid_connect_with_url' : 'cubrid_pconnect_with_url'; - return ($matches[2] === '' && $matches[3] === '' && $this->username !== '' && $this->password !== '') - ? $func($this->dsn, $this->username, $this->password) - : $func($this->dsn); - } - - $func = ($persistent !== TRUE) ? 'cubrid_connect' : 'cubrid_pconnect'; - return ($this->username !== '') - ? $func($this->hostname, $this->port, $this->database, $this->username, $this->password) - : $func($this->hostname, $this->port, $this->database); - } - - // -------------------------------------------------------------------- - - /** - * Reconnect - * - * Keep / reestablish the db connection if no queries have been - * sent for a length of time exceeding the server's idle timeout - * - * @return void - */ - public function reconnect() - { - if (cubrid_ping($this->conn_id) === FALSE) - { - $this->conn_id = FALSE; - } - } - - // -------------------------------------------------------------------- - - /** - * Database version number - * - * @return string - */ - public function version() - { - if (isset($this->data_cache['version'])) - { - return $this->data_cache['version']; - } - - return ( ! $this->conn_id OR ($version = cubrid_get_server_info($this->conn_id)) === FALSE) - ? FALSE - : $this->data_cache['version'] = $version; - } - - // -------------------------------------------------------------------- - - /** - * Execute the query - * - * @param string $sql an SQL query - * @return resource - */ - protected function _execute($sql) - { - return cubrid_query($sql, $this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * Begin Transaction - * - * @return bool - */ - protected function _trans_begin() - { - if (($autocommit = cubrid_get_autocommit($this->conn_id)) === NULL) - { - return FALSE; - } - elseif ($autocommit === TRUE) - { - return cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_FALSE); - } - - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Commit Transaction - * - * @return bool - */ - protected function _trans_commit() - { - if ( ! cubrid_commit($this->conn_id)) - { - return FALSE; - } - - if ($this->auto_commit && ! cubrid_get_autocommit($this->conn_id)) - { - return cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_TRUE); - } - - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Rollback Transaction - * - * @return bool - */ - protected function _trans_rollback() - { - if ( ! cubrid_rollback($this->conn_id)) - { - return FALSE; - } - - if ($this->auto_commit && ! cubrid_get_autocommit($this->conn_id)) - { - cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_TRUE); - } - - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Platform-dependent string escape - * - * @param string - * @return string - */ - protected function _escape_str($str) - { - return cubrid_real_escape_string($str, $this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * Affected Rows - * - * @return int - */ - public function affected_rows() - { - return cubrid_affected_rows(); - } - - // -------------------------------------------------------------------- - - /** - * Insert ID - * - * @return int - */ - public function insert_id() - { - return cubrid_insert_id($this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * List table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool $prefix_limit - * @return string - */ - protected function _list_tables($prefix_limit = FALSE) - { - $sql = 'SHOW TABLES'; - - if ($prefix_limit !== FALSE && $this->dbprefix !== '') - { - return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'"; - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Show column query - * - * Generates a platform-specific query string so that the column names can be fetched - * - * @param string $table - * @return string - */ - protected function _list_columns($table = '') - { - return 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE); - } - - // -------------------------------------------------------------------- - - /** - * Returns an object with field data - * - * @param string $table - * @return array - */ - public function field_data($table) - { - if (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE) - { - return FALSE; - } - $query = $query->result_object(); - - $retval = array(); - for ($i = 0, $c = count($query); $i < $c; $i++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = $query[$i]->Field; - - sscanf($query[$i]->Type, '%[a-z](%d)', - $retval[$i]->type, - $retval[$i]->max_length - ); - - $retval[$i]->default = $query[$i]->Default; - $retval[$i]->primary_key = (int) ($query[$i]->Key === 'PRI'); - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Error - * - * Returns an array containing code and message of the last - * database error that has occurred. - * - * @return array - */ - public function error() - { - return array('code' => cubrid_errno($this->conn_id), 'message' => cubrid_error($this->conn_id)); - } - - // -------------------------------------------------------------------- - - /** - * FROM tables - * - * Groups tables in FROM clauses if needed, so there is no confusion - * about operator precedence. - * - * @return string - */ - protected function _from_tables() - { - if ( ! empty($this->qb_join) && count($this->qb_from) > 1) - { - return '('.implode(', ', $this->qb_from).')'; - } - - return implode(', ', $this->qb_from); - } - - // -------------------------------------------------------------------- - - /** - * Close DB Connection - * - * @return void - */ - protected function _close() - { - cubrid_close($this->conn_id); - } - -} diff --git a/system/database/drivers/cubrid/cubrid_forge.php b/system/database/drivers/cubrid/cubrid_forge.php deleted file mode 100644 index 95e7ca1..0000000 --- a/system/database/drivers/cubrid/cubrid_forge.php +++ /dev/null @@ -1,230 +0,0 @@ - 'INTEGER', - 'SMALLINT' => 'INTEGER', - 'INT' => 'BIGINT', - 'INTEGER' => 'BIGINT', - 'BIGINT' => 'NUMERIC', - 'FLOAT' => 'DOUBLE', - 'REAL' => 'DOUBLE' - ); - - // -------------------------------------------------------------------- - - /** - * ALTER TABLE - * - * @param string $alter_type ALTER type - * @param string $table Table name - * @param mixed $field Column definition - * @return string|string[] - */ - protected function _alter_table($alter_type, $table, $field) - { - if (in_array($alter_type, array('DROP', 'ADD'), TRUE)) - { - return parent::_alter_table($alter_type, $table, $field); - } - - $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table); - $sqls = array(); - for ($i = 0, $c = count($field); $i < $c; $i++) - { - if ($field[$i]['_literal'] !== FALSE) - { - $sqls[] = $sql.' CHANGE '.$field[$i]['_literal']; - } - else - { - $alter_type = empty($field[$i]['new_name']) ? ' MODIFY ' : ' CHANGE '; - $sqls[] = $sql.$alter_type.$this->_process_column($field[$i]); - } - } - - return $sqls; - } - - // -------------------------------------------------------------------- - - /** - * Process column - * - * @param array $field - * @return string - */ - protected function _process_column($field) - { - $extra_clause = isset($field['after']) - ? ' AFTER '.$this->db->escape_identifiers($field['after']) : ''; - - if (empty($extra_clause) && isset($field['first']) && $field['first'] === TRUE) - { - $extra_clause = ' FIRST'; - } - - return $this->db->escape_identifiers($field['name']) - .(empty($field['new_name']) ? '' : ' '.$this->db->escape_identifiers($field['new_name'])) - .' '.$field['type'].$field['length'] - .$field['unsigned'] - .$field['null'] - .$field['default'] - .$field['auto_increment'] - .$field['unique'] - .$extra_clause; - } - - // -------------------------------------------------------------------- - - /** - * Field attribute TYPE - * - * Performs a data type mapping between different databases. - * - * @param array &$attributes - * @return void - */ - protected function _attr_type(&$attributes) - { - switch (strtoupper($attributes['TYPE'])) - { - case 'TINYINT': - $attributes['TYPE'] = 'SMALLINT'; - $attributes['UNSIGNED'] = FALSE; - return; - case 'MEDIUMINT': - $attributes['TYPE'] = 'INTEGER'; - $attributes['UNSIGNED'] = FALSE; - return; - case 'LONGTEXT': - $attributes['TYPE'] = 'STRING'; - return; - default: return; - } - } - - // -------------------------------------------------------------------- - - /** - * Process indexes - * - * @param string $table (ignored) - * @return string - */ - protected function _process_indexes($table) - { - $sql = ''; - - for ($i = 0, $c = count($this->keys); $i < $c; $i++) - { - if (is_array($this->keys[$i])) - { - for ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++) - { - if ( ! isset($this->fields[$this->keys[$i][$i2]])) - { - unset($this->keys[$i][$i2]); - continue; - } - } - } - elseif ( ! isset($this->fields[$this->keys[$i]])) - { - unset($this->keys[$i]); - continue; - } - - is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]); - - $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i])) - .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')'; - } - - $this->keys = array(); - - return $sql; - } - -} diff --git a/system/database/drivers/cubrid/cubrid_result.php b/system/database/drivers/cubrid/cubrid_result.php deleted file mode 100644 index a71b1a2..0000000 --- a/system/database/drivers/cubrid/cubrid_result.php +++ /dev/null @@ -1,177 +0,0 @@ -num_rows) - ? $this->num_rows - : $this->num_rows = cubrid_num_rows($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Number of fields in the result set - * - * @return int - */ - public function num_fields() - { - return cubrid_num_fields($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Fetch Field Names - * - * Generates an array of column names - * - * @return array - */ - public function list_fields() - { - return cubrid_column_names($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Field data - * - * Generates an array of objects containing field meta-data - * - * @return array - */ - public function field_data() - { - $retval = array(); - - for ($i = 0, $c = $this->num_fields(); $i < $c; $i++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = cubrid_field_name($this->result_id, $i); - $retval[$i]->type = cubrid_field_type($this->result_id, $i); - $retval[$i]->max_length = cubrid_field_len($this->result_id, $i); - $retval[$i]->primary_key = (int) (strpos(cubrid_field_flags($this->result_id, $i), 'primary_key') !== FALSE); - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Free the result - * - * @return void - */ - public function free_result() - { - if (is_resource($this->result_id) OR - (get_resource_type($this->result_id) === 'Unknown' && preg_match('/Resource id #/', strval($this->result_id)))) - { - cubrid_close_request($this->result_id); - $this->result_id = FALSE; - } - } - - // -------------------------------------------------------------------- - - /** - * Data Seek - * - * Moves the internal pointer to the desired offset. We call - * this internally before fetching results to make sure the - * result set starts at zero. - * - * @param int $n - * @return bool - */ - public function data_seek($n = 0) - { - return cubrid_data_seek($this->result_id, $n); - } - - // -------------------------------------------------------------------- - - /** - * Result - associative array - * - * Returns the result set as an array - * - * @return array - */ - protected function _fetch_assoc() - { - return cubrid_fetch_assoc($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Result - object - * - * Returns the result set as an object - * - * @param string $class_name - * @return object - */ - protected function _fetch_object($class_name = 'stdClass') - { - return cubrid_fetch_object($this->result_id, $class_name); - } - -} diff --git a/system/database/drivers/cubrid/cubrid_utility.php b/system/database/drivers/cubrid/cubrid_utility.php deleted file mode 100644 index eb906ae..0000000 --- a/system/database/drivers/cubrid/cubrid_utility.php +++ /dev/null @@ -1,79 +0,0 @@ -db->data_cache['db_names'])) - { - return $this->db->data_cache['db_names']; - } - - return $this->db->data_cache['db_names'] = cubrid_list_dbs($this->db->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * CUBRID Export - * - * @param array Preferences - * @return mixed - */ - protected function _backup($params = array()) - { - // No SQL based support in CUBRID as of version 8.4.0. Database or - // table backup can be performed using CUBRID Manager - // database administration tool. - return $this->db->display_error('db_unsupported_feature'); - } -} diff --git a/system/database/drivers/cubrid/index.html b/system/database/drivers/cubrid/index.html deleted file mode 100644 index b702fbc..0000000 --- a/system/database/drivers/cubrid/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - 403 Forbidden - - - -

Directory access is forbidden.

- - - diff --git a/system/database/drivers/ibase/ibase_driver.php b/system/database/drivers/ibase/ibase_driver.php deleted file mode 100644 index fd866ff..0000000 --- a/system/database/drivers/ibase/ibase_driver.php +++ /dev/null @@ -1,413 +0,0 @@ -hostname.':'.$this->database, $this->username, $this->password, $this->char_set) - : ibase_connect($this->hostname.':'.$this->database, $this->username, $this->password, $this->char_set); - } - - // -------------------------------------------------------------------- - - /** - * Database version number - * - * @return string - */ - public function version() - { - if (isset($this->data_cache['version'])) - { - return $this->data_cache['version']; - } - - if (($service = ibase_service_attach($this->hostname, $this->username, $this->password))) - { - $this->data_cache['version'] = ibase_server_info($service, IBASE_SVC_SERVER_VERSION); - - // Don't keep the service open - ibase_service_detach($service); - return $this->data_cache['version']; - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Execute the query - * - * @param string $sql an SQL query - * @return resource - */ - protected function _execute($sql) - { - return ibase_query(isset($this->_ibase_trans) ? $this->_ibase_trans : $this->conn_id, $sql); - } - - // -------------------------------------------------------------------- - - /** - * Begin Transaction - * - * @return bool - */ - protected function _trans_begin() - { - if (($trans_handle = ibase_trans($this->conn_id)) === FALSE) - { - return FALSE; - } - - $this->_ibase_trans = $trans_handle; - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Commit Transaction - * - * @return bool - */ - protected function _trans_commit() - { - if (ibase_commit($this->_ibase_trans)) - { - $this->_ibase_trans = NULL; - return TRUE; - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Rollback Transaction - * - * @return bool - */ - protected function _trans_rollback() - { - if (ibase_rollback($this->_ibase_trans)) - { - $this->_ibase_trans = NULL; - return TRUE; - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Affected Rows - * - * @return int - */ - public function affected_rows() - { - return ibase_affected_rows($this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * Insert ID - * - * @param string $generator_name - * @param int $inc_by - * @return int - */ - public function insert_id($generator_name, $inc_by = 0) - { - //If a generator hasn't been used before it will return 0 - return ibase_gen_id('"'.$generator_name.'"', $inc_by); - } - - // -------------------------------------------------------------------- - - /** - * List table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool $prefix_limit - * @return string - */ - protected function _list_tables($prefix_limit = FALSE) - { - $sql = 'SELECT TRIM("RDB$RELATION_NAME") AS TABLE_NAME FROM "RDB$RELATIONS" WHERE "RDB$RELATION_NAME" NOT LIKE \'RDB$%\' AND "RDB$RELATION_NAME" NOT LIKE \'MON$%\''; - - if ($prefix_limit !== FALSE && $this->dbprefix !== '') - { - return $sql.' AND TRIM("RDB$RELATION_NAME") AS TABLE_NAME LIKE \''.$this->escape_like_str($this->dbprefix)."%' " - .sprintf($this->_like_escape_str, $this->_like_escape_chr); - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Show column query - * - * Generates a platform-specific query string so that the column names can be fetched - * - * @param string $table - * @return string - */ - protected function _list_columns($table = '') - { - return 'SELECT TRIM("RDB$FIELD_NAME") AS COLUMN_NAME FROM "RDB$RELATION_FIELDS" WHERE "RDB$RELATION_NAME" = '.$this->escape($table); - } - - // -------------------------------------------------------------------- - - /** - * Returns an object with field data - * - * @param string $table - * @return array - */ - public function field_data($table) - { - $sql = 'SELECT "rfields"."RDB$FIELD_NAME" AS "name", - CASE "fields"."RDB$FIELD_TYPE" - WHEN 7 THEN \'SMALLINT\' - WHEN 8 THEN \'INTEGER\' - WHEN 9 THEN \'QUAD\' - WHEN 10 THEN \'FLOAT\' - WHEN 11 THEN \'DFLOAT\' - WHEN 12 THEN \'DATE\' - WHEN 13 THEN \'TIME\' - WHEN 14 THEN \'CHAR\' - WHEN 16 THEN \'INT64\' - WHEN 27 THEN \'DOUBLE\' - WHEN 35 THEN \'TIMESTAMP\' - WHEN 37 THEN \'VARCHAR\' - WHEN 40 THEN \'CSTRING\' - WHEN 261 THEN \'BLOB\' - ELSE NULL - END AS "type", - "fields"."RDB$FIELD_LENGTH" AS "max_length", - "rfields"."RDB$DEFAULT_VALUE" AS "default" - FROM "RDB$RELATION_FIELDS" "rfields" - JOIN "RDB$FIELDS" "fields" ON "rfields"."RDB$FIELD_SOURCE" = "fields"."RDB$FIELD_NAME" - WHERE "rfields"."RDB$RELATION_NAME" = '.$this->escape($table).' - ORDER BY "rfields"."RDB$FIELD_POSITION"'; - - return (($query = $this->query($sql)) !== FALSE) - ? $query->result_object() - : FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Error - * - * Returns an array containing code and message of the last - * database error that has occurred. - * - * @return array - */ - public function error() - { - return array('code' => ibase_errcode(), 'message' => ibase_errmsg()); - } - - // -------------------------------------------------------------------- - - /** - * Update statement - * - * Generates a platform-specific update string from the supplied data - * - * @param string $table - * @param array $values - * @return string - */ - protected function _update($table, $values) - { - $this->qb_limit = FALSE; - return parent::_update($table, $values); - } - - // -------------------------------------------------------------------- - - /** - * Truncate statement - * - * Generates a platform-specific truncate string from the supplied data - * - * If the database does not support the TRUNCATE statement, - * then this method maps to 'DELETE FROM table' - * - * @param string $table - * @return string - */ - protected function _truncate($table) - { - return 'DELETE FROM '.$table; - } - - // -------------------------------------------------------------------- - - /** - * Delete statement - * - * Generates a platform-specific delete string from the supplied data - * - * @param string $table - * @return string - */ - protected function _delete($table) - { - $this->qb_limit = FALSE; - return parent::_delete($table); - } - - // -------------------------------------------------------------------- - - /** - * LIMIT - * - * Generates a platform-specific LIMIT clause - * - * @param string $sql SQL Query - * @return string - */ - protected function _limit($sql) - { - // Limit clause depends on if Interbase or Firebird - if (stripos($this->version(), 'firebird') !== FALSE) - { - $select = 'FIRST '.$this->qb_limit - .($this->qb_offset ? ' SKIP '.$this->qb_offset : ''); - } - else - { - $select = 'ROWS ' - .($this->qb_offset ? $this->qb_offset.' TO '.($this->qb_limit + $this->qb_offset) : $this->qb_limit); - } - - return preg_replace('`SELECT`i', 'SELECT '.$select, $sql, 1); - } - - // -------------------------------------------------------------------- - - /** - * Insert batch statement - * - * Generates a platform-specific insert string from the supplied data. - * - * @param string $table Table name - * @param array $keys INSERT keys - * @param array $values INSERT values - * @return string|bool - */ - protected function _insert_batch($table, $keys, $values) - { - return ($this->db_debug) ? $this->display_error('db_unsupported_feature') : FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Close DB Connection - * - * @return void - */ - protected function _close() - { - ibase_close($this->conn_id); - } - -} diff --git a/system/database/drivers/ibase/ibase_forge.php b/system/database/drivers/ibase/ibase_forge.php deleted file mode 100644 index 77aa4ae..0000000 --- a/system/database/drivers/ibase/ibase_forge.php +++ /dev/null @@ -1,251 +0,0 @@ - 'INTEGER', - 'INTEGER' => 'INT64', - 'FLOAT' => 'DOUBLE PRECISION' - ); - - /** - * NULL value representation in CREATE/ALTER TABLE statements - * - * @var string - */ - protected $_null = 'NULL'; - - // -------------------------------------------------------------------- - - /** - * Create database - * - * @param string $db_name - * @return bool - */ - public function create_database($db_name) - { - // Firebird databases are flat files, so a path is required - - // Hostname is needed for remote access - empty($this->db->hostname) OR $db_name = $this->hostname.':'.$db_name; - - return parent::create_database('"'.$db_name.'"'); - } - - // -------------------------------------------------------------------- - - /** - * Drop database - * - * @param string $db_name (ignored) - * @return bool - */ - public function drop_database($db_name) - { - if ( ! ibase_drop_db($this->conn_id)) - { - return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE; - } - elseif ( ! empty($this->db->data_cache['db_names'])) - { - $key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE); - if ($key !== FALSE) - { - unset($this->db->data_cache['db_names'][$key]); - } - } - - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * ALTER TABLE - * - * @param string $alter_type ALTER type - * @param string $table Table name - * @param mixed $field Column definition - * @return string|string[] - */ - protected function _alter_table($alter_type, $table, $field) - { - if (in_array($alter_type, array('DROP', 'ADD'), TRUE)) - { - return parent::_alter_table($alter_type, $table, $field); - } - - $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table); - $sqls = array(); - for ($i = 0, $c = count($field); $i < $c; $i++) - { - if ($field[$i]['_literal'] !== FALSE) - { - return FALSE; - } - - if (isset($field[$i]['type'])) - { - $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identififers($field[$i]['name']) - .' TYPE '.$field[$i]['type'].$field[$i]['length']; - } - - if ( ! empty($field[$i]['default'])) - { - $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name']) - .' SET DEFAULT '.$field[$i]['default']; - } - - if (isset($field[$i]['null'])) - { - $sqls[] = 'UPDATE "RDB$RELATION_FIELDS" SET "RDB$NULL_FLAG" = ' - .($field[$i]['null'] === TRUE ? 'NULL' : '1') - .' WHERE "RDB$FIELD_NAME" = '.$this->db->escape($field[$i]['name']) - .' AND "RDB$RELATION_NAME" = '.$this->db->escape($table); - } - - if ( ! empty($field[$i]['new_name'])) - { - $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name']) - .' TO '.$this->db->escape_identifiers($field[$i]['new_name']); - } - } - - return $sqls; - } - - // -------------------------------------------------------------------- - - /** - * Process column - * - * @param array $field - * @return string - */ - protected function _process_column($field) - { - return $this->db->escape_identifiers($field['name']) - .' '.$field['type'].$field['length'] - .$field['null'] - .$field['unique'] - .$field['default']; - } - - // -------------------------------------------------------------------- - - /** - * Field attribute TYPE - * - * Performs a data type mapping between different databases. - * - * @param array &$attributes - * @return void - */ - protected function _attr_type(&$attributes) - { - switch (strtoupper($attributes['TYPE'])) - { - case 'TINYINT': - $attributes['TYPE'] = 'SMALLINT'; - $attributes['UNSIGNED'] = FALSE; - return; - case 'MEDIUMINT': - $attributes['TYPE'] = 'INTEGER'; - $attributes['UNSIGNED'] = FALSE; - return; - case 'INT': - $attributes['TYPE'] = 'INTEGER'; - return; - case 'BIGINT': - $attributes['TYPE'] = 'INT64'; - return; - default: return; - } - } - - // -------------------------------------------------------------------- - - /** - * Field attribute AUTO_INCREMENT - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_auto_increment(&$attributes, &$field) - { - // Not supported - } - -} diff --git a/system/database/drivers/ibase/ibase_result.php b/system/database/drivers/ibase/ibase_result.php deleted file mode 100644 index b548f32..0000000 --- a/system/database/drivers/ibase/ibase_result.php +++ /dev/null @@ -1,161 +0,0 @@ -result_id); - } - - // -------------------------------------------------------------------- - - /** - * Fetch Field Names - * - * Generates an array of column names - * - * @return array - */ - public function list_fields() - { - $field_names = array(); - for ($i = 0, $num_fields = $this->num_fields(); $i < $num_fields; $i++) - { - $info = ibase_field_info($this->result_id, $i); - $field_names[] = $info['name']; - } - - return $field_names; - } - - // -------------------------------------------------------------------- - - /** - * Field data - * - * Generates an array of objects containing field meta-data - * - * @return array - */ - public function field_data() - { - $retval = array(); - for ($i = 0, $c = $this->num_fields(); $i < $c; $i++) - { - $info = ibase_field_info($this->result_id, $i); - - $retval[$i] = new stdClass(); - $retval[$i]->name = $info['name']; - $retval[$i]->type = $info['type']; - $retval[$i]->max_length = $info['length']; - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Free the result - * - * @return void - */ - public function free_result() - { - ibase_free_result($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Result - associative array - * - * Returns the result set as an array - * - * @return array - */ - protected function _fetch_assoc() - { - return ibase_fetch_assoc($this->result_id, IBASE_FETCH_BLOBS); - } - - // -------------------------------------------------------------------- - - /** - * Result - object - * - * Returns the result set as an object - * - * @param string $class_name - * @return object - */ - protected function _fetch_object($class_name = 'stdClass') - { - $row = ibase_fetch_object($this->result_id, IBASE_FETCH_BLOBS); - - if ($class_name === 'stdClass' OR ! $row) - { - return $row; - } - - $class_name = new $class_name(); - foreach ($row as $key => $value) - { - $class_name->$key = $value; - } - - return $class_name; - } - -} diff --git a/system/database/drivers/ibase/ibase_utility.php b/system/database/drivers/ibase/ibase_utility.php deleted file mode 100644 index a1e5d69..0000000 --- a/system/database/drivers/ibase/ibase_utility.php +++ /dev/null @@ -1,69 +0,0 @@ -db->hostname, $this->db->username, $this->db->password)) - { - $res = ibase_backup($service, $this->db->database, $filename.'.fbk'); - - // Close the service connection - ibase_service_detach($service); - return $res; - } - - return FALSE; - } - -} diff --git a/system/database/drivers/ibase/index.html b/system/database/drivers/ibase/index.html deleted file mode 100644 index b702fbc..0000000 --- a/system/database/drivers/ibase/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - 403 Forbidden - - - -

Directory access is forbidden.

- - - diff --git a/system/database/drivers/index.html b/system/database/drivers/index.html deleted file mode 100644 index b702fbc..0000000 --- a/system/database/drivers/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - 403 Forbidden - - - -

Directory access is forbidden.

- - - diff --git a/system/database/drivers/mssql/index.html b/system/database/drivers/mssql/index.html deleted file mode 100644 index b702fbc..0000000 --- a/system/database/drivers/mssql/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - 403 Forbidden - - - -

Directory access is forbidden.

- - - diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php deleted file mode 100644 index b2b17d0..0000000 --- a/system/database/drivers/mssql/mssql_driver.php +++ /dev/null @@ -1,518 +0,0 @@ -port)) - { - $this->hostname .= (DIRECTORY_SEPARATOR === '\\' ? ',' : ':').$this->port; - } - } - - // -------------------------------------------------------------------- - - /** - * Non-persistent database connection - * - * @param bool $persistent - * @return resource - */ - public function db_connect($persistent = FALSE) - { - $this->conn_id = ($persistent) - ? mssql_pconnect($this->hostname, $this->username, $this->password) - : mssql_connect($this->hostname, $this->username, $this->password); - - if ( ! $this->conn_id) - { - return FALSE; - } - - // ---------------------------------------------------------------- - - // Select the DB... assuming a database name is specified in the config file - if ($this->database !== '' && ! $this->db_select()) - { - log_message('error', 'Unable to select database: '.$this->database); - - return ($this->db_debug === TRUE) - ? $this->display_error('db_unable_to_select', $this->database) - : FALSE; - } - - // Determine how identifiers are escaped - $query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi'); - $query = $query->row_array(); - $this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi']; - $this->_escape_char = ($this->_quoted_identifier) ? '"' : array('[', ']'); - - return $this->conn_id; - } - - // -------------------------------------------------------------------- - - /** - * Select the database - * - * @param string $database - * @return bool - */ - public function db_select($database = '') - { - if ($database === '') - { - $database = $this->database; - } - - // Note: Escaping is required in the event that the DB name - // contains reserved characters. - if (mssql_select_db('['.$database.']', $this->conn_id)) - { - $this->database = $database; - $this->data_cache = array(); - return TRUE; - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Execute the query - * - * @param string $sql an SQL query - * @return mixed resource if rows are returned, bool otherwise - */ - protected function _execute($sql) - { - return mssql_query($sql, $this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * Begin Transaction - * - * @return bool - */ - protected function _trans_begin() - { - return $this->simple_query('BEGIN TRAN'); - } - - // -------------------------------------------------------------------- - - /** - * Commit Transaction - * - * @return bool - */ - protected function _trans_commit() - { - return $this->simple_query('COMMIT TRAN'); - } - - // -------------------------------------------------------------------- - - /** - * Rollback Transaction - * - * @return bool - */ - protected function _trans_rollback() - { - return $this->simple_query('ROLLBACK TRAN'); - } - - // -------------------------------------------------------------------- - - /** - * Affected Rows - * - * @return int - */ - public function affected_rows() - { - return mssql_rows_affected($this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * Insert ID - * - * Returns the last id created in the Identity column. - * - * @return string - */ - public function insert_id() - { - $query = version_compare($this->version(), '8', '>=') - ? 'SELECT SCOPE_IDENTITY() AS last_id' - : 'SELECT @@IDENTITY AS last_id'; - - $query = $this->query($query); - $query = $query->row(); - return $query->last_id; - } - - // -------------------------------------------------------------------- - - /** - * Set client character set - * - * @param string $charset - * @return bool - */ - protected function _db_set_charset($charset) - { - return (ini_set('mssql.charset', $charset) !== FALSE); - } - - // -------------------------------------------------------------------- - - /** - * Version number query string - * - * @return string - */ - protected function _version() - { - return "SELECT SERVERPROPERTY('ProductVersion') AS ver"; - } - - // -------------------------------------------------------------------- - - /** - * List table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool $prefix_limit - * @return string - */ - protected function _list_tables($prefix_limit = FALSE) - { - $sql = 'SELECT '.$this->escape_identifiers('name') - .' FROM '.$this->escape_identifiers('sysobjects') - .' WHERE '.$this->escape_identifiers('type')." = 'U'"; - - if ($prefix_limit !== FALSE && $this->dbprefix !== '') - { - $sql .= ' AND '.$this->escape_identifiers('name')." LIKE '".$this->escape_like_str($this->dbprefix)."%' " - .sprintf($this->_like_escape_str, $this->_like_escape_chr); - } - - return $sql.' ORDER BY '.$this->escape_identifiers('name'); - } - - // -------------------------------------------------------------------- - - /** - * List column query - * - * Generates a platform-specific query string so that the column names can be fetched - * - * @param string $table - * @return string - */ - protected function _list_columns($table = '') - { - return 'SELECT COLUMN_NAME - FROM INFORMATION_SCHEMA.Columns - WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table)); - } - - // -------------------------------------------------------------------- - - /** - * Returns an object with field data - * - * @param string $table - * @return array - */ - public function field_data($table) - { - $sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, COLUMN_DEFAULT - FROM INFORMATION_SCHEMA.Columns - WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table)); - - if (($query = $this->query($sql)) === FALSE) - { - return FALSE; - } - $query = $query->result_object(); - - $retval = array(); - for ($i = 0, $c = count($query); $i < $c; $i++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = $query[$i]->COLUMN_NAME; - $retval[$i]->type = $query[$i]->DATA_TYPE; - $retval[$i]->max_length = ($query[$i]->CHARACTER_MAXIMUM_LENGTH > 0) ? $query[$i]->CHARACTER_MAXIMUM_LENGTH : $query[$i]->NUMERIC_PRECISION; - $retval[$i]->default = $query[$i]->COLUMN_DEFAULT; - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Error - * - * Returns an array containing code and message of the last - * database error that has occurred. - * - * @return array - */ - public function error() - { - // We need this because the error info is discarded by the - // server the first time you request it, and query() already - // calls error() once for logging purposes when a query fails. - static $error = array('code' => 0, 'message' => NULL); - - $message = mssql_get_last_message(); - if ( ! empty($message)) - { - $error['code'] = $this->query('SELECT @@ERROR AS code')->row()->code; - $error['message'] = $message; - } - - return $error; - } - - // -------------------------------------------------------------------- - - /** - * Update statement - * - * Generates a platform-specific update string from the supplied data - * - * @param string $table - * @param array $values - * @return string - */ - protected function _update($table, $values) - { - $this->qb_limit = FALSE; - $this->qb_orderby = array(); - return parent::_update($table, $values); - } - - // -------------------------------------------------------------------- - - /** - * Truncate statement - * - * Generates a platform-specific truncate string from the supplied data - * - * If the database does not support the TRUNCATE statement, - * then this method maps to 'DELETE FROM table' - * - * @param string $table - * @return string - */ - protected function _truncate($table) - { - return 'TRUNCATE TABLE '.$table; - } - - // -------------------------------------------------------------------- - - /** - * Delete statement - * - * Generates a platform-specific delete string from the supplied data - * - * @param string $table - * @return string - */ - protected function _delete($table) - { - if ($this->qb_limit) - { - return 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete'; - } - - return parent::_delete($table); - } - - // -------------------------------------------------------------------- - - /** - * LIMIT - * - * Generates a platform-specific LIMIT clause - * - * @param string $sql SQL Query - * @return string - */ - protected function _limit($sql) - { - $limit = $this->qb_offset + $this->qb_limit; - - // As of SQL Server 2005 (9.0.*) ROW_NUMBER() is supported, - // however an ORDER BY clause is required for it to work - if (version_compare($this->version(), '9', '>=') && $this->qb_offset && ! empty($this->qb_orderby)) - { - $orderby = $this->_compile_order_by(); - - // We have to strip the ORDER BY clause - $sql = trim(substr($sql, 0, strrpos($sql, $orderby))); - - // Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results - if (count($this->qb_select) === 0 OR strpos(implode(',', $this->qb_select), '*') !== FALSE) - { - $select = '*'; // Inevitable - } - else - { - // Use only field names and their aliases, everything else is out of our scope. - $select = array(); - $field_regexp = ($this->_quoted_identifier) - ? '("[^\"]+")' : '(\[[^\]]+\])'; - for ($i = 0, $c = count($this->qb_select); $i < $c; $i++) - { - $select[] = preg_match('/(?:\s|\.)'.$field_regexp.'$/i', $this->qb_select[$i], $m) - ? $m[1] : $this->qb_select[$i]; - } - $select = implode(', ', $select); - } - - return 'SELECT '.$select." FROM (\n\n" - .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.trim($orderby).') AS '.$this->escape_identifiers('CI_rownum').', ', $sql) - ."\n\n) ".$this->escape_identifiers('CI_subquery') - ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit; - } - - return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql); - } - - // -------------------------------------------------------------------- - - /** - * Insert batch statement - * - * Generates a platform-specific insert string from the supplied data. - * - * @param string $table Table name - * @param array $keys INSERT keys - * @param array $values INSERT values - * @return string|bool - */ - protected function _insert_batch($table, $keys, $values) - { - // Multiple-value inserts are only supported as of SQL Server 2008 - if (version_compare($this->version(), '10', '>=')) - { - return parent::_insert_batch($table, $keys, $values); - } - - return ($this->db_debug) ? $this->display_error('db_unsupported_feature') : FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Close DB Connection - * - * @return void - */ - protected function _close() - { - mssql_close($this->conn_id); - } - -} diff --git a/system/database/drivers/mssql/mssql_forge.php b/system/database/drivers/mssql/mssql_forge.php deleted file mode 100644 index 9a3e3eb..0000000 --- a/system/database/drivers/mssql/mssql_forge.php +++ /dev/null @@ -1,151 +0,0 @@ - 'SMALLINT', - 'SMALLINT' => 'INT', - 'INT' => 'BIGINT', - 'REAL' => 'FLOAT' - ); - - // -------------------------------------------------------------------- - - /** - * ALTER TABLE - * - * @param string $alter_type ALTER type - * @param string $table Table name - * @param mixed $field Column definition - * @return string|string[] - */ - protected function _alter_table($alter_type, $table, $field) - { - if (in_array($alter_type, array('ADD', 'DROP'), TRUE)) - { - return parent::_alter_table($alter_type, $table, $field); - } - - $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ALTER COLUMN '; - $sqls = array(); - for ($i = 0, $c = count($field); $i < $c; $i++) - { - $sqls[] = $sql.$this->_process_column($field[$i]); - } - - return $sqls; - } - - // -------------------------------------------------------------------- - - /** - * Field attribute TYPE - * - * Performs a data type mapping between different databases. - * - * @param array &$attributes - * @return void - */ - protected function _attr_type(&$attributes) - { - if (isset($attributes['CONSTRAINT']) && strpos($attributes['TYPE'], 'INT') !== FALSE) - { - unset($attributes['CONSTRAINT']); - } - - switch (strtoupper($attributes['TYPE'])) - { - case 'MEDIUMINT': - $attributes['TYPE'] = 'INTEGER'; - $attributes['UNSIGNED'] = FALSE; - return; - case 'INTEGER': - $attributes['TYPE'] = 'INT'; - return; - default: return; - } - } - - // -------------------------------------------------------------------- - - /** - * Field attribute AUTO_INCREMENT - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_auto_increment(&$attributes, &$field) - { - if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE) - { - $field['auto_increment'] = ' IDENTITY(1,1)'; - } - } - -} diff --git a/system/database/drivers/mssql/mssql_result.php b/system/database/drivers/mssql/mssql_result.php deleted file mode 100644 index 8e1f416..0000000 --- a/system/database/drivers/mssql/mssql_result.php +++ /dev/null @@ -1,198 +0,0 @@ -num_rows) - ? $this->num_rows - : $this->num_rows = mssql_num_rows($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Number of fields in the result set - * - * @return int - */ - public function num_fields() - { - return mssql_num_fields($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Fetch Field Names - * - * Generates an array of column names - * - * @return array - */ - public function list_fields() - { - $field_names = array(); - mssql_field_seek($this->result_id, 0); - while ($field = mssql_fetch_field($this->result_id)) - { - $field_names[] = $field->name; - } - - return $field_names; - } - - // -------------------------------------------------------------------- - - /** - * Field data - * - * Generates an array of objects containing field meta-data - * - * @return array - */ - public function field_data() - { - $retval = array(); - for ($i = 0, $c = $this->num_fields(); $i < $c; $i++) - { - $field = mssql_fetch_field($this->result_id, $i); - - $retval[$i] = new stdClass(); - $retval[$i]->name = $field->name; - $retval[$i]->type = $field->type; - $retval[$i]->max_length = $field->max_length; - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Free the result - * - * @return void - */ - public function free_result() - { - if (is_resource($this->result_id)) - { - mssql_free_result($this->result_id); - $this->result_id = FALSE; - } - } - - // -------------------------------------------------------------------- - - /** - * Data Seek - * - * Moves the internal pointer to the desired offset. We call - * this internally before fetching results to make sure the - * result set starts at zero. - * - * @param int $n - * @return bool - */ - public function data_seek($n = 0) - { - return mssql_data_seek($this->result_id, $n); - } - - // -------------------------------------------------------------------- - - /** - * Result - associative array - * - * Returns the result set as an array - * - * @return array - */ - protected function _fetch_assoc() - { - return mssql_fetch_assoc($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Result - object - * - * Returns the result set as an object - * - * @param string $class_name - * @return object - */ - protected function _fetch_object($class_name = 'stdClass') - { - $row = mssql_fetch_object($this->result_id); - - if ($class_name === 'stdClass' OR ! $row) - { - return $row; - } - - $class_name = new $class_name(); - foreach ($row as $key => $value) - { - $class_name->$key = $value; - } - - return $class_name; - } - -} diff --git a/system/database/drivers/mssql/mssql_utility.php b/system/database/drivers/mssql/mssql_utility.php deleted file mode 100644 index 90b7107..0000000 --- a/system/database/drivers/mssql/mssql_utility.php +++ /dev/null @@ -1,77 +0,0 @@ -db->display_error('db_unsupported_feature'); - } - -} diff --git a/system/database/drivers/mysql/index.html b/system/database/drivers/mysql/index.html deleted file mode 100644 index b702fbc..0000000 --- a/system/database/drivers/mysql/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - 403 Forbidden - - - -

Directory access is forbidden.

- - - diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php deleted file mode 100644 index 05a3283..0000000 --- a/system/database/drivers/mysql/mysql_driver.php +++ /dev/null @@ -1,494 +0,0 @@ -port)) - { - $this->hostname .= ':'.$this->port; - } - } - - // -------------------------------------------------------------------- - - /** - * Non-persistent database connection - * - * @param bool $persistent - * @return resource - */ - public function db_connect($persistent = FALSE) - { - $client_flags = ($this->compress === FALSE) ? 0 : MYSQL_CLIENT_COMPRESS; - - if ($this->encrypt === TRUE) - { - $client_flags = $client_flags | MYSQL_CLIENT_SSL; - } - - // Error suppression is necessary mostly due to PHP 5.5+ issuing E_DEPRECATED messages - $this->conn_id = ($persistent === TRUE) - ? mysql_pconnect($this->hostname, $this->username, $this->password, $client_flags) - : mysql_connect($this->hostname, $this->username, $this->password, TRUE, $client_flags); - - // ---------------------------------------------------------------- - - // Select the DB... assuming a database name is specified in the config file - if ($this->database !== '' && ! $this->db_select()) - { - log_message('error', 'Unable to select database: '.$this->database); - - return ($this->db_debug === TRUE) - ? $this->display_error('db_unable_to_select', $this->database) - : FALSE; - } - - if (isset($this->stricton) && is_resource($this->conn_id)) - { - if ($this->stricton) - { - $this->simple_query('SET SESSION sql_mode = CONCAT(@@sql_mode, ",", "STRICT_ALL_TABLES")'); - } - else - { - $this->simple_query( - 'SET SESSION sql_mode = - REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( - @@sql_mode, - "STRICT_ALL_TABLES,", ""), - ",STRICT_ALL_TABLES", ""), - "STRICT_ALL_TABLES", ""), - "STRICT_TRANS_TABLES,", ""), - ",STRICT_TRANS_TABLES", ""), - "STRICT_TRANS_TABLES", "")' - ); - } - } - - return $this->conn_id; - } - - // -------------------------------------------------------------------- - - /** - * Reconnect - * - * Keep / reestablish the db connection if no queries have been - * sent for a length of time exceeding the server's idle timeout - * - * @return void - */ - public function reconnect() - { - if (mysql_ping($this->conn_id) === FALSE) - { - $this->conn_id = FALSE; - } - } - - // -------------------------------------------------------------------- - - /** - * Select the database - * - * @param string $database - * @return bool - */ - public function db_select($database = '') - { - if ($database === '') - { - $database = $this->database; - } - - if (mysql_select_db($database, $this->conn_id)) - { - $this->database = $database; - $this->data_cache = array(); - return TRUE; - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Set client character set - * - * @param string $charset - * @return bool - */ - protected function _db_set_charset($charset) - { - return mysql_set_charset($charset, $this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * Database version number - * - * @return string - */ - public function version() - { - if (isset($this->data_cache['version'])) - { - return $this->data_cache['version']; - } - - if ( ! $this->conn_id OR ($version = mysql_get_server_info($this->conn_id)) === FALSE) - { - return FALSE; - } - - return $this->data_cache['version'] = $version; - } - - // -------------------------------------------------------------------- - - /** - * Execute the query - * - * @param string $sql an SQL query - * @return mixed - */ - protected function _execute($sql) - { - return mysql_query($this->_prep_query($sql), $this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * Prep the query - * - * If needed, each database adapter can prep the query string - * - * @param string $sql an SQL query - * @return string - */ - protected function _prep_query($sql) - { - // mysql_affected_rows() returns 0 for "DELETE FROM TABLE" queries. This hack - // modifies the query so that it a proper number of affected rows is returned. - if ($this->delete_hack === TRUE && preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $sql)) - { - return trim($sql).' WHERE 1=1'; - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Begin Transaction - * - * @return bool - */ - protected function _trans_begin() - { - $this->simple_query('SET AUTOCOMMIT=0'); - return $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK - } - - // -------------------------------------------------------------------- - - /** - * Commit Transaction - * - * @return bool - */ - protected function _trans_commit() - { - if ($this->simple_query('COMMIT')) - { - $this->simple_query('SET AUTOCOMMIT=1'); - return TRUE; - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Rollback Transaction - * - * @return bool - */ - protected function _trans_rollback() - { - if ($this->simple_query('ROLLBACK')) - { - $this->simple_query('SET AUTOCOMMIT=1'); - return TRUE; - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Platform-dependent string escape - * - * @param string - * @return string - */ - protected function _escape_str($str) - { - return mysql_real_escape_string($str, $this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * Affected Rows - * - * @return int - */ - public function affected_rows() - { - return mysql_affected_rows($this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * Insert ID - * - * @return int - */ - public function insert_id() - { - return mysql_insert_id($this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * List table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool $prefix_limit - * @return string - */ - protected function _list_tables($prefix_limit = FALSE) - { - $sql = 'SHOW TABLES FROM '.$this->escape_identifiers($this->database); - - if ($prefix_limit !== FALSE && $this->dbprefix !== '') - { - return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'"; - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Show column query - * - * Generates a platform-specific query string so that the column names can be fetched - * - * @param string $table - * @return string - */ - protected function _list_columns($table = '') - { - return 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE); - } - - // -------------------------------------------------------------------- - - /** - * Returns an object with field data - * - * @param string $table - * @return array - */ - public function field_data($table) - { - if (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE) - { - return FALSE; - } - $query = $query->result_object(); - - $retval = array(); - for ($i = 0, $c = count($query); $i < $c; $i++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = $query[$i]->Field; - - sscanf($query[$i]->Type, '%[a-z](%d)', - $retval[$i]->type, - $retval[$i]->max_length - ); - - $retval[$i]->default = $query[$i]->Default; - $retval[$i]->primary_key = (int) ($query[$i]->Key === 'PRI'); - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Error - * - * Returns an array containing code and message of the last - * database error that has occurred. - * - * @return array - */ - public function error() - { - return array('code' => mysql_errno($this->conn_id), 'message' => mysql_error($this->conn_id)); - } - - // -------------------------------------------------------------------- - - /** - * FROM tables - * - * Groups tables in FROM clauses if needed, so there is no confusion - * about operator precedence. - * - * @return string - */ - protected function _from_tables() - { - if ( ! empty($this->qb_join) && count($this->qb_from) > 1) - { - return '('.implode(', ', $this->qb_from).')'; - } - - return implode(', ', $this->qb_from); - } - - // -------------------------------------------------------------------- - - /** - * Close DB Connection - * - * @return void - */ - protected function _close() - { - // Error suppression to avoid annoying E_WARNINGs in cases - // where the connection has already been closed for some reason. - @mysql_close($this->conn_id); - } - -} diff --git a/system/database/drivers/mysql/mysql_forge.php b/system/database/drivers/mysql/mysql_forge.php deleted file mode 100644 index f8a998b..0000000 --- a/system/database/drivers/mysql/mysql_forge.php +++ /dev/null @@ -1,243 +0,0 @@ -db->char_set) && ! strpos($sql, 'CHARACTER SET') && ! strpos($sql, 'CHARSET')) - { - $sql .= ' DEFAULT CHARACTER SET = '.$this->db->char_set; - } - - if ( ! empty($this->db->dbcollat) && ! strpos($sql, 'COLLATE')) - { - $sql .= ' COLLATE = '.$this->db->dbcollat; - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * ALTER TABLE - * - * @param string $alter_type ALTER type - * @param string $table Table name - * @param mixed $field Column definition - * @return string|string[] - */ - protected function _alter_table($alter_type, $table, $field) - { - if ($alter_type === 'DROP') - { - return parent::_alter_table($alter_type, $table, $field); - } - - $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table); - for ($i = 0, $c = count($field); $i < $c; $i++) - { - if ($field[$i]['_literal'] !== FALSE) - { - $field[$i] = ($alter_type === 'ADD') - ? "\n\tADD ".$field[$i]['_literal'] - : "\n\tMODIFY ".$field[$i]['_literal']; - } - else - { - if ($alter_type === 'ADD') - { - $field[$i]['_literal'] = "\n\tADD "; - } - else - { - $field[$i]['_literal'] = empty($field[$i]['new_name']) ? "\n\tMODIFY " : "\n\tCHANGE "; - } - - $field[$i] = $field[$i]['_literal'].$this->_process_column($field[$i]); - } - } - - return array($sql.implode(',', $field)); - } - - // -------------------------------------------------------------------- - - /** - * Process column - * - * @param array $field - * @return string - */ - protected function _process_column($field) - { - $extra_clause = isset($field['after']) - ? ' AFTER '.$this->db->escape_identifiers($field['after']) : ''; - - if (empty($extra_clause) && isset($field['first']) && $field['first'] === TRUE) - { - $extra_clause = ' FIRST'; - } - - - return $this->db->escape_identifiers($field['name']) - .(empty($field['new_name']) ? '' : ' '.$this->db->escape_identifiers($field['new_name'])) - .' '.$field['type'].$field['length'] - .$field['unsigned'] - .$field['null'] - .$field['default'] - .$field['auto_increment'] - .$field['unique'] - .(empty($field['comment']) ? '' : ' COMMENT '.$field['comment']) - .$extra_clause; - } - - // -------------------------------------------------------------------- - - /** - * Process indexes - * - * @param string $table (ignored) - * @return string - */ - protected function _process_indexes($table) - { - $sql = ''; - - for ($i = 0, $c = count($this->keys); $i < $c; $i++) - { - if (is_array($this->keys[$i])) - { - for ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++) - { - if ( ! isset($this->fields[$this->keys[$i][$i2]])) - { - unset($this->keys[$i][$i2]); - continue; - } - } - } - elseif ( ! isset($this->fields[$this->keys[$i]])) - { - unset($this->keys[$i]); - continue; - } - - is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]); - - $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i])) - .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')'; - } - - $this->keys = array(); - - return $sql; - } - -} diff --git a/system/database/drivers/mysql/mysql_result.php b/system/database/drivers/mysql/mysql_result.php deleted file mode 100644 index 07d5187..0000000 --- a/system/database/drivers/mysql/mysql_result.php +++ /dev/null @@ -1,199 +0,0 @@ -num_rows = mysql_num_rows($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Number of rows in the result set - * - * @return int - */ - public function num_rows() - { - return $this->num_rows; - } - - // -------------------------------------------------------------------- - - /** - * Number of fields in the result set - * - * @return int - */ - public function num_fields() - { - return mysql_num_fields($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Fetch Field Names - * - * Generates an array of column names - * - * @return array - */ - public function list_fields() - { - $field_names = array(); - mysql_field_seek($this->result_id, 0); - while ($field = mysql_fetch_field($this->result_id)) - { - $field_names[] = $field->name; - } - - return $field_names; - } - - // -------------------------------------------------------------------- - - /** - * Field data - * - * Generates an array of objects containing field meta-data - * - * @return array - */ - public function field_data() - { - $retval = array(); - for ($i = 0, $c = $this->num_fields(); $i < $c; $i++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = mysql_field_name($this->result_id, $i); - $retval[$i]->type = mysql_field_type($this->result_id, $i); - $retval[$i]->max_length = mysql_field_len($this->result_id, $i); - $retval[$i]->primary_key = (int) (strpos(mysql_field_flags($this->result_id, $i), 'primary_key') !== FALSE); - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Free the result - * - * @return void - */ - public function free_result() - { - if (is_resource($this->result_id)) - { - mysql_free_result($this->result_id); - $this->result_id = FALSE; - } - } - - // -------------------------------------------------------------------- - - /** - * Data Seek - * - * Moves the internal pointer to the desired offset. We call - * this internally before fetching results to make sure the - * result set starts at zero. - * - * @param int $n - * @return bool - */ - public function data_seek($n = 0) - { - return $this->num_rows - ? mysql_data_seek($this->result_id, $n) - : FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Result - associative array - * - * Returns the result set as an array - * - * @return array - */ - protected function _fetch_assoc() - { - return mysql_fetch_assoc($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Result - object - * - * Returns the result set as an object - * - * @param string $class_name - * @return object - */ - protected function _fetch_object($class_name = 'stdClass') - { - return mysql_fetch_object($this->result_id, $class_name); - } - -} diff --git a/system/database/drivers/mysql/mysql_utility.php b/system/database/drivers/mysql/mysql_utility.php deleted file mode 100644 index ae3c26c..0000000 --- a/system/database/drivers/mysql/mysql_utility.php +++ /dev/null @@ -1,211 +0,0 @@ -db->query('SHOW CREATE TABLE '.$this->db->escape_identifiers($this->db->database.'.'.$table)); - - // No result means the table name was invalid - if ($query === FALSE) - { - continue; - } - - // Write out the table schema - $output .= '#'.$newline.'# TABLE STRUCTURE FOR: '.$table.$newline.'#'.$newline.$newline; - - if ($add_drop === TRUE) - { - $output .= 'DROP TABLE IF EXISTS '.$this->db->protect_identifiers($table).';'.$newline.$newline; - } - - $i = 0; - $result = $query->result_array(); - foreach ($result[0] as $val) - { - if ($i++ % 2) - { - $output .= $val.';'.$newline.$newline; - } - } - - // If inserts are not needed we're done... - if ($add_insert === FALSE) - { - continue; - } - - // Grab all the data from the current table - $query = $this->db->query('SELECT * FROM '.$this->db->protect_identifiers($table)); - - if ($query->num_rows() === 0) - { - continue; - } - - // Fetch the field names and determine if the field is an - // integer type. We use this info to decide whether to - // surround the data with quotes or not - - $i = 0; - $field_str = ''; - $is_int = array(); - while ($field = mysql_fetch_field($query->result_id)) - { - // Most versions of MySQL store timestamp as a string - $is_int[$i] = in_array(strtolower(mysql_field_type($query->result_id, $i)), - array('tinyint', 'smallint', 'mediumint', 'int', 'bigint'), //, 'timestamp'), - TRUE); - - // Create a string of field names - $field_str .= $this->db->escape_identifiers($field->name).', '; - $i++; - } - - // Trim off the end comma - $field_str = preg_replace('/, $/' , '', $field_str); - - // Build the insert string - foreach ($query->result_array() as $row) - { - $val_str = ''; - - $i = 0; - foreach ($row as $v) - { - // Is the value NULL? - if ($v === NULL) - { - $val_str .= 'NULL'; - } - else - { - // Escape the data if it's not an integer - $val_str .= ($is_int[$i] === FALSE) ? $this->db->escape($v) : $v; - } - - // Append a comma - $val_str .= ', '; - $i++; - } - - // Remove the comma at the end of the string - $val_str = preg_replace('/, $/' , '', $val_str); - - // Build the INSERT string - $output .= 'INSERT INTO '.$this->db->protect_identifiers($table).' ('.$field_str.') VALUES ('.$val_str.');'.$newline; - } - - $output .= $newline.$newline; - } - - // Do we need to include a statement to re-enable foreign key checks? - if ($foreign_key_checks === FALSE) - { - $output .= 'SET foreign_key_checks = 1;'.$newline; - } - - return $output; - } - -} diff --git a/system/database/drivers/mysqli/index.html b/system/database/drivers/mysqli/index.html deleted file mode 100644 index b702fbc..0000000 --- a/system/database/drivers/mysqli/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - 403 Forbidden - - - -

Directory access is forbidden.

- - - diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php deleted file mode 100644 index 7cec29e..0000000 --- a/system/database/drivers/mysqli/mysqli_driver.php +++ /dev/null @@ -1,544 +0,0 @@ -hostname[0] === '/') - { - $hostname = NULL; - $port = NULL; - $socket = $this->hostname; - } - else - { - $hostname = ($persistent === TRUE) - ? 'p:'.$this->hostname : $this->hostname; - $port = empty($this->port) ? NULL : $this->port; - $socket = NULL; - } - - $client_flags = ($this->compress === TRUE) ? MYSQLI_CLIENT_COMPRESS : 0; - $this->_mysqli = mysqli_init(); - - $this->_mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 10); - - if (isset($this->stricton)) - { - if ($this->stricton) - { - $this->_mysqli->options(MYSQLI_INIT_COMMAND, 'SET SESSION sql_mode = CONCAT(@@sql_mode, ",", "STRICT_ALL_TABLES")'); - } - else - { - $this->_mysqli->options(MYSQLI_INIT_COMMAND, - 'SET SESSION sql_mode = - REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( - @@sql_mode, - "STRICT_ALL_TABLES,", ""), - ",STRICT_ALL_TABLES", ""), - "STRICT_ALL_TABLES", ""), - "STRICT_TRANS_TABLES,", ""), - ",STRICT_TRANS_TABLES", ""), - "STRICT_TRANS_TABLES", "")' - ); - } - } - - if (is_array($this->encrypt)) - { - $ssl = array(); - empty($this->encrypt['ssl_key']) OR $ssl['key'] = $this->encrypt['ssl_key']; - empty($this->encrypt['ssl_cert']) OR $ssl['cert'] = $this->encrypt['ssl_cert']; - empty($this->encrypt['ssl_ca']) OR $ssl['ca'] = $this->encrypt['ssl_ca']; - empty($this->encrypt['ssl_capath']) OR $ssl['capath'] = $this->encrypt['ssl_capath']; - empty($this->encrypt['ssl_cipher']) OR $ssl['cipher'] = $this->encrypt['ssl_cipher']; - - if ( ! empty($ssl)) - { - if (isset($this->encrypt['ssl_verify'])) - { - if ($this->encrypt['ssl_verify']) - { - defined('MYSQLI_OPT_SSL_VERIFY_SERVER_CERT') && $this->_mysqli->options(MYSQLI_OPT_SSL_VERIFY_SERVER_CERT, TRUE); - } - // Apparently (when it exists), setting MYSQLI_OPT_SSL_VERIFY_SERVER_CERT - // to FALSE didn't do anything, so PHP 5.6.16 introduced yet another - // constant ... - // - // https://secure.php.net/ChangeLog-5.php#5.6.16 - // https://bugs.php.net/bug.php?id=68344 - elseif (defined('MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT')) - { - $client_flags |= MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT; - } - } - - $client_flags |= MYSQLI_CLIENT_SSL; - $this->_mysqli->ssl_set( - isset($ssl['key']) ? $ssl['key'] : NULL, - isset($ssl['cert']) ? $ssl['cert'] : NULL, - isset($ssl['ca']) ? $ssl['ca'] : NULL, - isset($ssl['capath']) ? $ssl['capath'] : NULL, - isset($ssl['cipher']) ? $ssl['cipher'] : NULL - ); - } - } - - if ($this->_mysqli->real_connect($hostname, $this->username, $this->password, $this->database, $port, $socket, $client_flags)) - { - // Prior to version 5.7.3, MySQL silently downgrades to an unencrypted connection if SSL setup fails - if ( - ($client_flags & MYSQLI_CLIENT_SSL) - && version_compare($this->_mysqli->client_info, '5.7.3', '<=') - && empty($this->_mysqli->query("SHOW STATUS LIKE 'ssl_cipher'")->fetch_object()->Value) - ) - { - $this->_mysqli->close(); - $message = 'MySQLi was configured for an SSL connection, but got an unencrypted connection instead!'; - log_message('error', $message); - return ($this->db_debug) ? $this->display_error($message, '', TRUE) : FALSE; - } - - return $this->_mysqli; - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Reconnect - * - * Keep / reestablish the db connection if no queries have been - * sent for a length of time exceeding the server's idle timeout - * - * @return void - */ - public function reconnect() - { - if ($this->conn_id !== FALSE && $this->conn_id->ping() === FALSE) - { - $this->conn_id = FALSE; - } - } - - // -------------------------------------------------------------------- - - /** - * Select the database - * - * @param string $database - * @return bool - */ - public function db_select($database = '') - { - if ($database === '') - { - $database = $this->database; - } - - if ($this->conn_id->select_db($database)) - { - $this->database = $database; - $this->data_cache = array(); - return TRUE; - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Set client character set - * - * @param string $charset - * @return bool - */ - protected function _db_set_charset($charset) - { - return $this->conn_id->set_charset($charset); - } - - // -------------------------------------------------------------------- - - /** - * Database version number - * - * @return string - */ - public function version() - { - if (isset($this->data_cache['version'])) - { - return $this->data_cache['version']; - } - - return $this->data_cache['version'] = $this->conn_id->server_info; - } - - // -------------------------------------------------------------------- - - /** - * Execute the query - * - * @param string $sql an SQL query - * @return mixed - */ - protected function _execute($sql) - { - return $this->conn_id->query($this->_prep_query($sql)); - } - - // -------------------------------------------------------------------- - - /** - * Prep the query - * - * If needed, each database adapter can prep the query string - * - * @param string $sql an SQL query - * @return string - */ - protected function _prep_query($sql) - { - // mysqli_affected_rows() returns 0 for "DELETE FROM TABLE" queries. This hack - // modifies the query so that it a proper number of affected rows is returned. - if ($this->delete_hack === TRUE && preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $sql)) - { - return trim($sql).' WHERE 1=1'; - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Begin Transaction - * - * @return bool - */ - protected function _trans_begin() - { - $this->conn_id->autocommit(FALSE); - return is_php('5.5') - ? $this->conn_id->begin_transaction() - : $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK - } - - // -------------------------------------------------------------------- - - /** - * Commit Transaction - * - * @return bool - */ - protected function _trans_commit() - { - if ($this->conn_id->commit()) - { - $this->conn_id->autocommit(TRUE); - return TRUE; - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Rollback Transaction - * - * @return bool - */ - protected function _trans_rollback() - { - if ($this->conn_id->rollback()) - { - $this->conn_id->autocommit(TRUE); - return TRUE; - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Platform-dependent string escape - * - * @param string - * @return string - */ - protected function _escape_str($str) - { - return $this->conn_id->real_escape_string($str); - } - - // -------------------------------------------------------------------- - - /** - * Affected Rows - * - * @return int - */ - public function affected_rows() - { - return $this->conn_id->affected_rows; - } - - // -------------------------------------------------------------------- - - /** - * Insert ID - * - * @return int - */ - public function insert_id() - { - return $this->conn_id->insert_id; - } - - // -------------------------------------------------------------------- - - /** - * List table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool $prefix_limit - * @return string - */ - protected function _list_tables($prefix_limit = FALSE) - { - $sql = 'SHOW TABLES FROM '.$this->escape_identifiers($this->database); - - if ($prefix_limit !== FALSE && $this->dbprefix !== '') - { - return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'"; - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Show column query - * - * Generates a platform-specific query string so that the column names can be fetched - * - * @param string $table - * @return string - */ - protected function _list_columns($table = '') - { - return 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE); - } - - // -------------------------------------------------------------------- - - /** - * Returns an object with field data - * - * @param string $table - * @return array - */ - public function field_data($table) - { - if (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE) - { - return FALSE; - } - $query = $query->result_object(); - - $retval = array(); - for ($i = 0, $c = count($query); $i < $c; $i++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = $query[$i]->Field; - - sscanf($query[$i]->Type, '%[a-z](%d)', - $retval[$i]->type, - $retval[$i]->max_length - ); - - $retval[$i]->default = $query[$i]->Default; - $retval[$i]->primary_key = (int) ($query[$i]->Key === 'PRI'); - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Error - * - * Returns an array containing code and message of the last - * database error that has occurred. - * - * @return array - */ - public function error() - { - if ( ! empty($this->_mysqli->connect_errno)) - { - return array( - 'code' => $this->_mysqli->connect_errno, - 'message' => $this->_mysqli->connect_error - ); - } - - return array('code' => $this->conn_id->errno, 'message' => $this->conn_id->error); - } - - // -------------------------------------------------------------------- - - /** - * FROM tables - * - * Groups tables in FROM clauses if needed, so there is no confusion - * about operator precedence. - * - * @return string - */ - protected function _from_tables() - { - if ( ! empty($this->qb_join) && count($this->qb_from) > 1) - { - return '('.implode(', ', $this->qb_from).')'; - } - - return implode(', ', $this->qb_from); - } - - // -------------------------------------------------------------------- - - /** - * Close DB Connection - * - * @return void - */ - protected function _close() - { - $this->conn_id->close(); - } - -} diff --git a/system/database/drivers/mysqli/mysqli_forge.php b/system/database/drivers/mysqli/mysqli_forge.php deleted file mode 100644 index dd77edc..0000000 --- a/system/database/drivers/mysqli/mysqli_forge.php +++ /dev/null @@ -1,244 +0,0 @@ -db->char_set) && ! strpos($sql, 'CHARACTER SET') && ! strpos($sql, 'CHARSET')) - { - $sql .= ' DEFAULT CHARACTER SET = '.$this->db->char_set; - } - - if ( ! empty($this->db->dbcollat) && ! strpos($sql, 'COLLATE')) - { - $sql .= ' COLLATE = '.$this->db->dbcollat; - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * ALTER TABLE - * - * @param string $alter_type ALTER type - * @param string $table Table name - * @param mixed $field Column definition - * @return string|string[] - */ - protected function _alter_table($alter_type, $table, $field) - { - if ($alter_type === 'DROP') - { - return parent::_alter_table($alter_type, $table, $field); - } - - $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table); - for ($i = 0, $c = count($field); $i < $c; $i++) - { - if ($field[$i]['_literal'] !== FALSE) - { - $field[$i] = ($alter_type === 'ADD') - ? "\n\tADD ".$field[$i]['_literal'] - : "\n\tMODIFY ".$field[$i]['_literal']; - } - else - { - if ($alter_type === 'ADD') - { - $field[$i]['_literal'] = "\n\tADD "; - } - else - { - $field[$i]['_literal'] = empty($field[$i]['new_name']) ? "\n\tMODIFY " : "\n\tCHANGE "; - } - - $field[$i] = $field[$i]['_literal'].$this->_process_column($field[$i]); - } - } - - return array($sql.implode(',', $field)); - } - - // -------------------------------------------------------------------- - - /** - * Process column - * - * @param array $field - * @return string - */ - protected function _process_column($field) - { - $extra_clause = isset($field['after']) - ? ' AFTER '.$this->db->escape_identifiers($field['after']) : ''; - - if (empty($extra_clause) && isset($field['first']) && $field['first'] === TRUE) - { - $extra_clause = ' FIRST'; - } - - return $this->db->escape_identifiers($field['name']) - .(empty($field['new_name']) ? '' : ' '.$this->db->escape_identifiers($field['new_name'])) - .' '.$field['type'].$field['length'] - .$field['unsigned'] - .$field['null'] - .$field['default'] - .$field['auto_increment'] - .$field['unique'] - .(empty($field['comment']) ? '' : ' COMMENT '.$field['comment']) - .$extra_clause; - } - - // -------------------------------------------------------------------- - - /** - * Process indexes - * - * @param string $table (ignored) - * @return string - */ - protected function _process_indexes($table) - { - $sql = ''; - - for ($i = 0, $c = count($this->keys); $i < $c; $i++) - { - if (is_array($this->keys[$i])) - { - for ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++) - { - if ( ! isset($this->fields[$this->keys[$i][$i2]])) - { - unset($this->keys[$i][$i2]); - continue; - } - } - } - elseif ( ! isset($this->fields[$this->keys[$i]])) - { - unset($this->keys[$i]); - continue; - } - - is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]); - - $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i])) - .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')'; - } - - $this->keys = array(); - - return $sql; - } - -} diff --git a/system/database/drivers/mysqli/mysqli_result.php b/system/database/drivers/mysqli/mysqli_result.php deleted file mode 100644 index bac0737..0000000 --- a/system/database/drivers/mysqli/mysqli_result.php +++ /dev/null @@ -1,232 +0,0 @@ -num_rows) - ? $this->num_rows - : $this->num_rows = $this->result_id->num_rows; - } - - // -------------------------------------------------------------------- - - /** - * Number of fields in the result set - * - * @return int - */ - public function num_fields() - { - return $this->result_id->field_count; - } - - // -------------------------------------------------------------------- - - /** - * Fetch Field Names - * - * Generates an array of column names - * - * @return array - */ - public function list_fields() - { - $field_names = array(); - $this->result_id->field_seek(0); - while ($field = $this->result_id->fetch_field()) - { - $field_names[] = $field->name; - } - - return $field_names; - } - - // -------------------------------------------------------------------- - - /** - * Field data - * - * Generates an array of objects containing field meta-data - * - * @return array - */ - public function field_data() - { - $retval = array(); - $field_data = $this->result_id->fetch_fields(); - for ($i = 0, $c = count($field_data); $i < $c; $i++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = $field_data[$i]->name; - $retval[$i]->type = static::_get_field_type($field_data[$i]->type); - $retval[$i]->max_length = $field_data[$i]->max_length; - $retval[$i]->primary_key = (int) ($field_data[$i]->flags & MYSQLI_PRI_KEY_FLAG); - $retval[$i]->default = $field_data[$i]->def; - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Get field type - * - * Extracts field type info from the bitflags returned by - * mysqli_result::fetch_fields() - * - * @used-by CI_DB_mysqli_result::field_data() - * @param int $type - * @return string - */ - private static function _get_field_type($type) - { - static $map; - isset($map) OR $map = array( - MYSQLI_TYPE_DECIMAL => 'decimal', - MYSQLI_TYPE_BIT => 'bit', - MYSQLI_TYPE_TINY => 'tinyint', - MYSQLI_TYPE_SHORT => 'smallint', - MYSQLI_TYPE_INT24 => 'mediumint', - MYSQLI_TYPE_LONG => 'int', - MYSQLI_TYPE_LONGLONG => 'bigint', - MYSQLI_TYPE_FLOAT => 'float', - MYSQLI_TYPE_DOUBLE => 'double', - MYSQLI_TYPE_TIMESTAMP => 'timestamp', - MYSQLI_TYPE_DATE => 'date', - MYSQLI_TYPE_TIME => 'time', - MYSQLI_TYPE_DATETIME => 'datetime', - MYSQLI_TYPE_YEAR => 'year', - MYSQLI_TYPE_NEWDATE => 'date', - MYSQLI_TYPE_INTERVAL => 'interval', - MYSQLI_TYPE_ENUM => 'enum', - MYSQLI_TYPE_SET => 'set', - MYSQLI_TYPE_TINY_BLOB => 'tinyblob', - MYSQLI_TYPE_MEDIUM_BLOB => 'mediumblob', - MYSQLI_TYPE_BLOB => 'blob', - MYSQLI_TYPE_LONG_BLOB => 'longblob', - MYSQLI_TYPE_STRING => 'char', - MYSQLI_TYPE_VAR_STRING => 'varchar', - MYSQLI_TYPE_GEOMETRY => 'geometry' - ); - - return isset($map[$type]) ? $map[$type] : $type; - } - - // -------------------------------------------------------------------- - - /** - * Free the result - * - * @return void - */ - public function free_result() - { - if (is_object($this->result_id)) - { - $this->result_id->free(); - $this->result_id = FALSE; - } - } - - // -------------------------------------------------------------------- - - /** - * Data Seek - * - * Moves the internal pointer to the desired offset. We call - * this internally before fetching results to make sure the - * result set starts at zero. - * - * @param int $n - * @return bool - */ - public function data_seek($n = 0) - { - return $this->result_id->data_seek($n); - } - - // -------------------------------------------------------------------- - - /** - * Result - associative array - * - * Returns the result set as an array - * - * @return array - */ - protected function _fetch_assoc() - { - return $this->result_id->fetch_assoc(); - } - - // -------------------------------------------------------------------- - - /** - * Result - object - * - * Returns the result set as an object - * - * @param string $class_name - * @return object - */ - protected function _fetch_object($class_name = 'stdClass') - { - return $this->result_id->fetch_object($class_name); - } - -} diff --git a/system/database/drivers/mysqli/mysqli_utility.php b/system/database/drivers/mysqli/mysqli_utility.php deleted file mode 100644 index 332da60..0000000 --- a/system/database/drivers/mysqli/mysqli_utility.php +++ /dev/null @@ -1,211 +0,0 @@ -db->query('SHOW CREATE TABLE '.$this->db->escape_identifiers($this->db->database.'.'.$table)); - - // No result means the table name was invalid - if ($query === FALSE) - { - continue; - } - - // Write out the table schema - $output .= '#'.$newline.'# TABLE STRUCTURE FOR: '.$table.$newline.'#'.$newline.$newline; - - if ($add_drop === TRUE) - { - $output .= 'DROP TABLE IF EXISTS '.$this->db->protect_identifiers($table).';'.$newline.$newline; - } - - $i = 0; - $result = $query->result_array(); - foreach ($result[0] as $val) - { - if ($i++ % 2) - { - $output .= $val.';'.$newline.$newline; - } - } - - // If inserts are not needed we're done... - if ($add_insert === FALSE) - { - continue; - } - - // Grab all the data from the current table - $query = $this->db->query('SELECT * FROM '.$this->db->protect_identifiers($table)); - - if ($query->num_rows() === 0) - { - continue; - } - - // Fetch the field names and determine if the field is an - // integer type. We use this info to decide whether to - // surround the data with quotes or not - - $i = 0; - $field_str = ''; - $is_int = array(); - while ($field = $query->result_id->fetch_field()) - { - // Most versions of MySQL store timestamp as a string - $is_int[$i] = in_array($field->type, array(MYSQLI_TYPE_TINY, MYSQLI_TYPE_SHORT, MYSQLI_TYPE_INT24, MYSQLI_TYPE_LONG), TRUE); - - // Create a string of field names - $field_str .= $this->db->escape_identifiers($field->name).', '; - $i++; - } - - // Trim off the end comma - $field_str = preg_replace('/, $/' , '', $field_str); - - // Build the insert string - foreach ($query->result_array() as $row) - { - $val_str = ''; - - $i = 0; - foreach ($row as $v) - { - // Is the value NULL? - if ($v === NULL) - { - $val_str .= 'NULL'; - } - else - { - // Escape the data if it's not an integer - $val_str .= ($is_int[$i] === FALSE) ? $this->db->escape($v) : $v; - } - - // Append a comma - $val_str .= ', '; - $i++; - } - - // Remove the comma at the end of the string - $val_str = preg_replace('/, $/' , '', $val_str); - - // Build the INSERT string - $output .= 'INSERT INTO '.$this->db->protect_identifiers($table).' ('.$field_str.') VALUES ('.$val_str.');'.$newline; - } - - $output .= $newline.$newline; - } - - // Do we need to include a statement to re-enable foreign key checks? - if ($foreign_key_checks === FALSE) - { - $output .= 'SET foreign_key_checks = 1;'.$newline; - } - - return $output; - } - -} diff --git a/system/database/drivers/oci8/index.html b/system/database/drivers/oci8/index.html deleted file mode 100644 index b702fbc..0000000 --- a/system/database/drivers/oci8/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - 403 Forbidden - - - -

Directory access is forbidden.

- - - diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php deleted file mode 100644 index b90db4b..0000000 --- a/system/database/drivers/oci8/oci8_driver.php +++ /dev/null @@ -1,701 +0,0 @@ - '/^\(DESCRIPTION=(\(.+\)){2,}\)$/', // TNS - // Easy Connect string (Oracle 10g+) - 'ec' => '/^(\/\/)?[a-z0-9.:_-]+(:[1-9][0-9]{0,4})?(\/[a-z0-9$_]+)?(:[^\/])?(\/[a-z0-9$_]+)?$/i', - 'in' => '/^[a-z0-9$_]+$/i' // Instance name (defined in tnsnames.ora) - ); - - /* Space characters don't have any effect when actually - * connecting, but can be a hassle while validating the DSN. - */ - $this->dsn = str_replace(array("\n", "\r", "\t", ' '), '', $this->dsn); - - if ($this->dsn !== '') - { - foreach ($valid_dsns as $regexp) - { - if (preg_match($regexp, $this->dsn)) - { - return; - } - } - } - - // Legacy support for TNS in the hostname configuration field - $this->hostname = str_replace(array("\n", "\r", "\t", ' '), '', $this->hostname); - if (preg_match($valid_dsns['tns'], $this->hostname)) - { - $this->dsn = $this->hostname; - return; - } - elseif ($this->hostname !== '' && strpos($this->hostname, '/') === FALSE && strpos($this->hostname, ':') === FALSE - && (( ! empty($this->port) && ctype_digit($this->port)) OR $this->database !== '')) - { - /* If the hostname field isn't empty, doesn't contain - * ':' and/or '/' and if port and/or database aren't - * empty, then the hostname field is most likely indeed - * just a hostname. Therefore we'll try and build an - * Easy Connect string from these 3 settings, assuming - * that the database field is a service name. - */ - $this->dsn = $this->hostname - .(( ! empty($this->port) && ctype_digit($this->port)) ? ':'.$this->port : '') - .($this->database !== '' ? '/'.ltrim($this->database, '/') : ''); - - if (preg_match($valid_dsns['ec'], $this->dsn)) - { - return; - } - } - - /* At this point, we can only try and validate the hostname and - * database fields separately as DSNs. - */ - if (preg_match($valid_dsns['ec'], $this->hostname) OR preg_match($valid_dsns['in'], $this->hostname)) - { - $this->dsn = $this->hostname; - return; - } - - $this->database = str_replace(array("\n", "\r", "\t", ' '), '', $this->database); - foreach ($valid_dsns as $regexp) - { - if (preg_match($regexp, $this->database)) - { - return; - } - } - - /* Well - OK, an empty string should work as well. - * PHP will try to use environment variables to - * determine which Oracle instance to connect to. - */ - $this->dsn = ''; - } - - // -------------------------------------------------------------------- - - /** - * Non-persistent database connection - * - * @param bool $persistent - * @return resource - */ - public function db_connect($persistent = FALSE) - { - $func = ($persistent === TRUE) ? 'oci_pconnect' : 'oci_connect'; - return empty($this->char_set) - ? $func($this->username, $this->password, $this->dsn) - : $func($this->username, $this->password, $this->dsn, $this->char_set); - } - - // -------------------------------------------------------------------- - - /** - * Database version number - * - * @return string - */ - public function version() - { - if (isset($this->data_cache['version'])) - { - return $this->data_cache['version']; - } - - if ( ! $this->conn_id OR ($version_string = oci_server_version($this->conn_id)) === FALSE) - { - return FALSE; - } - elseif (preg_match('#Release\s(\d+(?:\.\d+)+)#', $version_string, $match)) - { - return $this->data_cache['version'] = $match[1]; - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Execute the query - * - * @param string $sql an SQL query - * @return resource - */ - protected function _execute($sql) - { - /* Oracle must parse the query before it is run. All of the actions with - * the query are based on the statement id returned by oci_parse(). - */ - if ($this->_reset_stmt_id === TRUE) - { - $this->stmt_id = oci_parse($this->conn_id, $sql); - } - - oci_set_prefetch($this->stmt_id, 1000); - return oci_execute($this->stmt_id, $this->commit_mode); - } - - // -------------------------------------------------------------------- - - /** - * Get cursor. Returns a cursor from the database - * - * @return resource - */ - public function get_cursor() - { - return $this->curs_id = oci_new_cursor($this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * Stored Procedure. Executes a stored procedure - * - * @param string package name in which the stored procedure is in - * @param string stored procedure name to execute - * @param array parameters - * @return mixed - * - * params array keys - * - * KEY OPTIONAL NOTES - * name no the name of the parameter should be in : format - * value no the value of the parameter. If this is an OUT or IN OUT parameter, - * this should be a reference to a variable - * type yes the type of the parameter - * length yes the max size of the parameter - */ - public function stored_procedure($package, $procedure, array $params) - { - if ($package === '' OR $procedure === '') - { - log_message('error', 'Invalid query: '.$package.'.'.$procedure); - return ($this->db_debug) ? $this->display_error('db_invalid_query') : FALSE; - } - - // Build the query string - $sql = 'BEGIN '.$package.'.'.$procedure.'('; - - $have_cursor = FALSE; - foreach ($params as $param) - { - $sql .= $param['name'].','; - - if (isset($param['type']) && $param['type'] === OCI_B_CURSOR) - { - $have_cursor = TRUE; - } - } - $sql = trim($sql, ',').'); END;'; - - $this->_reset_stmt_id = FALSE; - $this->stmt_id = oci_parse($this->conn_id, $sql); - $this->_bind_params($params); - $result = $this->query($sql, FALSE, $have_cursor); - $this->_reset_stmt_id = TRUE; - return $result; - } - - // -------------------------------------------------------------------- - - /** - * Bind parameters - * - * @param array $params - * @return void - */ - protected function _bind_params($params) - { - if ( ! is_array($params) OR ! is_resource($this->stmt_id)) - { - return; - } - - foreach ($params as $param) - { - foreach (array('name', 'value', 'type', 'length') as $val) - { - if ( ! isset($param[$val])) - { - $param[$val] = ''; - } - } - - oci_bind_by_name($this->stmt_id, $param['name'], $param['value'], $param['length'], $param['type']); - } - } - - // -------------------------------------------------------------------- - - /** - * Begin Transaction - * - * @return bool - */ - protected function _trans_begin() - { - $this->commit_mode = OCI_NO_AUTO_COMMIT; - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Commit Transaction - * - * @return bool - */ - protected function _trans_commit() - { - $this->commit_mode = OCI_COMMIT_ON_SUCCESS; - - return oci_commit($this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * Rollback Transaction - * - * @return bool - */ - protected function _trans_rollback() - { - $this->commit_mode = OCI_COMMIT_ON_SUCCESS; - return oci_rollback($this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * Affected Rows - * - * @return int - */ - public function affected_rows() - { - return oci_num_rows($this->stmt_id); - } - - // -------------------------------------------------------------------- - - /** - * Insert ID - * - * @return int - */ - public function insert_id() - { - // not supported in oracle - return $this->display_error('db_unsupported_function'); - } - - // -------------------------------------------------------------------- - - /** - * Show table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool $prefix_limit - * @return string - */ - protected function _list_tables($prefix_limit = FALSE) - { - $sql = 'SELECT "TABLE_NAME" FROM "ALL_TABLES"'; - - if ($prefix_limit !== FALSE && $this->dbprefix !== '') - { - return $sql.' WHERE "TABLE_NAME" LIKE \''.$this->escape_like_str($this->dbprefix)."%' " - .sprintf($this->_like_escape_str, $this->_like_escape_chr); - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Show column query - * - * Generates a platform-specific query string so that the column names can be fetched - * - * @param string $table - * @return string - */ - protected function _list_columns($table = '') - { - if (strpos($table, '.') !== FALSE) - { - sscanf($table, '%[^.].%s', $owner, $table); - } - else - { - $owner = $this->username; - } - - return 'SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS - WHERE UPPER(OWNER) = '.$this->escape(strtoupper($owner)).' - AND UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table)); - } - - // -------------------------------------------------------------------- - - /** - * Returns an object with field data - * - * @param string $table - * @return array - */ - public function field_data($table) - { - if (strpos($table, '.') !== FALSE) - { - sscanf($table, '%[^.].%s', $owner, $table); - } - else - { - $owner = $this->username; - } - - $sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHAR_LENGTH, DATA_PRECISION, DATA_LENGTH, DATA_DEFAULT, NULLABLE - FROM ALL_TAB_COLUMNS - WHERE UPPER(OWNER) = '.$this->escape(strtoupper($owner)).' - AND UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table)); - - if (($query = $this->query($sql)) === FALSE) - { - return FALSE; - } - $query = $query->result_object(); - - $retval = array(); - for ($i = 0, $c = count($query); $i < $c; $i++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = $query[$i]->COLUMN_NAME; - $retval[$i]->type = $query[$i]->DATA_TYPE; - - $length = ($query[$i]->CHAR_LENGTH > 0) - ? $query[$i]->CHAR_LENGTH : $query[$i]->DATA_PRECISION; - if ($length === NULL) - { - $length = $query[$i]->DATA_LENGTH; - } - $retval[$i]->max_length = $length; - - $default = $query[$i]->DATA_DEFAULT; - if ($default === NULL && $query[$i]->NULLABLE === 'N') - { - $default = ''; - } - $retval[$i]->default = $default; - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Error - * - * Returns an array containing code and message of the last - * database error that has occurred. - * - * @return array - */ - public function error() - { - // oci_error() returns an array that already contains - // 'code' and 'message' keys, but it can return false - // if there was no error .... - if (is_resource($this->curs_id)) - { - $error = oci_error($this->curs_id); - } - elseif (is_resource($this->stmt_id)) - { - $error = oci_error($this->stmt_id); - } - elseif (is_resource($this->conn_id)) - { - $error = oci_error($this->conn_id); - } - else - { - $error = oci_error(); - } - - return is_array($error) - ? $error - : array('code' => '', 'message' => ''); - } - - // -------------------------------------------------------------------- - - /** - * Insert batch statement - * - * Generates a platform-specific insert string from the supplied data - * - * @param string $table Table name - * @param array $keys INSERT keys - * @param array $values INSERT values - * @return string - */ - protected function _insert_batch($table, $keys, $values) - { - $keys = implode(', ', $keys); - $sql = "INSERT ALL\n"; - - for ($i = 0, $c = count($values); $i < $c; $i++) - { - $sql .= ' INTO '.$table.' ('.$keys.') VALUES '.$values[$i]."\n"; - } - - return $sql.'SELECT * FROM dual'; - } - - // -------------------------------------------------------------------- - - /** - * Truncate statement - * - * Generates a platform-specific truncate string from the supplied data - * - * If the database does not support the TRUNCATE statement, - * then this method maps to 'DELETE FROM table' - * - * @param string $table - * @return string - */ - protected function _truncate($table) - { - return 'TRUNCATE TABLE '.$table; - } - - // -------------------------------------------------------------------- - - /** - * Delete statement - * - * Generates a platform-specific delete string from the supplied data - * - * @param string $table - * @return string - */ - protected function _delete($table) - { - if ($this->qb_limit) - { - $this->where('rownum <= ',$this->qb_limit, FALSE); - $this->qb_limit = FALSE; - } - - return parent::_delete($table); - } - - // -------------------------------------------------------------------- - - /** - * LIMIT - * - * Generates a platform-specific LIMIT clause - * - * @param string $sql SQL Query - * @return string - */ - protected function _limit($sql) - { - if (version_compare($this->version(), '12.1', '>=')) - { - // OFFSET-FETCH can be used only with the ORDER BY clause - empty($this->qb_orderby) && $sql .= ' ORDER BY 1'; - - return $sql.' OFFSET '.(int) $this->qb_offset.' ROWS FETCH NEXT '.$this->qb_limit.' ROWS ONLY'; - } - - $this->limit_used = TRUE; - return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($this->qb_offset + $this->qb_limit + 1).')' - .($this->qb_offset ? ' WHERE rnum >= '.($this->qb_offset + 1) : ''); - } - - // -------------------------------------------------------------------- - - /** - * Close DB Connection - * - * @return void - */ - protected function _close() - { - oci_close($this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * We need to reset our $limit_used hack flag, so it doesn't propagate - * to subsequent queries. - * - * @return void - */ - protected function _reset_select() - { - $this->limit_used = FALSE; - parent::_reset_select(); - } -} diff --git a/system/database/drivers/oci8/oci8_forge.php b/system/database/drivers/oci8/oci8_forge.php deleted file mode 100644 index 0011bb0..0000000 --- a/system/database/drivers/oci8/oci8_forge.php +++ /dev/null @@ -1,187 +0,0 @@ -db->escape_identifiers($table); - $sqls = array(); - for ($i = 0, $c = count($field); $i < $c; $i++) - { - if ($field[$i]['_literal'] !== FALSE) - { - $field[$i] = "\n\t".$field[$i]['_literal']; - } - else - { - $field[$i]['_literal'] = "\n\t".$this->_process_column($field[$i]); - - if ( ! empty($field[$i]['comment'])) - { - $sqls[] = 'COMMENT ON COLUMN ' - .$this->db->escape_identifiers($table).'.'.$this->db->escape_identifiers($field[$i]['name']) - .' IS '.$field[$i]['comment']; - } - - if ($alter_type === 'MODIFY' && ! empty($field[$i]['new_name'])) - { - $sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name']) - .' TO '.$this->db->escape_identifiers($field[$i]['new_name']); - } - - $field[$i] = "\n\t".$field[$i]['_literal']; - } - } - - $sql .= ' '.$alter_type.' '; - $sql .= (count($field) === 1) - ? $field[0] - : '('.implode(',', $field).')'; - - // RENAME COLUMN must be executed after MODIFY - array_unshift($sqls, $sql); - return $sqls; - } - - // -------------------------------------------------------------------- - - /** - * Field attribute AUTO_INCREMENT - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_auto_increment(&$attributes, &$field) - { - // Not supported - sequences and triggers must be used instead - } - - // -------------------------------------------------------------------- - - /** - * Field attribute TYPE - * - * Performs a data type mapping between different databases. - * - * @param array &$attributes - * @return void - */ - protected function _attr_type(&$attributes) - { - switch (strtoupper($attributes['TYPE'])) - { - case 'TINYINT': - $attributes['TYPE'] = 'NUMBER'; - return; - case 'MEDIUMINT': - $attributes['TYPE'] = 'NUMBER'; - return; - case 'INT': - $attributes['TYPE'] = 'NUMBER'; - return; - case 'BIGINT': - $attributes['TYPE'] = 'NUMBER'; - return; - default: return; - } - } -} diff --git a/system/database/drivers/oci8/oci8_result.php b/system/database/drivers/oci8/oci8_result.php deleted file mode 100644 index 1c4196f..0000000 --- a/system/database/drivers/oci8/oci8_result.php +++ /dev/null @@ -1,229 +0,0 @@ -stmt_id = $driver_object->stmt_id; - $this->curs_id = $driver_object->curs_id; - $this->limit_used = $driver_object->limit_used; - $this->commit_mode =& $driver_object->commit_mode; - $driver_object->stmt_id = FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Number of fields in the result set - * - * @return int - */ - public function num_fields() - { - $count = oci_num_fields($this->stmt_id); - - // if we used a limit we subtract it - return ($this->limit_used) ? $count - 1 : $count; - } - - // -------------------------------------------------------------------- - - /** - * Fetch Field Names - * - * Generates an array of column names - * - * @return array - */ - public function list_fields() - { - $field_names = array(); - for ($c = 1, $fieldCount = $this->num_fields(); $c <= $fieldCount; $c++) - { - $field_names[] = oci_field_name($this->stmt_id, $c); - } - return $field_names; - } - - // -------------------------------------------------------------------- - - /** - * Field data - * - * Generates an array of objects containing field meta-data - * - * @return array - */ - public function field_data() - { - $retval = array(); - for ($c = 1, $fieldCount = $this->num_fields(); $c <= $fieldCount; $c++) - { - $F = new stdClass(); - $F->name = oci_field_name($this->stmt_id, $c); - $F->type = oci_field_type($this->stmt_id, $c); - $F->max_length = oci_field_size($this->stmt_id, $c); - - $retval[] = $F; - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Free the result - * - * @return void - */ - public function free_result() - { - if (is_resource($this->result_id)) - { - oci_free_statement($this->result_id); - $this->result_id = FALSE; - } - - if (is_resource($this->stmt_id)) - { - oci_free_statement($this->stmt_id); - } - - if (is_resource($this->curs_id)) - { - oci_cancel($this->curs_id); - $this->curs_id = NULL; - } - } - - // -------------------------------------------------------------------- - - /** - * Result - associative array - * - * Returns the result set as an array - * - * @return array - */ - protected function _fetch_assoc() - { - $id = ($this->curs_id) ? $this->curs_id : $this->stmt_id; - return oci_fetch_assoc($id); - } - - // -------------------------------------------------------------------- - - /** - * Result - object - * - * Returns the result set as an object - * - * @param string $class_name - * @return object - */ - protected function _fetch_object($class_name = 'stdClass') - { - $row = ($this->curs_id) - ? oci_fetch_object($this->curs_id) - : oci_fetch_object($this->stmt_id); - - if ($class_name === 'stdClass' OR ! $row) - { - return $row; - } - - $class_name = new $class_name(); - foreach ($row as $key => $value) - { - $class_name->$key = $value; - } - - return $class_name; - } - -} diff --git a/system/database/drivers/oci8/oci8_utility.php b/system/database/drivers/oci8/oci8_utility.php deleted file mode 100644 index 574ff68..0000000 --- a/system/database/drivers/oci8/oci8_utility.php +++ /dev/null @@ -1,68 +0,0 @@ -db->display_error('db_unsupported_feature'); - } - -} diff --git a/system/database/drivers/odbc/index.html b/system/database/drivers/odbc/index.html deleted file mode 100644 index b702fbc..0000000 --- a/system/database/drivers/odbc/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - 403 Forbidden - - - -

Directory access is forbidden.

- - - diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php deleted file mode 100644 index c853903..0000000 --- a/system/database/drivers/odbc/odbc_driver.php +++ /dev/null @@ -1,425 +0,0 @@ -dsn)) - { - $this->dsn = $this->hostname; - } - } - - // -------------------------------------------------------------------- - - /** - * Non-persistent database connection - * - * @param bool $persistent - * @return resource - */ - public function db_connect($persistent = FALSE) - { - return ($persistent === TRUE) - ? odbc_pconnect($this->dsn, $this->username, $this->password) - : odbc_connect($this->dsn, $this->username, $this->password); - } - - // -------------------------------------------------------------------- - - /** - * Compile Bindings - * - * @param string $sql SQL statement - * @param array $binds An array of values to bind - * @return string - */ - public function compile_binds($sql, $binds) - { - if (empty($binds) OR empty($this->bind_marker) OR strpos($sql, $this->bind_marker) === FALSE) - { - return $sql; - } - elseif ( ! is_array($binds)) - { - $binds = array($binds); - $bind_count = 1; - } - else - { - // Make sure we're using numeric keys - $binds = array_values($binds); - $bind_count = count($binds); - } - - // We'll need the marker length later - $ml = strlen($this->bind_marker); - - // Make sure not to replace a chunk inside a string that happens to match the bind marker - if ($c = preg_match_all("/'[^']*'|\"[^\"]*\"/i", $sql, $matches)) - { - $c = preg_match_all('/'.preg_quote($this->bind_marker, '/').'/i', - str_replace($matches[0], - str_replace($this->bind_marker, str_repeat(' ', $ml), $matches[0]), - $sql, $c), - $matches, PREG_OFFSET_CAPTURE); - - // Bind values' count must match the count of markers in the query - if ($bind_count !== $c) - { - return $sql; - } - } - elseif (($c = preg_match_all('/'.preg_quote($this->bind_marker, '/').'/i', $sql, $matches, PREG_OFFSET_CAPTURE)) !== $bind_count) - { - return $sql; - } - - if ($this->bind_marker !== '?') - { - do - { - $c--; - $sql = substr_replace($sql, '?', $matches[0][$c][1], $ml); - } - while ($c !== 0); - } - - if (FALSE !== ($this->odbc_result = odbc_prepare($this->conn_id, $sql))) - { - $this->binds = array_values($binds); - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Execute the query - * - * @param string $sql an SQL query - * @return resource - */ - protected function _execute($sql) - { - if ( ! isset($this->odbc_result)) - { - return odbc_exec($this->conn_id, $sql); - } - elseif ($this->odbc_result === FALSE) - { - return FALSE; - } - - if (TRUE === ($success = odbc_execute($this->odbc_result, $this->binds))) - { - // For queries that return result sets, return the result_id resource on success - $this->is_write_type($sql) OR $success = $this->odbc_result; - } - - $this->odbc_result = NULL; - $this->binds = array(); - - return $success; - } - - // -------------------------------------------------------------------- - - /** - * Begin Transaction - * - * @return bool - */ - protected function _trans_begin() - { - return odbc_autocommit($this->conn_id, FALSE); - } - - // -------------------------------------------------------------------- - - /** - * Commit Transaction - * - * @return bool - */ - protected function _trans_commit() - { - if (odbc_commit($this->conn_id)) - { - odbc_autocommit($this->conn_id, TRUE); - return TRUE; - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Rollback Transaction - * - * @return bool - */ - protected function _trans_rollback() - { - if (odbc_rollback($this->conn_id)) - { - odbc_autocommit($this->conn_id, TRUE); - return TRUE; - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Determines if a query is a "write" type. - * - * @param string An SQL query string - * @return bool - */ - public function is_write_type($sql) - { - if (preg_match('#^(INSERT|UPDATE).*RETURNING\s.+(\,\s?.+)*$#is', $sql)) - { - return FALSE; - } - - return parent::is_write_type($sql); - } - - // -------------------------------------------------------------------- - - /** - * Platform-dependent string escape - * - * @param string - * @return string - */ - protected function _escape_str($str) - { - $this->display_error('db_unsupported_feature'); - } - - // -------------------------------------------------------------------- - - /** - * Affected Rows - * - * @return int - */ - public function affected_rows() - { - return odbc_num_rows($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Insert ID - * - * @return bool - */ - public function insert_id() - { - return ($this->db_debug) ? $this->display_error('db_unsupported_feature') : FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Show table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool $prefix_limit - * @return string - */ - protected function _list_tables($prefix_limit = FALSE) - { - $sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = '".$this->schema."'"; - - if ($prefix_limit !== FALSE && $this->dbprefix !== '') - { - return $sql." AND table_name LIKE '".$this->escape_like_str($this->dbprefix)."%' " - .sprintf($this->_like_escape_str, $this->_like_escape_chr); - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Show column query - * - * Generates a platform-specific query string so that the column names can be fetched - * - * @param string $table - * @return string - */ - protected function _list_columns($table = '') - { - return 'SHOW COLUMNS FROM '.$table; - } - - // -------------------------------------------------------------------- - - /** - * Field data query - * - * Generates a platform-specific query so that the column data can be retrieved - * - * @param string $table - * @return string - */ - protected function _field_data($table) - { - return 'SELECT TOP 1 FROM '.$table; - } - - // -------------------------------------------------------------------- - - /** - * Error - * - * Returns an array containing code and message of the last - * database error that has occurred. - * - * @return array - */ - public function error() - { - return array('code' => odbc_error($this->conn_id), 'message' => odbc_errormsg($this->conn_id)); - } - - // -------------------------------------------------------------------- - - /** - * Close DB Connection - * - * @return void - */ - protected function _close() - { - odbc_close($this->conn_id); - } -} diff --git a/system/database/drivers/odbc/odbc_forge.php b/system/database/drivers/odbc/odbc_forge.php deleted file mode 100644 index 761e81f..0000000 --- a/system/database/drivers/odbc/odbc_forge.php +++ /dev/null @@ -1,86 +0,0 @@ -num_rows)) - { - return $this->num_rows; - } - elseif (($this->num_rows = odbc_num_rows($this->result_id)) !== -1) - { - return $this->num_rows; - } - - // Work-around for ODBC subdrivers that don't support num_rows() - if (count($this->result_array) > 0) - { - return $this->num_rows = count($this->result_array); - } - elseif (count($this->result_object) > 0) - { - return $this->num_rows = count($this->result_object); - } - - return $this->num_rows = count($this->result_array()); - } - - // -------------------------------------------------------------------- - - /** - * Number of fields in the result set - * - * @return int - */ - public function num_fields() - { - return odbc_num_fields($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Fetch Field Names - * - * Generates an array of column names - * - * @return array - */ - public function list_fields() - { - $field_names = array(); - $num_fields = $this->num_fields(); - - if ($num_fields > 0) - { - for ($i = 1; $i <= $num_fields; $i++) - { - $field_names[] = odbc_field_name($this->result_id, $i); - } - } - - return $field_names; - } - - // -------------------------------------------------------------------- - - /** - * Field data - * - * Generates an array of objects containing field meta-data - * - * @return array - */ - public function field_data() - { - $retval = array(); - for ($i = 0, $odbc_index = 1, $c = $this->num_fields(); $i < $c; $i++, $odbc_index++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = odbc_field_name($this->result_id, $odbc_index); - $retval[$i]->type = odbc_field_type($this->result_id, $odbc_index); - $retval[$i]->max_length = odbc_field_len($this->result_id, $odbc_index); - $retval[$i]->primary_key = 0; - $retval[$i]->default = ''; - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Free the result - * - * @return void - */ - public function free_result() - { - if (is_resource($this->result_id)) - { - odbc_free_result($this->result_id); - $this->result_id = FALSE; - } - } - - // -------------------------------------------------------------------- - - /** - * Result - associative array - * - * Returns the result set as an array - * - * @return array - */ - protected function _fetch_assoc() - { - return odbc_fetch_array($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Result - object - * - * Returns the result set as an object - * - * @param string $class_name - * @return object - */ - protected function _fetch_object($class_name = 'stdClass') - { - $row = odbc_fetch_object($this->result_id); - - if ($class_name === 'stdClass' OR ! $row) - { - return $row; - } - - $class_name = new $class_name(); - foreach ($row as $key => $value) - { - $class_name->$key = $value; - } - - return $class_name; - } - -} - -// -------------------------------------------------------------------- - -if ( ! function_exists('odbc_fetch_array')) -{ - /** - * ODBC Fetch array - * - * Emulates the native odbc_fetch_array() function when - * it is not available (odbc_fetch_array() requires unixODBC) - * - * @param resource &$result - * @param int $rownumber - * @return array - */ - function odbc_fetch_array(&$result, $rownumber = 1) - { - $rs = array(); - if ( ! odbc_fetch_into($result, $rs, $rownumber)) - { - return FALSE; - } - - $rs_assoc = array(); - foreach ($rs as $k => $v) - { - $field_name = odbc_field_name($result, $k+1); - $rs_assoc[$field_name] = $v; - } - - return $rs_assoc; - } -} - -// -------------------------------------------------------------------- - -if ( ! function_exists('odbc_fetch_object')) -{ - /** - * ODBC Fetch object - * - * Emulates the native odbc_fetch_object() function when - * it is not available. - * - * @param resource &$result - * @param int $rownumber - * @return object - */ - function odbc_fetch_object(&$result, $rownumber = 1) - { - $rs = array(); - if ( ! odbc_fetch_into($result, $rs, $rownumber)) - { - return FALSE; - } - - $rs_object = new stdClass(); - foreach ($rs as $k => $v) - { - $field_name = odbc_field_name($result, $k+1); - $rs_object->$field_name = $v; - } - - return $rs_object; - } -} diff --git a/system/database/drivers/odbc/odbc_utility.php b/system/database/drivers/odbc/odbc_utility.php deleted file mode 100644 index 2a33428..0000000 --- a/system/database/drivers/odbc/odbc_utility.php +++ /dev/null @@ -1,63 +0,0 @@ -db->display_error('db_unsupported_feature'); - } - -} diff --git a/system/database/drivers/pdo/index.html b/system/database/drivers/pdo/index.html deleted file mode 100644 index b702fbc..0000000 --- a/system/database/drivers/pdo/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - 403 Forbidden - - - -

Directory access is forbidden.

- - - diff --git a/system/database/drivers/pdo/pdo_driver.php b/system/database/drivers/pdo/pdo_driver.php deleted file mode 100644 index c99bb06..0000000 --- a/system/database/drivers/pdo/pdo_driver.php +++ /dev/null @@ -1,329 +0,0 @@ -dsn, $match) && count($match) === 2) - { - // If there is a minimum valid dsn string pattern found, we're done - // This is for general PDO users, who tend to have a full DSN string. - $this->subdriver = $match[1]; - return; - } - // Legacy support for DSN specified in the hostname field - elseif (preg_match('/([^:]+):/', $this->hostname, $match) && count($match) === 2) - { - $this->dsn = $this->hostname; - $this->hostname = NULL; - $this->subdriver = $match[1]; - return; - } - elseif (in_array($this->subdriver, array('mssql', 'sybase'), TRUE)) - { - $this->subdriver = 'dblib'; - } - elseif ($this->subdriver === '4D') - { - $this->subdriver = '4d'; - } - elseif ( ! in_array($this->subdriver, array('4d', 'cubrid', 'dblib', 'firebird', 'ibm', 'informix', 'mysql', 'oci', 'odbc', 'pgsql', 'sqlite', 'sqlsrv'), TRUE)) - { - log_message('error', 'PDO: Invalid or non-existent subdriver'); - - if ($this->db_debug) - { - show_error('Invalid or non-existent PDO subdriver'); - } - } - - $this->dsn = NULL; - } - - // -------------------------------------------------------------------- - - /** - * Database connection - * - * @param bool $persistent - * @return object - */ - public function db_connect($persistent = FALSE) - { - if ($persistent === TRUE) - { - $this->options[PDO::ATTR_PERSISTENT] = TRUE; - } - - try - { - return new PDO($this->dsn, $this->username, $this->password, $this->options); - } - catch (PDOException $e) - { - if ($this->db_debug && empty($this->failover)) - { - $this->display_error($e->getMessage(), '', TRUE); - } - - return FALSE; - } - } - - // -------------------------------------------------------------------- - - /** - * Database version number - * - * @return string - */ - public function version() - { - if (isset($this->data_cache['version'])) - { - return $this->data_cache['version']; - } - - // Not all subdrivers support the getAttribute() method - try - { - return $this->data_cache['version'] = $this->conn_id->getAttribute(PDO::ATTR_SERVER_VERSION); - } - catch (PDOException $e) - { - return parent::version(); - } - } - - // -------------------------------------------------------------------- - - /** - * Execute the query - * - * @param string $sql SQL query - * @return mixed - */ - protected function _execute($sql) - { - return $this->conn_id->query($sql); - } - - // -------------------------------------------------------------------- - - /** - * Begin Transaction - * - * @return bool - */ - protected function _trans_begin() - { - return $this->conn_id->beginTransaction(); - } - - // -------------------------------------------------------------------- - - /** - * Commit Transaction - * - * @return bool - */ - protected function _trans_commit() - { - return $this->conn_id->commit(); - } - - // -------------------------------------------------------------------- - - /** - * Rollback Transaction - * - * @return bool - */ - protected function _trans_rollback() - { - return $this->conn_id->rollBack(); - } - - // -------------------------------------------------------------------- - - /** - * Platform-dependent string escape - * - * @param string - * @return string - */ - protected function _escape_str($str) - { - // Escape the string - $str = $this->conn_id->quote($str); - - // If there are duplicated quotes, trim them away - return ($str[0] === "'") - ? substr($str, 1, -1) - : $str; - } - - // -------------------------------------------------------------------- - - /** - * Affected Rows - * - * @return int - */ - public function affected_rows() - { - return is_object($this->result_id) ? $this->result_id->rowCount() : 0; - } - - // -------------------------------------------------------------------- - - /** - * Insert ID - * - * @param string $name - * @return int - */ - public function insert_id($name = NULL) - { - return $this->conn_id->lastInsertId($name); - } - - // -------------------------------------------------------------------- - - /** - * Field data query - * - * Generates a platform-specific query so that the column data can be retrieved - * - * @param string $table - * @return string - */ - protected function _field_data($table) - { - return 'SELECT TOP 1 * FROM '.$this->protect_identifiers($table); - } - - // -------------------------------------------------------------------- - - /** - * Error - * - * Returns an array containing code and message of the last - * database error that has occurred. - * - * @return array - */ - public function error() - { - $error = array('code' => '00000', 'message' => ''); - $pdo_error = $this->conn_id->errorInfo(); - - if (empty($pdo_error[0])) - { - return $error; - } - - $error['code'] = isset($pdo_error[1]) ? $pdo_error[0].'/'.$pdo_error[1] : $pdo_error[0]; - if (isset($pdo_error[2])) - { - $error['message'] = $pdo_error[2]; - } - - return $error; - } - - // -------------------------------------------------------------------- - - /** - * Truncate statement - * - * Generates a platform-specific truncate string from the supplied data - * - * If the database does not support the TRUNCATE statement, - * then this method maps to 'DELETE FROM table' - * - * @param string $table - * @return string - */ - protected function _truncate($table) - { - return 'TRUNCATE TABLE '.$table; - } - -} diff --git a/system/database/drivers/pdo/pdo_forge.php b/system/database/drivers/pdo/pdo_forge.php deleted file mode 100644 index c77a849..0000000 --- a/system/database/drivers/pdo/pdo_forge.php +++ /dev/null @@ -1,65 +0,0 @@ -num_rows)) - { - return $this->num_rows; - } - elseif (count($this->result_array) > 0) - { - return $this->num_rows = count($this->result_array); - } - elseif (count($this->result_object) > 0) - { - return $this->num_rows = count($this->result_object); - } - elseif (($num_rows = $this->result_id->rowCount()) > 0) - { - return $this->num_rows = $num_rows; - } - - return $this->num_rows = count($this->result_array()); - } - - // -------------------------------------------------------------------- - - /** - * Number of fields in the result set - * - * @return int - */ - public function num_fields() - { - return $this->result_id->columnCount(); - } - - // -------------------------------------------------------------------- - - /** - * Fetch Field Names - * - * Generates an array of column names - * - * @return bool - */ - public function list_fields() - { - $field_names = array(); - for ($i = 0, $c = $this->num_fields(); $i < $c; $i++) - { - // Might trigger an E_WARNING due to not all subdrivers - // supporting getColumnMeta() - $field_names[$i] = @$this->result_id->getColumnMeta($i); - $field_names[$i] = $field_names[$i]['name']; - } - - return $field_names; - } - - // -------------------------------------------------------------------- - - /** - * Field data - * - * Generates an array of objects containing field meta-data - * - * @return array - */ - public function field_data() - { - try - { - $retval = array(); - - for ($i = 0, $c = $this->num_fields(); $i < $c; $i++) - { - $field = $this->result_id->getColumnMeta($i); - - $retval[$i] = new stdClass(); - $retval[$i]->name = $field['name']; - $retval[$i]->type = $field['native_type']; - $retval[$i]->max_length = ($field['len'] > 0) ? $field['len'] : NULL; - $retval[$i]->primary_key = (int) ( ! empty($field['flags']) && in_array('primary_key', $field['flags'], TRUE)); - } - - return $retval; - } - catch (Exception $e) - { - if ($this->db->db_debug) - { - return $this->db->display_error('db_unsupported_feature'); - } - - return FALSE; - } - } - - // -------------------------------------------------------------------- - - /** - * Free the result - * - * @return void - */ - public function free_result() - { - if (is_object($this->result_id)) - { - $this->result_id = FALSE; - } - } - - // -------------------------------------------------------------------- - - /** - * Result - associative array - * - * Returns the result set as an array - * - * @return array - */ - protected function _fetch_assoc() - { - return $this->result_id->fetch(PDO::FETCH_ASSOC); - } - - // -------------------------------------------------------------------- - - /** - * Result - object - * - * Returns the result set as an object - * - * @param string $class_name - * @return object - */ - protected function _fetch_object($class_name = 'stdClass') - { - return $this->result_id->fetchObject($class_name); - } - -} diff --git a/system/database/drivers/pdo/pdo_utility.php b/system/database/drivers/pdo/pdo_utility.php deleted file mode 100644 index 9091ea5..0000000 --- a/system/database/drivers/pdo/pdo_utility.php +++ /dev/null @@ -1,63 +0,0 @@ -db->display_error('db_unsupported_feature'); - } - -} diff --git a/system/database/drivers/pdo/subdrivers/index.html b/system/database/drivers/pdo/subdrivers/index.html deleted file mode 100644 index b702fbc..0000000 --- a/system/database/drivers/pdo/subdrivers/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - 403 Forbidden - - - -

Directory access is forbidden.

- - - diff --git a/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php b/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php deleted file mode 100644 index bbb675d..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_4d_driver.php +++ /dev/null @@ -1,200 +0,0 @@ -dsn)) - { - $this->dsn = '4D:host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname); - - empty($this->port) OR $this->dsn .= ';port='.$this->port; - empty($this->database) OR $this->dsn .= ';dbname='.$this->database; - empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set; - } - elseif ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 3) === FALSE) - { - $this->dsn .= ';charset='.$this->char_set; - } - } - - // -------------------------------------------------------------------- - - /** - * Show table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool $prefix_limit - * @return string - */ - protected function _list_tables($prefix_limit = FALSE) - { - $sql = 'SELECT '.$this->escape_identifiers('TABLE_NAME').' FROM '.$this->escape_identifiers('_USER_TABLES'); - - if ($prefix_limit === TRUE && $this->dbprefix !== '') - { - $sql .= ' WHERE '.$this->escape_identifiers('TABLE_NAME')." LIKE '".$this->escape_like_str($this->dbprefix)."%' " - .sprintf($this->_like_escape_str, $this->_like_escape_chr); - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Show column query - * - * Generates a platform-specific query string so that the column names can be fetched - * - * @param string $table - * @return string - */ - protected function _list_columns($table = '') - { - return 'SELECT '.$this->escape_identifiers('COLUMN_NAME').' FROM '.$this->escape_identifiers('_USER_COLUMNS') - .' WHERE '.$this->escape_identifiers('TABLE_NAME').' = '.$this->escape($table); - } - - // -------------------------------------------------------------------- - - /** - * Field data query - * - * Generates a platform-specific query so that the column data can be retrieved - * - * @param string $table - * @return string - */ - protected function _field_data($table) - { - return 'SELECT * FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE).' LIMIT 1'; - } - - // -------------------------------------------------------------------- - - /** - * Update statement - * - * Generates a platform-specific update string from the supplied data - * - * @param string $table - * @param array $values - * @return string - */ - protected function _update($table, $values) - { - $this->qb_limit = FALSE; - $this->qb_orderby = array(); - return parent::_update($table, $values); - } - - // -------------------------------------------------------------------- - - /** - * Delete statement - * - * Generates a platform-specific delete string from the supplied data - * - * @param string $table - * @return string - */ - protected function _delete($table) - { - $this->qb_limit = FALSE; - return parent::_delete($table); - } - - // -------------------------------------------------------------------- - - /** - * LIMIT - * - * Generates a platform-specific LIMIT clause - * - * @param string $sql SQL Query - * @return string - */ - protected function _limit($sql) - { - return $sql.' LIMIT '.$this->qb_limit.($this->qb_offset ? ' OFFSET '.$this->qb_offset : ''); - } - -} diff --git a/system/database/drivers/pdo/subdrivers/pdo_4d_forge.php b/system/database/drivers/pdo/subdrivers/pdo_4d_forge.php deleted file mode 100644 index 7135aa1..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_4d_forge.php +++ /dev/null @@ -1,217 +0,0 @@ - 'INT', - 'SMALLINT' => 'INT', - 'INT' => 'INT64', - 'INT32' => 'INT64' - ); - - /** - * DEFAULT value representation in CREATE/ALTER TABLE statements - * - * @var string - */ - protected $_default = FALSE; - - // -------------------------------------------------------------------- - - /** - * ALTER TABLE - * - * @param string $alter_type ALTER type - * @param string $table Table name - * @param mixed $field Column definition - * @return string|string[] - */ - protected function _alter_table($alter_type, $table, $field) - { - if (in_array($alter_type, array('ADD', 'DROP'), TRUE)) - { - return parent::_alter_table($alter_type, $table, $field); - } - - // No method of modifying columns is supported - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Process column - * - * @param array $field - * @return string - */ - protected function _process_column($field) - { - return $this->db->escape_identifiers($field['name']) - .' '.$field['type'].$field['length'] - .$field['null'] - .$field['unique'] - .$field['auto_increment']; - } - - // -------------------------------------------------------------------- - - /** - * Field attribute TYPE - * - * Performs a data type mapping between different databases. - * - * @param array &$attributes - * @return void - */ - protected function _attr_type(&$attributes) - { - switch (strtoupper($attributes['TYPE'])) - { - case 'TINYINT': - $attributes['TYPE'] = 'SMALLINT'; - $attributes['UNSIGNED'] = FALSE; - return; - case 'MEDIUMINT': - $attributes['TYPE'] = 'INTEGER'; - $attributes['UNSIGNED'] = FALSE; - return; - case 'INTEGER': - $attributes['TYPE'] = 'INT'; - return; - case 'BIGINT': - $attributes['TYPE'] = 'INT64'; - return; - default: return; - } - } - - // -------------------------------------------------------------------- - - /** - * Field attribute UNIQUE - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_unique(&$attributes, &$field) - { - if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE) - { - $field['unique'] = ' UNIQUE'; - - // UNIQUE must be used with NOT NULL - $field['null'] = ' NOT NULL'; - } - } - - // -------------------------------------------------------------------- - - /** - * Field attribute AUTO_INCREMENT - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_auto_increment(&$attributes, &$field) - { - if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE) - { - if (stripos($field['type'], 'int') !== FALSE) - { - $field['auto_increment'] = ' AUTO_INCREMENT'; - } - elseif (strcasecmp($field['type'], 'UUID') === 0) - { - $field['auto_increment'] = ' AUTO_GENERATE'; - } - } - } - -} diff --git a/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php b/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php deleted file mode 100644 index 3189aab..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php +++ /dev/null @@ -1,209 +0,0 @@ -dsn)) - { - $this->dsn = 'cubrid:host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname); - - empty($this->port) OR $this->dsn .= ';port='.$this->port; - empty($this->database) OR $this->dsn .= ';dbname='.$this->database; - empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set; - } - } - - // -------------------------------------------------------------------- - - /** - * Show table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool $prefix_limit - * @return string - */ - protected function _list_tables($prefix_limit = FALSE) - { - $sql = 'SHOW TABLES'; - - if ($prefix_limit === TRUE && $this->dbprefix !== '') - { - return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'"; - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Show column query - * - * Generates a platform-specific query string so that the column names can be fetched - * - * @param string $table - * @return string - */ - protected function _list_columns($table = '') - { - return 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE); - } - - // -------------------------------------------------------------------- - - /** - * Returns an object with field data - * - * @param string $table - * @return array - */ - public function field_data($table) - { - if (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE) - { - return FALSE; - } - $query = $query->result_object(); - - $retval = array(); - for ($i = 0, $c = count($query); $i < $c; $i++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = $query[$i]->Field; - - sscanf($query[$i]->Type, '%[a-z](%d)', - $retval[$i]->type, - $retval[$i]->max_length - ); - - $retval[$i]->default = $query[$i]->Default; - $retval[$i]->primary_key = (int) ($query[$i]->Key === 'PRI'); - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Truncate statement - * - * Generates a platform-specific truncate string from the supplied data - * - * If the database does not support the TRUNCATE statement, - * then this method maps to 'DELETE FROM table' - * - * @param string $table - * @return string - */ - protected function _truncate($table) - { - return 'TRUNCATE '.$table; - } - - // -------------------------------------------------------------------- - - /** - * FROM tables - * - * Groups tables in FROM clauses if needed, so there is no confusion - * about operator precedence. - * - * @return string - */ - protected function _from_tables() - { - if ( ! empty($this->qb_join) && count($this->qb_from) > 1) - { - return '('.implode(', ', $this->qb_from).')'; - } - - return implode(', ', $this->qb_from); - } - -} diff --git a/system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php b/system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php deleted file mode 100644 index 624ce51..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php +++ /dev/null @@ -1,230 +0,0 @@ - 'INTEGER', - 'SMALLINT' => 'INTEGER', - 'INT' => 'BIGINT', - 'INTEGER' => 'BIGINT', - 'BIGINT' => 'NUMERIC', - 'FLOAT' => 'DOUBLE', - 'REAL' => 'DOUBLE' - ); - - // -------------------------------------------------------------------- - - /** - * ALTER TABLE - * - * @param string $alter_type ALTER type - * @param string $table Table name - * @param mixed $field Column definition - * @return string|string[] - */ - protected function _alter_table($alter_type, $table, $field) - { - if (in_array($alter_type, array('DROP', 'ADD'), TRUE)) - { - return parent::_alter_table($alter_type, $table, $field); - } - - $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table); - $sqls = array(); - for ($i = 0, $c = count($field); $i < $c; $i++) - { - if ($field[$i]['_literal'] !== FALSE) - { - $sqls[] = $sql.' CHANGE '.$field[$i]['_literal']; - } - else - { - $alter_type = empty($field[$i]['new_name']) ? ' MODIFY ' : ' CHANGE '; - $sqls[] = $sql.$alter_type.$this->_process_column($field[$i]); - } - } - - return $sqls; - } - - // -------------------------------------------------------------------- - - /** - * Process column - * - * @param array $field - * @return string - */ - protected function _process_column($field) - { - $extra_clause = isset($field['after']) - ? ' AFTER '.$this->db->escape_identifiers($field['after']) : ''; - - if (empty($extra_clause) && isset($field['first']) && $field['first'] === TRUE) - { - $extra_clause = ' FIRST'; - } - - return $this->db->escape_identifiers($field['name']) - .(empty($field['new_name']) ? '' : ' '.$this->db->escape_identifiers($field['new_name'])) - .' '.$field['type'].$field['length'] - .$field['unsigned'] - .$field['null'] - .$field['default'] - .$field['auto_increment'] - .$field['unique'] - .$extra_clause; - } - - // -------------------------------------------------------------------- - - /** - * Field attribute TYPE - * - * Performs a data type mapping between different databases. - * - * @param array &$attributes - * @return void - */ - protected function _attr_type(&$attributes) - { - switch (strtoupper($attributes['TYPE'])) - { - case 'TINYINT': - $attributes['TYPE'] = 'SMALLINT'; - $attributes['UNSIGNED'] = FALSE; - return; - case 'MEDIUMINT': - $attributes['TYPE'] = 'INTEGER'; - $attributes['UNSIGNED'] = FALSE; - return; - case 'LONGTEXT': - $attributes['TYPE'] = 'STRING'; - return; - default: return; - } - } - - // -------------------------------------------------------------------- - - /** - * Process indexes - * - * @param string $table (ignored) - * @return string - */ - protected function _process_indexes($table) - { - $sql = ''; - - for ($i = 0, $c = count($this->keys); $i < $c; $i++) - { - if (is_array($this->keys[$i])) - { - for ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++) - { - if ( ! isset($this->fields[$this->keys[$i][$i2]])) - { - unset($this->keys[$i][$i2]); - continue; - } - } - } - elseif ( ! isset($this->fields[$this->keys[$i]])) - { - unset($this->keys[$i]); - continue; - } - - is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]); - - $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i])) - .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')'; - } - - $this->keys = array(); - - return $sql; - } - -} diff --git a/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php b/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php deleted file mode 100644 index d04f8b3..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php +++ /dev/null @@ -1,353 +0,0 @@ -dsn)) - { - $this->dsn = $params['subdriver'].':host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname); - - if ( ! empty($this->port)) - { - $this->dsn .= (DIRECTORY_SEPARATOR === '\\' ? ',' : ':').$this->port; - } - - empty($this->database) OR $this->dsn .= ';dbname='.$this->database; - empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set; - empty($this->appname) OR $this->dsn .= ';appname='.$this->appname; - } - else - { - if ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 6) === FALSE) - { - $this->dsn .= ';charset='.$this->char_set; - } - - $this->subdriver = 'dblib'; - } - } - - // -------------------------------------------------------------------- - - /** - * Database connection - * - * @param bool $persistent - * @return object - */ - public function db_connect($persistent = FALSE) - { - if ($persistent === TRUE) - { - log_message('debug', "dblib driver doesn't support persistent connections"); - } - - $this->conn_id = parent::db_connect(FALSE); - - if ( ! is_object($this->conn_id)) - { - return $this->conn_id; - } - - // Determine how identifiers are escaped - $query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi'); - $query = $query->row_array(); - $this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi']; - $this->_escape_char = ($this->_quoted_identifier) ? '"' : array('[', ']'); - - return $this->conn_id; - } - - // -------------------------------------------------------------------- - - /** - * Show table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool $prefix_limit - * @return string - */ - protected function _list_tables($prefix_limit = FALSE) - { - $sql = 'SELECT '.$this->escape_identifiers('name') - .' FROM '.$this->escape_identifiers('sysobjects') - .' WHERE '.$this->escape_identifiers('type')." = 'U'"; - - if ($prefix_limit === TRUE && $this->dbprefix !== '') - { - $sql .= ' AND '.$this->escape_identifiers('name')." LIKE '".$this->escape_like_str($this->dbprefix)."%' " - .sprintf($this->_like_escape_str, $this->_like_escape_chr); - } - - return $sql.' ORDER BY '.$this->escape_identifiers('name'); - } - - // -------------------------------------------------------------------- - - /** - * Show column query - * - * Generates a platform-specific query string so that the column names can be fetched - * - * @param string $table - * @return string - */ - protected function _list_columns($table = '') - { - return 'SELECT COLUMN_NAME - FROM INFORMATION_SCHEMA.Columns - WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table)); - } - - // -------------------------------------------------------------------- - - /** - * Returns an object with field data - * - * @param string $table - * @return array - */ - public function field_data($table) - { - $sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, COLUMN_DEFAULT - FROM INFORMATION_SCHEMA.Columns - WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table)); - - if (($query = $this->query($sql)) === FALSE) - { - return FALSE; - } - $query = $query->result_object(); - - $retval = array(); - for ($i = 0, $c = count($query); $i < $c; $i++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = $query[$i]->COLUMN_NAME; - $retval[$i]->type = $query[$i]->DATA_TYPE; - $retval[$i]->max_length = ($query[$i]->CHARACTER_MAXIMUM_LENGTH > 0) ? $query[$i]->CHARACTER_MAXIMUM_LENGTH : $query[$i]->NUMERIC_PRECISION; - $retval[$i]->default = $query[$i]->COLUMN_DEFAULT; - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Update statement - * - * Generates a platform-specific update string from the supplied data - * - * @param string $table - * @param array $values - * @return string - */ - protected function _update($table, $values) - { - $this->qb_limit = FALSE; - $this->qb_orderby = array(); - return parent::_update($table, $values); - } - - // -------------------------------------------------------------------- - - /** - * Delete statement - * - * Generates a platform-specific delete string from the supplied data - * - * @param string $table - * @return string - */ - protected function _delete($table) - { - if ($this->qb_limit) - { - return 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete'; - } - - return parent::_delete($table); - } - - // -------------------------------------------------------------------- - - /** - * LIMIT - * - * Generates a platform-specific LIMIT clause - * - * @param string $sql SQL Query - * @return string - */ - protected function _limit($sql) - { - $limit = $this->qb_offset + $this->qb_limit; - - // As of SQL Server 2005 (9.0.*) ROW_NUMBER() is supported, - // however an ORDER BY clause is required for it to work - if (version_compare($this->version(), '9', '>=') && $this->qb_offset && ! empty($this->qb_orderby)) - { - $orderby = $this->_compile_order_by(); - - // We have to strip the ORDER BY clause - $sql = trim(substr($sql, 0, strrpos($sql, $orderby))); - - // Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results - if (count($this->qb_select) === 0 OR strpos(implode(',', $this->qb_select), '*') !== FALSE) - { - $select = '*'; // Inevitable - } - else - { - // Use only field names and their aliases, everything else is out of our scope. - $select = array(); - $field_regexp = ($this->_quoted_identifier) - ? '("[^\"]+")' : '(\[[^\]]+\])'; - for ($i = 0, $c = count($this->qb_select); $i < $c; $i++) - { - $select[] = preg_match('/(?:\s|\.)'.$field_regexp.'$/i', $this->qb_select[$i], $m) - ? $m[1] : $this->qb_select[$i]; - } - $select = implode(', ', $select); - } - - return 'SELECT '.$select." FROM (\n\n" - .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.trim($orderby).') AS '.$this->escape_identifiers('CI_rownum').', ', $sql) - ."\n\n) ".$this->escape_identifiers('CI_subquery') - ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit; - } - - return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql); - } - - // -------------------------------------------------------------------- - - /** - * Insert batch statement - * - * Generates a platform-specific insert string from the supplied data. - * - * @param string $table Table name - * @param array $keys INSERT keys - * @param array $values INSERT values - * @return string|bool - */ - protected function _insert_batch($table, $keys, $values) - { - // Multiple-value inserts are only supported as of SQL Server 2008 - if (version_compare($this->version(), '10', '>=')) - { - return parent::_insert_batch($table, $keys, $values); - } - - return ($this->db_debug) ? $this->display_error('db_unsupported_feature') : FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Database version number - * - * @return string - */ - public function version() - { - if (isset($this->data_cache['version'])) - { - return $this->data_cache['version']; - } - - return $this->data_cache['version'] = $this->conn_id->query("SELECT SERVERPROPERTY('ProductVersion') AS ver")->fetchColumn(0); - } -} diff --git a/system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php b/system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php deleted file mode 100644 index 0216b59..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php +++ /dev/null @@ -1,149 +0,0 @@ - 'SMALLINT', - 'SMALLINT' => 'INT', - 'INT' => 'BIGINT', - 'REAL' => 'FLOAT' - ); - - // -------------------------------------------------------------------- - - /** - * ALTER TABLE - * - * @param string $alter_type ALTER type - * @param string $table Table name - * @param mixed $field Column definition - * @return string|string[] - */ - protected function _alter_table($alter_type, $table, $field) - { - if (in_array($alter_type, array('ADD', 'DROP'), TRUE)) - { - return parent::_alter_table($alter_type, $table, $field); - } - - $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ALTER COLUMN '; - $sqls = array(); - for ($i = 0, $c = count($field); $i < $c; $i++) - { - $sqls[] = $sql.$this->_process_column($field[$i]); - } - - return $sqls; - } - - // -------------------------------------------------------------------- - - /** - * Field attribute TYPE - * - * Performs a data type mapping between different databases. - * - * @param array &$attributes - * @return void - */ - protected function _attr_type(&$attributes) - { - if (isset($attributes['CONSTRAINT']) && strpos($attributes['TYPE'], 'INT') !== FALSE) - { - unset($attributes['CONSTRAINT']); - } - - switch (strtoupper($attributes['TYPE'])) - { - case 'MEDIUMINT': - $attributes['TYPE'] = 'INTEGER'; - $attributes['UNSIGNED'] = FALSE; - return; - case 'INTEGER': - $attributes['TYPE'] = 'INT'; - return; - default: return; - } - } - - // -------------------------------------------------------------------- - - /** - * Field attribute AUTO_INCREMENT - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_auto_increment(&$attributes, &$field) - { - if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE) - { - $field['auto_increment'] = ' IDENTITY(1,1)'; - } - } - -} diff --git a/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php b/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php deleted file mode 100644 index eec5bf2..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php +++ /dev/null @@ -1,279 +0,0 @@ -dsn)) - { - $this->dsn = 'firebird:'; - - if ( ! empty($this->database)) - { - $this->dsn .= 'dbname='.$this->database; - } - elseif ( ! empty($this->hostname)) - { - $this->dsn .= 'dbname='.$this->hostname; - } - - empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set; - empty($this->role) OR $this->dsn .= ';role='.$this->role; - } - elseif ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 9) === FALSE) - { - $this->dsn .= ';charset='.$this->char_set; - } - } - - // -------------------------------------------------------------------- - - /** - * Show table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool $prefix_limit - * @return string - */ - protected function _list_tables($prefix_limit = FALSE) - { - $sql = 'SELECT "RDB$RELATION_NAME" FROM "RDB$RELATIONS" WHERE "RDB$RELATION_NAME" NOT LIKE \'RDB$%\' AND "RDB$RELATION_NAME" NOT LIKE \'MON$%\''; - - if ($prefix_limit === TRUE && $this->dbprefix !== '') - { - return $sql.' AND "RDB$RELATION_NAME" LIKE \''.$this->escape_like_str($this->dbprefix)."%' " - .sprintf($this->_like_escape_str, $this->_like_escape_chr); - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Show column query - * - * Generates a platform-specific query string so that the column names can be fetched - * - * @param string $table - * @return string - */ - protected function _list_columns($table = '') - { - return 'SELECT "RDB$FIELD_NAME" FROM "RDB$RELATION_FIELDS" WHERE "RDB$RELATION_NAME" = '.$this->escape($table); - } - - // -------------------------------------------------------------------- - - /** - * Returns an object with field data - * - * @param string $table - * @return array - */ - public function field_data($table) - { - $sql = 'SELECT "rfields"."RDB$FIELD_NAME" AS "name", - CASE "fields"."RDB$FIELD_TYPE" - WHEN 7 THEN \'SMALLINT\' - WHEN 8 THEN \'INTEGER\' - WHEN 9 THEN \'QUAD\' - WHEN 10 THEN \'FLOAT\' - WHEN 11 THEN \'DFLOAT\' - WHEN 12 THEN \'DATE\' - WHEN 13 THEN \'TIME\' - WHEN 14 THEN \'CHAR\' - WHEN 16 THEN \'INT64\' - WHEN 27 THEN \'DOUBLE\' - WHEN 35 THEN \'TIMESTAMP\' - WHEN 37 THEN \'VARCHAR\' - WHEN 40 THEN \'CSTRING\' - WHEN 261 THEN \'BLOB\' - ELSE NULL - END AS "type", - "fields"."RDB$FIELD_LENGTH" AS "max_length", - "rfields"."RDB$DEFAULT_VALUE" AS "default" - FROM "RDB$RELATION_FIELDS" "rfields" - JOIN "RDB$FIELDS" "fields" ON "rfields"."RDB$FIELD_SOURCE" = "fields"."RDB$FIELD_NAME" - WHERE "rfields"."RDB$RELATION_NAME" = '.$this->escape($table).' - ORDER BY "rfields"."RDB$FIELD_POSITION"'; - - return (($query = $this->query($sql)) !== FALSE) - ? $query->result_object() - : FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Update statement - * - * Generates a platform-specific update string from the supplied data - * - * @param string $table - * @param array $values - * @return string - */ - protected function _update($table, $values) - { - $this->qb_limit = FALSE; - return parent::_update($table, $values); - } - - // -------------------------------------------------------------------- - - /** - * Truncate statement - * - * Generates a platform-specific truncate string from the supplied data - * - * If the database does not support the TRUNCATE statement, - * then this method maps to 'DELETE FROM table' - * - * @param string $table - * @return string - */ - protected function _truncate($table) - { - return 'DELETE FROM '.$table; - } - - // -------------------------------------------------------------------- - - /** - * Delete statement - * - * Generates a platform-specific delete string from the supplied data - * - * @param string $table - * @return string - */ - protected function _delete($table) - { - $this->qb_limit = FALSE; - return parent::_delete($table); - } - - // -------------------------------------------------------------------- - - /** - * LIMIT - * - * Generates a platform-specific LIMIT clause - * - * @param string $sql SQL Query - * @return string - */ - protected function _limit($sql) - { - // Limit clause depends on if Interbase or Firebird - if (stripos($this->version(), 'firebird') !== FALSE) - { - $select = 'FIRST '.$this->qb_limit - .($this->qb_offset > 0 ? ' SKIP '.$this->qb_offset : ''); - } - else - { - $select = 'ROWS ' - .($this->qb_offset > 0 ? $this->qb_offset.' TO '.($this->qb_limit + $this->qb_offset) : $this->qb_limit); - } - - return preg_replace('`SELECT`i', 'SELECT '.$select, $sql); - } - - // -------------------------------------------------------------------- - - /** - * Insert batch statement - * - * Generates a platform-specific insert string from the supplied data. - * - * @param string $table Table name - * @param array $keys INSERT keys - * @param array $values INSERT values - * @return string|bool - */ - protected function _insert_batch($table, $keys, $values) - { - return ($this->db_debug) ? $this->display_error('db_unsupported_feature') : FALSE; - } -} diff --git a/system/database/drivers/pdo/subdrivers/pdo_firebird_forge.php b/system/database/drivers/pdo/subdrivers/pdo_firebird_forge.php deleted file mode 100644 index 2a5fa64..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_firebird_forge.php +++ /dev/null @@ -1,237 +0,0 @@ - 'INTEGER', - 'INTEGER' => 'INT64', - 'FLOAT' => 'DOUBLE PRECISION' - ); - - /** - * NULL value representation in CREATE/ALTER TABLE statements - * - * @var string - */ - protected $_null = 'NULL'; - - // -------------------------------------------------------------------- - - /** - * Create database - * - * @param string $db_name - * @return string - */ - public function create_database($db_name) - { - // Firebird databases are flat files, so a path is required - - // Hostname is needed for remote access - empty($this->db->hostname) OR $db_name = $this->hostname.':'.$db_name; - - return parent::create_database('"'.$db_name.'"'); - } - - // -------------------------------------------------------------------- - - /** - * Drop database - * - * @param string $db_name (ignored) - * @return bool - */ - public function drop_database($db_name) - { - if ( ! ibase_drop_db($this->conn_id)) - { - return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE; - } - elseif ( ! empty($this->db->data_cache['db_names'])) - { - $key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE); - if ($key !== FALSE) - { - unset($this->db->data_cache['db_names'][$key]); - } - } - - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * ALTER TABLE - * - * @param string $alter_type ALTER type - * @param string $table Table name - * @param mixed $field Column definition - * @return string|string[] - */ - protected function _alter_table($alter_type, $table, $field) - { - if (in_array($alter_type, array('DROP', 'ADD'), TRUE)) - { - return parent::_alter_table($alter_type, $table, $field); - } - - $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table); - $sqls = array(); - for ($i = 0, $c = count($field); $i < $c; $i++) - { - if ($field[$i]['_literal'] !== FALSE) - { - return FALSE; - } - - if (isset($field[$i]['type'])) - { - $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name']) - .' TYPE '.$field[$i]['type'].$field[$i]['length']; - } - - if ( ! empty($field[$i]['default'])) - { - $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name']) - .' SET DEFAULT '.$field[$i]['default']; - } - - if (isset($field[$i]['null'])) - { - $sqls[] = 'UPDATE "RDB$RELATION_FIELDS" SET "RDB$NULL_FLAG" = ' - .($field[$i]['null'] === TRUE ? 'NULL' : '1') - .' WHERE "RDB$FIELD_NAME" = '.$this->db->escape($field[$i]['name']) - .' AND "RDB$RELATION_NAME" = '.$this->db->escape($table); - } - - if ( ! empty($field[$i]['new_name'])) - { - $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name']) - .' TO '.$this->db->escape_identifiers($field[$i]['new_name']); - } - } - - return $sqls; - } - - // -------------------------------------------------------------------- - - /** - * Process column - * - * @param array $field - * @return string - */ - protected function _process_column($field) - { - return $this->db->escape_identifiers($field['name']) - .' '.$field['type'].$field['length'] - .$field['null'] - .$field['unique'] - .$field['default']; - } - - // -------------------------------------------------------------------- - - /** - * Field attribute TYPE - * - * Performs a data type mapping between different databases. - * - * @param array &$attributes - * @return void - */ - protected function _attr_type(&$attributes) - { - switch (strtoupper($attributes['TYPE'])) - { - case 'TINYINT': - $attributes['TYPE'] = 'SMALLINT'; - $attributes['UNSIGNED'] = FALSE; - return; - case 'MEDIUMINT': - $attributes['TYPE'] = 'INTEGER'; - $attributes['UNSIGNED'] = FALSE; - return; - case 'INT': - $attributes['TYPE'] = 'INTEGER'; - return; - case 'BIGINT': - $attributes['TYPE'] = 'INT64'; - return; - default: return; - } - } - - // -------------------------------------------------------------------- - - /** - * Field attribute AUTO_INCREMENT - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_auto_increment(&$attributes, &$field) - { - // Not supported - } - -} diff --git a/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php b/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php deleted file mode 100644 index 43400a4..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php +++ /dev/null @@ -1,244 +0,0 @@ -dsn)) - { - $this->dsn = 'ibm:'; - - // Pre-defined DSN - if (empty($this->hostname) && empty($this->HOSTNAME) && empty($this->port) && empty($this->PORT)) - { - if (isset($this->DSN)) - { - $this->dsn .= 'DSN='.$this->DSN; - } - elseif ( ! empty($this->database)) - { - $this->dsn .= 'DSN='.$this->database; - } - - return; - } - - $this->dsn .= 'DRIVER='.(isset($this->DRIVER) ? '{'.$this->DRIVER.'}' : '{IBM DB2 ODBC DRIVER}').';'; - - if (isset($this->DATABASE)) - { - $this->dsn .= 'DATABASE='.$this->DATABASE.';'; - } - elseif ( ! empty($this->database)) - { - $this->dsn .= 'DATABASE='.$this->database.';'; - } - - if (isset($this->HOSTNAME)) - { - $this->dsn .= 'HOSTNAME='.$this->HOSTNAME.';'; - } - else - { - $this->dsn .= 'HOSTNAME='.(empty($this->hostname) ? '127.0.0.1;' : $this->hostname.';'); - } - - if (isset($this->PORT)) - { - $this->dsn .= 'PORT='.$this->port.';'; - } - elseif ( ! empty($this->port)) - { - $this->dsn .= ';PORT='.$this->port.';'; - } - - $this->dsn .= 'PROTOCOL='.(isset($this->PROTOCOL) ? $this->PROTOCOL.';' : 'TCPIP;'); - } - } - - // -------------------------------------------------------------------- - - /** - * Show table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool $prefix_limit - * @return string - */ - protected function _list_tables($prefix_limit = FALSE) - { - $sql = 'SELECT "tabname" FROM "syscat"."tables" - WHERE "type" = \'T\' AND LOWER("tabschema") = '.$this->escape(strtolower($this->database)); - - if ($prefix_limit === TRUE && $this->dbprefix !== '') - { - $sql .= ' AND "tabname" LIKE \''.$this->escape_like_str($this->dbprefix)."%' " - .sprintf($this->_like_escape_str, $this->_like_escape_chr); - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Show column query - * - * Generates a platform-specific query string so that the column names can be fetched - * - * @param string $table - * @return array - */ - protected function _list_columns($table = '') - { - return 'SELECT "colname" FROM "syscat"."columns" - WHERE LOWER("tabschema") = '.$this->escape(strtolower($this->database)).' - AND LOWER("tabname") = '.$this->escape(strtolower($table)); - } - - // -------------------------------------------------------------------- - - /** - * Returns an object with field data - * - * @param string $table - * @return array - */ - public function field_data($table) - { - $sql = 'SELECT "colname" AS "name", "typename" AS "type", "default" AS "default", "length" AS "max_length", - CASE "keyseq" WHEN NULL THEN 0 ELSE 1 END AS "primary_key" - FROM "syscat"."columns" - WHERE LOWER("tabschema") = '.$this->escape(strtolower($this->database)).' - AND LOWER("tabname") = '.$this->escape(strtolower($table)).' - ORDER BY "colno"'; - - return (($query = $this->query($sql)) !== FALSE) - ? $query->result_object() - : FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Update statement - * - * Generates a platform-specific update string from the supplied data - * - * @param string $table - * @param array $values - * @return string - */ - protected function _update($table, $values) - { - $this->qb_limit = FALSE; - $this->qb_orderby = array(); - return parent::_update($table, $values); - } - - // -------------------------------------------------------------------- - - /** - * Delete statement - * - * Generates a platform-specific delete string from the supplied data - * - * @param string $table - * @return string - */ - protected function _delete($table) - { - $this->qb_limit = FALSE; - return parent::_delete($table); - } - - // -------------------------------------------------------------------- - - /** - * LIMIT - * - * Generates a platform-specific LIMIT clause - * - * @param string $sql SQL Query - * @return string - */ - protected function _limit($sql) - { - $sql .= ' FETCH FIRST '.($this->qb_limit + $this->qb_offset).' ROWS ONLY'; - - return ($this->qb_offset) - ? 'SELECT * FROM ('.$sql.') WHERE rownum > '.$this->qb_offset - : $sql; - } - -} diff --git a/system/database/drivers/pdo/subdrivers/pdo_ibm_forge.php b/system/database/drivers/pdo/subdrivers/pdo_ibm_forge.php deleted file mode 100644 index f1bd2c3..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_ibm_forge.php +++ /dev/null @@ -1,154 +0,0 @@ - 'INTEGER', - 'INT' => 'BIGINT', - 'INTEGER' => 'BIGINT' - ); - - /** - * DEFAULT value representation in CREATE/ALTER TABLE statements - * - * @var string - */ - protected $_default = FALSE; - - // -------------------------------------------------------------------- - - /** - * ALTER TABLE - * - * @param string $alter_type ALTER type - * @param string $table Table name - * @param mixed $field Column definition - * @return string|string[] - */ - protected function _alter_table($alter_type, $table, $field) - { - if ($alter_type === 'CHANGE') - { - $alter_type = 'MODIFY'; - } - - return parent::_alter_table($alter_type, $table, $field); - } - - // -------------------------------------------------------------------- - - /** - * Field attribute TYPE - * - * Performs a data type mapping between different databases. - * - * @param array &$attributes - * @return void - */ - protected function _attr_type(&$attributes) - { - switch (strtoupper($attributes['TYPE'])) - { - case 'TINYINT': - $attributes['TYPE'] = 'SMALLINT'; - $attributes['UNSIGNED'] = FALSE; - return; - case 'MEDIUMINT': - $attributes['TYPE'] = 'INTEGER'; - $attributes['UNSIGNED'] = FALSE; - return; - default: return; - } - } - - // -------------------------------------------------------------------- - - /** - * Field attribute UNIQUE - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_unique(&$attributes, &$field) - { - if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE) - { - $field['unique'] = ' UNIQUE'; - - // UNIQUE must be used with NOT NULL - $field['null'] = ' NOT NULL'; - } - } - - // -------------------------------------------------------------------- - - /** - * Field attribute AUTO_INCREMENT - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_auto_increment(&$attributes, &$field) - { - // Not supported - } - -} diff --git a/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php b/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php deleted file mode 100644 index e44dcb8..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_informix_driver.php +++ /dev/null @@ -1,309 +0,0 @@ -dsn)) - { - $this->dsn = 'informix:'; - - // Pre-defined DSN - if (empty($this->hostname) && empty($this->host) && empty($this->port) && empty($this->service)) - { - if (isset($this->DSN)) - { - $this->dsn .= 'DSN='.$this->DSN; - } - elseif ( ! empty($this->database)) - { - $this->dsn .= 'DSN='.$this->database; - } - - return; - } - - if (isset($this->host)) - { - $this->dsn .= 'host='.$this->host; - } - else - { - $this->dsn .= 'host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname); - } - - if (isset($this->service)) - { - $this->dsn .= '; service='.$this->service; - } - elseif ( ! empty($this->port)) - { - $this->dsn .= '; service='.$this->port; - } - - empty($this->database) OR $this->dsn .= '; database='.$this->database; - empty($this->server) OR $this->dsn .= '; server='.$this->server; - - $this->dsn .= '; protocol='.(isset($this->protocol) ? $this->protocol : 'onsoctcp') - .'; EnableScrollableCursors=1'; - } - } - - // -------------------------------------------------------------------- - - /** - * Show table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool $prefix_limit - * @return string - */ - protected function _list_tables($prefix_limit = FALSE) - { - $sql = 'SELECT "tabname" FROM "systables" - WHERE "tabid" > 99 AND "tabtype" = \'T\' AND LOWER("owner") = '.$this->escape(strtolower($this->username)); - - if ($prefix_limit === TRUE && $this->dbprefix !== '') - { - $sql .= ' AND "tabname" LIKE \''.$this->escape_like_str($this->dbprefix)."%' " - .sprintf($this->_like_escape_str, $this->_like_escape_chr); - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Show column query - * - * Generates a platform-specific query string so that the column names can be fetched - * - * @param string $table - * @return string - */ - protected function _list_columns($table = '') - { - if (strpos($table, '.') !== FALSE) - { - sscanf($table, '%[^.].%s', $owner, $table); - } - else - { - $owner = $this->username; - } - - return 'SELECT "colname" FROM "systables", "syscolumns" - WHERE "systables"."tabid" = "syscolumns"."tabid" - AND "systables"."tabtype" = \'T\' - AND LOWER("systables"."owner") = '.$this->escape(strtolower($owner)).' - AND LOWER("systables"."tabname") = '.$this->escape(strtolower($table)); - } - - // -------------------------------------------------------------------- - - /** - * Returns an object with field data - * - * @param string $table - * @return array - */ - public function field_data($table) - { - $sql = 'SELECT "syscolumns"."colname" AS "name", - CASE "syscolumns"."coltype" - WHEN 0 THEN \'CHAR\' - WHEN 1 THEN \'SMALLINT\' - WHEN 2 THEN \'INTEGER\' - WHEN 3 THEN \'FLOAT\' - WHEN 4 THEN \'SMALLFLOAT\' - WHEN 5 THEN \'DECIMAL\' - WHEN 6 THEN \'SERIAL\' - WHEN 7 THEN \'DATE\' - WHEN 8 THEN \'MONEY\' - WHEN 9 THEN \'NULL\' - WHEN 10 THEN \'DATETIME\' - WHEN 11 THEN \'BYTE\' - WHEN 12 THEN \'TEXT\' - WHEN 13 THEN \'VARCHAR\' - WHEN 14 THEN \'INTERVAL\' - WHEN 15 THEN \'NCHAR\' - WHEN 16 THEN \'NVARCHAR\' - WHEN 17 THEN \'INT8\' - WHEN 18 THEN \'SERIAL8\' - WHEN 19 THEN \'SET\' - WHEN 20 THEN \'MULTISET\' - WHEN 21 THEN \'LIST\' - WHEN 22 THEN \'Unnamed ROW\' - WHEN 40 THEN \'LVARCHAR\' - WHEN 41 THEN \'BLOB/CLOB/BOOLEAN\' - WHEN 4118 THEN \'Named ROW\' - ELSE "syscolumns"."coltype" - END AS "type", - "syscolumns"."collength" as "max_length", - CASE "sysdefaults"."type" - WHEN \'L\' THEN "sysdefaults"."default" - ELSE NULL - END AS "default" - FROM "syscolumns", "systables", "sysdefaults" - WHERE "syscolumns"."tabid" = "systables"."tabid" - AND "systables"."tabid" = "sysdefaults"."tabid" - AND "syscolumns"."colno" = "sysdefaults"."colno" - AND "systables"."tabtype" = \'T\' - AND LOWER("systables"."owner") = '.$this->escape(strtolower($this->username)).' - AND LOWER("systables"."tabname") = '.$this->escape(strtolower($table)).' - ORDER BY "syscolumns"."colno"'; - - return (($query = $this->query($sql)) !== FALSE) - ? $query->result_object() - : FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Update statement - * - * Generates a platform-specific update string from the supplied data - * - * @param string $table - * @param array $values - * @return string - */ - protected function _update($table, $values) - { - $this->qb_limit = FALSE; - $this->qb_orderby = array(); - return parent::_update($table, $values); - } - - // -------------------------------------------------------------------- - - /** - * Truncate statement - * - * Generates a platform-specific truncate string from the supplied data - * - * If the database does not support the TRUNCATE statement, - * then this method maps to 'DELETE FROM table' - * - * @param string $table - * @return string - */ - protected function _truncate($table) - { - return 'TRUNCATE TABLE ONLY '.$table; - } - - // -------------------------------------------------------------------- - - /** - * Delete statement - * - * Generates a platform-specific delete string from the supplied data - * - * @param string $table - * @return string - */ - protected function _delete($table) - { - $this->qb_limit = FALSE; - return parent::_delete($table); - } - - // -------------------------------------------------------------------- - - /** - * LIMIT - * - * Generates a platform-specific LIMIT clause - * - * @param string $sql $SQL Query - * @return string - */ - protected function _limit($sql) - { - $select = 'SELECT '.($this->qb_offset ? 'SKIP '.$this->qb_offset : '').'FIRST '.$this->qb_limit.' '; - return preg_replace('/^(SELECT\s)/i', $select, $sql, 1); - } - -} diff --git a/system/database/drivers/pdo/subdrivers/pdo_informix_forge.php b/system/database/drivers/pdo/subdrivers/pdo_informix_forge.php deleted file mode 100644 index e4202c2..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_informix_forge.php +++ /dev/null @@ -1,163 +0,0 @@ - 'INTEGER', - 'INT' => 'BIGINT', - 'INTEGER' => 'BIGINT', - 'REAL' => 'DOUBLE PRECISION', - 'SMALLFLOAT' => 'DOUBLE PRECISION' - ); - - /** - * DEFAULT value representation in CREATE/ALTER TABLE statements - * - * @var string - */ - protected $_default = ', '; - - // -------------------------------------------------------------------- - - /** - * ALTER TABLE - * - * @param string $alter_type ALTER type - * @param string $table Table name - * @param mixed $field Column definition - * @return string|string[] - */ - protected function _alter_table($alter_type, $table, $field) - { - if ($alter_type === 'CHANGE') - { - $alter_type = 'MODIFY'; - } - - return parent::_alter_table($alter_type, $table, $field); - } - - // -------------------------------------------------------------------- - - /** - * Field attribute TYPE - * - * Performs a data type mapping between different databases. - * - * @param array &$attributes - * @return void - */ - protected function _attr_type(&$attributes) - { - switch (strtoupper($attributes['TYPE'])) - { - case 'TINYINT': - $attributes['TYPE'] = 'SMALLINT'; - $attributes['UNSIGNED'] = FALSE; - return; - case 'MEDIUMINT': - $attributes['TYPE'] = 'INTEGER'; - $attributes['UNSIGNED'] = FALSE; - return; - case 'BYTE': - case 'TEXT': - case 'BLOB': - case 'CLOB': - $attributes['UNIQUE'] = FALSE; - if (isset($attributes['DEFAULT'])) - { - unset($attributes['DEFAULT']); - } - return; - default: return; - } - } - - // -------------------------------------------------------------------- - - /** - * Field attribute UNIQUE - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_unique(&$attributes, &$field) - { - if ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE) - { - $field['unique'] = ' UNIQUE CONSTRAINT '.$this->db->escape_identifiers($field['name']); - } - } - - // -------------------------------------------------------------------- - - /** - * Field attribute AUTO_INCREMENT - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_auto_increment(&$attributes, &$field) - { - // Not supported - } - -} diff --git a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php deleted file mode 100644 index e172145..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php +++ /dev/null @@ -1,374 +0,0 @@ -dsn)) - { - $this->dsn = 'mysql:host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname); - - empty($this->port) OR $this->dsn .= ';port='.$this->port; - empty($this->database) OR $this->dsn .= ';dbname='.$this->database; - empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set; - } - elseif ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 6) === FALSE) - { - $this->dsn .= ';charset='.$this->char_set; - } - } - - // -------------------------------------------------------------------- - - /** - * Database connection - * - * @param bool $persistent - * @return object - */ - public function db_connect($persistent = FALSE) - { - if (isset($this->stricton)) - { - if ($this->stricton) - { - $sql = 'CONCAT(@@sql_mode, ",", "STRICT_ALL_TABLES")'; - } - else - { - $sql = 'REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( - @@sql_mode, - "STRICT_ALL_TABLES,", ""), - ",STRICT_ALL_TABLES", ""), - "STRICT_ALL_TABLES", ""), - "STRICT_TRANS_TABLES,", ""), - ",STRICT_TRANS_TABLES", ""), - "STRICT_TRANS_TABLES", "")'; - } - - if ( ! empty($sql)) - { - if (empty($this->options[PDO::MYSQL_ATTR_INIT_COMMAND])) - { - $this->options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET SESSION sql_mode = '.$sql; - } - else - { - $this->options[PDO::MYSQL_ATTR_INIT_COMMAND] .= ', @@session.sql_mode = '.$sql; - } - } - } - - if ($this->compress === TRUE) - { - $this->options[PDO::MYSQL_ATTR_COMPRESS] = TRUE; - } - - if (is_array($this->encrypt)) - { - $ssl = array(); - empty($this->encrypt['ssl_key']) OR $ssl[PDO::MYSQL_ATTR_SSL_KEY] = $this->encrypt['ssl_key']; - empty($this->encrypt['ssl_cert']) OR $ssl[PDO::MYSQL_ATTR_SSL_CERT] = $this->encrypt['ssl_cert']; - empty($this->encrypt['ssl_ca']) OR $ssl[PDO::MYSQL_ATTR_SSL_CA] = $this->encrypt['ssl_ca']; - empty($this->encrypt['ssl_capath']) OR $ssl[PDO::MYSQL_ATTR_SSL_CAPATH] = $this->encrypt['ssl_capath']; - empty($this->encrypt['ssl_cipher']) OR $ssl[PDO::MYSQL_ATTR_SSL_CIPHER] = $this->encrypt['ssl_cipher']; - - // DO NOT use array_merge() here! - // It re-indexes numeric keys and the PDO_MYSQL_ATTR_SSL_* constants are integers. - empty($ssl) OR $this->options += $ssl; - } - - // Prior to version 5.7.3, MySQL silently downgrades to an unencrypted connection if SSL setup fails - if ( - ($pdo = parent::db_connect($persistent)) !== FALSE - && ! empty($ssl) - && version_compare($pdo->getAttribute(PDO::ATTR_CLIENT_VERSION), '5.7.3', '<=') - && empty($pdo->query("SHOW STATUS LIKE 'ssl_cipher'")->fetchObject()->Value) - ) - { - $message = 'PDO_MYSQL was configured for an SSL connection, but got an unencrypted connection instead!'; - log_message('error', $message); - return ($this->db_debug) ? $this->display_error($message, '', TRUE) : FALSE; - } - - return $pdo; - } - - // -------------------------------------------------------------------- - - /** - * Select the database - * - * @param string $database - * @return bool - */ - public function db_select($database = '') - { - if ($database === '') - { - $database = $this->database; - } - - if (FALSE !== $this->simple_query('USE '.$this->escape_identifiers($database))) - { - $this->database = $database; - $this->data_cache = array(); - return TRUE; - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Begin Transaction - * - * @return bool - */ - protected function _trans_begin() - { - $this->conn_id->setAttribute(PDO::ATTR_AUTOCOMMIT, FALSE); - return $this->conn_id->beginTransaction(); - } - - // -------------------------------------------------------------------- - - /** - * Commit Transaction - * - * @return bool - */ - protected function _trans_commit() - { - if ($this->conn_id->commit()) - { - $this->conn_id->setAttribute(PDO::ATTR_AUTOCOMMIT, TRUE); - return TRUE; - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Rollback Transaction - * - * @return bool - */ - protected function _trans_rollback() - { - if ($this->conn_id->rollBack()) - { - $this->conn_id->setAttribute(PDO::ATTR_AUTOCOMMIT, TRUE); - return TRUE; - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Show table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool $prefix_limit - * @return string - */ - protected function _list_tables($prefix_limit = FALSE) - { - $sql = 'SHOW TABLES'; - - if ($prefix_limit === TRUE && $this->dbprefix !== '') - { - return $sql." LIKE '".$this->escape_like_str($this->dbprefix)."%'"; - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Show column query - * - * Generates a platform-specific query string so that the column names can be fetched - * - * @param string $table - * @return string - */ - protected function _list_columns($table = '') - { - return 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE); - } - - // -------------------------------------------------------------------- - - /** - * Returns an object with field data - * - * @param string $table - * @return array - */ - public function field_data($table) - { - if (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE) - { - return FALSE; - } - $query = $query->result_object(); - - $retval = array(); - for ($i = 0, $c = count($query); $i < $c; $i++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = $query[$i]->Field; - - sscanf($query[$i]->Type, '%[a-z](%d)', - $retval[$i]->type, - $retval[$i]->max_length - ); - - $retval[$i]->default = $query[$i]->Default; - $retval[$i]->primary_key = (int) ($query[$i]->Key === 'PRI'); - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Truncate statement - * - * Generates a platform-specific truncate string from the supplied data - * - * If the database does not support the TRUNCATE statement, - * then this method maps to 'DELETE FROM table' - * - * @param string $table - * @return string - */ - protected function _truncate($table) - { - return 'TRUNCATE '.$table; - } - - // -------------------------------------------------------------------- - - /** - * FROM tables - * - * Groups tables in FROM clauses if needed, so there is no confusion - * about operator precedence. - * - * @return string - */ - protected function _from_tables() - { - if ( ! empty($this->qb_join) && count($this->qb_from) > 1) - { - return '('.implode(', ', $this->qb_from).')'; - } - - return implode(', ', $this->qb_from); - } - -} diff --git a/system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php b/system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php deleted file mode 100644 index 629e0a9..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php +++ /dev/null @@ -1,256 +0,0 @@ -db->char_set) && ! strpos($sql, 'CHARACTER SET') && ! strpos($sql, 'CHARSET')) - { - $sql .= ' DEFAULT CHARACTER SET = '.$this->db->char_set; - } - - if ( ! empty($this->db->dbcollat) && ! strpos($sql, 'COLLATE')) - { - $sql .= ' COLLATE = '.$this->db->dbcollat; - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * ALTER TABLE - * - * @param string $alter_type ALTER type - * @param string $table Table name - * @param mixed $field Column definition - * @return string|string[] - */ - protected function _alter_table($alter_type, $table, $field) - { - if ($alter_type === 'DROP') - { - return parent::_alter_table($alter_type, $table, $field); - } - - $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table); - for ($i = 0, $c = count($field); $i < $c; $i++) - { - if ($field[$i]['_literal'] !== FALSE) - { - $field[$i] = ($alter_type === 'ADD') - ? "\n\tADD ".$field[$i]['_literal'] - : "\n\tMODIFY ".$field[$i]['_literal']; - } - else - { - if ($alter_type === 'ADD') - { - $field[$i]['_literal'] = "\n\tADD "; - } - else - { - $field[$i]['_literal'] = empty($field[$i]['new_name']) ? "\n\tMODIFY " : "\n\tCHANGE "; - } - - $field[$i] = $field[$i]['_literal'].$this->_process_column($field[$i]); - } - } - - return array($sql.implode(',', $field)); - } - - // -------------------------------------------------------------------- - - /** - * Process column - * - * @param array $field - * @return string - */ - protected function _process_column($field) - { - $extra_clause = isset($field['after']) - ? ' AFTER '.$this->db->escape_identifiers($field['after']) : ''; - - if (empty($extra_clause) && isset($field['first']) && $field['first'] === TRUE) - { - $extra_clause = ' FIRST'; - } - - return $this->db->escape_identifiers($field['name']) - .(empty($field['new_name']) ? '' : ' '.$this->db->escape_identifiers($field['new_name'])) - .' '.$field['type'].$field['length'] - .$field['unsigned'] - .$field['null'] - .$field['default'] - .$field['auto_increment'] - .$field['unique'] - .(empty($field['comment']) ? '' : ' COMMENT '.$field['comment']) - .$extra_clause; - } - - // -------------------------------------------------------------------- - - /** - * Process indexes - * - * @param string $table (ignored) - * @return string - */ - protected function _process_indexes($table) - { - $sql = ''; - - for ($i = 0, $c = count($this->keys); $i < $c; $i++) - { - if (is_array($this->keys[$i])) - { - for ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++) - { - if ( ! isset($this->fields[$this->keys[$i][$i2]])) - { - unset($this->keys[$i][$i2]); - continue; - } - } - } - elseif ( ! isset($this->fields[$this->keys[$i]])) - { - unset($this->keys[$i]); - continue; - } - - is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]); - - $sql .= ",\n\tKEY ".$this->db->escape_identifiers(implode('_', $this->keys[$i])) - .' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')'; - } - - $this->keys = array(); - - return $sql; - } - -} diff --git a/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php b/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php deleted file mode 100644 index fef7a9a..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_oci_driver.php +++ /dev/null @@ -1,326 +0,0 @@ -dsn)) - { - $this->dsn = 'oci:dbname='; - - // Oracle has a slightly different PDO DSN format (Easy Connect), - // which also supports pre-defined DSNs. - if (empty($this->hostname) && empty($this->port)) - { - $this->dsn .= $this->database; - } - else - { - $this->dsn .= '//'.(empty($this->hostname) ? '127.0.0.1' : $this->hostname) - .(empty($this->port) ? '' : ':'.$this->port).'/'; - - empty($this->database) OR $this->dsn .= $this->database; - } - - empty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set; - } - elseif ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 4) === FALSE) - { - $this->dsn .= ';charset='.$this->char_set; - } - } - - // -------------------------------------------------------------------- - - /** - * Database version number - * - * @return string - */ - public function version() - { - if (isset($this->data_cache['version'])) - { - return $this->data_cache['version']; - } - - $version_string = parent::version(); - if (preg_match('#Release\s(?\d+(?:\.\d+)+)#', $version_string, $match)) - { - return $this->data_cache['version'] = $match[1]; - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Show table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool $prefix_limit - * @return string - */ - protected function _list_tables($prefix_limit = FALSE) - { - $sql = 'SELECT "TABLE_NAME" FROM "ALL_TABLES"'; - - if ($prefix_limit === TRUE && $this->dbprefix !== '') - { - return $sql.' WHERE "TABLE_NAME" LIKE \''.$this->escape_like_str($this->dbprefix)."%' " - .sprintf($this->_like_escape_str, $this->_like_escape_chr); - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Show column query - * - * Generates a platform-specific query string so that the column names can be fetched - * - * @param string $table - * @return string - */ - protected function _list_columns($table = '') - { - if (strpos($table, '.') !== FALSE) - { - sscanf($table, '%[^.].%s', $owner, $table); - } - else - { - $owner = $this->username; - } - - return 'SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS - WHERE UPPER(OWNER) = '.$this->escape(strtoupper($owner)).' - AND UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table)); - } - - // -------------------------------------------------------------------- - - /** - * Returns an object with field data - * - * @param string $table - * @return array - */ - public function field_data($table) - { - if (strpos($table, '.') !== FALSE) - { - sscanf($table, '%[^.].%s', $owner, $table); - } - else - { - $owner = $this->username; - } - - $sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHAR_LENGTH, DATA_PRECISION, DATA_LENGTH, DATA_DEFAULT, NULLABLE - FROM ALL_TAB_COLUMNS - WHERE UPPER(OWNER) = '.$this->escape(strtoupper($owner)).' - AND UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table)); - - if (($query = $this->query($sql)) === FALSE) - { - return FALSE; - } - $query = $query->result_object(); - - $retval = array(); - for ($i = 0, $c = count($query); $i < $c; $i++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = $query[$i]->COLUMN_NAME; - $retval[$i]->type = $query[$i]->DATA_TYPE; - - $length = ($query[$i]->CHAR_LENGTH > 0) - ? $query[$i]->CHAR_LENGTH : $query[$i]->DATA_PRECISION; - if ($length === NULL) - { - $length = $query[$i]->DATA_LENGTH; - } - $retval[$i]->max_length = $length; - - $default = $query[$i]->DATA_DEFAULT; - if ($default === NULL && $query[$i]->NULLABLE === 'N') - { - $default = ''; - } - $retval[$i]->default = $query[$i]->COLUMN_DEFAULT; - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Insert batch statement - * - * @param string $table Table name - * @param array $keys INSERT keys - * @param array $values INSERT values - * @return string - */ - protected function _insert_batch($table, $keys, $values) - { - $keys = implode(', ', $keys); - $sql = "INSERT ALL\n"; - - for ($i = 0, $c = count($values); $i < $c; $i++) - { - $sql .= ' INTO '.$table.' ('.$keys.') VALUES '.$values[$i]."\n"; - } - - return $sql.'SELECT * FROM dual'; - } - - // -------------------------------------------------------------------- - - /** - * Delete statement - * - * Generates a platform-specific delete string from the supplied data - * - * @param string $table - * @return string - */ - protected function _delete($table) - { - if ($this->qb_limit) - { - $this->where('rownum <= ',$this->qb_limit, FALSE); - $this->qb_limit = FALSE; - } - - return parent::_delete($table); - } - - // -------------------------------------------------------------------- - - /** - * LIMIT - * - * Generates a platform-specific LIMIT clause - * - * @param string $sql SQL Query - * @return string - */ - protected function _limit($sql) - { - if (version_compare($this->version(), '12.1', '>=')) - { - // OFFSET-FETCH can be used only with the ORDER BY clause - empty($this->qb_orderby) && $sql .= ' ORDER BY 1'; - - return $sql.' OFFSET '.(int) $this->qb_offset.' ROWS FETCH NEXT '.$this->qb_limit.' ROWS ONLY'; - } - - return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($this->qb_offset + $this->qb_limit + 1).')' - .($this->qb_offset ? ' WHERE rnum >= '.($this->qb_offset + 1): ''); - } - -} diff --git a/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php b/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php deleted file mode 100644 index ad26561..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_oci_forge.php +++ /dev/null @@ -1,176 +0,0 @@ -db->escape_identifiers($table); - $sqls = array(); - for ($i = 0, $c = count($field); $i < $c; $i++) - { - if ($field[$i]['_literal'] !== FALSE) - { - $field[$i] = "\n\t".$field[$i]['_literal']; - } - else - { - $field[$i]['_literal'] = "\n\t".$this->_process_column($field[$i]); - - if ( ! empty($field[$i]['comment'])) - { - $sqls[] = 'COMMENT ON COLUMN ' - .$this->db->escape_identifiers($table).'.'.$this->db->escape_identifiers($field[$i]['name']) - .' IS '.$field[$i]['comment']; - } - - if ($alter_type === 'MODIFY' && ! empty($field[$i]['new_name'])) - { - $sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name']) - .' TO '.$this->db->escape_identifiers($field[$i]['new_name']); - } - } - } - - $sql .= ' '.$alter_type.' '; - $sql .= (count($field) === 1) - ? $field[0] - : '('.implode(',', $field).')'; - - // RENAME COLUMN must be executed after MODIFY - array_unshift($sqls, $sql); - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Field attribute AUTO_INCREMENT - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_auto_increment(&$attributes, &$field) - { - // Not supported - sequences and triggers must be used instead - } - - /** - * Field attribute TYPE - * - * Performs a data type mapping between different databases. - * - * @param array &$attributes - * @return void - */ - protected function _attr_type(&$attributes) - { - switch (strtoupper($attributes['TYPE'])) - { - case 'TINYINT': - $attributes['TYPE'] = 'NUMBER'; - return; - case 'MEDIUMINT': - $attributes['TYPE'] = 'NUMBER'; - return; - case 'INT': - $attributes['TYPE'] = 'NUMBER'; - return; - case 'BIGINT': - $attributes['TYPE'] = 'NUMBER'; - return; - default: return; - } - } -} diff --git a/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php b/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php deleted file mode 100644 index 4890988..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php +++ /dev/null @@ -1,229 +0,0 @@ -dsn)) - { - $this->dsn = 'odbc:'; - - // Pre-defined DSN - if (empty($this->hostname) && empty($this->HOSTNAME) && empty($this->port) && empty($this->PORT)) - { - if (isset($this->DSN)) - { - $this->dsn .= 'DSN='.$this->DSN; - } - elseif ( ! empty($this->database)) - { - $this->dsn .= 'DSN='.$this->database; - } - - return; - } - - // If the DSN is not pre-configured - try to build an IBM DB2 connection string - $this->dsn .= 'DRIVER='.(isset($this->DRIVER) ? '{'.$this->DRIVER.'}' : '{IBM DB2 ODBC DRIVER}').';'; - - if (isset($this->DATABASE)) - { - $this->dsn .= 'DATABASE='.$this->DATABASE.';'; - } - elseif ( ! empty($this->database)) - { - $this->dsn .= 'DATABASE='.$this->database.';'; - } - - if (isset($this->HOSTNAME)) - { - $this->dsn .= 'HOSTNAME='.$this->HOSTNAME.';'; - } - else - { - $this->dsn .= 'HOSTNAME='.(empty($this->hostname) ? '127.0.0.1;' : $this->hostname.';'); - } - - if (isset($this->PORT)) - { - $this->dsn .= 'PORT='.$this->port.';'; - } - elseif ( ! empty($this->port)) - { - $this->dsn .= ';PORT='.$this->port.';'; - } - - $this->dsn .= 'PROTOCOL='.(isset($this->PROTOCOL) ? $this->PROTOCOL.';' : 'TCPIP;'); - } - } - - // -------------------------------------------------------------------- - - /** - * Platform-dependent string escape - * - * @param string - * @return string - */ - protected function _escape_str($str) - { - $this->display_error('db_unsupported_feature'); - } - - // -------------------------------------------------------------------- - - /** - * Determines if a query is a "write" type. - * - * @param string An SQL query string - * @return bool - */ - public function is_write_type($sql) - { - if (preg_match('#^(INSERT|UPDATE).*RETURNING\s.+(\,\s?.+)*$#is', $sql)) - { - return FALSE; - } - - return parent::is_write_type($sql); - } - - // -------------------------------------------------------------------- - - /** - * Show table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool $prefix_limit - * @return string - */ - protected function _list_tables($prefix_limit = FALSE) - { - $sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = '".$this->schema."'"; - - if ($prefix_limit !== FALSE && $this->dbprefix !== '') - { - return $sql." AND table_name LIKE '".$this->escape_like_str($this->dbprefix)."%' " - .sprintf($this->_like_escape_str, $this->_like_escape_chr); - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Show column query - * - * Generates a platform-specific query string so that the column names can be fetched - * - * @param string $table - * @return string - */ - protected function _list_columns($table = '') - { - return 'SELECT column_name FROM information_schema.columns WHERE table_name = '.$this->escape($table); - } -} diff --git a/system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php b/system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php deleted file mode 100644 index 02b6a2a..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php +++ /dev/null @@ -1,70 +0,0 @@ -dsn)) - { - $this->dsn = 'pgsql:host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname); - - empty($this->port) OR $this->dsn .= ';port='.$this->port; - empty($this->database) OR $this->dsn .= ';dbname='.$this->database; - - if ( ! empty($this->username)) - { - $this->dsn .= ';username='.$this->username; - empty($this->password) OR $this->dsn .= ';password='.$this->password; - } - } - } - - // -------------------------------------------------------------------- - - /** - * Database connection - * - * @param bool $persistent - * @return object - */ - public function db_connect($persistent = FALSE) - { - $this->conn_id = parent::db_connect($persistent); - - if (is_object($this->conn_id) && ! empty($this->schema)) - { - $this->simple_query('SET search_path TO '.$this->schema.',public'); - } - - return $this->conn_id; - } - - // -------------------------------------------------------------------- - - /** - * Insert ID - * - * @param string $name - * @return int - */ - public function insert_id($name = NULL) - { - if ($name === NULL && version_compare($this->version(), '8.1', '>=')) - { - $query = $this->query('SELECT LASTVAL() AS ins_id'); - $query = $query->row(); - return $query->ins_id; - } - - return $this->conn_id->lastInsertId($name); - } - - // -------------------------------------------------------------------- - - /** - * Determines if a query is a "write" type. - * - * @param string An SQL query string - * @return bool - */ - public function is_write_type($sql) - { - if (preg_match('#^(INSERT|UPDATE).*RETURNING\s.+(\,\s?.+)*$#is', $sql)) - { - return FALSE; - } - - return parent::is_write_type($sql); - } - - // -------------------------------------------------------------------- - - /** - * "Smart" Escape String - * - * Escapes data based on type - * - * @param string $str - * @return mixed - */ - public function escape($str) - { - if (is_bool($str)) - { - return ($str) ? 'TRUE' : 'FALSE'; - } - - return parent::escape($str); - } - - // -------------------------------------------------------------------- - - /** - * ORDER BY - * - * @param string $orderby - * @param string $direction ASC, DESC or RANDOM - * @param bool $escape - * @return object - */ - public function order_by($orderby, $direction = '', $escape = NULL) - { - $direction = strtoupper(trim($direction)); - if ($direction === 'RANDOM') - { - if ( ! is_float($orderby) && ctype_digit((string) $orderby)) - { - $orderby = ($orderby > 1) - ? (float) '0.'.$orderby - : (float) $orderby; - } - - if (is_float($orderby)) - { - $this->simple_query('SET SEED '.$orderby); - } - - $orderby = $this->_random_keyword[0]; - $direction = ''; - $escape = FALSE; - } - - return parent::order_by($orderby, $direction, $escape); - } - - // -------------------------------------------------------------------- - - /** - * Show table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool $prefix_limit - * @return string - */ - protected function _list_tables($prefix_limit = FALSE) - { - $sql = 'SELECT "table_name" FROM "information_schema"."tables" WHERE "table_schema" = \''.$this->schema."'"; - - if ($prefix_limit === TRUE && $this->dbprefix !== '') - { - return $sql.' AND "table_name" LIKE \'' - .$this->escape_like_str($this->dbprefix)."%' " - .sprintf($this->_like_escape_str, $this->_like_escape_chr); - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * List column query - * - * Generates a platform-specific query string so that the column names can be fetched - * - * @param string $table - * @return string - */ - protected function _list_columns($table = '') - { - return 'SELECT "column_name" - FROM "information_schema"."columns" - WHERE LOWER("table_name") = '.$this->escape(strtolower($table)); - } - - // -------------------------------------------------------------------- - - /** - * Returns an object with field data - * - * @param string $table - * @return array - */ - public function field_data($table) - { - $sql = 'SELECT "column_name", "data_type", "character_maximum_length", "numeric_precision", "column_default" - FROM "information_schema"."columns" - WHERE LOWER("table_name") = '.$this->escape(strtolower($table)); - - if (($query = $this->query($sql)) === FALSE) - { - return FALSE; - } - $query = $query->result_object(); - - $retval = array(); - for ($i = 0, $c = count($query); $i < $c; $i++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = $query[$i]->column_name; - $retval[$i]->type = $query[$i]->data_type; - $retval[$i]->max_length = ($query[$i]->character_maximum_length > 0) ? $query[$i]->character_maximum_length : $query[$i]->numeric_precision; - $retval[$i]->default = $query[$i]->column_default; - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Update statement - * - * Generates a platform-specific update string from the supplied data - * - * @param string $table - * @param array $values - * @return string - */ - protected function _update($table, $values) - { - $this->qb_limit = FALSE; - $this->qb_orderby = array(); - return parent::_update($table, $values); - } - - // -------------------------------------------------------------------- - - /** - * Update_Batch statement - * - * Generates a platform-specific batch update string from the supplied data - * - * @param string $table Table name - * @param array $values Update data - * @param string $index WHERE key - * @return string - */ - protected function _update_batch($table, $values, $index) - { - $ids = array(); - foreach ($values as $key => $val) - { - $ids[] = $val[$index]['value']; - - foreach (array_keys($val) as $field) - { - if ($field !== $index) - { - $final[$val[$field]['field']][] = 'WHEN '.$val[$index]['value'].' THEN '.$val[$field]['value']; - } - } - } - - $cases = ''; - foreach ($final as $k => $v) - { - $cases .= $k.' = (CASE '.$val[$index]['field']."\n" - .implode("\n", $v)."\n" - .'ELSE '.$k.' END), '; - } - - $this->where($val[$index]['field'].' IN('.implode(',', $ids).')', NULL, FALSE); - - return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where'); - } - - // -------------------------------------------------------------------- - - /** - * Delete statement - * - * Generates a platform-specific delete string from the supplied data - * - * @param string $table - * @return string - */ - protected function _delete($table) - { - $this->qb_limit = FALSE; - return parent::_delete($table); - } - - // -------------------------------------------------------------------- - - /** - * LIMIT - * - * Generates a platform-specific LIMIT clause - * - * @param string $sql SQL Query - * @return string - */ - protected function _limit($sql) - { - return $sql.' LIMIT '.$this->qb_limit.($this->qb_offset ? ' OFFSET '.$this->qb_offset : ''); - } - -} diff --git a/system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php b/system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php deleted file mode 100644 index e5bfee6..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php +++ /dev/null @@ -1,210 +0,0 @@ - 'INTEGER', - 'SMALLINT' => 'INTEGER', - 'INT' => 'BIGINT', - 'INT4' => 'BIGINT', - 'INTEGER' => 'BIGINT', - 'INT8' => 'NUMERIC', - 'BIGINT' => 'NUMERIC', - 'REAL' => 'DOUBLE PRECISION', - 'FLOAT' => 'DOUBLE PRECISION' - ); - - /** - * NULL value representation in CREATE/ALTER TABLE statements - * - * @var string - */ - protected $_null = 'NULL'; - - // -------------------------------------------------------------------- - - /** - * Class constructor - * - * @param object &$db Database object - * @return void - */ - public function __construct(&$db) - { - parent::__construct($db); - - if (version_compare($this->db->version(), '9.0', '>')) - { - $this->create_table_if = 'CREATE TABLE IF NOT EXISTS'; - } - } - - // -------------------------------------------------------------------- - - /** - * ALTER TABLE - * - * @param string $alter_type ALTER type - * @param string $table Table name - * @param mixed $field Column definition - * @return string|string[] - */ - protected function _alter_table($alter_type, $table, $field) - { - if (in_array($alter_type, array('DROP', 'ADD'), TRUE)) - { - return parent::_alter_table($alter_type, $table, $field); - } - - $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table); - $sqls = array(); - for ($i = 0, $c = count($field); $i < $c; $i++) - { - if ($field[$i]['_literal'] !== FALSE) - { - return FALSE; - } - - if (version_compare($this->db->version(), '8', '>=') && isset($field[$i]['type'])) - { - $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name']) - .' TYPE '.$field[$i]['type'].$field[$i]['length']; - } - - if ( ! empty($field[$i]['default'])) - { - $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name']) - .' SET DEFAULT '.$field[$i]['default']; - } - - if (isset($field[$i]['null'])) - { - $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name']) - .($field[$i]['null'] === TRUE ? ' DROP NOT NULL' : ' SET NOT NULL'); - } - - if ( ! empty($field[$i]['new_name'])) - { - $sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name']) - .' TO '.$this->db->escape_identifiers($field[$i]['new_name']); - } - - if ( ! empty($field[$i]['comment'])) - { - $sqls[] = 'COMMENT ON COLUMN ' - .$this->db->escape_identifiers($table).'.'.$this->db->escape_identifiers($field[$i]['name']) - .' IS '.$field[$i]['comment']; - } - } - - return $sqls; - } - - // -------------------------------------------------------------------- - - /** - * Field attribute TYPE - * - * Performs a data type mapping between different databases. - * - * @param array &$attributes - * @return void - */ - protected function _attr_type(&$attributes) - { - // Reset field lengths for data types that don't support it - if (isset($attributes['CONSTRAINT']) && stripos($attributes['TYPE'], 'int') !== FALSE) - { - $attributes['CONSTRAINT'] = NULL; - } - - switch (strtoupper($attributes['TYPE'])) - { - case 'TINYINT': - $attributes['TYPE'] = 'SMALLINT'; - $attributes['UNSIGNED'] = FALSE; - return; - case 'MEDIUMINT': - $attributes['TYPE'] = 'INTEGER'; - $attributes['UNSIGNED'] = FALSE; - return; - default: return; - } - } - - // -------------------------------------------------------------------- - - /** - * Field attribute AUTO_INCREMENT - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_auto_increment(&$attributes, &$field) - { - if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE) - { - $field['type'] = ($field['type'] === 'NUMERIC') - ? 'BIGSERIAL' - : 'SERIAL'; - } - } - -} diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php b/system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php deleted file mode 100644 index 93871a9..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php +++ /dev/null @@ -1,219 +0,0 @@ -dsn)) - { - $this->dsn = 'sqlite:'; - - if (empty($this->database) && empty($this->hostname)) - { - $this->database = ':memory:'; - } - - $this->database = empty($this->database) ? $this->hostname : $this->database; - } - } - - // -------------------------------------------------------------------- - - /** - * Show table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool $prefix_limit - * @return string - */ - protected function _list_tables($prefix_limit = FALSE) - { - $sql = 'SELECT "NAME" FROM "SQLITE_MASTER" WHERE "TYPE" = \'table\''; - - if ($prefix_limit === TRUE && $this->dbprefix !== '') - { - return $sql.' AND "NAME" LIKE \''.$this->escape_like_str($this->dbprefix)."%' " - .sprintf($this->_like_escape_str, $this->_like_escape_chr); - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Fetch Field Names - * - * @param string $table Table name - * @return array - */ - public function list_fields($table) - { - // Is there a cached result? - if (isset($this->data_cache['field_names'][$table])) - { - return $this->data_cache['field_names'][$table]; - } - - if (($result = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE) - { - return FALSE; - } - - $this->data_cache['field_names'][$table] = array(); - foreach ($result->result_array() as $row) - { - $this->data_cache['field_names'][$table][] = $row['name']; - } - - return $this->data_cache['field_names'][$table]; - } - - // -------------------------------------------------------------------- - - /** - * Returns an object with field data - * - * @param string $table - * @return array - */ - public function field_data($table) - { - if (($query = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE) - { - return FALSE; - } - - $query = $query->result_array(); - if (empty($query)) - { - return FALSE; - } - - $retval = array(); - for ($i = 0, $c = count($query); $i < $c; $i++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = $query[$i]['name']; - $retval[$i]->type = $query[$i]['type']; - $retval[$i]->max_length = NULL; - $retval[$i]->default = $query[$i]['dflt_value']; - $retval[$i]->primary_key = isset($query[$i]['pk']) ? (int) $query[$i]['pk'] : 0; - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Replace statement - * - * @param string $table Table name - * @param array $keys INSERT keys - * @param array $values INSERT values - * @return string - */ - protected function _replace($table, $keys, $values) - { - return 'INSERT OR '.parent::_replace($table, $keys, $values); - } - - // -------------------------------------------------------------------- - - /** - * Truncate statement - * - * Generates a platform-specific truncate string from the supplied data - * - * If the database does not support the TRUNCATE statement, - * then this method maps to 'DELETE FROM table' - * - * @param string $table - * @return string - */ - protected function _truncate($table) - { - return 'DELETE FROM '.$table; - } - -} diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php b/system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php deleted file mode 100644 index 67fe6ee..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php +++ /dev/null @@ -1,238 +0,0 @@ -db->version(), '3.3', '<')) - { - $this->_create_table_if = FALSE; - $this->_drop_table_if = FALSE; - } - } - - // -------------------------------------------------------------------- - - /** - * Create database - * - * @param string $db_name (ignored) - * @return bool - */ - public function create_database($db_name) - { - // In SQLite, a database is created when you connect to the database. - // We'll return TRUE so that an error isn't generated - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Drop database - * - * @param string $db_name (ignored) - * @return bool - */ - public function drop_database($db_name) - { - // In SQLite, a database is dropped when we delete a file - if (file_exists($this->db->database)) - { - // We need to close the pseudo-connection first - $this->db->close(); - if ( ! @unlink($this->db->database)) - { - return $this->db->db_debug ? $this->db->display_error('db_unable_to_drop') : FALSE; - } - elseif ( ! empty($this->db->data_cache['db_names'])) - { - $key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE); - if ($key !== FALSE) - { - unset($this->db->data_cache['db_names'][$key]); - } - } - - return TRUE; - } - - return $this->db->db_debug ? $this->db->display_error('db_unable_to_drop') : FALSE; - } - - // -------------------------------------------------------------------- - - /** - * ALTER TABLE - * - * @param string $alter_type ALTER type - * @param string $table Table name - * @param mixed $field Column definition - * @return string|string[] - */ - protected function _alter_table($alter_type, $table, $field) - { - if ($alter_type === 'DROP' OR $alter_type === 'CHANGE') - { - // drop_column(): - // BEGIN TRANSACTION; - // CREATE TEMPORARY TABLE t1_backup(a,b); - // INSERT INTO t1_backup SELECT a,b FROM t1; - // DROP TABLE t1; - // CREATE TABLE t1(a,b); - // INSERT INTO t1 SELECT a,b FROM t1_backup; - // DROP TABLE t1_backup; - // COMMIT; - - return FALSE; - } - - return parent::_alter_table($alter_type, $table, $field); - } - - // -------------------------------------------------------------------- - - /** - * Process column - * - * @param array $field - * @return string - */ - protected function _process_column($field) - { - return $this->db->escape_identifiers($field['name']) - .' '.$field['type'] - .$field['auto_increment'] - .$field['null'] - .$field['unique'] - .$field['default']; - } - - // -------------------------------------------------------------------- - - /** - * Field attribute TYPE - * - * Performs a data type mapping between different databases. - * - * @param array &$attributes - * @return void - */ - protected function _attr_type(&$attributes) - { - switch (strtoupper($attributes['TYPE'])) - { - case 'ENUM': - case 'SET': - $attributes['TYPE'] = 'TEXT'; - return; - default: return; - } - } - - // -------------------------------------------------------------------- - - /** - * Field attribute AUTO_INCREMENT - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_auto_increment(&$attributes, &$field) - { - if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE) - { - $field['type'] = 'INTEGER PRIMARY KEY'; - $field['default'] = ''; - $field['null'] = ''; - $field['unique'] = ''; - $field['auto_increment'] = ' AUTOINCREMENT'; - - $this->primary_keys = array(); - } - } - -} diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php deleted file mode 100644 index db10029..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php +++ /dev/null @@ -1,369 +0,0 @@ -dsn)) - { - $this->dsn = 'sqlsrv:Server='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname); - - empty($this->port) OR $this->dsn .= ','.$this->port; - empty($this->database) OR $this->dsn .= ';Database='.$this->database; - - // Some custom options - - if (isset($this->QuotedId)) - { - $this->dsn .= ';QuotedId='.$this->QuotedId; - $this->_quoted_identifier = (bool) $this->QuotedId; - } - - if (isset($this->ConnectionPooling)) - { - $this->dsn .= ';ConnectionPooling='.$this->ConnectionPooling; - } - - if ($this->encrypt === TRUE) - { - $this->dsn .= ';Encrypt=1'; - } - - if (isset($this->TraceOn)) - { - $this->dsn .= ';TraceOn='.$this->TraceOn; - } - - if (isset($this->TrustServerCertificate)) - { - $this->dsn .= ';TrustServerCertificate='.$this->TrustServerCertificate; - } - - empty($this->APP) OR $this->dsn .= ';APP='.$this->APP; - empty($this->Failover_Partner) OR $this->dsn .= ';Failover_Partner='.$this->Failover_Partner; - empty($this->LoginTimeout) OR $this->dsn .= ';LoginTimeout='.$this->LoginTimeout; - empty($this->MultipleActiveResultSets) OR $this->dsn .= ';MultipleActiveResultSets='.$this->MultipleActiveResultSets; - empty($this->TraceFile) OR $this->dsn .= ';TraceFile='.$this->TraceFile; - empty($this->WSID) OR $this->dsn .= ';WSID='.$this->WSID; - } - elseif (preg_match('/QuotedId=(0|1)/', $this->dsn, $match)) - { - $this->_quoted_identifier = (bool) $match[1]; - } - } - - // -------------------------------------------------------------------- - - /** - * Database connection - * - * @param bool $persistent - * @return object - */ - public function db_connect($persistent = FALSE) - { - if ( ! empty($this->char_set) && preg_match('/utf[^8]*8/i', $this->char_set)) - { - $this->options[PDO::SQLSRV_ENCODING_UTF8] = 1; - } - - $this->conn_id = parent::db_connect($persistent); - - if ( ! is_object($this->conn_id) OR is_bool($this->_quoted_identifier)) - { - return $this->conn_id; - } - - // Determine how identifiers are escaped - $query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi'); - $query = $query->row_array(); - $this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi']; - $this->_escape_char = ($this->_quoted_identifier) ? '"' : array('[', ']'); - - return $this->conn_id; - } - - // -------------------------------------------------------------------- - - /** - * Show table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool $prefix_limit - * @return string - */ - protected function _list_tables($prefix_limit = FALSE) - { - $sql = 'SELECT '.$this->escape_identifiers('name') - .' FROM '.$this->escape_identifiers('sysobjects') - .' WHERE '.$this->escape_identifiers('type')." = 'U'"; - - if ($prefix_limit === TRUE && $this->dbprefix !== '') - { - $sql .= ' AND '.$this->escape_identifiers('name')." LIKE '".$this->escape_like_str($this->dbprefix)."%' " - .sprintf($this->_like_escape_str, $this->_like_escape_chr); - } - - return $sql.' ORDER BY '.$this->escape_identifiers('name'); - } - - // -------------------------------------------------------------------- - - /** - * Show column query - * - * Generates a platform-specific query string so that the column names can be fetched - * - * @param string $table - * @return string - */ - protected function _list_columns($table = '') - { - return 'SELECT COLUMN_NAME - FROM INFORMATION_SCHEMA.Columns - WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table)); - } - - // -------------------------------------------------------------------- - - /** - * Returns an object with field data - * - * @param string $table - * @return array - */ - public function field_data($table) - { - $sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, COLUMN_DEFAULT - FROM INFORMATION_SCHEMA.Columns - WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table)); - - if (($query = $this->query($sql)) === FALSE) - { - return FALSE; - } - $query = $query->result_object(); - - $retval = array(); - for ($i = 0, $c = count($query); $i < $c; $i++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = $query[$i]->COLUMN_NAME; - $retval[$i]->type = $query[$i]->DATA_TYPE; - $retval[$i]->max_length = ($query[$i]->CHARACTER_MAXIMUM_LENGTH > 0) ? $query[$i]->CHARACTER_MAXIMUM_LENGTH : $query[$i]->NUMERIC_PRECISION; - $retval[$i]->default = $query[$i]->COLUMN_DEFAULT; - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Update statement - * - * Generates a platform-specific update string from the supplied data - * - * @param string $table - * @param array $values - * @return string - */ - protected function _update($table, $values) - { - $this->qb_limit = FALSE; - $this->qb_orderby = array(); - return parent::_update($table, $values); - } - - // -------------------------------------------------------------------- - - /** - * Delete statement - * - * Generates a platform-specific delete string from the supplied data - * - * @param string $table - * @return string - */ - protected function _delete($table) - { - if ($this->qb_limit) - { - return 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete'; - } - - return parent::_delete($table); - } - - // -------------------------------------------------------------------- - - /** - * LIMIT - * - * Generates a platform-specific LIMIT clause - * - * @param string $sql SQL Query - * @return string - */ - protected function _limit($sql) - { - // As of SQL Server 2012 (11.0.*) OFFSET is supported - if (version_compare($this->version(), '11', '>=')) - { - // SQL Server OFFSET-FETCH can be used only with the ORDER BY clause - empty($this->qb_orderby) && $sql .= ' ORDER BY 1'; - - return $sql.' OFFSET '.(int) $this->qb_offset.' ROWS FETCH NEXT '.$this->qb_limit.' ROWS ONLY'; - } - - $limit = $this->qb_offset + $this->qb_limit; - - // An ORDER BY clause is required for ROW_NUMBER() to work - if ($this->qb_offset && ! empty($this->qb_orderby)) - { - $orderby = $this->_compile_order_by(); - - // We have to strip the ORDER BY clause - $sql = trim(substr($sql, 0, strrpos($sql, $orderby))); - - // Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results - if (count($this->qb_select) === 0 OR strpos(implode(',', $this->qb_select), '*') !== FALSE) - { - $select = '*'; // Inevitable - } - else - { - // Use only field names and their aliases, everything else is out of our scope. - $select = array(); - $field_regexp = ($this->_quoted_identifier) - ? '("[^\"]+")' : '(\[[^\]]+\])'; - for ($i = 0, $c = count($this->qb_select); $i < $c; $i++) - { - $select[] = preg_match('/(?:\s|\.)'.$field_regexp.'$/i', $this->qb_select[$i], $m) - ? $m[1] : $this->qb_select[$i]; - } - $select = implode(', ', $select); - } - - return 'SELECT '.$select." FROM (\n\n" - .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.trim($orderby).') AS '.$this->escape_identifiers('CI_rownum').', ', $sql) - ."\n\n) ".$this->escape_identifiers('CI_subquery') - ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit; - } - - return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql); - } - - // -------------------------------------------------------------------- - - /** - * Insert batch statement - * - * Generates a platform-specific insert string from the supplied data. - * - * @param string $table Table name - * @param array $keys INSERT keys - * @param array $values INSERT values - * @return string|bool - */ - protected function _insert_batch($table, $keys, $values) - { - // Multiple-value inserts are only supported as of SQL Server 2008 - if (version_compare($this->version(), '10', '>=')) - { - return parent::_insert_batch($table, $keys, $values); - } - - return ($this->db_debug) ? $this->display_error('db_unsupported_feature') : FALSE; - } - -} diff --git a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php b/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php deleted file mode 100644 index 4c9dbe6..0000000 --- a/system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php +++ /dev/null @@ -1,149 +0,0 @@ - 'SMALLINT', - 'SMALLINT' => 'INT', - 'INT' => 'BIGINT', - 'REAL' => 'FLOAT' - ); - - // -------------------------------------------------------------------- - - /** - * ALTER TABLE - * - * @param string $alter_type ALTER type - * @param string $table Table name - * @param mixed $field Column definition - * @return string|string[] - */ - protected function _alter_table($alter_type, $table, $field) - { - if (in_array($alter_type, array('ADD', 'DROP'), TRUE)) - { - return parent::_alter_table($alter_type, $table, $field); - } - - $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ALTER COLUMN '; - $sqls = array(); - for ($i = 0, $c = count($field); $i < $c; $i++) - { - $sqls[] = $sql.$this->_process_column($field[$i]); - } - - return $sqls; - } - - // -------------------------------------------------------------------- - - /** - * Field attribute TYPE - * - * Performs a data type mapping between different databases. - * - * @param array &$attributes - * @return void - */ - protected function _attr_type(&$attributes) - { - if (isset($attributes['CONSTRAINT']) && strpos($attributes['TYPE'], 'INT') !== FALSE) - { - unset($attributes['CONSTRAINT']); - } - - switch (strtoupper($attributes['TYPE'])) - { - case 'MEDIUMINT': - $attributes['TYPE'] = 'INTEGER'; - $attributes['UNSIGNED'] = FALSE; - return; - case 'INTEGER': - $attributes['TYPE'] = 'INT'; - return; - default: return; - } - } - - // -------------------------------------------------------------------- - - /** - * Field attribute AUTO_INCREMENT - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_auto_increment(&$attributes, &$field) - { - if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE) - { - $field['auto_increment'] = ' IDENTITY(1,1)'; - } - } - -} diff --git a/system/database/drivers/postgre/index.html b/system/database/drivers/postgre/index.html deleted file mode 100644 index b702fbc..0000000 --- a/system/database/drivers/postgre/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - 403 Forbidden - - - -

Directory access is forbidden.

- - - diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php deleted file mode 100644 index 5779c87..0000000 --- a/system/database/drivers/postgre/postgre_driver.php +++ /dev/null @@ -1,619 +0,0 @@ -dsn)) - { - return; - } - - $this->dsn === '' OR $this->dsn = ''; - - if (strpos($this->hostname, '/') !== FALSE) - { - // If UNIX sockets are used, we shouldn't set a port - $this->port = ''; - } - - $this->hostname === '' OR $this->dsn = 'host='.$this->hostname.' '; - - if ( ! empty($this->port) && ctype_digit($this->port)) - { - $this->dsn .= 'port='.$this->port.' '; - } - - if ($this->username !== '') - { - $this->dsn .= 'user='.$this->username.' '; - - /* An empty password is valid! - * - * $db['password'] = NULL must be done in order to ignore it. - */ - $this->password === NULL OR $this->dsn .= "password='".$this->password."' "; - } - - $this->database === '' OR $this->dsn .= 'dbname='.$this->database.' '; - - /* We don't have these options as elements in our standard configuration - * array, but they might be set by parse_url() if the configuration was - * provided via string. Example: - * - * postgre://username:password@localhost:5432/database?connect_timeout=5&sslmode=1 - */ - foreach (array('connect_timeout', 'options', 'sslmode', 'service') as $key) - { - if (isset($this->$key) && is_string($this->$key) && $this->$key !== '') - { - $this->dsn .= $key."='".$this->$key."' "; - } - } - - $this->dsn = rtrim($this->dsn); - } - - // -------------------------------------------------------------------- - - /** - * Database connection - * - * @param bool $persistent - * @return resource - */ - public function db_connect($persistent = FALSE) - { - $this->conn_id = ($persistent === TRUE) - ? pg_pconnect($this->dsn) - : pg_connect($this->dsn); - - if ($this->conn_id !== FALSE) - { - if ($persistent === TRUE - && pg_connection_status($this->conn_id) === PGSQL_CONNECTION_BAD - && pg_ping($this->conn_id) === FALSE - ) - { - return FALSE; - } - - empty($this->schema) OR $this->simple_query('SET search_path TO '.$this->schema.',public'); - } - - return $this->conn_id; - } - - // -------------------------------------------------------------------- - - /** - * Reconnect - * - * Keep / reestablish the db connection if no queries have been - * sent for a length of time exceeding the server's idle timeout - * - * @return void - */ - public function reconnect() - { - if (pg_ping($this->conn_id) === FALSE) - { - $this->conn_id = FALSE; - } - } - - // -------------------------------------------------------------------- - - /** - * Set client character set - * - * @param string $charset - * @return bool - */ - protected function _db_set_charset($charset) - { - return (pg_set_client_encoding($this->conn_id, $charset) === 0); - } - - // -------------------------------------------------------------------- - - /** - * Database version number - * - * @return string - */ - public function version() - { - if (isset($this->data_cache['version'])) - { - return $this->data_cache['version']; - } - - if ( ! $this->conn_id OR ($pg_version = pg_version($this->conn_id)) === FALSE) - { - return FALSE; - } - - /* If PHP was compiled with PostgreSQL lib versions earlier - * than 7.4, pg_version() won't return the server version - * and so we'll have to fall back to running a query in - * order to get it. - */ - return (isset($pg_version['server']) && preg_match('#^(\d+\.\d+)#', $pg_version['server'], $match)) - ? $this->data_cache['version'] = $match[1] - : parent::version(); - } - - // -------------------------------------------------------------------- - - /** - * Execute the query - * - * @param string $sql an SQL query - * @return resource - */ - protected function _execute($sql) - { - return pg_query($this->conn_id, $sql); - } - - // -------------------------------------------------------------------- - - /** - * Begin Transaction - * - * @return bool - */ - protected function _trans_begin() - { - return (bool) pg_query($this->conn_id, 'BEGIN'); - } - - // -------------------------------------------------------------------- - - /** - * Commit Transaction - * - * @return bool - */ - protected function _trans_commit() - { - return (bool) pg_query($this->conn_id, 'COMMIT'); - } - - // -------------------------------------------------------------------- - - /** - * Rollback Transaction - * - * @return bool - */ - protected function _trans_rollback() - { - return (bool) pg_query($this->conn_id, 'ROLLBACK'); - } - - // -------------------------------------------------------------------- - - /** - * Determines if a query is a "write" type. - * - * @param string An SQL query string - * @return bool - */ - public function is_write_type($sql) - { - if (preg_match('#^(INSERT|UPDATE).*RETURNING\s.+(\,\s?.+)*$#is', $sql)) - { - return FALSE; - } - - return parent::is_write_type($sql); - } - - // -------------------------------------------------------------------- - - /** - * Platform-dependent string escape - * - * @param string - * @return string - */ - protected function _escape_str($str) - { - return pg_escape_string($this->conn_id, $str); - } - - // -------------------------------------------------------------------- - - /** - * "Smart" Escape String - * - * Escapes data based on type - * - * @param string $str - * @return mixed - */ - public function escape($str) - { - if (is_php('5.4.4') && (is_string($str) OR (is_object($str) && method_exists($str, '__toString')))) - { - return pg_escape_literal($this->conn_id, $str); - } - elseif (is_bool($str)) - { - return ($str) ? 'TRUE' : 'FALSE'; - } - - return parent::escape($str); - } - - // -------------------------------------------------------------------- - - /** - * Affected Rows - * - * @return int - */ - public function affected_rows() - { - return pg_affected_rows($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Insert ID - * - * @return string - */ - public function insert_id() - { - $v = $this->version(); - - $table = (func_num_args() > 0) ? func_get_arg(0) : NULL; - $column = (func_num_args() > 1) ? func_get_arg(1) : NULL; - - if ($table === NULL && $v >= '8.1') - { - $sql = 'SELECT LASTVAL() AS ins_id'; - } - elseif ($table !== NULL) - { - if ($column !== NULL && $v >= '8.0') - { - $sql = 'SELECT pg_get_serial_sequence(\''.$table."', '".$column."') AS seq"; - $query = $this->query($sql); - $query = $query->row(); - $seq = $query->seq; - } - else - { - // seq_name passed in table parameter - $seq = $table; - } - - $sql = 'SELECT CURRVAL(\''.$seq."') AS ins_id"; - } - else - { - return pg_last_oid($this->result_id); - } - - $query = $this->query($sql); - $query = $query->row(); - return (int) $query->ins_id; - } - - // -------------------------------------------------------------------- - - /** - * Show table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool $prefix_limit - * @return string - */ - protected function _list_tables($prefix_limit = FALSE) - { - $sql = 'SELECT "table_name" FROM "information_schema"."tables" WHERE "table_schema" = \''.$this->schema."'"; - - if ($prefix_limit !== FALSE && $this->dbprefix !== '') - { - return $sql.' AND "table_name" LIKE \'' - .$this->escape_like_str($this->dbprefix)."%' " - .sprintf($this->_like_escape_str, $this->_like_escape_chr); - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * List column query - * - * Generates a platform-specific query string so that the column names can be fetched - * - * @param string $table - * @return string - */ - protected function _list_columns($table = '') - { - return 'SELECT "column_name" - FROM "information_schema"."columns" - WHERE LOWER("table_name") = '.$this->escape(strtolower($table)); - } - - // -------------------------------------------------------------------- - - /** - * Returns an object with field data - * - * @param string $table - * @return array - */ - public function field_data($table) - { - $sql = 'SELECT "column_name", "data_type", "character_maximum_length", "numeric_precision", "column_default" - FROM "information_schema"."columns" - WHERE LOWER("table_name") = '.$this->escape(strtolower($table)); - - if (($query = $this->query($sql)) === FALSE) - { - return FALSE; - } - $query = $query->result_object(); - - $retval = array(); - for ($i = 0, $c = count($query); $i < $c; $i++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = $query[$i]->column_name; - $retval[$i]->type = $query[$i]->data_type; - $retval[$i]->max_length = ($query[$i]->character_maximum_length > 0) ? $query[$i]->character_maximum_length : $query[$i]->numeric_precision; - $retval[$i]->default = $query[$i]->column_default; - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Error - * - * Returns an array containing code and message of the last - * database error that has occurred. - * - * @return array - */ - public function error() - { - return array('code' => '', 'message' => pg_last_error($this->conn_id)); - } - - // -------------------------------------------------------------------- - - /** - * ORDER BY - * - * @param string $orderby - * @param string $direction ASC, DESC or RANDOM - * @param bool $escape - * @return object - */ - public function order_by($orderby, $direction = '', $escape = NULL) - { - $direction = strtoupper(trim($direction)); - if ($direction === 'RANDOM') - { - if ( ! is_float($orderby) && ctype_digit((string) $orderby)) - { - $orderby = ($orderby > 1) - ? (float) '0.'.$orderby - : (float) $orderby; - } - - if (is_float($orderby)) - { - $this->simple_query('SET SEED '.$orderby); - } - - $orderby = $this->_random_keyword[0]; - $direction = ''; - $escape = FALSE; - } - - return parent::order_by($orderby, $direction, $escape); - } - - // -------------------------------------------------------------------- - - /** - * Update statement - * - * Generates a platform-specific update string from the supplied data - * - * @param string $table - * @param array $values - * @return string - */ - protected function _update($table, $values) - { - $this->qb_limit = FALSE; - $this->qb_orderby = array(); - return parent::_update($table, $values); - } - - // -------------------------------------------------------------------- - - /** - * Update_Batch statement - * - * Generates a platform-specific batch update string from the supplied data - * - * @param string $table Table name - * @param array $values Update data - * @param string $index WHERE key - * @return string - */ - protected function _update_batch($table, $values, $index) - { - $ids = array(); - foreach ($values as $key => $val) - { - $ids[] = $val[$index]['value']; - - foreach (array_keys($val) as $field) - { - if ($field !== $index) - { - $final[$val[$field]['field']][] = 'WHEN '.$val[$index]['value'].' THEN '.$val[$field]['value']; - } - } - } - - $cases = ''; - foreach ($final as $k => $v) - { - $cases .= $k.' = (CASE '.$val[$index]['field']."\n" - .implode("\n", $v)."\n" - .'ELSE '.$k.' END), '; - } - - $this->where($val[$index]['field'].' IN('.implode(',', $ids).')', NULL, FALSE); - - return 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where'); - } - - // -------------------------------------------------------------------- - - /** - * Delete statement - * - * Generates a platform-specific delete string from the supplied data - * - * @param string $table - * @return string - */ - protected function _delete($table) - { - $this->qb_limit = FALSE; - return parent::_delete($table); - } - - // -------------------------------------------------------------------- - - /** - * LIMIT - * - * Generates a platform-specific LIMIT clause - * - * @param string $sql SQL Query - * @return string - */ - protected function _limit($sql) - { - return $sql.' LIMIT '.$this->qb_limit.($this->qb_offset ? ' OFFSET '.$this->qb_offset : ''); - } - - // -------------------------------------------------------------------- - - /** - * Close DB Connection - * - * @return void - */ - protected function _close() - { - pg_close($this->conn_id); - } - -} diff --git a/system/database/drivers/postgre/postgre_forge.php b/system/database/drivers/postgre/postgre_forge.php deleted file mode 100644 index cf90325..0000000 --- a/system/database/drivers/postgre/postgre_forge.php +++ /dev/null @@ -1,205 +0,0 @@ - 'INTEGER', - 'SMALLINT' => 'INTEGER', - 'INT' => 'BIGINT', - 'INT4' => 'BIGINT', - 'INTEGER' => 'BIGINT', - 'INT8' => 'NUMERIC', - 'BIGINT' => 'NUMERIC', - 'REAL' => 'DOUBLE PRECISION', - 'FLOAT' => 'DOUBLE PRECISION' - ); - - /** - * NULL value representation in CREATE/ALTER TABLE statements - * - * @var string - */ - protected $_null = 'NULL'; - - // -------------------------------------------------------------------- - - /** - * Class constructor - * - * @param object &$db Database object - * @return void - */ - public function __construct(&$db) - { - parent::__construct($db); - - if (version_compare($this->db->version(), '9.0', '>')) - { - $this->create_table_if = 'CREATE TABLE IF NOT EXISTS'; - } - } - - // -------------------------------------------------------------------- - - /** - * ALTER TABLE - * - * @param string $alter_type ALTER type - * @param string $table Table name - * @param mixed $field Column definition - * @return string|string[] - */ - protected function _alter_table($alter_type, $table, $field) - { - if (in_array($alter_type, array('DROP', 'ADD'), TRUE)) - { - return parent::_alter_table($alter_type, $table, $field); - } - - $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table); - $sqls = array(); - for ($i = 0, $c = count($field); $i < $c; $i++) - { - if ($field[$i]['_literal'] !== FALSE) - { - return FALSE; - } - - if (version_compare($this->db->version(), '8', '>=') && isset($field[$i]['type'])) - { - $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name']) - .' TYPE '.$field[$i]['type'].$field[$i]['length']; - } - - if ( ! empty($field[$i]['default'])) - { - $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name']) - .' SET DEFAULT '.$field[$i]['default']; - } - - if (isset($field[$i]['null'])) - { - $sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name']) - .($field[$i]['null'] === TRUE ? ' DROP NOT NULL' : ' SET NOT NULL'); - } - - if ( ! empty($field[$i]['new_name'])) - { - $sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name']) - .' TO '.$this->db->escape_identifiers($field[$i]['new_name']); - } - - if ( ! empty($field[$i]['comment'])) - { - $sqls[] = 'COMMENT ON COLUMN ' - .$this->db->escape_identifiers($table).'.'.$this->db->escape_identifiers($field[$i]['name']) - .' IS '.$field[$i]['comment']; - } - } - - return $sqls; - } - - // -------------------------------------------------------------------- - - /** - * Field attribute TYPE - * - * Performs a data type mapping between different databases. - * - * @param array &$attributes - * @return void - */ - protected function _attr_type(&$attributes) - { - // Reset field lengths for data types that don't support it - if (isset($attributes['CONSTRAINT']) && stripos($attributes['TYPE'], 'int') !== FALSE) - { - $attributes['CONSTRAINT'] = NULL; - } - - switch (strtoupper($attributes['TYPE'])) - { - case 'TINYINT': - $attributes['TYPE'] = 'SMALLINT'; - $attributes['UNSIGNED'] = FALSE; - return; - case 'MEDIUMINT': - $attributes['TYPE'] = 'INTEGER'; - $attributes['UNSIGNED'] = FALSE; - return; - default: return; - } - } - - // -------------------------------------------------------------------- - - /** - * Field attribute AUTO_INCREMENT - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_auto_increment(&$attributes, &$field) - { - if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE) - { - $field['type'] = ($field['type'] === 'NUMERIC') - ? 'BIGSERIAL' - : 'SERIAL'; - } - } - -} diff --git a/system/database/drivers/postgre/postgre_result.php b/system/database/drivers/postgre/postgre_result.php deleted file mode 100644 index daf3306..0000000 --- a/system/database/drivers/postgre/postgre_result.php +++ /dev/null @@ -1,182 +0,0 @@ -num_rows) - ? $this->num_rows - : $this->num_rows = pg_num_rows($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Number of fields in the result set - * - * @return int - */ - public function num_fields() - { - return pg_num_fields($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Fetch Field Names - * - * Generates an array of column names - * - * @return array - */ - public function list_fields() - { - $field_names = array(); - for ($i = 0, $c = $this->num_fields(); $i < $c; $i++) - { - $field_names[] = pg_field_name($this->result_id, $i); - } - - return $field_names; - } - - // -------------------------------------------------------------------- - - /** - * Field data - * - * Generates an array of objects containing field meta-data - * - * @return array - */ - public function field_data() - { - $retval = array(); - for ($i = 0, $c = $this->num_fields(); $i < $c; $i++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = pg_field_name($this->result_id, $i); - $retval[$i]->type = pg_field_type($this->result_id, $i); - $retval[$i]->max_length = pg_field_size($this->result_id, $i); - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Free the result - * - * @return void - */ - public function free_result() - { - if (is_resource($this->result_id)) - { - pg_free_result($this->result_id); - $this->result_id = FALSE; - } - } - - // -------------------------------------------------------------------- - - /** - * Data Seek - * - * Moves the internal pointer to the desired offset. We call - * this internally before fetching results to make sure the - * result set starts at zero. - * - * @param int $n - * @return bool - */ - public function data_seek($n = 0) - { - return pg_result_seek($this->result_id, $n); - } - - // -------------------------------------------------------------------- - - /** - * Result - associative array - * - * Returns the result set as an array - * - * @return array - */ - protected function _fetch_assoc() - { - return pg_fetch_assoc($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Result - object - * - * Returns the result set as an object - * - * @param string $class_name - * @return object - */ - protected function _fetch_object($class_name = 'stdClass') - { - return pg_fetch_object($this->result_id, NULL, $class_name); - } - -} diff --git a/system/database/drivers/postgre/postgre_utility.php b/system/database/drivers/postgre/postgre_utility.php deleted file mode 100644 index 3af225f..0000000 --- a/system/database/drivers/postgre/postgre_utility.php +++ /dev/null @@ -1,78 +0,0 @@ -db->display_error('db_unsupported_feature'); - } -} diff --git a/system/database/drivers/sqlite/index.html b/system/database/drivers/sqlite/index.html deleted file mode 100644 index b702fbc..0000000 --- a/system/database/drivers/sqlite/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - 403 Forbidden - - - -

Directory access is forbidden.

- - - diff --git a/system/database/drivers/sqlite/sqlite_driver.php b/system/database/drivers/sqlite/sqlite_driver.php deleted file mode 100644 index a061229..0000000 --- a/system/database/drivers/sqlite/sqlite_driver.php +++ /dev/null @@ -1,330 +0,0 @@ -database, 0666, $error) - : sqlite_open($this->database, 0666, $error); - - isset($error) && log_message('error', $error); - - return $conn_id; - } - - // -------------------------------------------------------------------- - - /** - * Database version number - * - * @return string - */ - public function version() - { - return isset($this->data_cache['version']) - ? $this->data_cache['version'] - : $this->data_cache['version'] = sqlite_libversion(); - } - - // -------------------------------------------------------------------- - - /** - * Execute the query - * - * @param string $sql an SQL query - * @return resource - */ - protected function _execute($sql) - { - return $this->is_write_type($sql) - ? sqlite_exec($this->conn_id, $sql) - : sqlite_query($this->conn_id, $sql); - } - - // -------------------------------------------------------------------- - - /** - * Begin Transaction - * - * @return bool - */ - protected function _trans_begin() - { - return $this->simple_query('BEGIN TRANSACTION'); - } - - // -------------------------------------------------------------------- - - /** - * Commit Transaction - * - * @return bool - */ - protected function _trans_commit() - { - return $this->simple_query('COMMIT'); - } - - // -------------------------------------------------------------------- - - /** - * Rollback Transaction - * - * @return bool - */ - protected function _trans_rollback() - { - return $this->simple_query('ROLLBACK'); - } - - // -------------------------------------------------------------------- - - /** - * Platform-dependant string escape - * - * @param string - * @return string - */ - protected function _escape_str($str) - { - return sqlite_escape_string($str); - } - - // -------------------------------------------------------------------- - - /** - * Affected Rows - * - * @return int - */ - public function affected_rows() - { - return sqlite_changes($this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * Insert ID - * - * @return int - */ - public function insert_id() - { - return sqlite_last_insert_rowid($this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * List table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool $prefix_limit - * @return string - */ - protected function _list_tables($prefix_limit = FALSE) - { - $sql = "SELECT name FROM sqlite_master WHERE type='table'"; - - if ($prefix_limit !== FALSE && $this->dbprefix != '') - { - return $sql." AND 'name' LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr); - } - - return $sql; - } - - // -------------------------------------------------------------------- - - /** - * Show column query - * - * Generates a platform-specific query string so that the column names can be fetched - * - * @param string $table - * @return bool - */ - protected function _list_columns($table = '') - { - // Not supported - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Returns an object with field data - * - * @param string $table - * @return array - */ - public function field_data($table) - { - if (($query = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE) - { - return FALSE; - } - - $query = $query->result_array(); - if (empty($query)) - { - return FALSE; - } - - $retval = array(); - for ($i = 0, $c = count($query); $i < $c; $i++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = $query[$i]['name']; - $retval[$i]->type = $query[$i]['type']; - $retval[$i]->max_length = NULL; - $retval[$i]->default = $query[$i]['dflt_value']; - $retval[$i]->primary_key = isset($query[$i]['pk']) ? (int) $query[$i]['pk'] : 0; - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Error - * - * Returns an array containing code and message of the last - * database error that has occured. - * - * @return array - */ - public function error() - { - $error = array('code' => sqlite_last_error($this->conn_id)); - $error['message'] = sqlite_error_string($error['code']); - return $error; - } - - // -------------------------------------------------------------------- - - /** - * Replace statement - * - * Generates a platform-specific replace string from the supplied data - * - * @param string $table Table name - * @param array $keys INSERT keys - * @param array $values INSERT values - * @return string - */ - protected function _replace($table, $keys, $values) - { - return 'INSERT OR '.parent::_replace($table, $keys, $values); - } - - // -------------------------------------------------------------------- - - /** - * Truncate statement - * - * Generates a platform-specific truncate string from the supplied data - * - * If the database does not support the TRUNCATE statement, - * then this function maps to 'DELETE FROM table' - * - * @param string $table - * @return string - */ - protected function _truncate($table) - { - return 'DELETE FROM '.$table; - } - - // -------------------------------------------------------------------- - - /** - * Close DB Connection - * - * @return void - */ - protected function _close() - { - sqlite_close($this->conn_id); - } - -} diff --git a/system/database/drivers/sqlite/sqlite_forge.php b/system/database/drivers/sqlite/sqlite_forge.php deleted file mode 100644 index 10d5fe6..0000000 --- a/system/database/drivers/sqlite/sqlite_forge.php +++ /dev/null @@ -1,205 +0,0 @@ -db->database) OR ! @unlink($this->db->database)) - { - return ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE; - } - elseif ( ! empty($this->db->data_cache['db_names'])) - { - $key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE); - if ($key !== FALSE) - { - unset($this->db->data_cache['db_names'][$key]); - } - } - - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * ALTER TABLE - * - * @todo implement drop_column(), modify_column() - * @param string $alter_type ALTER type - * @param string $table Table name - * @param mixed $field Column definition - * @return string|string[] - */ - protected function _alter_table($alter_type, $table, $field) - { - if ($alter_type === 'DROP' OR $alter_type === 'CHANGE') - { - // drop_column(): - // BEGIN TRANSACTION; - // CREATE TEMPORARY TABLE t1_backup(a,b); - // INSERT INTO t1_backup SELECT a,b FROM t1; - // DROP TABLE t1; - // CREATE TABLE t1(a,b); - // INSERT INTO t1 SELECT a,b FROM t1_backup; - // DROP TABLE t1_backup; - // COMMIT; - - return FALSE; - } - - return parent::_alter_table($alter_type, $table, $field); - } - - // -------------------------------------------------------------------- - - /** - * Process column - * - * @param array $field - * @return string - */ - protected function _process_column($field) - { - return $this->db->escape_identifiers($field['name']) - .' '.$field['type'] - .$field['auto_increment'] - .$field['null'] - .$field['unique'] - .$field['default']; - } - - // -------------------------------------------------------------------- - - /** - * Field attribute TYPE - * - * Performs a data type mapping between different databases. - * - * @param array &$attributes - * @return void - */ - protected function _attr_type(&$attributes) - { - switch (strtoupper($attributes['TYPE'])) - { - case 'ENUM': - case 'SET': - $attributes['TYPE'] = 'TEXT'; - return; - default: return; - } - } - - // -------------------------------------------------------------------- - - /** - * Field attribute AUTO_INCREMENT - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_auto_increment(&$attributes, &$field) - { - if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE) - { - $field['type'] = 'INTEGER PRIMARY KEY'; - $field['default'] = ''; - $field['null'] = ''; - $field['unique'] = ''; - $field['auto_increment'] = ' AUTOINCREMENT'; - - $this->primary_keys = array(); - } - } - -} diff --git a/system/database/drivers/sqlite/sqlite_result.php b/system/database/drivers/sqlite/sqlite_result.php deleted file mode 100644 index 59516b0..0000000 --- a/system/database/drivers/sqlite/sqlite_result.php +++ /dev/null @@ -1,164 +0,0 @@ -num_rows) - ? $this->num_rows - : $this->num_rows = @sqlite_num_rows($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Number of fields in the result set - * - * @return int - */ - public function num_fields() - { - return @sqlite_num_fields($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Fetch Field Names - * - * Generates an array of column names - * - * @return array - */ - public function list_fields() - { - $field_names = array(); - for ($i = 0, $c = $this->num_fields(); $i < $c; $i++) - { - $field_names[$i] = sqlite_field_name($this->result_id, $i); - } - - return $field_names; - } - - // -------------------------------------------------------------------- - - /** - * Field data - * - * Generates an array of objects containing field meta-data - * - * @return array - */ - public function field_data() - { - $retval = array(); - for ($i = 0, $c = $this->num_fields(); $i < $c; $i++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = sqlite_field_name($this->result_id, $i); - $retval[$i]->type = NULL; - $retval[$i]->max_length = NULL; - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Data Seek - * - * Moves the internal pointer to the desired offset. We call - * this internally before fetching results to make sure the - * result set starts at zero. - * - * @param int $n - * @return bool - */ - public function data_seek($n = 0) - { - return sqlite_seek($this->result_id, $n); - } - - // -------------------------------------------------------------------- - - /** - * Result - associative array - * - * Returns the result set as an array - * - * @return array - */ - protected function _fetch_assoc() - { - return sqlite_fetch_array($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Result - object - * - * Returns the result set as an object - * - * @param string $class_name - * @return object - */ - protected function _fetch_object($class_name = 'stdClass') - { - return sqlite_fetch_object($this->result_id, $class_name); - } - -} diff --git a/system/database/drivers/sqlite/sqlite_utility.php b/system/database/drivers/sqlite/sqlite_utility.php deleted file mode 100644 index 57f685e..0000000 --- a/system/database/drivers/sqlite/sqlite_utility.php +++ /dev/null @@ -1,61 +0,0 @@ -db->display_error('db_unsupported_feature'); - } - -} diff --git a/system/database/drivers/sqlite3/index.html b/system/database/drivers/sqlite3/index.html deleted file mode 100644 index b702fbc..0000000 --- a/system/database/drivers/sqlite3/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - 403 Forbidden - - - -

Directory access is forbidden.

- - - diff --git a/system/database/drivers/sqlite3/sqlite3_driver.php b/system/database/drivers/sqlite3/sqlite3_driver.php deleted file mode 100644 index 41d9d48..0000000 --- a/system/database/drivers/sqlite3/sqlite3_driver.php +++ /dev/null @@ -1,350 +0,0 @@ -password) - ? new SQLite3($this->database) - : new SQLite3($this->database, SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE, $this->password); - } - catch (Exception $e) - { - return FALSE; - } - } - - // -------------------------------------------------------------------- - - /** - * Database version number - * - * @return string - */ - public function version() - { - if (isset($this->data_cache['version'])) - { - return $this->data_cache['version']; - } - - $version = SQLite3::version(); - return $this->data_cache['version'] = $version['versionString']; - } - - // -------------------------------------------------------------------- - - /** - * Execute the query - * - * @todo Implement use of SQLite3::querySingle(), if needed - * @param string $sql - * @return mixed SQLite3Result object or bool - */ - protected function _execute($sql) - { - return $this->is_write_type($sql) - ? $this->conn_id->exec($sql) - : $this->conn_id->query($sql); - } - - // -------------------------------------------------------------------- - - /** - * Begin Transaction - * - * @return bool - */ - protected function _trans_begin() - { - return $this->conn_id->exec('BEGIN TRANSACTION'); - } - - // -------------------------------------------------------------------- - - /** - * Commit Transaction - * - * @return bool - */ - protected function _trans_commit() - { - return $this->conn_id->exec('END TRANSACTION'); - } - - // -------------------------------------------------------------------- - - /** - * Rollback Transaction - * - * @return bool - */ - protected function _trans_rollback() - { - return $this->conn_id->exec('ROLLBACK'); - } - - // -------------------------------------------------------------------- - - /** - * Platform-dependent string escape - * - * @param string - * @return string - */ - protected function _escape_str($str) - { - return $this->conn_id->escapeString($str); - } - - // -------------------------------------------------------------------- - - /** - * Affected Rows - * - * @return int - */ - public function affected_rows() - { - return $this->conn_id->changes(); - } - - // -------------------------------------------------------------------- - - /** - * Insert ID - * - * @return int - */ - public function insert_id() - { - return $this->conn_id->lastInsertRowID(); - } - - // -------------------------------------------------------------------- - - /** - * Show table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool $prefix_limit - * @return string - */ - protected function _list_tables($prefix_limit = FALSE) - { - return 'SELECT "NAME" FROM "SQLITE_MASTER" WHERE "TYPE" = \'table\'' - .(($prefix_limit !== FALSE && $this->dbprefix != '') - ? ' AND "NAME" LIKE \''.$this->escape_like_str($this->dbprefix).'%\' '.sprintf($this->_like_escape_str, $this->_like_escape_chr) - : ''); - } - - // -------------------------------------------------------------------- - - /** - * Fetch Field Names - * - * @param string $table Table name - * @return array - */ - public function list_fields($table) - { - // Is there a cached result? - if (isset($this->data_cache['field_names'][$table])) - { - return $this->data_cache['field_names'][$table]; - } - - if (($result = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE) - { - return FALSE; - } - - $this->data_cache['field_names'][$table] = array(); - foreach ($result->result_array() as $row) - { - $this->data_cache['field_names'][$table][] = $row['name']; - } - - return $this->data_cache['field_names'][$table]; - } - - // -------------------------------------------------------------------- - - /** - * Returns an object with field data - * - * @param string $table - * @return array - */ - public function field_data($table) - { - if (($query = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE) - { - return FALSE; - } - - $query = $query->result_array(); - if (empty($query)) - { - return FALSE; - } - - $retval = array(); - for ($i = 0, $c = count($query); $i < $c; $i++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = $query[$i]['name']; - $retval[$i]->type = $query[$i]['type']; - $retval[$i]->max_length = NULL; - $retval[$i]->default = $query[$i]['dflt_value']; - $retval[$i]->primary_key = isset($query[$i]['pk']) ? (int) $query[$i]['pk'] : 0; - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Error - * - * Returns an array containing code and message of the last - * database error that has occurred. - * - * @return array - */ - public function error() - { - return array('code' => $this->conn_id->lastErrorCode(), 'message' => $this->conn_id->lastErrorMsg()); - } - - // -------------------------------------------------------------------- - - /** - * Replace statement - * - * Generates a platform-specific replace string from the supplied data - * - * @param string $table Table name - * @param array $keys INSERT keys - * @param array $values INSERT values - * @return string - */ - protected function _replace($table, $keys, $values) - { - return 'INSERT OR '.parent::_replace($table, $keys, $values); - } - - // -------------------------------------------------------------------- - - /** - * Truncate statement - * - * Generates a platform-specific truncate string from the supplied data - * - * If the database does not support the TRUNCATE statement, - * then this method maps to 'DELETE FROM table' - * - * @param string $table - * @return string - */ - protected function _truncate($table) - { - return 'DELETE FROM '.$table; - } - - // -------------------------------------------------------------------- - - /** - * Close DB Connection - * - * @return void - */ - protected function _close() - { - $this->conn_id->close(); - } - -} diff --git a/system/database/drivers/sqlite3/sqlite3_forge.php b/system/database/drivers/sqlite3/sqlite3_forge.php deleted file mode 100644 index 48c5efc..0000000 --- a/system/database/drivers/sqlite3/sqlite3_forge.php +++ /dev/null @@ -1,225 +0,0 @@ -db->version(), '3.3', '<')) - { - $this->_create_table_if = FALSE; - $this->_drop_table_if = FALSE; - } - } - - // -------------------------------------------------------------------- - - /** - * Create database - * - * @param string $db_name - * @return bool - */ - public function create_database($db_name) - { - // In SQLite, a database is created when you connect to the database. - // We'll return TRUE so that an error isn't generated - return TRUE; - } - - // -------------------------------------------------------------------- - - /** - * Drop database - * - * @param string $db_name (ignored) - * @return bool - */ - public function drop_database($db_name) - { - // In SQLite, a database is dropped when we delete a file - if (file_exists($this->db->database)) - { - // We need to close the pseudo-connection first - $this->db->close(); - if ( ! @unlink($this->db->database)) - { - return $this->db->db_debug ? $this->db->display_error('db_unable_to_drop') : FALSE; - } - elseif ( ! empty($this->db->data_cache['db_names'])) - { - $key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE); - if ($key !== FALSE) - { - unset($this->db->data_cache['db_names'][$key]); - } - } - - return TRUE; - } - - return $this->db->db_debug ? $this->db->display_error('db_unable_to_drop') : FALSE; - } - - // -------------------------------------------------------------------- - - /** - * ALTER TABLE - * - * @todo implement drop_column(), modify_column() - * @param string $alter_type ALTER type - * @param string $table Table name - * @param mixed $field Column definition - * @return string|string[] - */ - protected function _alter_table($alter_type, $table, $field) - { - if ($alter_type === 'DROP' OR $alter_type === 'CHANGE') - { - // drop_column(): - // BEGIN TRANSACTION; - // CREATE TEMPORARY TABLE t1_backup(a,b); - // INSERT INTO t1_backup SELECT a,b FROM t1; - // DROP TABLE t1; - // CREATE TABLE t1(a,b); - // INSERT INTO t1 SELECT a,b FROM t1_backup; - // DROP TABLE t1_backup; - // COMMIT; - - return FALSE; - } - - return parent::_alter_table($alter_type, $table, $field); - } - - // -------------------------------------------------------------------- - - /** - * Process column - * - * @param array $field - * @return string - */ - protected function _process_column($field) - { - return $this->db->escape_identifiers($field['name']) - .' '.$field['type'] - .$field['auto_increment'] - .$field['null'] - .$field['unique'] - .$field['default']; - } - - // -------------------------------------------------------------------- - - /** - * Field attribute TYPE - * - * Performs a data type mapping between different databases. - * - * @param array &$attributes - * @return void - */ - protected function _attr_type(&$attributes) - { - switch (strtoupper($attributes['TYPE'])) - { - case 'ENUM': - case 'SET': - $attributes['TYPE'] = 'TEXT'; - return; - default: return; - } - } - - // -------------------------------------------------------------------- - - /** - * Field attribute AUTO_INCREMENT - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_auto_increment(&$attributes, &$field) - { - if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE) - { - $field['type'] = 'INTEGER PRIMARY KEY'; - $field['default'] = ''; - $field['null'] = ''; - $field['unique'] = ''; - $field['auto_increment'] = ' AUTOINCREMENT'; - - $this->primary_keys = array(); - } - } - -} diff --git a/system/database/drivers/sqlite3/sqlite3_result.php b/system/database/drivers/sqlite3/sqlite3_result.php deleted file mode 100644 index a143fd7..0000000 --- a/system/database/drivers/sqlite3/sqlite3_result.php +++ /dev/null @@ -1,194 +0,0 @@ -result_id->numColumns(); - } - - // -------------------------------------------------------------------- - - /** - * Fetch Field Names - * - * Generates an array of column names - * - * @return array - */ - public function list_fields() - { - $field_names = array(); - for ($i = 0, $c = $this->num_fields(); $i < $c; $i++) - { - $field_names[] = $this->result_id->columnName($i); - } - - return $field_names; - } - - // -------------------------------------------------------------------- - - /** - * Field data - * - * Generates an array of objects containing field meta-data - * - * @return array - */ - public function field_data() - { - static $data_types = array( - SQLITE3_INTEGER => 'integer', - SQLITE3_FLOAT => 'float', - SQLITE3_TEXT => 'text', - SQLITE3_BLOB => 'blob', - SQLITE3_NULL => 'null' - ); - - $retval = array(); - for ($i = 0, $c = $this->num_fields(); $i < $c; $i++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = $this->result_id->columnName($i); - - $type = $this->result_id->columnType($i); - $retval[$i]->type = isset($data_types[$type]) ? $data_types[$type] : $type; - - $retval[$i]->max_length = NULL; - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Free the result - * - * @return void - */ - public function free_result() - { - if (is_object($this->result_id)) - { - $this->result_id->finalize(); - $this->result_id = NULL; - } - } - - // -------------------------------------------------------------------- - - /** - * Result - associative array - * - * Returns the result set as an array - * - * @return array - */ - protected function _fetch_assoc() - { - return $this->result_id->fetchArray(SQLITE3_ASSOC); - } - - // -------------------------------------------------------------------- - - /** - * Result - object - * - * Returns the result set as an object - * - * @param string $class_name - * @return object - */ - protected function _fetch_object($class_name = 'stdClass') - { - // No native support for fetching rows as objects - if (($row = $this->result_id->fetchArray(SQLITE3_ASSOC)) === FALSE) - { - return FALSE; - } - elseif ($class_name === 'stdClass') - { - return (object) $row; - } - - $class_name = new $class_name(); - foreach (array_keys($row) as $key) - { - $class_name->$key = $row[$key]; - } - - return $class_name; - } - - // -------------------------------------------------------------------- - - /** - * Data Seek - * - * Moves the internal pointer to the desired offset. We call - * this internally before fetching results to make sure the - * result set starts at zero. - * - * @param int $n (ignored) - * @return array - */ - public function data_seek($n = 0) - { - // Only resetting to the start of the result set is supported - return ($n > 0) ? FALSE : $this->result_id->reset(); - } - -} diff --git a/system/database/drivers/sqlite3/sqlite3_utility.php b/system/database/drivers/sqlite3/sqlite3_utility.php deleted file mode 100644 index c829c1f..0000000 --- a/system/database/drivers/sqlite3/sqlite3_utility.php +++ /dev/null @@ -1,61 +0,0 @@ -db->display_error('db_unsupported_feature'); - } - -} diff --git a/system/database/drivers/sqlsrv/index.html b/system/database/drivers/sqlsrv/index.html deleted file mode 100644 index b702fbc..0000000 --- a/system/database/drivers/sqlsrv/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - 403 Forbidden - - - -

Directory access is forbidden.

- - - diff --git a/system/database/drivers/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php deleted file mode 100644 index 05d35a4..0000000 --- a/system/database/drivers/sqlsrv/sqlsrv_driver.php +++ /dev/null @@ -1,543 +0,0 @@ -scrollable === NULL) - { - $this->scrollable = defined('SQLSRV_CURSOR_CLIENT_BUFFERED') - ? SQLSRV_CURSOR_CLIENT_BUFFERED - : FALSE; - } - } - - // -------------------------------------------------------------------- - - /** - * Database connection - * - * @param bool $pooling - * @return resource - */ - public function db_connect($pooling = FALSE) - { - $charset = in_array(strtolower($this->char_set), array('utf-8', 'utf8'), TRUE) - ? 'UTF-8' : SQLSRV_ENC_CHAR; - - $connection = array( - 'UID' => empty($this->username) ? '' : $this->username, - 'PWD' => empty($this->password) ? '' : $this->password, - 'Database' => $this->database, - 'ConnectionPooling' => ($pooling === TRUE) ? 1 : 0, - 'CharacterSet' => $charset, - 'Encrypt' => ($this->encrypt === TRUE) ? 1 : 0, - 'ReturnDatesAsStrings' => 1 - ); - - // If the username and password are both empty, assume this is a - // 'Windows Authentication Mode' connection. - if (empty($connection['UID']) && empty($connection['PWD'])) - { - unset($connection['UID'], $connection['PWD']); - } - - if (FALSE !== ($this->conn_id = sqlsrv_connect($this->hostname, $connection))) - { - // Determine how identifiers are escaped - $query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi'); - $query = $query->row_array(); - $this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi']; - $this->_escape_char = ($this->_quoted_identifier) ? '"' : array('[', ']'); - } - - return $this->conn_id; - } - - // -------------------------------------------------------------------- - - /** - * Select the database - * - * @param string $database - * @return bool - */ - public function db_select($database = '') - { - if ($database === '') - { - $database = $this->database; - } - - if ($this->_execute('USE '.$this->escape_identifiers($database))) - { - $this->database = $database; - $this->data_cache = array(); - return TRUE; - } - - return FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Execute the query - * - * @param string $sql an SQL query - * @return resource - */ - protected function _execute($sql) - { - return ($this->scrollable === FALSE OR $this->is_write_type($sql)) - ? sqlsrv_query($this->conn_id, $sql) - : sqlsrv_query($this->conn_id, $sql, NULL, array('Scrollable' => $this->scrollable)); - } - - // -------------------------------------------------------------------- - - /** - * Begin Transaction - * - * @return bool - */ - protected function _trans_begin() - { - return sqlsrv_begin_transaction($this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * Commit Transaction - * - * @return bool - */ - protected function _trans_commit() - { - return sqlsrv_commit($this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * Rollback Transaction - * - * @return bool - */ - protected function _trans_rollback() - { - return sqlsrv_rollback($this->conn_id); - } - - // -------------------------------------------------------------------- - - /** - * Affected Rows - * - * @return int - */ - public function affected_rows() - { - return sqlsrv_rows_affected($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Insert ID - * - * Returns the last id created in the Identity column. - * - * @return string - */ - public function insert_id() - { - return $this->query('SELECT SCOPE_IDENTITY() AS insert_id')->row()->insert_id; - } - - // -------------------------------------------------------------------- - - /** - * Database version number - * - * @return string - */ - public function version() - { - if (isset($this->data_cache['version'])) - { - return $this->data_cache['version']; - } - - if ( ! $this->conn_id OR ($info = sqlsrv_server_info($this->conn_id)) === FALSE) - { - return FALSE; - } - - return $this->data_cache['version'] = $info['SQLServerVersion']; - } - - // -------------------------------------------------------------------- - - /** - * List table query - * - * Generates a platform-specific query string so that the table names can be fetched - * - * @param bool - * @return string $prefix_limit - */ - protected function _list_tables($prefix_limit = FALSE) - { - $sql = 'SELECT '.$this->escape_identifiers('name') - .' FROM '.$this->escape_identifiers('sysobjects') - .' WHERE '.$this->escape_identifiers('type')." = 'U'"; - - if ($prefix_limit === TRUE && $this->dbprefix !== '') - { - $sql .= ' AND '.$this->escape_identifiers('name')." LIKE '".$this->escape_like_str($this->dbprefix)."%' " - .sprintf($this->_escape_like_str, $this->_escape_like_chr); - } - - return $sql.' ORDER BY '.$this->escape_identifiers('name'); - } - - // -------------------------------------------------------------------- - - /** - * List column query - * - * Generates a platform-specific query string so that the column names can be fetched - * - * @param string $table - * @return string - */ - protected function _list_columns($table = '') - { - return 'SELECT COLUMN_NAME - FROM INFORMATION_SCHEMA.Columns - WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table)); - } - - // -------------------------------------------------------------------- - - /** - * Returns an object with field data - * - * @param string $table - * @return array - */ - public function field_data($table) - { - $sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, COLUMN_DEFAULT - FROM INFORMATION_SCHEMA.Columns - WHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table)); - - if (($query = $this->query($sql)) === FALSE) - { - return FALSE; - } - $query = $query->result_object(); - - $retval = array(); - for ($i = 0, $c = count($query); $i < $c; $i++) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = $query[$i]->COLUMN_NAME; - $retval[$i]->type = $query[$i]->DATA_TYPE; - $retval[$i]->max_length = ($query[$i]->CHARACTER_MAXIMUM_LENGTH > 0) ? $query[$i]->CHARACTER_MAXIMUM_LENGTH : $query[$i]->NUMERIC_PRECISION; - $retval[$i]->default = $query[$i]->COLUMN_DEFAULT; - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Error - * - * Returns an array containing code and message of the last - * database error that has occurred. - * - * @return array - */ - public function error() - { - $error = array('code' => '00000', 'message' => ''); - $sqlsrv_errors = sqlsrv_errors(SQLSRV_ERR_ERRORS); - - if ( ! is_array($sqlsrv_errors)) - { - return $error; - } - - $sqlsrv_error = array_shift($sqlsrv_errors); - if (isset($sqlsrv_error['SQLSTATE'])) - { - $error['code'] = isset($sqlsrv_error['code']) ? $sqlsrv_error['SQLSTATE'].'/'.$sqlsrv_error['code'] : $sqlsrv_error['SQLSTATE']; - } - elseif (isset($sqlsrv_error['code'])) - { - $error['code'] = $sqlsrv_error['code']; - } - - if (isset($sqlsrv_error['message'])) - { - $error['message'] = $sqlsrv_error['message']; - } - - return $error; - } - - // -------------------------------------------------------------------- - - /** - * Update statement - * - * Generates a platform-specific update string from the supplied data - * - * @param string $table - * @param array $values - * @return string - */ - protected function _update($table, $values) - { - $this->qb_limit = FALSE; - $this->qb_orderby = array(); - return parent::_update($table, $values); - } - - // -------------------------------------------------------------------- - - /** - * Truncate statement - * - * Generates a platform-specific truncate string from the supplied data - * - * If the database does not support the TRUNCATE statement, - * then this method maps to 'DELETE FROM table' - * - * @param string $table - * @return string - */ - protected function _truncate($table) - { - return 'TRUNCATE TABLE '.$table; - } - - // -------------------------------------------------------------------- - - /** - * Delete statement - * - * Generates a platform-specific delete string from the supplied data - * - * @param string $table - * @return string - */ - protected function _delete($table) - { - if ($this->qb_limit) - { - return 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete'; - } - - return parent::_delete($table); - } - - // -------------------------------------------------------------------- - - /** - * LIMIT - * - * Generates a platform-specific LIMIT clause - * - * @param string $sql SQL Query - * @return string - */ - protected function _limit($sql) - { - // As of SQL Server 2012 (11.0.*) OFFSET is supported - if (version_compare($this->version(), '11', '>=')) - { - // SQL Server OFFSET-FETCH can be used only with the ORDER BY clause - empty($this->qb_orderby) && $sql .= ' ORDER BY 1'; - - return $sql.' OFFSET '.(int) $this->qb_offset.' ROWS FETCH NEXT '.$this->qb_limit.' ROWS ONLY'; - } - - $limit = $this->qb_offset + $this->qb_limit; - - // An ORDER BY clause is required for ROW_NUMBER() to work - if ($this->qb_offset && ! empty($this->qb_orderby)) - { - $orderby = $this->_compile_order_by(); - - // We have to strip the ORDER BY clause - $sql = trim(substr($sql, 0, strrpos($sql, $orderby))); - - // Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results - if (count($this->qb_select) === 0 OR strpos(implode(',', $this->qb_select), '*') !== FALSE) - { - $select = '*'; // Inevitable - } - else - { - // Use only field names and their aliases, everything else is out of our scope. - $select = array(); - $field_regexp = ($this->_quoted_identifier) - ? '("[^\"]+")' : '(\[[^\]]+\])'; - for ($i = 0, $c = count($this->qb_select); $i < $c; $i++) - { - $select[] = preg_match('/(?:\s|\.)'.$field_regexp.'$/i', $this->qb_select[$i], $m) - ? $m[1] : $this->qb_select[$i]; - } - $select = implode(', ', $select); - } - - return 'SELECT '.$select." FROM (\n\n" - .preg_replace('/^(SELECT( DISTINCT)?)/i', '\\1 ROW_NUMBER() OVER('.trim($orderby).') AS '.$this->escape_identifiers('CI_rownum').', ', $sql) - ."\n\n) ".$this->escape_identifiers('CI_subquery') - ."\nWHERE ".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit; - } - - return preg_replace('/(^\SELECT (DISTINCT)?)/i','\\1 TOP '.$limit.' ', $sql); - } - - // -------------------------------------------------------------------- - - /** - * Insert batch statement - * - * Generates a platform-specific insert string from the supplied data. - * - * @param string $table Table name - * @param array $keys INSERT keys - * @param array $values INSERT values - * @return string|bool - */ - protected function _insert_batch($table, $keys, $values) - { - // Multiple-value inserts are only supported as of SQL Server 2008 - if (version_compare($this->version(), '10', '>=')) - { - return parent::_insert_batch($table, $keys, $values); - } - - return ($this->db_debug) ? $this->display_error('db_unsupported_feature') : FALSE; - } - - // -------------------------------------------------------------------- - - /** - * Close DB Connection - * - * @return void - */ - protected function _close() - { - sqlsrv_close($this->conn_id); - } - -} diff --git a/system/database/drivers/sqlsrv/sqlsrv_forge.php b/system/database/drivers/sqlsrv/sqlsrv_forge.php deleted file mode 100644 index 01547e8..0000000 --- a/system/database/drivers/sqlsrv/sqlsrv_forge.php +++ /dev/null @@ -1,149 +0,0 @@ - 'SMALLINT', - 'SMALLINT' => 'INT', - 'INT' => 'BIGINT', - 'REAL' => 'FLOAT' - ); - - // -------------------------------------------------------------------- - - /** - * ALTER TABLE - * - * @param string $alter_type ALTER type - * @param string $table Table name - * @param mixed $field Column definition - * @return string|string[] - */ - protected function _alter_table($alter_type, $table, $field) - { - if (in_array($alter_type, array('ADD', 'DROP'), TRUE)) - { - return parent::_alter_table($alter_type, $table, $field); - } - - $sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ALTER COLUMN '; - $sqls = array(); - for ($i = 0, $c = count($field); $i < $c; $i++) - { - $sqls[] = $sql.$this->_process_column($field[$i]); - } - - return $sqls; - } - - // -------------------------------------------------------------------- - - /** - * Field attribute TYPE - * - * Performs a data type mapping between different databases. - * - * @param array &$attributes - * @return void - */ - protected function _attr_type(&$attributes) - { - if (isset($attributes['CONSTRAINT']) && strpos($attributes['TYPE'], 'INT') !== FALSE) - { - unset($attributes['CONSTRAINT']); - } - - switch (strtoupper($attributes['TYPE'])) - { - case 'MEDIUMINT': - $attributes['TYPE'] = 'INTEGER'; - $attributes['UNSIGNED'] = FALSE; - return; - case 'INTEGER': - $attributes['TYPE'] = 'INT'; - return; - default: return; - } - } - - // -------------------------------------------------------------------- - - /** - * Field attribute AUTO_INCREMENT - * - * @param array &$attributes - * @param array &$field - * @return void - */ - protected function _attr_auto_increment(&$attributes, &$field) - { - if ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE) - { - $field['auto_increment'] = ' IDENTITY(1,1)'; - } - } - -} diff --git a/system/database/drivers/sqlsrv/sqlsrv_result.php b/system/database/drivers/sqlsrv/sqlsrv_result.php deleted file mode 100644 index 1d0272f..0000000 --- a/system/database/drivers/sqlsrv/sqlsrv_result.php +++ /dev/null @@ -1,193 +0,0 @@ -scrollable = $driver_object->scrollable; - } - - // -------------------------------------------------------------------- - - /** - * Number of rows in the result set - * - * @return int - */ - public function num_rows() - { - // sqlsrv_num_rows() doesn't work with the FORWARD and DYNAMIC cursors (FALSE is the same as FORWARD) - if ( ! in_array($this->scrollable, array(FALSE, SQLSRV_CURSOR_FORWARD, SQLSRV_CURSOR_DYNAMIC), TRUE)) - { - return parent::num_rows(); - } - - return is_int($this->num_rows) - ? $this->num_rows - : $this->num_rows = sqlsrv_num_rows($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Number of fields in the result set - * - * @return int - */ - public function num_fields() - { - return @sqlsrv_num_fields($this->result_id); - } - - // -------------------------------------------------------------------- - - /** - * Fetch Field Names - * - * Generates an array of column names - * - * @return array - */ - public function list_fields() - { - $field_names = array(); - foreach (sqlsrv_field_metadata($this->result_id) as $offset => $field) - { - $field_names[] = $field['Name']; - } - - return $field_names; - } - - // -------------------------------------------------------------------- - - /** - * Field data - * - * Generates an array of objects containing field meta-data - * - * @return array - */ - public function field_data() - { - $retval = array(); - foreach (sqlsrv_field_metadata($this->result_id) as $i => $field) - { - $retval[$i] = new stdClass(); - $retval[$i]->name = $field['Name']; - $retval[$i]->type = $field['Type']; - $retval[$i]->max_length = $field['Size']; - } - - return $retval; - } - - // -------------------------------------------------------------------- - - /** - * Free the result - * - * @return void - */ - public function free_result() - { - if (is_resource($this->result_id)) - { - sqlsrv_free_stmt($this->result_id); - $this->result_id = FALSE; - } - } - - // -------------------------------------------------------------------- - - /** - * Result - associative array - * - * Returns the result set as an array - * - * @return array - */ - protected function _fetch_assoc() - { - return sqlsrv_fetch_array($this->result_id, SQLSRV_FETCH_ASSOC); - } - - // -------------------------------------------------------------------- - - /** - * Result - object - * - * Returns the result set as an object - * - * @param string $class_name - * @return object - */ - protected function _fetch_object($class_name = 'stdClass') - { - return sqlsrv_fetch_object($this->result_id, $class_name); - } - -} diff --git a/system/database/drivers/sqlsrv/sqlsrv_utility.php b/system/database/drivers/sqlsrv/sqlsrv_utility.php deleted file mode 100644 index 001107d..0000000 --- a/system/database/drivers/sqlsrv/sqlsrv_utility.php +++ /dev/null @@ -1,77 +0,0 @@ -db->display_error('db_unsupported_feature'); - } - -} diff --git a/system/database/index.html b/system/database/index.html deleted file mode 100644 index b702fbc..0000000 --- a/system/database/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - 403 Forbidden - - - -

Directory access is forbidden.

- - - diff --git a/system/fonts/index.html b/system/fonts/index.html deleted file mode 100644 index b702fbc..0000000 --- a/system/fonts/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - 403 Forbidden - - - -

Directory access is forbidden.

- - - diff --git a/system/fonts/texb.ttf b/system/fonts/texb.ttf deleted file mode 100644 index 383c88b86b7c17e2e284732af48b2bfc359647ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 143830 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 z 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 n`i '', - 'img_path' => '', - 'img_url' => '', - 'img_width' => '150', - 'img_height' => '30', - 'font_path' => '', - 'expiration' => 7200, - 'word_length' => 8, - 'font_size' => 16, - 'img_id' => '', - 'pool' => '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', - 'colors' => array( - 'background' => array(255,255,255), - 'border' => array(153,102,102), - 'text' => array(204,153,153), - 'grid' => array(255,182,182) - ) - ); - - foreach ($defaults as $key => $val) - { - if ( ! is_array($data) && empty($$key)) - { - $$key = $val; - } - else - { - $$key = isset($data[$key]) ? $data[$key] : $val; - } - } - - if ($img_path === '' OR $img_url === '' - OR ! is_dir($img_path) OR ! is_really_writable($img_path) - OR ! extension_loaded('gd')) - { - return FALSE; - } - - // ----------------------------------- - // Remove old images - // ----------------------------------- - - $now = microtime(TRUE); - - $current_dir = @opendir($img_path); - while ($filename = @readdir($current_dir)) - { - if (in_array(substr($filename, -4), array('.jpg', '.png')) - && (str_replace(array('.jpg', '.png'), '', $filename) + $expiration) < $now) - { - @unlink($img_path.$filename); - } - } - - @closedir($current_dir); - - // ----------------------------------- - // Do we have a "word" yet? - // ----------------------------------- - - if (empty($word)) - { - $word = ''; - $pool_length = strlen($pool); - $rand_max = $pool_length - 1; - - // PHP7 or a suitable polyfill - if (function_exists('random_int')) - { - try - { - for ($i = 0; $i < $word_length; $i++) - { - $word .= $pool[random_int(0, $rand_max)]; - } - } - catch (Exception $e) - { - // This means fallback to the next possible - // alternative to random_int() - $word = ''; - } - } - } - - if (empty($word)) - { - // Nobody will have a larger character pool than - // 256 characters, but let's handle it just in case ... - // - // No, I do not care that the fallback to mt_rand() can - // handle it; if you trigger this, you're very obviously - // trying to break it. -- Narf - if ($pool_length > 256) - { - return FALSE; - } - - // We'll try using the operating system's PRNG first, - // which we can access through CI_Security::get_random_bytes() - $security = get_instance()->security; - - // To avoid numerous get_random_bytes() calls, we'll - // just try fetching as much bytes as we need at once. - if (($bytes = $security->get_random_bytes($pool_length)) !== FALSE) - { - $byte_index = $word_index = 0; - while ($word_index < $word_length) - { - // Do we have more random data to use? - // It could be exhausted by previous iterations - // ignoring bytes higher than $rand_max. - if ($byte_index === $pool_length) - { - // No failures should be possible if the - // first get_random_bytes() call didn't - // return FALSE, but still ... - for ($i = 0; $i < 5; $i++) - { - if (($bytes = $security->get_random_bytes($pool_length)) === FALSE) - { - continue; - } - - $byte_index = 0; - break; - } - - if ($bytes === FALSE) - { - // Sadly, this means fallback to mt_rand() - $word = ''; - break; - } - } - - list(, $rand_index) = unpack('C', $bytes[$byte_index++]); - if ($rand_index > $rand_max) - { - continue; - } - - $word .= $pool[$rand_index]; - $word_index++; - } - } - } - - if (empty($word)) - { - for ($i = 0; $i < $word_length; $i++) - { - $word .= $pool[mt_rand(0, $rand_max)]; - } - } - elseif ( ! is_string($word)) - { - $word = (string) $word; - } - - // ----------------------------------- - // Determine angle and position - // ----------------------------------- - $length = strlen($word); - $angle = ($length >= 6) ? mt_rand(-($length-6), ($length-6)) : 0; - $x_axis = mt_rand(6, (360/$length)-16); - $y_axis = ($angle >= 0) ? mt_rand($img_height, $img_width) : mt_rand(6, $img_height); - - // Create image - // PHP.net recommends imagecreatetruecolor(), but it isn't always available - $im = function_exists('imagecreatetruecolor') - ? imagecreatetruecolor($img_width, $img_height) - : imagecreate($img_width, $img_height); - - // ----------------------------------- - // Assign colors - // ---------------------------------- - - is_array($colors) OR $colors = $defaults['colors']; - - foreach (array_keys($defaults['colors']) as $key) - { - // Check for a possible missing value - is_array($colors[$key]) OR $colors[$key] = $defaults['colors'][$key]; - $colors[$key] = imagecolorallocate($im, $colors[$key][0], $colors[$key][1], $colors[$key][2]); - } - - // Create the rectangle - ImageFilledRectangle($im, 0, 0, $img_width, $img_height, $colors['background']); - - // ----------------------------------- - // Create the spiral pattern - // ----------------------------------- - $theta = 1; - $thetac = 7; - $radius = 16; - $circles = 20; - $points = 32; - - for ($i = 0, $cp = ($circles * $points) - 1; $i < $cp; $i++) - { - $theta += $thetac; - $rad = $radius * ($i / $points); - $x = ($rad * cos($theta)) + $x_axis; - $y = ($rad * sin($theta)) + $y_axis; - $theta += $thetac; - $rad1 = $radius * (($i + 1) / $points); - $x1 = ($rad1 * cos($theta)) + $x_axis; - $y1 = ($rad1 * sin($theta)) + $y_axis; - imageline($im, $x, $y, $x1, $y1, $colors['grid']); - $theta -= $thetac; - } - - // ----------------------------------- - // Write the text - // ----------------------------------- - - $use_font = ($font_path !== '' && file_exists($font_path) && function_exists('imagettftext')); - if ($use_font === FALSE) - { - ($font_size > 5) && $font_size = 5; - $x = mt_rand(0, $img_width / ($length / 3)); - $y = 0; - } - else - { - ($font_size > 30) && $font_size = 30; - $x = mt_rand(0, $img_width / ($length / 1.5)); - $y = $font_size + 2; - } - - for ($i = 0; $i < $length; $i++) - { - if ($use_font === FALSE) - { - $y = mt_rand(0 , $img_height / 2); - imagestring($im, $font_size, $x, $y, $word[$i], $colors['text']); - $x += ($font_size * 2); - } - else - { - $y = mt_rand($img_height / 2, $img_height - 3); - imagettftext($im, $font_size, $angle, $x, $y, $colors['text'], $font_path, $word[$i]); - $x += $font_size; - } - } - - // Create the border - imagerectangle($im, 0, 0, $img_width - 1, $img_height - 1, $colors['border']); - - // ----------------------------------- - // Generate the image - // ----------------------------------- - $img_url = rtrim($img_url, '/').'/'; - - if (function_exists('imagejpeg')) - { - $img_filename = $now.'.jpg'; - imagejpeg($im, $img_path.$img_filename); - } - elseif (function_exists('imagepng')) - { - $img_filename = $now.'.png'; - imagepng($im, $img_path.$img_filename); - } - else - { - return FALSE; - } - - $img = ' '; - ImageDestroy($im); - - return array('word' => $word, 'time' => $now, 'image' => $img, 'filename' => $img_filename); - } -} diff --git a/system/helpers/cookie_helper.php b/system/helpers/cookie_helper.php deleted file mode 100644 index eccd2f3..0000000 --- a/system/helpers/cookie_helper.php +++ /dev/null @@ -1,113 +0,0 @@ -input->set_cookie($name, $value, $expire, $domain, $path, $prefix, $secure, $httponly); - } -} - -// -------------------------------------------------------------------- - -if ( ! function_exists('get_cookie')) -{ - /** - * Fetch an item from the COOKIE array - * - * @param string - * @param bool - * @return mixed - */ - function get_cookie($index, $xss_clean = NULL) - { - is_bool($xss_clean) OR $xss_clean = (config_item('global_xss_filtering') === TRUE); - $prefix = isset($_COOKIE[$index]) ? '' : config_item('cookie_prefix'); - return get_instance()->input->cookie($prefix.$index, $xss_clean); - } -} - -// -------------------------------------------------------------------- - -if ( ! function_exists('delete_cookie')) -{ - /** - * Delete a COOKIE - * - * @param mixed - * @param string the cookie domain. Usually: .yourdomain.com - * @param string the cookie path - * @param string the cookie prefix - * @return void - */ - function delete_cookie($name, $domain = '', $path = '/', $prefix = '') - { - set_cookie($name, '', '', $domain, $path, $prefix); - } -} diff --git a/system/helpers/date_helper.php b/system/helpers/date_helper.php deleted file mode 100644 index eca1fc0..0000000 --- a/system/helpers/date_helper.php +++ /dev/null @@ -1,742 +0,0 @@ -format('j-n-Y G:i:s'), '%d-%d-%d %d:%d:%d', $day, $month, $year, $hour, $minute, $second); - - return mktime($hour, $minute, $second, $month, $day, $year); - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('mdate')) -{ - /** - * Convert MySQL Style Datecodes - * - * This function is identical to PHPs date() function, - * except that it allows date codes to be formatted using - * the MySQL style, where each code letter is preceded - * with a percent sign: %Y %m %d etc... - * - * The benefit of doing dates this way is that you don't - * have to worry about escaping your text letters that - * match the date codes. - * - * @param string - * @param int - * @return int - */ - function mdate($datestr = '', $time = '') - { - if ($datestr === '') - { - return ''; - } - elseif (empty($time)) - { - $time = now(); - } - - $datestr = str_replace( - '%\\', - '', - preg_replace('/([a-z]+?){1}/i', '\\\\\\1', $datestr) - ); - - return date($datestr, $time); - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('standard_date')) -{ - /** - * Standard Date - * - * Returns a date formatted according to the submitted standard. - * - * As of PHP 5.2, the DateTime extension provides constants that - * serve for the exact same purpose and are used with date(). - * - * @todo Remove in version 3.1+. - * @deprecated 3.0.0 Use PHP's native date() instead. - * @link http://www.php.net/manual/en/class.datetime.php#datetime.constants.types - * - * @example date(DATE_RFC822, now()); // default - * @example date(DATE_W3C, $time); // a different format and time - * - * @param string $fmt = 'DATE_RFC822' the chosen format - * @param int $time = NULL Unix timestamp - * @return string - */ - function standard_date($fmt = 'DATE_RFC822', $time = NULL) - { - if (empty($time)) - { - $time = now(); - } - - // Procedural style pre-defined constants from the DateTime extension - if (strpos($fmt, 'DATE_') !== 0 OR defined($fmt) === FALSE) - { - return FALSE; - } - - return date(constant($fmt), $time); - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('timespan')) -{ - /** - * Timespan - * - * Returns a span of seconds in this format: - * 10 days 14 hours 36 minutes 47 seconds - * - * @param int a number of seconds - * @param int Unix timestamp - * @param int a number of display units - * @return string - */ - function timespan($seconds = 1, $time = '', $units = 7) - { - $CI =& get_instance(); - $CI->lang->load('date'); - - is_numeric($seconds) OR $seconds = 1; - is_numeric($time) OR $time = time(); - is_numeric($units) OR $units = 7; - - $seconds = ($time <= $seconds) ? 1 : $time - $seconds; - - $str = array(); - $years = floor($seconds / 31557600); - - if ($years > 0) - { - $str[] = $years.' '.$CI->lang->line($years > 1 ? 'date_years' : 'date_year'); - } - - $seconds -= $years * 31557600; - $months = floor($seconds / 2629743); - - if (count($str) < $units && ($years > 0 OR $months > 0)) - { - if ($months > 0) - { - $str[] = $months.' '.$CI->lang->line($months > 1 ? 'date_months' : 'date_month'); - } - - $seconds -= $months * 2629743; - } - - $weeks = floor($seconds / 604800); - - if (count($str) < $units && ($years > 0 OR $months > 0 OR $weeks > 0)) - { - if ($weeks > 0) - { - $str[] = $weeks.' '.$CI->lang->line($weeks > 1 ? 'date_weeks' : 'date_week'); - } - - $seconds -= $weeks * 604800; - } - - $days = floor($seconds / 86400); - - if (count($str) < $units && ($months > 0 OR $weeks > 0 OR $days > 0)) - { - if ($days > 0) - { - $str[] = $days.' '.$CI->lang->line($days > 1 ? 'date_days' : 'date_day'); - } - - $seconds -= $days * 86400; - } - - $hours = floor($seconds / 3600); - - if (count($str) < $units && ($days > 0 OR $hours > 0)) - { - if ($hours > 0) - { - $str[] = $hours.' '.$CI->lang->line($hours > 1 ? 'date_hours' : 'date_hour'); - } - - $seconds -= $hours * 3600; - } - - $minutes = floor($seconds / 60); - - if (count($str) < $units && ($days > 0 OR $hours > 0 OR $minutes > 0)) - { - if ($minutes > 0) - { - $str[] = $minutes.' '.$CI->lang->line($minutes > 1 ? 'date_minutes' : 'date_minute'); - } - - $seconds -= $minutes * 60; - } - - if (count($str) === 0) - { - $str[] = $seconds.' '.$CI->lang->line($seconds > 1 ? 'date_seconds' : 'date_second'); - } - - return implode(', ', $str); - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('days_in_month')) -{ - /** - * Number of days in a month - * - * Takes a month/year as input and returns the number of days - * for the given month/year. Takes leap years into consideration. - * - * @param int a numeric month - * @param int a numeric year - * @return int - */ - function days_in_month($month = 0, $year = '') - { - if ($month < 1 OR $month > 12) - { - return 0; - } - elseif ( ! is_numeric($year) OR strlen($year) !== 4) - { - $year = date('Y'); - } - - if (defined('CAL_GREGORIAN')) - { - return cal_days_in_month(CAL_GREGORIAN, $month, $year); - } - - if ($year >= 1970) - { - return (int) date('t', mktime(12, 0, 0, $month, 1, $year)); - } - - if ($month == 2) - { - if ($year % 400 === 0 OR ($year % 4 === 0 && $year % 100 !== 0)) - { - return 29; - } - } - - $days_in_month = array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); - return $days_in_month[$month - 1]; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('local_to_gmt')) -{ - /** - * Converts a local Unix timestamp to GMT - * - * @param int Unix timestamp - * @return int - */ - function local_to_gmt($time = '') - { - if ($time === '') - { - $time = time(); - } - - return mktime( - gmdate('G', $time), - gmdate('i', $time), - gmdate('s', $time), - gmdate('n', $time), - gmdate('j', $time), - gmdate('Y', $time) - ); - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('gmt_to_local')) -{ - /** - * Converts GMT time to a localized value - * - * Takes a Unix timestamp (in GMT) as input, and returns - * at the local value based on the timezone and DST setting - * submitted - * - * @param int Unix timestamp - * @param string timezone - * @param bool whether DST is active - * @return int - */ - function gmt_to_local($time = '', $timezone = 'UTC', $dst = FALSE) - { - if ($time === '') - { - return now(); - } - - $time += timezones($timezone) * 3600; - - return ($dst === TRUE) ? $time + 3600 : $time; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('mysql_to_unix')) -{ - /** - * Converts a MySQL Timestamp to Unix - * - * @param int MySQL timestamp YYYY-MM-DD HH:MM:SS - * @return int Unix timstamp - */ - function mysql_to_unix($time = '') - { - // We'll remove certain characters for backward compatibility - // since the formatting changed with MySQL 4.1 - // YYYY-MM-DD HH:MM:SS - - $time = str_replace(array('-', ':', ' '), '', $time); - - // YYYYMMDDHHMMSS - return mktime( - substr($time, 8, 2), - substr($time, 10, 2), - substr($time, 12, 2), - substr($time, 4, 2), - substr($time, 6, 2), - substr($time, 0, 4) - ); - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('unix_to_human')) -{ - /** - * Unix to "Human" - * - * Formats Unix timestamp to the following prototype: 2006-08-21 11:35 PM - * - * @param int Unix timestamp - * @param bool whether to show seconds - * @param string format: us or euro - * @return string - */ - function unix_to_human($time = '', $seconds = FALSE, $fmt = 'us') - { - $r = date('Y', $time).'-'.date('m', $time).'-'.date('d', $time).' '; - - if ($fmt === 'us') - { - $r .= date('h', $time).':'.date('i', $time); - } - else - { - $r .= date('H', $time).':'.date('i', $time); - } - - if ($seconds) - { - $r .= ':'.date('s', $time); - } - - if ($fmt === 'us') - { - return $r.' '.date('A', $time); - } - - return $r; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('human_to_unix')) -{ - /** - * Convert "human" date to GMT - * - * Reverses the above process - * - * @param string format: us or euro - * @return int - */ - function human_to_unix($datestr = '') - { - if ($datestr === '') - { - return FALSE; - } - - $datestr = preg_replace('/\040+/', ' ', trim($datestr)); - - if ( ! preg_match('/^(\d{2}|\d{4})\-[0-9]{1,2}\-[0-9]{1,2}\s[0-9]{1,2}:[0-9]{1,2}(?::[0-9]{1,2})?(?:\s[AP]M)?$/i', $datestr)) - { - return FALSE; - } - - sscanf($datestr, '%d-%d-%d %s %s', $year, $month, $day, $time, $ampm); - sscanf($time, '%d:%d:%d', $hour, $min, $sec); - isset($sec) OR $sec = 0; - - if (isset($ampm)) - { - $ampm = strtolower($ampm); - - if ($ampm[0] === 'p' && $hour < 12) - { - $hour += 12; - } - elseif ($ampm[0] === 'a' && $hour === 12) - { - $hour = 0; - } - } - - return mktime($hour, $min, $sec, $month, $day, $year); - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('nice_date')) -{ - /** - * Turns many "reasonably-date-like" strings into something - * that is actually useful. This only works for dates after unix epoch. - * - * @deprecated 3.1.3 Use DateTime::createFromFormat($input_format, $input)->format($output_format); - * @param string The terribly formatted date-like string - * @param string Date format to return (same as php date function) - * @return string - */ - function nice_date($bad_date = '', $format = FALSE) - { - if (empty($bad_date)) - { - return 'Unknown'; - } - elseif (empty($format)) - { - $format = 'U'; - } - - // Date like: YYYYMM - if (preg_match('/^\d{6}$/i', $bad_date)) - { - if (in_array(substr($bad_date, 0, 2), array('19', '20'))) - { - $year = substr($bad_date, 0, 4); - $month = substr($bad_date, 4, 2); - } - else - { - $month = substr($bad_date, 0, 2); - $year = substr($bad_date, 2, 4); - } - - return date($format, strtotime($year.'-'.$month.'-01')); - } - - // Date Like: YYYYMMDD - if (preg_match('/^\d{8}$/i', $bad_date, $matches)) - { - return DateTime::createFromFormat('Ymd', $bad_date)->format($format); - } - - // Date Like: MM-DD-YYYY __or__ M-D-YYYY (or anything in between) - if (preg_match('/^(\d{1,2})-(\d{1,2})-(\d{4})$/i', $bad_date, $matches)) - { - return date($format, strtotime($matches[3].'-'.$matches[1].'-'.$matches[2])); - } - - // Any other kind of string, when converted into UNIX time, - // produces "0 seconds after epoc..." is probably bad... - // return "Invalid Date". - if (date('U', strtotime($bad_date)) === '0') - { - return 'Invalid Date'; - } - - // It's probably a valid-ish date format already - return date($format, strtotime($bad_date)); - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('timezone_menu')) -{ - /** - * Timezone Menu - * - * Generates a drop-down menu of timezones. - * - * @param string timezone - * @param string classname - * @param string menu name - * @param mixed attributes - * @return string - */ - function timezone_menu($default = 'UTC', $class = '', $name = 'timezones', $attributes = '') - { - $CI =& get_instance(); - $CI->lang->load('date'); - - $default = ($default === 'GMT') ? 'UTC' : $default; - - $menu = ''; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('timezones')) -{ - /** - * Timezones - * - * Returns an array of timezones. This is a helper function - * for various other ones in this library - * - * @param string timezone - * @return string - */ - function timezones($tz = '') - { - // Note: Don't change the order of these even though - // some items appear to be in the wrong order - - $zones = array( - 'UM12' => -12, - 'UM11' => -11, - 'UM10' => -10, - 'UM95' => -9.5, - 'UM9' => -9, - 'UM8' => -8, - 'UM7' => -7, - 'UM6' => -6, - 'UM5' => -5, - 'UM45' => -4.5, - 'UM4' => -4, - 'UM35' => -3.5, - 'UM3' => -3, - 'UM2' => -2, - 'UM1' => -1, - 'UTC' => 0, - 'UP1' => +1, - 'UP2' => +2, - 'UP3' => +3, - 'UP35' => +3.5, - 'UP4' => +4, - 'UP45' => +4.5, - 'UP5' => +5, - 'UP55' => +5.5, - 'UP575' => +5.75, - 'UP6' => +6, - 'UP65' => +6.5, - 'UP7' => +7, - 'UP8' => +8, - 'UP875' => +8.75, - 'UP9' => +9, - 'UP95' => +9.5, - 'UP10' => +10, - 'UP105' => +10.5, - 'UP11' => +11, - 'UP115' => +11.5, - 'UP12' => +12, - 'UP1275' => +12.75, - 'UP13' => +13, - 'UP14' => +14 - ); - - if ($tz === '') - { - return $zones; - } - - return isset($zones[$tz]) ? $zones[$tz] : 0; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('date_range')) -{ - /** - * Date range - * - * Returns a list of dates within a specified period. - * - * @param int unix_start UNIX timestamp of period start date - * @param int unix_end|days UNIX timestamp of period end date - * or interval in days. - * @param mixed is_unix Specifies whether the second parameter - * is a UNIX timestamp or a day interval - * - TRUE or 'unix' for a timestamp - * - FALSE or 'days' for an interval - * @param string date_format Output date format, same as in date() - * @return array - */ - function date_range($unix_start = '', $mixed = '', $is_unix = TRUE, $format = 'Y-m-d') - { - if ($unix_start == '' OR $mixed == '' OR $format == '') - { - return FALSE; - } - - $is_unix = ! ( ! $is_unix OR $is_unix === 'days'); - - // Validate input and try strtotime() on invalid timestamps/intervals, just in case - if ( ( ! ctype_digit((string) $unix_start) && ($unix_start = @strtotime($unix_start)) === FALSE) - OR ( ! ctype_digit((string) $mixed) && ($is_unix === FALSE OR ($mixed = @strtotime($mixed)) === FALSE)) - OR ($is_unix === TRUE && $mixed < $unix_start)) - { - return FALSE; - } - - if ($is_unix && ($unix_start == $mixed OR date($format, $unix_start) === date($format, $mixed))) - { - return array(date($format, $unix_start)); - } - - $range = array(); - - $from = new DateTime(); - $from->setTimestamp($unix_start); - - if ($is_unix) - { - $arg = new DateTime(); - $arg->setTimestamp($mixed); - } - else - { - $arg = (int) $mixed; - } - - $period = new DatePeriod($from, new DateInterval('P1D'), $arg); - foreach ($period as $date) - { - $range[] = $date->format($format); - } - - /* If a period end date was passed to the DatePeriod constructor, it might not - * be in our results. Not sure if this is a bug or it's just possible because - * the end date might actually be less than 24 hours away from the previously - * generated DateTime object, but either way - we have to append it manually. - */ - if ( ! is_int($arg) && $range[count($range) - 1] !== $arg->format($format)) - { - $range[] = $arg->format($format); - } - - return $range; - } -} diff --git a/system/helpers/directory_helper.php b/system/helpers/directory_helper.php deleted file mode 100644 index 0d3f205..0000000 --- a/system/helpers/directory_helper.php +++ /dev/null @@ -1,101 +0,0 @@ - 0) && is_dir($source_dir.$file)) - { - $filedata[$file] = directory_map($source_dir.$file, $new_depth, $hidden); - } - else - { - $filedata[] = $file; - } - } - - closedir($fp); - return $filedata; - } - - return FALSE; - } -} diff --git a/system/helpers/download_helper.php b/system/helpers/download_helper.php deleted file mode 100644 index a9bea94..0000000 --- a/system/helpers/download_helper.php +++ /dev/null @@ -1,158 +0,0 @@ - 0) - ? @rmdir($path) - : TRUE; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('get_filenames')) -{ - /** - * Get Filenames - * - * Reads the specified directory and builds an array containing the filenames. - * Any sub-folders contained within the specified path are read as well. - * - * @param string path to source - * @param bool whether to include the path as part of the filename - * @param bool internal variable to determine recursion status - do not use in calls - * @return array - */ - function get_filenames($source_dir, $include_path = FALSE, $_recursion = FALSE) - { - static $_filedata = array(); - - if ($fp = @opendir($source_dir)) - { - // reset the array and make sure $source_dir has a trailing slash on the initial call - if ($_recursion === FALSE) - { - $_filedata = array(); - $source_dir = rtrim(realpath($source_dir), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR; - } - - while (FALSE !== ($file = readdir($fp))) - { - if (is_dir($source_dir.$file) && $file[0] !== '.') - { - get_filenames($source_dir.$file.DIRECTORY_SEPARATOR, $include_path, TRUE); - } - elseif ($file[0] !== '.') - { - $_filedata[] = ($include_path === TRUE) ? $source_dir.$file : $file; - } - } - - closedir($fp); - return $_filedata; - } - - return FALSE; - } -} - -// -------------------------------------------------------------------- - -if ( ! function_exists('get_dir_file_info')) -{ - /** - * Get Directory File Information - * - * Reads the specified directory and builds an array containing the filenames, - * filesize, dates, and permissions - * - * Any sub-folders contained within the specified path are read as well. - * - * @param string path to source - * @param bool Look only at the top level directory specified? - * @param bool internal variable to determine recursion status - do not use in calls - * @return array - */ - function get_dir_file_info($source_dir, $top_level_only = TRUE, $_recursion = FALSE) - { - static $_filedata = array(); - $relative_path = $source_dir; - - if ($fp = @opendir($source_dir)) - { - // reset the array and make sure $source_dir has a trailing slash on the initial call - if ($_recursion === FALSE) - { - $_filedata = array(); - $source_dir = rtrim(realpath($source_dir), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR; - } - - // Used to be foreach (scandir($source_dir, 1) as $file), but scandir() is simply not as fast - while (FALSE !== ($file = readdir($fp))) - { - if (is_dir($source_dir.$file) && $file[0] !== '.' && $top_level_only === FALSE) - { - get_dir_file_info($source_dir.$file.DIRECTORY_SEPARATOR, $top_level_only, TRUE); - } - elseif ($file[0] !== '.') - { - $_filedata[$file] = get_file_info($source_dir.$file); - $_filedata[$file]['relative_path'] = $relative_path; - } - } - - closedir($fp); - return $_filedata; - } - - return FALSE; - } -} - -// -------------------------------------------------------------------- - -if ( ! function_exists('get_file_info')) -{ - /** - * Get File Info - * - * Given a file and path, returns the name, path, size, date modified - * Second parameter allows you to explicitly declare what information you want returned - * Options are: name, server_path, size, date, readable, writable, executable, fileperms - * Returns FALSE if the file cannot be found. - * - * @param string path to file - * @param mixed array or comma separated string of information returned - * @return array - */ - function get_file_info($file, $returned_values = array('name', 'server_path', 'size', 'date')) - { - if ( ! file_exists($file)) - { - return FALSE; - } - - if (is_string($returned_values)) - { - $returned_values = explode(',', $returned_values); - } - - foreach ($returned_values as $key) - { - switch ($key) - { - case 'name': - $fileinfo['name'] = basename($file); - break; - case 'server_path': - $fileinfo['server_path'] = $file; - break; - case 'size': - $fileinfo['size'] = filesize($file); - break; - case 'date': - $fileinfo['date'] = filemtime($file); - break; - case 'readable': - $fileinfo['readable'] = is_readable($file); - break; - case 'writable': - $fileinfo['writable'] = is_really_writable($file); - break; - case 'executable': - $fileinfo['executable'] = is_executable($file); - break; - case 'fileperms': - $fileinfo['fileperms'] = fileperms($file); - break; - } - } - - return $fileinfo; - } -} - -// -------------------------------------------------------------------- - -if ( ! function_exists('get_mime_by_extension')) -{ - /** - * Get Mime by Extension - * - * Translates a file extension into a mime type based on config/mimes.php. - * Returns FALSE if it can't determine the type, or open the mime config file - * - * Note: this is NOT an accurate way of determining file mime types, and is here strictly as a convenience - * It should NOT be trusted, and should certainly NOT be used for security - * - * @param string $filename File name - * @return string - */ - function get_mime_by_extension($filename) - { - static $mimes; - - if ( ! is_array($mimes)) - { - $mimes = get_mimes(); - - if (empty($mimes)) - { - return FALSE; - } - } - - $extension = strtolower(substr(strrchr($filename, '.'), 1)); - - if (isset($mimes[$extension])) - { - return is_array($mimes[$extension]) - ? current($mimes[$extension]) // Multiple mime types, just give the first one - : $mimes[$extension]; - } - - return FALSE; - } -} - -// -------------------------------------------------------------------- - -if ( ! function_exists('symbolic_permissions')) -{ - /** - * Symbolic Permissions - * - * Takes a numeric value representing a file's permissions and returns - * standard symbolic notation representing that value - * - * @param int $perms Permissions - * @return string - */ - function symbolic_permissions($perms) - { - if (($perms & 0xC000) === 0xC000) - { - $symbolic = 's'; // Socket - } - elseif (($perms & 0xA000) === 0xA000) - { - $symbolic = 'l'; // Symbolic Link - } - elseif (($perms & 0x8000) === 0x8000) - { - $symbolic = '-'; // Regular - } - elseif (($perms & 0x6000) === 0x6000) - { - $symbolic = 'b'; // Block special - } - elseif (($perms & 0x4000) === 0x4000) - { - $symbolic = 'd'; // Directory - } - elseif (($perms & 0x2000) === 0x2000) - { - $symbolic = 'c'; // Character special - } - elseif (($perms & 0x1000) === 0x1000) - { - $symbolic = 'p'; // FIFO pipe - } - else - { - $symbolic = 'u'; // Unknown - } - - // Owner - $symbolic .= (($perms & 0x0100) ? 'r' : '-') - .(($perms & 0x0080) ? 'w' : '-') - .(($perms & 0x0040) ? (($perms & 0x0800) ? 's' : 'x' ) : (($perms & 0x0800) ? 'S' : '-')); - - // Group - $symbolic .= (($perms & 0x0020) ? 'r' : '-') - .(($perms & 0x0010) ? 'w' : '-') - .(($perms & 0x0008) ? (($perms & 0x0400) ? 's' : 'x' ) : (($perms & 0x0400) ? 'S' : '-')); - - // World - $symbolic .= (($perms & 0x0004) ? 'r' : '-') - .(($perms & 0x0002) ? 'w' : '-') - .(($perms & 0x0001) ? (($perms & 0x0200) ? 't' : 'x' ) : (($perms & 0x0200) ? 'T' : '-')); - - return $symbolic; - } -} - -// -------------------------------------------------------------------- - -if ( ! function_exists('octal_permissions')) -{ - /** - * Octal Permissions - * - * Takes a numeric value representing a file's permissions and returns - * a three character string representing the file's octal permissions - * - * @param int $perms Permissions - * @return string - */ - function octal_permissions($perms) - { - return substr(sprintf('%o', $perms), -3); - } -} diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php deleted file mode 100644 index 8746045..0000000 --- a/system/helpers/form_helper.php +++ /dev/null @@ -1,1055 +0,0 @@ -config->site_url($CI->uri->uri_string()); - } - // If an action is not a full URL then turn it into one - elseif (strpos($action, '://') === FALSE) - { - $action = $CI->config->site_url($action); - } - - $attributes = _attributes_to_string($attributes); - - if (stripos($attributes, 'method=') === FALSE) - { - $attributes .= ' method="post"'; - } - - if (stripos($attributes, 'accept-charset=') === FALSE) - { - $attributes .= ' accept-charset="'.strtolower(config_item('charset')).'"'; - } - - $form = '
\n"; - - if (is_array($hidden)) - { - foreach ($hidden as $name => $value) - { - $form .= ''."\n"; - } - } - - // Add CSRF field if enabled, but leave it out for GET requests and requests to external websites - if ($CI->config->item('csrf_protection') === TRUE && strpos($action, $CI->config->base_url()) !== FALSE && ! stripos($form, 'method="get"')) - { - // Prepend/append random-length "white noise" around the CSRF - // token input, as a form of protection against BREACH attacks - if (FALSE !== ($noise = $CI->security->get_random_bytes(1))) - { - list(, $noise) = unpack('c', $noise); - } - else - { - $noise = mt_rand(-128, 127); - } - - // Prepend if $noise has a negative value, append if positive, do nothing for zero - $prepend = $append = ''; - if ($noise < 0) - { - $prepend = str_repeat(" ", abs($noise)); - } - elseif ($noise > 0) - { - $append = str_repeat(" ", $noise); - } - - $form .= sprintf( - '%s%s%s', - $prepend, - $CI->security->get_csrf_token_name(), - $CI->security->get_csrf_hash(), - $append, - "\n" - ); - } - - return $form; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('form_open_multipart')) -{ - /** - * Form Declaration - Multipart type - * - * Creates the opening portion of the form, but with "multipart/form-data". - * - * @param string the URI segments of the form destination - * @param array a key/value pair of attributes - * @param array a key/value pair hidden data - * @return string - */ - function form_open_multipart($action = '', $attributes = array(), $hidden = array()) - { - if (is_string($attributes)) - { - $attributes .= ' enctype="multipart/form-data"'; - } - else - { - $attributes['enctype'] = 'multipart/form-data'; - } - - return form_open($action, $attributes, $hidden); - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('form_hidden')) -{ - /** - * Hidden Input Field - * - * Generates hidden fields. You can pass a simple key/value string or - * an associative array with multiple values. - * - * @param mixed $name Field name - * @param string $value Field value - * @param bool $recursing - * @return string - */ - function form_hidden($name, $value = '', $recursing = FALSE) - { - static $form; - - if ($recursing === FALSE) - { - $form = "\n"; - } - - if (is_array($name)) - { - foreach ($name as $key => $val) - { - form_hidden($key, $val, TRUE); - } - - return $form; - } - - if ( ! is_array($value)) - { - $form .= '\n"; - } - else - { - foreach ($value as $k => $v) - { - $k = is_int($k) ? '' : $k; - form_hidden($name.'['.$k.']', $v, TRUE); - } - } - - return $form; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('form_input')) -{ - /** - * Text Input Field - * - * @param mixed - * @param string - * @param mixed - * @return string - */ - function form_input($data = '', $value = '', $extra = '') - { - $defaults = array( - 'type' => 'text', - 'name' => is_array($data) ? '' : $data, - 'value' => $value - ); - - return '\n"; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('form_password')) -{ - /** - * Password Field - * - * Identical to the input function but adds the "password" type - * - * @param mixed - * @param string - * @param mixed - * @return string - */ - function form_password($data = '', $value = '', $extra = '') - { - is_array($data) OR $data = array('name' => $data); - $data['type'] = 'password'; - return form_input($data, $value, $extra); - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('form_upload')) -{ - /** - * Upload Field - * - * Identical to the input function but adds the "file" type - * - * @param mixed - * @param string - * @param mixed - * @return string - */ - function form_upload($data = '', $value = '', $extra = '') - { - $defaults = array('type' => 'file', 'name' => ''); - is_array($data) OR $data = array('name' => $data); - $data['type'] = 'file'; - - return '\n"; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('form_textarea')) -{ - /** - * Textarea field - * - * @param mixed $data - * @param string $value - * @param mixed $extra - * @return string - */ - function form_textarea($data = '', $value = '', $extra = '') - { - $defaults = array( - 'name' => is_array($data) ? '' : $data, - 'cols' => '40', - 'rows' => '10' - ); - - if ( ! is_array($data) OR ! isset($data['value'])) - { - $val = $value; - } - else - { - $val = $data['value']; - unset($data['value']); // textareas don't use the value attribute - } - - return '\n"; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('form_multiselect')) -{ - /** - * Multi-select menu - * - * @param string - * @param array - * @param mixed - * @param mixed - * @return string - */ - function form_multiselect($name = '', $options = array(), $selected = array(), $extra = '') - { - $extra = _attributes_to_string($extra); - if (stripos($extra, 'multiple') === FALSE) - { - $extra .= ' multiple="multiple"'; - } - - return form_dropdown($name, $options, $selected, $extra); - } -} - -// -------------------------------------------------------------------- - -if ( ! function_exists('form_dropdown')) -{ - /** - * Drop-down Menu - * - * @param mixed $data - * @param mixed $options - * @param mixed $selected - * @param mixed $extra - * @return string - */ - function form_dropdown($data = '', $options = array(), $selected = array(), $extra = '') - { - $defaults = array(); - - if (is_array($data)) - { - if (isset($data['selected'])) - { - $selected = $data['selected']; - unset($data['selected']); // select tags don't have a selected attribute - } - - if (isset($data['options'])) - { - $options = $data['options']; - unset($data['options']); // select tags don't use an options attribute - } - } - else - { - $defaults = array('name' => $data); - } - - is_array($selected) OR $selected = array($selected); - is_array($options) OR $options = array($options); - - // If no selected state was submitted we will attempt to set it automatically - if (empty($selected)) - { - if (is_array($data)) - { - if (isset($data['name'], $_POST[$data['name']])) - { - $selected = array($_POST[$data['name']]); - } - } - elseif (isset($_POST[$data])) - { - $selected = array($_POST[$data]); - } - } - - $extra = _attributes_to_string($extra); - - $multiple = (count($selected) > 1 && stripos($extra, 'multiple') === FALSE) ? ' multiple="multiple"' : ''; - - $form = '\n"; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('form_checkbox')) -{ - /** - * Checkbox Field - * - * @param mixed - * @param string - * @param bool - * @param mixed - * @return string - */ - function form_checkbox($data = '', $value = '', $checked = FALSE, $extra = '') - { - $defaults = array('type' => 'checkbox', 'name' => ( ! is_array($data) ? $data : ''), 'value' => $value); - - if (is_array($data) && array_key_exists('checked', $data)) - { - $checked = $data['checked']; - - if ($checked == FALSE) - { - unset($data['checked']); - } - else - { - $data['checked'] = 'checked'; - } - } - - if ($checked == TRUE) - { - $defaults['checked'] = 'checked'; - } - else - { - unset($defaults['checked']); - } - - return '\n"; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('form_radio')) -{ - /** - * Radio Button - * - * @param mixed - * @param string - * @param bool - * @param mixed - * @return string - */ - function form_radio($data = '', $value = '', $checked = FALSE, $extra = '') - { - is_array($data) OR $data = array('name' => $data); - $data['type'] = 'radio'; - - return form_checkbox($data, $value, $checked, $extra); - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('form_submit')) -{ - /** - * Submit Button - * - * @param mixed - * @param string - * @param mixed - * @return string - */ - function form_submit($data = '', $value = '', $extra = '') - { - $defaults = array( - 'type' => 'submit', - 'name' => is_array($data) ? '' : $data, - 'value' => $value - ); - - return '\n"; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('form_reset')) -{ - /** - * Reset Button - * - * @param mixed - * @param string - * @param mixed - * @return string - */ - function form_reset($data = '', $value = '', $extra = '') - { - $defaults = array( - 'type' => 'reset', - 'name' => is_array($data) ? '' : $data, - 'value' => $value - ); - - return '\n"; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('form_button')) -{ - /** - * Form Button - * - * @param mixed - * @param string - * @param mixed - * @return string - */ - function form_button($data = '', $content = '', $extra = '') - { - $defaults = array( - 'name' => is_array($data) ? '' : $data, - 'type' => 'button' - ); - - if (is_array($data) && isset($data['content'])) - { - $content = $data['content']; - unset($data['content']); // content is not an attribute - } - - return '\n"; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('form_label')) -{ - /** - * Form Label Tag - * - * @param string The text to appear onscreen - * @param string The id the label applies to - * @param mixed Additional attributes - * @return string - */ - function form_label($label_text = '', $id = '', $attributes = array()) - { - - $label = ''.$label_text.''; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('form_fieldset')) -{ - /** - * Fieldset Tag - * - * Used to produce
text. To close fieldset - * use form_fieldset_close() - * - * @param string The legend text - * @param array Additional attributes - * @return string - */ - function form_fieldset($legend_text = '', $attributes = array()) - { - $fieldset = '\n"; - if ($legend_text !== '') - { - return $fieldset.''.$legend_text."\n"; - } - - return $fieldset; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('form_fieldset_close')) -{ - /** - * Fieldset Close Tag - * - * @param string - * @return string - */ - function form_fieldset_close($extra = '') - { - return '
'.$extra; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('form_close')) -{ - /** - * Form Close Tag - * - * @param string - * @return string - */ - function form_close($extra = '') - { - return ''.$extra; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('form_prep')) -{ - /** - * Form Prep - * - * Formats text so that it can be safely placed in a form field in the event it has HTML tags. - * - * @deprecated 3.0.0 An alias for html_escape() - * @param string|string[] $str Value to escape - * @return string|string[] Escaped values - */ - function form_prep($str) - { - return html_escape($str, TRUE); - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('set_value')) -{ - /** - * Form Value - * - * Grabs a value from the POST array for the specified field so you can - * re-populate an input field or textarea. If Form Validation - * is active it retrieves the info from the validation class - * - * @param string $field Field name - * @param string $default Default value - * @param bool $html_escape Whether to escape HTML special characters or not - * @return string - */ - function set_value($field, $default = '', $html_escape = TRUE) - { - $CI =& get_instance(); - - $value = (isset($CI->form_validation) && is_object($CI->form_validation) && $CI->form_validation->has_rule($field)) - ? $CI->form_validation->set_value($field, $default) - : $CI->input->post($field, FALSE); - - isset($value) OR $value = $default; - return ($html_escape) ? html_escape($value) : $value; - } -} - -// ------------------------------------------------------------------------ - -if ( ! function_exists('set_select')) -{ - /** - * Set Select - * - * Let's you set the selected value of a