[
  {
    "path": ".gitignore",
    "content": "sftp-config.json\napplication/logs/*.log\napplication/business/*.json\nvendor/\nweapp-sdk/\ncomposer.lock"
  },
  {
    "path": ".htaccess",
    "content": "RewriteEngine on\nRewriteCond $1 !^(index\\.php)\nRewriteCond %{REQUEST_FILENAME} !-f\nRewriteCond %{REQUEST_FILENAME} !-d\nRewriteRule ^(.*)$ index.php/$1 [L,QSA]"
  },
  {
    "path": "LICENSE",
    "content": "LICENSE - \"MIT License\"\n\nCopyright (c) 2016 by Tencent Cloud\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE."
  },
  {
    "path": "README.md",
    "content": "# Wafer 服务端 Demo - PHP\n\n本仓库是 [Wafer](https://github.com/tencentyun/wafer) 组成部分，提供 PHP 版本业务服务器示例。示例需要和[微信小程序客户端示例](https://github.com/tencentyun/weapp-client-demo)配合一起使用。\n\n## 运行示例\n\n选择合适的方式[部署 Wafer](https://github.com/tencentyun/wafer/wiki#%E9%83%A8%E7%BD%B2%E6%96%B9%E5%BC%8F)，并按照[小程序创建资源配置指引](https://github.com/tencentyun/weapp-doc)进行操作，可以得到运行本示例所需的资源和服务。请参考以下配置。\n\n- SDK 配置文件：`/etc/qcloud/sdk.config`\n- 示例代码部署目录：`/data/release/php-weapp-demo`\n- 运行示例的 nginx 配置文件: `/etc/nginx/conf.d/php-weapp-demo.conf`\n- PHP 版本：`v5.6.27`\n- composer 版本：`v1.2.1`\n- nginx 版本：`v1.10.1`\n\n## 项目结构\n\n```\nDemo\n├── application\n│   ├── business\n│   │   └── ChatTunnelHandler.php\n│   ├── cache\n│   ├── config\n│   ├── controllers\n│   │   ├── Welcome.php\n│   │   ├── Login.php\n│   │   ├── User.php\n│   │   └── Tunnel.php\n│   ├── core\n│   ├── helpers\n│   │   └── general_helper.php\n│   ├── hooks\n│   ├── language\n│   ├── libraries\n│   ├── logs\n│   ├── models\n│   ├── third_party\n│   ├── vendor\n│   └── views\n│       └── welcome_message.php\n├── index.php\n├── install_qcloud_sdk.php\n├── composer.json\n└── system\n```\n\n示例使用 `CodeIgniter(v3.1)` 框架制作。其中，`index.php` 是 启动文件，`install_qcloud_sdk.php` 用于初始化 SDK 配置，配置从文件 `/etc/qcloud/sdk.config` 中读取。配置文件包含如下配置项：\n\n```json\n{\n    \"serverHost\": \"业务服务器的主机名\",\n    \"authServerUrl\": \"鉴权服务器地址\",\n    \"tunnelServerUrl\": \"信道服务器地址\",\n    \"tunnelSignatureKey\": \"和信道服务器通信的签名密钥\",\n    \"networkTimeout\": 30000\n}\n```\n其中 `networkTimeout` 为超时时间，单位是**毫秒**。\n\n`composer.json` 文件中声明了对 SDK 的依赖，可执行命令 `composer install` 安装依赖。\n\n`application/controllers/` 目录包含了示例用到的4个路由，路由和处理文件映射关系如下：\n\n```\n// 首页指引\n/ => application/controllers/Welcome.php\n\n// 登录\n/login => application/controllers/Login.php\n\n// 获取微信用户信息\n/user => application/controllers/User.php\n\n// 处理信道请求\n/tunnel => application/controllers/Tunnel.php\n```\n\n`application/business/ChatTunnelHandler.php` 是业务处理信道请求的示例代码。\n\n`application/helpers/general_helper.php` 包含简单的 `debug` 方法用于打印日志。\n\n\n## 更新 SDK 版本\n进入目录 `/data/release/php-weapp-demo`，然后执行命令 `composer update` 即可。\n\n\n## 如果在demo基础上开发\n将自己开发的接口放到如下目录下即可生效\n/data/release/php-weapp-demo/application/controllers/\n\n## 重启服务：\n        service php-fpm restart\n        \n"
  },
  {
    "path": "application/.htaccess",
    "content": "<IfModule authz_core_module>\n    Require all denied\n</IfModule>\n<IfModule !authz_core_module>\n    Deny from all\n</IfModule>"
  },
  {
    "path": "application/business/ChatTunnelHandler.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\nuse \\QCloud_WeApp_SDK\\Tunnel\\ITunnelHandler as ITunnelHandler;\nuse \\QCloud_WeApp_SDK\\Tunnel\\TunnelService as TunnelService;\n\n/**\n * 实现 WebSocket 信道处理器\n * 本示例配合客户端 Demo 实现一个简单的聊天室功能\n */\nclass ChatTunnelHandler implements ITunnelHandler {\n    /**\n     * 实现 onRequest 方法\n     * 在客户端请求 WebSocket 信道连接之后，\n     * 会调用 onRequest 方法，此时可以把信道 ID 和用户信息关联起来\n     */\n    public function onRequest($tunnelId, $userInfo) {\n        if (is_array($userInfo)) {\n            $data = self::loadData();\n\n            // 保存 信道ID => 用户信息 的映射\n            $data['userMap'][$tunnelId] = $userInfo;\n\n            self::saveData($data);\n        }\n    }\n\n    /**\n     * 实现 onConnect 方法\n     * 在客户端成功连接 WebSocket 信道服务之后会调用该方法，\n     * 此时通知所有其它在线的用户当前总人数以及刚加入的用户是谁\n     */\n    public function onConnect($tunnelId) {\n        $data = self::loadData();\n\n        if (array_key_exists($tunnelId, $data['userMap'])) {\n            $data['connectedTunnelIds'][] = $tunnelId;\n            self::saveData($data);\n\n            self::broadcast('people', array(\n                'total' => count($data['connectedTunnelIds']),\n                'enter' => $data['userMap'][$tunnelId],\n            ));\n\n        } else {\n            debug(\"Unknown tunnelId({$tunnelId}) was connectd, close it\");\n            self::closeTunnel($tunnelId);\n        }\n    }\n\n    /**\n     * 实现 onMessage 方法\n     * 客户端推送消息到 WebSocket 信道服务器上后，会调用该方法，此时可以处理信道的消息。\n     * 在本示例，我们处理 `speak` 类型的消息，该消息表示有用户发言。\n     * 我们把这个发言的信息广播到所有在线的 WebSocket 信道上\n     */\n    public function onMessage($tunnelId, $type, $content) {\n        switch ($type) {\n        case 'speak':\n            $data = self::loadData();\n\n            if (isset($data['userMap'][$tunnelId])) {\n                self::broadcast('speak', array(\n                    'who' => $data['userMap'][$tunnelId],\n                    'word' => $content['word'],\n                ));\n            } else {\n                self::closeTunnel($tunnelId);\n            }\n            break;\n        }\n    }\n\n    /**\n     * 实现 onClose 方法\n     * 客户端关闭 WebSocket 信道或者被信道服务器判断为已断开后，\n     * 会调用该方法，此时可以进行清理及通知操作\n     */\n    public function onClose($tunnelId) {\n        $data = self::loadData();\n\n        if (!array_key_exists($tunnelId, $data['userMap'])) {\n            debug('[onClose] 无效的信道 ID =>', $tunnelId);\n            self::closeTunnel($tunnelId);\n            return;\n        }\n\n        $leaveUser = $data['userMap'][$tunnelId];\n        unset($data['userMap'][$tunnelId]);\n\n        $index = array_search($tunnelId, $data['connectedTunnelIds']);\n        if ($index !== FALSE) {\n            array_splice($data['connectedTunnelIds'], $index, 1);\n        }\n\n        self::saveData($data);\n\n        // 聊天室没有人了（即无信道ID）不再需要广播消息\n        if (count($data['connectedTunnelIds']) > 0) {\n            self::broadcast('people', array(\n                'total' => count($data['connectedTunnelIds']),\n                'leave' => $leaveUser,\n            ));\n        }\n    }\n\n    /**\n     * 调用 TunnelService::broadcast() 进行广播\n     */\n    private static function broadcast($type, $content) {\n        $data = self::loadData();\n        $result = TunnelService::broadcast($data['connectedTunnelIds'], $type, $content);\n\n        if ($result['code'] === 0 && !empty($result['data']['invalidTunnelIds'])) {\n            $invalidTunnelIds = $result['data']['invalidTunnelIds'];\n            debug('检测到无效的信道 IDs =>', $invalidTunnelIds);\n\n            // 从`userMap`和`connectedTunnelIds`将无效的信道记录移除\n            foreach ($invalidTunnelIds as $tunnelId) {\n                unset($data['userMap'][$tunnelId]);\n\n                $index = array_search($tunnelId, $data['connectedTunnelIds']);\n                if ($index !== FALSE) {\n                    array_splice($data['connectedTunnelIds'], $index, 1);\n                }\n            }\n\n            self::saveData($data);\n        }\n    }\n\n    /**\n     * 调用 TunnelService::closeTunnel() 关闭信道\n     * @param  String $tunnelId 信道ID\n     */\n    private static function closeTunnel($tunnelId) {\n        TunnelService::closeTunnel($tunnelId);\n    }\n\n    /**\n     * 加载 WebSocket 信道对应的用户 => userMap\n     * 加载 当前已连接的 WebSocket 信道列表 => connectedTunnelIds\n     * 在实际的业务中，应该使用数据库进行存储跟踪，这里作为示例只是演示其作用\n     */\n    private static function loadData() {\n        $filepath = self::getDataFilePath();\n        $defaultData = array('userMap' => array(), 'connectedTunnelIds' => array());\n\n        if (!file_exists($filepath)) {\n            return $defaultData;\n        }\n\n        $content = file_get_contents($filepath);\n        $data = json_decode($content, TRUE);\n\n        return (is_array($data) ? $data : $defaultData);\n    }\n\n    /**\n     * 保存 WebSocket 信道对应的用户 => userMap\n     * 保存 当前已连接的 WebSocket 信道ID列表 => connectedTunnelIds\n     * 在实际的业务中，应该使用数据库进行存储跟踪，这里作为示例只是演示其作用\n     */\n    private static function saveData($data) {\n        $filepath = self::getDataFilePath();\n\n        if (version_compare(PHP_VERSION, '5.4.0') >= 0) {\n            $content = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);\n        } else {\n            $content = json_encode($data);\n        }\n\n        file_put_contents($filepath, $content, LOCK_EX);\n    }\n\n    /**\n     * 聊天室存取 JSON 数据对应的文件路径\n     */\n    private static function getDataFilePath() {\n        return (dirname(__FILE__) . DIRECTORY_SEPARATOR . 'chat_data.json');\n    }\n}\n"
  },
  {
    "path": "application/cache/.htaccess",
    "content": "<IfModule authz_core_module>\n    Require all denied\n</IfModule>\n<IfModule !authz_core_module>\n    Deny from all\n</IfModule>"
  },
  {
    "path": "application/cache/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "application/config/autoload.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/*\n| -------------------------------------------------------------------\n| AUTO-LOADER\n| -------------------------------------------------------------------\n| This file specifies which systems should be loaded by default.\n|\n| In order to keep the framework as light-weight as possible only the\n| absolute minimal resources are loaded by default. For example,\n| the database is not connected to automatically since no assumption\n| is made regarding whether you intend to use it.  This file lets\n| you globally define which systems you would like loaded with every\n| request.\n|\n| -------------------------------------------------------------------\n| Instructions\n| -------------------------------------------------------------------\n|\n| These are the things you can load automatically:\n|\n| 1. Packages\n| 2. Libraries\n| 3. Drivers\n| 4. Helper files\n| 5. Custom config files\n| 6. Language files\n| 7. Models\n|\n*/\n\n/*\n| -------------------------------------------------------------------\n|  Auto-load Packages\n| -------------------------------------------------------------------\n| Prototype:\n|\n|  $autoload['packages'] = array(APPPATH.'third_party', '/usr/local/shared');\n|\n*/\n$autoload['packages'] = array();\n\n/*\n| -------------------------------------------------------------------\n|  Auto-load Libraries\n| -------------------------------------------------------------------\n| These are the classes located in system/libraries/ or your\n| application/libraries/ directory, with the addition of the\n| 'database' library, which is somewhat of a special case.\n|\n| Prototype:\n|\n|\t$autoload['libraries'] = array('database', 'email', 'session');\n|\n| You can also supply an alternative library name to be assigned\n| in the controller:\n|\n|\t$autoload['libraries'] = array('user_agent' => 'ua');\n*/\n$autoload['libraries'] = array();\n\n/*\n| -------------------------------------------------------------------\n|  Auto-load Drivers\n| -------------------------------------------------------------------\n| These classes are located in system/libraries/ or in your\n| application/libraries/ directory, but are also placed inside their\n| own subdirectory and they extend the CI_Driver_Library class. They\n| offer multiple interchangeable driver options.\n|\n| Prototype:\n|\n|\t$autoload['drivers'] = array('cache');\n|\n| You can also supply an alternative property name to be assigned in\n| the controller:\n|\n|\t$autoload['drivers'] = array('cache' => 'cch');\n|\n*/\n$autoload['drivers'] = array();\n\n/*\n| -------------------------------------------------------------------\n|  Auto-load Helper Files\n| -------------------------------------------------------------------\n| Prototype:\n|\n|\t$autoload['helper'] = array('url', 'file');\n*/\n$autoload['helper'] = array('general');\n\n/*\n| -------------------------------------------------------------------\n|  Auto-load Config files\n| -------------------------------------------------------------------\n| Prototype:\n|\n|\t$autoload['config'] = array('config1', 'config2');\n|\n| NOTE: This item is intended for use ONLY if you have created custom\n| config files.  Otherwise, leave it blank.\n|\n*/\n$autoload['config'] = array();\n\n/*\n| -------------------------------------------------------------------\n|  Auto-load Language files\n| -------------------------------------------------------------------\n| Prototype:\n|\n|\t$autoload['language'] = array('lang1', 'lang2');\n|\n| NOTE: Do not include the \"_lang\" part of your file.  For example\n| \"codeigniter_lang.php\" would be referenced as array('codeigniter');\n|\n*/\n$autoload['language'] = array();\n\n/*\n| -------------------------------------------------------------------\n|  Auto-load Models\n| -------------------------------------------------------------------\n| Prototype:\n|\n|\t$autoload['model'] = array('first_model', 'second_model');\n|\n| You can also supply an alternative model name to be assigned\n| in the controller:\n|\n|\t$autoload['model'] = array('first_model' => 'first');\n*/\n$autoload['model'] = array();\n"
  },
  {
    "path": "application/config/config.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/*\n|--------------------------------------------------------------------------\n| Base Site URL\n|--------------------------------------------------------------------------\n|\n| URL to your CodeIgniter root. Typically this will be your base URL,\n| WITH a trailing slash:\n|\n|\thttp://example.com/\n|\n| WARNING: You MUST set this value!\n|\n| If it is not set, then CodeIgniter will try guess the protocol and path\n| your installation, but due to security concerns the hostname will be set\n| to $_SERVER['SERVER_ADDR'] if available, or localhost otherwise.\n| The auto-detection mechanism exists only for convenience during\n| development and MUST NOT be used in production!\n|\n| If you need to allow multiple domains, remember that this file is still\n| a PHP script and you can easily do that on your own.\n|\n*/\n$config['base_url'] = '';\n\n/*\n|--------------------------------------------------------------------------\n| Index File\n|--------------------------------------------------------------------------\n|\n| Typically this will be your index.php file, unless you've renamed it to\n| something else. If you are using mod_rewrite to remove the page set this\n| variable so that it is blank.\n|\n*/\n$config['index_page'] = 'index.php';\n\n/*\n|--------------------------------------------------------------------------\n| URI PROTOCOL\n|--------------------------------------------------------------------------\n|\n| This item determines which server global should be used to retrieve the\n| URI string.  The default setting of 'REQUEST_URI' works for most servers.\n| If your links do not seem to work, try one of the other delicious flavors:\n|\n| 'REQUEST_URI'    Uses $_SERVER['REQUEST_URI']\n| 'QUERY_STRING'   Uses $_SERVER['QUERY_STRING']\n| 'PATH_INFO'      Uses $_SERVER['PATH_INFO']\n|\n| WARNING: If you set this to 'PATH_INFO', URIs will always be URL-decoded!\n*/\n$config['uri_protocol']\t= 'REQUEST_URI';\n\n/*\n|--------------------------------------------------------------------------\n| URL suffix\n|--------------------------------------------------------------------------\n|\n| This option allows you to add a suffix to all URLs generated by CodeIgniter.\n| For more information please see the user guide:\n|\n| https://codeigniter.com/user_guide/general/urls.html\n*/\n$config['url_suffix'] = '';\n\n/*\n|--------------------------------------------------------------------------\n| Default Language\n|--------------------------------------------------------------------------\n|\n| This determines which set of language files should be used. Make sure\n| there is an available translation if you intend to use something other\n| than english.\n|\n*/\n$config['language']\t= 'english';\n\n/*\n|--------------------------------------------------------------------------\n| Default Character Set\n|--------------------------------------------------------------------------\n|\n| This determines which character set is used by default in various methods\n| that require a character set to be provided.\n|\n| See http://php.net/htmlspecialchars for a list of supported charsets.\n|\n*/\n$config['charset'] = 'UTF-8';\n\n/*\n|--------------------------------------------------------------------------\n| Enable/Disable System Hooks\n|--------------------------------------------------------------------------\n|\n| If you would like to use the 'hooks' feature you must enable it by\n| setting this variable to TRUE (boolean).  See the user guide for details.\n|\n*/\n$config['enable_hooks'] = FALSE;\n\n/*\n|--------------------------------------------------------------------------\n| Class Extension Prefix\n|--------------------------------------------------------------------------\n|\n| This item allows you to set the filename/classname prefix when extending\n| native libraries.  For more information please see the user guide:\n|\n| https://codeigniter.com/user_guide/general/core_classes.html\n| https://codeigniter.com/user_guide/general/creating_libraries.html\n|\n*/\n$config['subclass_prefix'] = 'MY_';\n\n/*\n|--------------------------------------------------------------------------\n| Composer auto-loading\n|--------------------------------------------------------------------------\n|\n| Enabling this setting will tell CodeIgniter to look for a Composer\n| package auto-loader script in application/vendor/autoload.php.\n|\n|\t$config['composer_autoload'] = TRUE;\n|\n| Or if you have your vendor/ directory located somewhere else, you\n| can opt to set a specific path as well:\n|\n|\t$config['composer_autoload'] = '/path/to/vendor/autoload.php';\n|\n| For more information about Composer, please visit http://getcomposer.org/\n|\n| Note: This will NOT disable or override the CodeIgniter-specific\n|\tautoloading (application/config/autoload.php)\n*/\n$config['composer_autoload'] = FALSE;\n\n/*\n|--------------------------------------------------------------------------\n| Allowed URL Characters\n|--------------------------------------------------------------------------\n|\n| This lets you specify which characters are permitted within your URLs.\n| When someone tries to submit a URL with disallowed characters they will\n| get a warning message.\n|\n| As a security measure you are STRONGLY encouraged to restrict URLs to\n| as few characters as possible.  By default only these are allowed: a-z 0-9~%.:_-\n|\n| Leave blank to allow all characters -- but only if you are insane.\n|\n| The configured value is actually a regular expression character group\n| and it will be executed as: ! preg_match('/^[<permitted_uri_chars>]+$/i\n|\n| DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!!\n|\n*/\n$config['permitted_uri_chars'] = 'a-z 0-9~%.:_\\-';\n\n/*\n|--------------------------------------------------------------------------\n| Enable Query Strings\n|--------------------------------------------------------------------------\n|\n| By default CodeIgniter uses search-engine friendly segment based URLs:\n| example.com/who/what/where/\n|\n| By default CodeIgniter enables access to the $_GET array.  If for some\n| reason you would like to disable it, set 'allow_get_array' to FALSE.\n|\n| You can optionally enable standard query string based URLs:\n| example.com?who=me&what=something&where=here\n|\n| Options are: TRUE or FALSE (boolean)\n|\n| The other items let you set the query string 'words' that will\n| invoke your controllers and its functions:\n| example.com/index.php?c=controller&m=function\n|\n| Please note that some of the helpers won't work as expected when\n| this feature is enabled, since CodeIgniter is designed primarily to\n| use segment based URLs.\n|\n*/\n$config['allow_get_array'] = TRUE;\n$config['enable_query_strings'] = FALSE;\n$config['controller_trigger'] = 'c';\n$config['function_trigger'] = 'm';\n$config['directory_trigger'] = 'd';\n\n/*\n|--------------------------------------------------------------------------\n| Error Logging Threshold\n|--------------------------------------------------------------------------\n|\n| You can enable error logging by setting a threshold over zero. The\n| threshold determines what gets logged. Threshold options are:\n|\n|\t0 = Disables logging, Error logging TURNED OFF\n|\t1 = Error Messages (including PHP errors)\n|\t2 = Debug Messages\n|\t3 = Informational Messages\n|\t4 = All Messages\n|\n| You can also pass an array with threshold levels to show individual error types\n|\n| \tarray(2) = Debug Messages, without Error Messages\n|\n| For a live site you'll usually only enable Errors (1) to be logged otherwise\n| your log files will fill up very fast.\n|\n*/\n$config['log_threshold'] = array(1, 2);\n\n/*\n|--------------------------------------------------------------------------\n| Error Logging Directory Path\n|--------------------------------------------------------------------------\n|\n| Leave this BLANK unless you would like to set something other than the default\n| application/logs/ directory. Use a full server path with trailing slash.\n|\n*/\n$config['log_path'] = '';\n\n/*\n|--------------------------------------------------------------------------\n| Log File Extension\n|--------------------------------------------------------------------------\n|\n| The default filename extension for log files. The default 'php' allows for\n| protecting the log files via basic scripting, when they are to be stored\n| under a publicly accessible directory.\n|\n| Note: Leaving it blank will default to 'php'.\n|\n*/\n$config['log_file_extension'] = 'log';\n\n/*\n|--------------------------------------------------------------------------\n| Log File Permissions\n|--------------------------------------------------------------------------\n|\n| The file system permissions to be applied on newly created log files.\n|\n| IMPORTANT: This MUST be an integer (no quotes) and you MUST use octal\n|            integer notation (i.e. 0700, 0644, etc.)\n*/\n$config['log_file_permissions'] = 0644;\n\n/*\n|--------------------------------------------------------------------------\n| Date Format for Logs\n|--------------------------------------------------------------------------\n|\n| Each item that is logged has an associated date. You can use PHP date\n| codes to set your own date formatting\n|\n*/\n$config['log_date_format'] = 'Y-m-d H:i:s';\n\n/*\n|--------------------------------------------------------------------------\n| Error Views Directory Path\n|--------------------------------------------------------------------------\n|\n| Leave this BLANK unless you would like to set something other than the default\n| application/views/errors/ directory.  Use a full server path with trailing slash.\n|\n*/\n$config['error_views_path'] = '';\n\n/*\n|--------------------------------------------------------------------------\n| Cache Directory Path\n|--------------------------------------------------------------------------\n|\n| Leave this BLANK unless you would like to set something other than the default\n| application/cache/ directory.  Use a full server path with trailing slash.\n|\n*/\n$config['cache_path'] = '';\n\n/*\n|--------------------------------------------------------------------------\n| Cache Include Query String\n|--------------------------------------------------------------------------\n|\n| Whether to take the URL query string into consideration when generating\n| output cache files. Valid options are:\n|\n|\tFALSE      = Disabled\n|\tTRUE       = Enabled, take all query parameters into account.\n|\t             Please be aware that this may result in numerous cache\n|\t             files generated for the same page over and over again.\n|\tarray('q') = Enabled, but only take into account the specified list\n|\t             of query parameters.\n|\n*/\n$config['cache_query_string'] = FALSE;\n\n/*\n|--------------------------------------------------------------------------\n| Encryption Key\n|--------------------------------------------------------------------------\n|\n| If you use the Encryption class, you must set an encryption key.\n| See the user guide for more info.\n|\n| https://codeigniter.com/user_guide/libraries/encryption.html\n|\n*/\n$config['encryption_key'] = '';\n\n/*\n|--------------------------------------------------------------------------\n| Session Variables\n|--------------------------------------------------------------------------\n|\n| 'sess_driver'\n|\n|\tThe storage driver to use: files, database, redis, memcached\n|\n| 'sess_cookie_name'\n|\n|\tThe session cookie name, must contain only [0-9a-z_-] characters\n|\n| 'sess_expiration'\n|\n|\tThe number of SECONDS you want the session to last.\n|\tSetting to 0 (zero) means expire when the browser is closed.\n|\n| 'sess_save_path'\n|\n|\tThe location to save sessions to, driver dependent.\n|\n|\tFor the 'files' driver, it's a path to a writable directory.\n|\tWARNING: Only absolute paths are supported!\n|\n|\tFor the 'database' driver, it's a table name.\n|\tPlease read up the manual for the format with other session drivers.\n|\n|\tIMPORTANT: You are REQUIRED to set a valid save path!\n|\n| 'sess_match_ip'\n|\n|\tWhether to match the user's IP address when reading the session data.\n|\n|\tWARNING: If you're using the database driver, don't forget to update\n|\t         your session table's PRIMARY KEY when changing this setting.\n|\n| 'sess_time_to_update'\n|\n|\tHow many seconds between CI regenerating the session ID.\n|\n| 'sess_regenerate_destroy'\n|\n|\tWhether to destroy session data associated with the old session ID\n|\twhen auto-regenerating the session ID. When set to FALSE, the data\n|\twill be later deleted by the garbage collector.\n|\n| Other session cookie settings are shared with the rest of the application,\n| except for 'cookie_prefix' and 'cookie_httponly', which are ignored here.\n|\n*/\n$config['sess_driver'] = 'files';\n$config['sess_cookie_name'] = 'ci_session';\n$config['sess_expiration'] = 7200;\n$config['sess_save_path'] = NULL;\n$config['sess_match_ip'] = FALSE;\n$config['sess_time_to_update'] = 300;\n$config['sess_regenerate_destroy'] = FALSE;\n\n/*\n|--------------------------------------------------------------------------\n| Cookie Related Variables\n|--------------------------------------------------------------------------\n|\n| 'cookie_prefix'   = Set a cookie name prefix if you need to avoid collisions\n| 'cookie_domain'   = Set to .your-domain.com for site-wide cookies\n| 'cookie_path'     = Typically will be a forward slash\n| 'cookie_secure'   = Cookie will only be set if a secure HTTPS connection exists.\n| 'cookie_httponly' = Cookie will only be accessible via HTTP(S) (no javascript)\n|\n| Note: These settings (with the exception of 'cookie_prefix' and\n|       'cookie_httponly') will also affect sessions.\n|\n*/\n$config['cookie_prefix']\t= '';\n$config['cookie_domain']\t= '';\n$config['cookie_path']\t\t= '/';\n$config['cookie_secure']\t= FALSE;\n$config['cookie_httponly'] \t= FALSE;\n\n/*\n|--------------------------------------------------------------------------\n| Standardize newlines\n|--------------------------------------------------------------------------\n|\n| Determines whether to standardize newline characters in input data,\n| meaning to replace \\r\\n, \\r, \\n occurrences with the PHP_EOL value.\n|\n| This is particularly useful for portability between UNIX-based OSes,\n| (usually \\n) and Windows (\\r\\n).\n|\n*/\n$config['standardize_newlines'] = FALSE;\n\n/*\n|--------------------------------------------------------------------------\n| Global XSS Filtering\n|--------------------------------------------------------------------------\n|\n| Determines whether the XSS filter is always active when GET, POST or\n| COOKIE data is encountered\n|\n| WARNING: This feature is DEPRECATED and currently available only\n|          for backwards compatibility purposes!\n|\n*/\n$config['global_xss_filtering'] = FALSE;\n\n/*\n|--------------------------------------------------------------------------\n| Cross Site Request Forgery\n|--------------------------------------------------------------------------\n| Enables a CSRF cookie token to be set. When set to TRUE, token will be\n| checked on a submitted form. If you are accepting user data, it is strongly\n| recommended CSRF protection be enabled.\n|\n| 'csrf_token_name' = The token name\n| 'csrf_cookie_name' = The cookie name\n| 'csrf_expire' = The number in seconds the token should expire.\n| 'csrf_regenerate' = Regenerate token on every submission\n| 'csrf_exclude_uris' = Array of URIs which ignore CSRF checks\n*/\n$config['csrf_protection'] = FALSE;\n$config['csrf_token_name'] = 'csrf_test_name';\n$config['csrf_cookie_name'] = 'csrf_cookie_name';\n$config['csrf_expire'] = 7200;\n$config['csrf_regenerate'] = TRUE;\n$config['csrf_exclude_uris'] = array();\n\n/*\n|--------------------------------------------------------------------------\n| Output Compression\n|--------------------------------------------------------------------------\n|\n| Enables Gzip output compression for faster page loads.  When enabled,\n| the output class will test whether your server supports Gzip.\n| Even if it does, however, not all browsers support compression\n| so enable only if you are reasonably sure your visitors can handle it.\n|\n| Only used if zlib.output_compression is turned off in your php.ini.\n| Please do not use it together with httpd-level output compression.\n|\n| VERY IMPORTANT:  If you are getting a blank page when compression is enabled it\n| means you are prematurely outputting something to your browser. It could\n| even be a line of whitespace at the end of one of your scripts.  For\n| compression to work, nothing can be sent before the output buffer is called\n| by the output class.  Do not 'echo' any values with compression enabled.\n|\n*/\n$config['compress_output'] = FALSE;\n\n/*\n|--------------------------------------------------------------------------\n| Master Time Reference\n|--------------------------------------------------------------------------\n|\n| Options are 'local' or any PHP supported timezone. This preference tells\n| the system whether to use your server's local time as the master 'now'\n| reference, or convert it to the configured one timezone. See the 'date\n| helper' page of the user guide for information regarding date handling.\n|\n*/\n$config['time_reference'] = 'local';\n\n/*\n|--------------------------------------------------------------------------\n| Rewrite PHP Short Tags\n|--------------------------------------------------------------------------\n|\n| If your PHP installation does not have short tag support enabled CI\n| can rewrite the tags on-the-fly, enabling you to utilize that syntax\n| in your view files.  Options are TRUE or FALSE (boolean)\n|\n| Note: You need to have eval() enabled for this to work.\n|\n*/\n$config['rewrite_short_tags'] = FALSE;\n\n/*\n|--------------------------------------------------------------------------\n| Reverse Proxy IPs\n|--------------------------------------------------------------------------\n|\n| If your server is behind a reverse proxy, you must whitelist the proxy\n| IP addresses from which CodeIgniter should trust headers such as\n| HTTP_X_FORWARDED_FOR and HTTP_CLIENT_IP in order to properly identify\n| the visitor's IP address.\n|\n| You can use both an array or a comma-separated list of proxy addresses,\n| as well as specifying whole subnets. Here are a few examples:\n|\n| Comma-separated:\t'10.0.1.200,192.168.5.0/24'\n| Array:\t\tarray('10.0.1.200', '192.168.5.0/24')\n*/\n$config['proxy_ips'] = '';\n"
  },
  {
    "path": "application/config/constants.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/*\n|--------------------------------------------------------------------------\n| Display Debug backtrace\n|--------------------------------------------------------------------------\n|\n| If set to TRUE, a backtrace will be displayed along with php errors. If\n| error_reporting is disabled, the backtrace will not display, regardless\n| of this setting\n|\n*/\ndefined('SHOW_DEBUG_BACKTRACE') OR define('SHOW_DEBUG_BACKTRACE', TRUE);\n\n/*\n|--------------------------------------------------------------------------\n| File and Directory Modes\n|--------------------------------------------------------------------------\n|\n| These prefs are used when checking and setting modes when working\n| with the file system.  The defaults are fine on servers with proper\n| security, but you may wish (or even need) to change the values in\n| certain environments (Apache running a separate process for each\n| user, PHP under CGI with Apache suEXEC, etc.).  Octal values should\n| always be used to set the mode correctly.\n|\n*/\ndefined('FILE_READ_MODE')  OR define('FILE_READ_MODE', 0644);\ndefined('FILE_WRITE_MODE') OR define('FILE_WRITE_MODE', 0666);\ndefined('DIR_READ_MODE')   OR define('DIR_READ_MODE', 0755);\ndefined('DIR_WRITE_MODE')  OR define('DIR_WRITE_MODE', 0755);\n\n/*\n|--------------------------------------------------------------------------\n| File Stream Modes\n|--------------------------------------------------------------------------\n|\n| These modes are used when working with fopen()/popen()\n|\n*/\ndefined('FOPEN_READ')                           OR define('FOPEN_READ', 'rb');\ndefined('FOPEN_READ_WRITE')                     OR define('FOPEN_READ_WRITE', 'r+b');\ndefined('FOPEN_WRITE_CREATE_DESTRUCTIVE')       OR define('FOPEN_WRITE_CREATE_DESTRUCTIVE', 'wb'); // truncates existing file data, use with care\ndefined('FOPEN_READ_WRITE_CREATE_DESTRUCTIVE')  OR define('FOPEN_READ_WRITE_CREATE_DESTRUCTIVE', 'w+b'); // truncates existing file data, use with care\ndefined('FOPEN_WRITE_CREATE')                   OR define('FOPEN_WRITE_CREATE', 'ab');\ndefined('FOPEN_READ_WRITE_CREATE')              OR define('FOPEN_READ_WRITE_CREATE', 'a+b');\ndefined('FOPEN_WRITE_CREATE_STRICT')            OR define('FOPEN_WRITE_CREATE_STRICT', 'xb');\ndefined('FOPEN_READ_WRITE_CREATE_STRICT')       OR define('FOPEN_READ_WRITE_CREATE_STRICT', 'x+b');\n\n/*\n|--------------------------------------------------------------------------\n| Exit Status Codes\n|--------------------------------------------------------------------------\n|\n| Used to indicate the conditions under which the script is exit()ing.\n| While there is no universal standard for error codes, there are some\n| broad conventions.  Three such conventions are mentioned below, for\n| those who wish to make use of them.  The CodeIgniter defaults were\n| chosen for the least overlap with these conventions, while still\n| leaving room for others to be defined in future versions and user\n| applications.\n|\n| The three main conventions used for determining exit status codes\n| are as follows:\n|\n|    Standard C/C++ Library (stdlibc):\n|       http://www.gnu.org/software/libc/manual/html_node/Exit-Status.html\n|       (This link also contains other GNU-specific conventions)\n|    BSD sysexits.h:\n|       http://www.gsp.com/cgi-bin/man.cgi?section=3&topic=sysexits\n|    Bash scripting:\n|       http://tldp.org/LDP/abs/html/exitcodes.html\n|\n*/\ndefined('EXIT_SUCCESS')        OR define('EXIT_SUCCESS', 0); // no errors\ndefined('EXIT_ERROR')          OR define('EXIT_ERROR', 1); // generic error\ndefined('EXIT_CONFIG')         OR define('EXIT_CONFIG', 3); // configuration error\ndefined('EXIT_UNKNOWN_FILE')   OR define('EXIT_UNKNOWN_FILE', 4); // file not found\ndefined('EXIT_UNKNOWN_CLASS')  OR define('EXIT_UNKNOWN_CLASS', 5); // unknown class\ndefined('EXIT_UNKNOWN_METHOD') OR define('EXIT_UNKNOWN_METHOD', 6); // unknown class member\ndefined('EXIT_USER_INPUT')     OR define('EXIT_USER_INPUT', 7); // invalid user input\ndefined('EXIT_DATABASE')       OR define('EXIT_DATABASE', 8); // database error\ndefined('EXIT__AUTO_MIN')      OR define('EXIT__AUTO_MIN', 9); // lowest automatically-assigned error code\ndefined('EXIT__AUTO_MAX')      OR define('EXIT__AUTO_MAX', 125); // highest automatically-assigned error code\n"
  },
  {
    "path": "application/config/database.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/*\n| -------------------------------------------------------------------\n| DATABASE CONNECTIVITY SETTINGS\n| -------------------------------------------------------------------\n| This file will contain the settings needed to access your database.\n|\n| For complete instructions please consult the 'Database Connection'\n| page of the User Guide.\n|\n| -------------------------------------------------------------------\n| EXPLANATION OF VARIABLES\n| -------------------------------------------------------------------\n|\n|\t['dsn']      The full DSN string describe a connection to the database.\n|\t['hostname'] The hostname of your database server.\n|\t['username'] The username used to connect to the database\n|\t['password'] The password used to connect to the database\n|\t['database'] The name of the database you want to connect to\n|\t['dbdriver'] The database driver. e.g.: mysqli.\n|\t\t\tCurrently supported:\n|\t\t\t\t cubrid, ibase, mssql, mysql, mysqli, oci8,\n|\t\t\t\t odbc, pdo, postgre, sqlite, sqlite3, sqlsrv\n|\t['dbprefix'] You can add an optional prefix, which will be added\n|\t\t\t\t to the table name when using the  Query Builder class\n|\t['pconnect'] TRUE/FALSE - Whether to use a persistent connection\n|\t['db_debug'] TRUE/FALSE - Whether database errors should be displayed.\n|\t['cache_on'] TRUE/FALSE - Enables/disables query caching\n|\t['cachedir'] The path to the folder where cache files should be stored\n|\t['char_set'] The character set used in communicating with the database\n|\t['dbcollat'] The character collation used in communicating with the database\n|\t\t\t\t NOTE: For MySQL and MySQLi databases, this setting is only used\n| \t\t\t\t as a backup if your server is running PHP < 5.2.3 or MySQL < 5.0.7\n|\t\t\t\t (and in table creation queries made with DB Forge).\n| \t\t\t\t There is an incompatibility in PHP with mysql_real_escape_string() which\n| \t\t\t\t can make your site vulnerable to SQL injection if you are using a\n| \t\t\t\t multi-byte character set and are running versions lower than these.\n| \t\t\t\t Sites using Latin-1 or UTF-8 database character set and collation are unaffected.\n|\t['swap_pre'] A default table prefix that should be swapped with the dbprefix\n|\t['encrypt']  Whether or not to use an encrypted connection.\n|\n|\t\t\t'mysql' (deprecated), 'sqlsrv' and 'pdo/sqlsrv' drivers accept TRUE/FALSE\n|\t\t\t'mysqli' and 'pdo/mysql' drivers accept an array with the following options:\n|\n|\t\t\t\t'ssl_key'    - Path to the private key file\n|\t\t\t\t'ssl_cert'   - Path to the public key certificate file\n|\t\t\t\t'ssl_ca'     - Path to the certificate authority file\n|\t\t\t\t'ssl_capath' - Path to a directory containing trusted CA certificats in PEM format\n|\t\t\t\t'ssl_cipher' - List of *allowed* ciphers to be used for the encryption, separated by colons (':')\n|\t\t\t\t'ssl_verify' - TRUE/FALSE; Whether verify the server certificate or not ('mysqli' only)\n|\n|\t['compress'] Whether or not to use client compression (MySQL only)\n|\t['stricton'] TRUE/FALSE - forces 'Strict Mode' connections\n|\t\t\t\t\t\t\t- good for ensuring strict SQL while developing\n|\t['ssl_options']\tUsed to set various SSL options that can be used when making SSL connections.\n|\t['failover'] array - A array with 0 or more data for connections if the main should fail.\n|\t['save_queries'] TRUE/FALSE - Whether to \"save\" all executed queries.\n| \t\t\t\tNOTE: Disabling this will also effectively disable both\n| \t\t\t\t$this->db->last_query() and profiling of DB queries.\n| \t\t\t\tWhen you run a query, with this setting set to TRUE (default),\n| \t\t\t\tCodeIgniter will store the SQL statement for debugging purposes.\n| \t\t\t\tHowever, this may cause high memory usage, especially if you run\n| \t\t\t\ta lot of SQL queries ... disable this to avoid that problem.\n|\n| The $active_group variable lets you choose which connection group to\n| make active.  By default there is only one group (the 'default' group).\n|\n| The $query_builder variables lets you determine whether or not to load\n| the query builder class.\n*/\n$active_group = 'default';\n$query_builder = TRUE;\n\n$db['default'] = array(\n\t'dsn'\t=> '',\n\t'hostname' => 'localhost',\n\t'username' => '',\n\t'password' => '',\n\t'database' => '',\n\t'dbdriver' => 'mysqli',\n\t'dbprefix' => '',\n\t'pconnect' => FALSE,\n\t'db_debug' => (ENVIRONMENT !== 'production'),\n\t'cache_on' => FALSE,\n\t'cachedir' => '',\n\t'char_set' => 'utf8',\n\t'dbcollat' => 'utf8_general_ci',\n\t'swap_pre' => '',\n\t'encrypt' => FALSE,\n\t'compress' => FALSE,\n\t'stricton' => FALSE,\n\t'failover' => array(),\n\t'save_queries' => TRUE\n);\n"
  },
  {
    "path": "application/config/doctypes.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n$_doctypes = array(\n\t'xhtml11' => '<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">',\n\t'xhtml1-strict' => '<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">',\n\t'xhtml1-trans' => '<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">',\n\t'xhtml1-frame' => '<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Frameset//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd\">',\n\t'xhtml-basic11' => '<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML Basic 1.1//EN\" \"http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd\">',\n\t'html5' => '<!DOCTYPE html>',\n\t'html4-strict' => '<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">',\n\t'html4-trans' => '<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">',\n\t'html4-frame' => '<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\" \"http://www.w3.org/TR/html4/frameset.dtd\">',\n\t'mathml1' => '<!DOCTYPE math SYSTEM \"http://www.w3.org/Math/DTD/mathml1/mathml.dtd\">',\n\t'mathml2' => '<!DOCTYPE math PUBLIC \"-//W3C//DTD MathML 2.0//EN\" \"http://www.w3.org/Math/DTD/mathml2/mathml2.dtd\">',\n\t'svg10' => '<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">',\n\t'svg11' => '<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">',\n\t'svg11-basic' => '<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1 Basic//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-basic.dtd\">',\n\t'svg11-tiny' => '<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1 Tiny//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd\">',\n\t'xhtml-math-svg-xh' => '<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN\" \"http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd\">',\n\t'xhtml-math-svg-sh' => '<!DOCTYPE svg:svg PUBLIC \"-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN\" \"http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd\">',\n\t'xhtml-rdfa-1' => '<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML+RDFa 1.0//EN\" \"http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd\">',\n\t'xhtml-rdfa-2' => '<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML+RDFa 1.1//EN\" \"http://www.w3.org/MarkUp/DTD/xhtml-rdfa-2.dtd\">'\n);\n"
  },
  {
    "path": "application/config/foreign_chars.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/*\n| -------------------------------------------------------------------\n| Foreign Characters\n| -------------------------------------------------------------------\n| This file contains an array of foreign characters for transliteration\n| conversion used by the Text helper\n|\n*/\n$foreign_characters = array(\n\t'/ä|æ|ǽ/' => 'ae',\n\t'/ö|œ/' => 'oe',\n\t'/ü/' => 'ue',\n\t'/Ä/' => 'Ae',\n\t'/Ü/' => 'Ue',\n\t'/Ö/' => 'Oe',\n\t'/À|Á|Â|Ã|Ä|Å|Ǻ|Ā|Ă|Ą|Ǎ|Α|Ά|Ả|Ạ|Ầ|Ẫ|Ẩ|Ậ|Ằ|Ắ|Ẵ|Ẳ|Ặ|А/' => 'A',\n\t'/à|á|â|ã|å|ǻ|ā|ă|ą|ǎ|ª|α|ά|ả|ạ|ầ|ấ|ẫ|ẩ|ậ|ằ|ắ|ẵ|ẳ|ặ|а/' => 'a',\n\t'/Б/' => 'B',\n\t'/б/' => 'b',\n\t'/Ç|Ć|Ĉ|Ċ|Č/' => 'C',\n\t'/ç|ć|ĉ|ċ|č/' => 'c',\n\t'/Д/' => 'D',\n\t'/д/' => 'd',\n\t'/Ð|Ď|Đ|Δ/' => 'Dj',\n\t'/ð|ď|đ|δ/' => 'dj',\n\t'/È|É|Ê|Ë|Ē|Ĕ|Ė|Ę|Ě|Ε|Έ|Ẽ|Ẻ|Ẹ|Ề|Ế|Ễ|Ể|Ệ|Е|Э/' => 'E',\n\t'/è|é|ê|ë|ē|ĕ|ė|ę|ě|έ|ε|ẽ|ẻ|ẹ|ề|ế|ễ|ể|ệ|е|э/' => 'e',\n\t'/Ф/' => 'F',\n\t'/ф/' => 'f',\n\t'/Ĝ|Ğ|Ġ|Ģ|Γ|Г|Ґ/' => 'G',\n\t'/ĝ|ğ|ġ|ģ|γ|г|ґ/' => 'g',\n\t'/Ĥ|Ħ/' => 'H',\n\t'/ĥ|ħ/' => 'h',\n\t'/Ì|Í|Î|Ï|Ĩ|Ī|Ĭ|Ǐ|Į|İ|Η|Ή|Ί|Ι|Ϊ|Ỉ|Ị|И|Ы/' => 'I',\n\t'/ì|í|î|ï|ĩ|ī|ĭ|ǐ|į|ı|η|ή|ί|ι|ϊ|ỉ|ị|и|ы|ї/' => 'i',\n\t'/Ĵ/' => 'J',\n\t'/ĵ/' => 'j',\n\t'/Ķ|Κ|К/' => 'K',\n\t'/ķ|κ|к/' => 'k',\n\t'/Ĺ|Ļ|Ľ|Ŀ|Ł|Λ|Л/' => 'L',\n\t'/ĺ|ļ|ľ|ŀ|ł|λ|л/' => 'l',\n\t'/М/' => 'M',\n\t'/м/' => 'm',\n\t'/Ñ|Ń|Ņ|Ň|Ν|Н/' => 'N',\n\t'/ñ|ń|ņ|ň|ŉ|ν|н/' => 'n',\n\t'/Ò|Ó|Ô|Õ|Ō|Ŏ|Ǒ|Ő|Ơ|Ø|Ǿ|Ο|Ό|Ω|Ώ|Ỏ|Ọ|Ồ|Ố|Ỗ|Ổ|Ộ|Ờ|Ớ|Ỡ|Ở|Ợ|О/' => 'O',\n\t'/ò|ó|ô|õ|ō|ŏ|ǒ|ő|ơ|ø|ǿ|º|ο|ό|ω|ώ|ỏ|ọ|ồ|ố|ỗ|ổ|ộ|ờ|ớ|ỡ|ở|ợ|о/' => 'o',\n\t'/П/' => 'P',\n\t'/п/' => 'p',\n\t'/Ŕ|Ŗ|Ř|Ρ|Р/' => 'R',\n\t'/ŕ|ŗ|ř|ρ|р/' => 'r',\n\t'/Ś|Ŝ|Ş|Ș|Š|Σ|С/' => 'S',\n\t'/ś|ŝ|ş|ș|š|ſ|σ|ς|с/' => 's',\n\t'/Ț|Ţ|Ť|Ŧ|τ|Т/' => 'T',\n\t'/ț|ţ|ť|ŧ|т/' => 't',\n\t'/Þ|þ/' => 'th',\n\t'/Ù|Ú|Û|Ũ|Ū|Ŭ|Ů|Ű|Ų|Ư|Ǔ|Ǖ|Ǘ|Ǚ|Ǜ|Ũ|Ủ|Ụ|Ừ|Ứ|Ữ|Ử|Ự|У/' => 'U',\n\t'/ù|ú|û|ũ|ū|ŭ|ů|ű|ų|ư|ǔ|ǖ|ǘ|ǚ|ǜ|υ|ύ|ϋ|ủ|ụ|ừ|ứ|ữ|ử|ự|у/' => 'u',\n\t'/Ý|Ÿ|Ŷ|Υ|Ύ|Ϋ|Ỳ|Ỹ|Ỷ|Ỵ|Й/' => 'Y',\n\t'/ý|ÿ|ŷ|ỳ|ỹ|ỷ|ỵ|й/' => 'y',\n\t'/В/' => 'V',\n\t'/в/' => 'v',\n\t'/Ŵ/' => 'W',\n\t'/ŵ/' => 'w',\n\t'/Ź|Ż|Ž|Ζ|З/' => 'Z',\n\t'/ź|ż|ž|ζ|з/' => 'z',\n\t'/Æ|Ǽ/' => 'AE',\n\t'/ß/' => 'ss',\n\t'/Ĳ/' => 'IJ',\n\t'/ĳ/' => 'ij',\n\t'/Œ/' => 'OE',\n\t'/ƒ/' => 'f',\n\t'/ξ/' => 'ks',\n\t'/π/' => 'p',\n\t'/β/' => 'v',\n\t'/μ/' => 'm',\n\t'/ψ/' => 'ps',\n\t'/Ё/' => 'Yo',\n\t'/ё/' => 'yo',\n\t'/Є/' => 'Ye',\n\t'/є/' => 'ye',\n\t'/Ї/' => 'Yi',\n\t'/Ж/' => 'Zh',\n\t'/ж/' => 'zh',\n\t'/Х/' => 'Kh',\n\t'/х/' => 'kh',\n\t'/Ц/' => 'Ts',\n\t'/ц/' => 'ts',\n\t'/Ч/' => 'Ch',\n\t'/ч/' => 'ch',\n\t'/Ш/' => 'Sh',\n\t'/ш/' => 'sh',\n\t'/Щ/' => 'Shch',\n\t'/щ/' => 'shch',\n\t'/Ъ|ъ|Ь|ь/' => '',\n\t'/Ю/' => 'Yu',\n\t'/ю/' => 'yu',\n\t'/Я/' => 'Ya',\n\t'/я/' => 'ya'\n);\n"
  },
  {
    "path": "application/config/hooks.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/*\n| -------------------------------------------------------------------------\n| Hooks\n| -------------------------------------------------------------------------\n| This file lets you define \"hooks\" to extend CI without hacking the core\n| files.  Please see the user guide for info:\n|\n|\thttps://codeigniter.com/user_guide/general/hooks.html\n|\n*/\n"
  },
  {
    "path": "application/config/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "application/config/memcached.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/*\n| -------------------------------------------------------------------------\n| Memcached settings\n| -------------------------------------------------------------------------\n| Your Memcached servers can be specified below.\n|\n|\tSee: https://codeigniter.com/user_guide/libraries/caching.html#memcached\n|\n*/\n$config = array(\n\t'default' => array(\n\t\t'hostname' => '127.0.0.1',\n\t\t'port'     => '11211',\n\t\t'weight'   => '1',\n\t),\n);\n"
  },
  {
    "path": "application/config/migration.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/*\n|--------------------------------------------------------------------------\n| Enable/Disable Migrations\n|--------------------------------------------------------------------------\n|\n| Migrations are disabled by default for security reasons.\n| You should enable migrations whenever you intend to do a schema migration\n| and disable it back when you're done.\n|\n*/\n$config['migration_enabled'] = FALSE;\n\n/*\n|--------------------------------------------------------------------------\n| Migration Type\n|--------------------------------------------------------------------------\n|\n| Migration file names may be based on a sequential identifier or on\n| a timestamp. Options are:\n|\n|   'sequential' = Sequential migration naming (001_add_blog.php)\n|   'timestamp'  = Timestamp migration naming (20121031104401_add_blog.php)\n|                  Use timestamp format YYYYMMDDHHIISS.\n|\n| Note: If this configuration value is missing the Migration library\n|       defaults to 'sequential' for backward compatibility with CI2.\n|\n*/\n$config['migration_type'] = 'timestamp';\n\n/*\n|--------------------------------------------------------------------------\n| Migrations table\n|--------------------------------------------------------------------------\n|\n| This is the name of the table that will store the current migrations state.\n| When migrations runs it will store in a database table which migration\n| level the system is at. It then compares the migration level in this\n| table to the $config['migration_version'] if they are not the same it\n| will migrate up. This must be set.\n|\n*/\n$config['migration_table'] = 'migrations';\n\n/*\n|--------------------------------------------------------------------------\n| Auto Migrate To Latest\n|--------------------------------------------------------------------------\n|\n| If this is set to TRUE when you load the migrations class and have\n| $config['migration_enabled'] set to TRUE the system will auto migrate\n| to your latest migration (whatever $config['migration_version'] is\n| set to). This way you do not have to call migrations anywhere else\n| in your code to have the latest migration.\n|\n*/\n$config['migration_auto_latest'] = FALSE;\n\n/*\n|--------------------------------------------------------------------------\n| Migrations version\n|--------------------------------------------------------------------------\n|\n| This is used to set migration version that the file system should be on.\n| If you run $this->migration->current() this is the version that schema will\n| be upgraded / downgraded to.\n|\n*/\n$config['migration_version'] = 0;\n\n/*\n|--------------------------------------------------------------------------\n| Migrations Path\n|--------------------------------------------------------------------------\n|\n| Path to your migrations folder.\n| Typically, it will be within your application path.\n| Also, writing permission is required within the migrations path.\n|\n*/\n$config['migration_path'] = APPPATH.'migrations/';\n"
  },
  {
    "path": "application/config/mimes.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/*\n| -------------------------------------------------------------------\n| MIME TYPES\n| -------------------------------------------------------------------\n| This file contains an array of mime types.  It is used by the\n| Upload class to help identify allowed file types.\n|\n*/\nreturn array(\n\t'hqx'\t=>\tarray('application/mac-binhex40', 'application/mac-binhex', 'application/x-binhex40', 'application/x-mac-binhex40'),\n\t'cpt'\t=>\t'application/mac-compactpro',\n\t'csv'\t=>\tarray('text/x-comma-separated-values', 'text/comma-separated-values', 'application/octet-stream', 'application/vnd.ms-excel', 'application/x-csv', 'text/x-csv', 'text/csv', 'application/csv', 'application/excel', 'application/vnd.msexcel', 'text/plain'),\n\t'bin'\t=>\tarray('application/macbinary', 'application/mac-binary', 'application/octet-stream', 'application/x-binary', 'application/x-macbinary'),\n\t'dms'\t=>\t'application/octet-stream',\n\t'lha'\t=>\t'application/octet-stream',\n\t'lzh'\t=>\t'application/octet-stream',\n\t'exe'\t=>\tarray('application/octet-stream', 'application/x-msdownload'),\n\t'class'\t=>\t'application/octet-stream',\n\t'psd'\t=>\tarray('application/x-photoshop', 'image/vnd.adobe.photoshop'),\n\t'so'\t=>\t'application/octet-stream',\n\t'sea'\t=>\t'application/octet-stream',\n\t'dll'\t=>\t'application/octet-stream',\n\t'oda'\t=>\t'application/oda',\n\t'pdf'\t=>\tarray('application/pdf', 'application/force-download', 'application/x-download', 'binary/octet-stream'),\n\t'ai'\t=>\tarray('application/pdf', 'application/postscript'),\n\t'eps'\t=>\t'application/postscript',\n\t'ps'\t=>\t'application/postscript',\n\t'smi'\t=>\t'application/smil',\n\t'smil'\t=>\t'application/smil',\n\t'mif'\t=>\t'application/vnd.mif',\n\t'xls'\t=>\tarray('application/vnd.ms-excel', 'application/msexcel', 'application/x-msexcel', 'application/x-ms-excel', 'application/x-excel', 'application/x-dos_ms_excel', 'application/xls', 'application/x-xls', 'application/excel', 'application/download', 'application/vnd.ms-office', 'application/msword'),\n\t'ppt'\t=>\tarray('application/powerpoint', 'application/vnd.ms-powerpoint', 'application/vnd.ms-office', 'application/msword'),\n\t'pptx'\t=> \tarray('application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/x-zip', 'application/zip'),\n\t'wbxml'\t=>\t'application/wbxml',\n\t'wmlc'\t=>\t'application/wmlc',\n\t'dcr'\t=>\t'application/x-director',\n\t'dir'\t=>\t'application/x-director',\n\t'dxr'\t=>\t'application/x-director',\n\t'dvi'\t=>\t'application/x-dvi',\n\t'gtar'\t=>\t'application/x-gtar',\n\t'gz'\t=>\t'application/x-gzip',\n\t'gzip'  =>\t'application/x-gzip',\n\t'php'\t=>\tarray('application/x-httpd-php', 'application/php', 'application/x-php', 'text/php', 'text/x-php', 'application/x-httpd-php-source'),\n\t'php4'\t=>\t'application/x-httpd-php',\n\t'php3'\t=>\t'application/x-httpd-php',\n\t'phtml'\t=>\t'application/x-httpd-php',\n\t'phps'\t=>\t'application/x-httpd-php-source',\n\t'js'\t=>\tarray('application/x-javascript', 'text/plain'),\n\t'swf'\t=>\t'application/x-shockwave-flash',\n\t'sit'\t=>\t'application/x-stuffit',\n\t'tar'\t=>\t'application/x-tar',\n\t'tgz'\t=>\tarray('application/x-tar', 'application/x-gzip-compressed'),\n\t'z'\t=>\t'application/x-compress',\n\t'xhtml'\t=>\t'application/xhtml+xml',\n\t'xht'\t=>\t'application/xhtml+xml',\n\t'zip'\t=>\tarray('application/x-zip', 'application/zip', 'application/x-zip-compressed', 'application/s-compressed', 'multipart/x-zip'),\n\t'rar'\t=>\tarray('application/x-rar', 'application/rar', 'application/x-rar-compressed'),\n\t'mid'\t=>\t'audio/midi',\n\t'midi'\t=>\t'audio/midi',\n\t'mpga'\t=>\t'audio/mpeg',\n\t'mp2'\t=>\t'audio/mpeg',\n\t'mp3'\t=>\tarray('audio/mpeg', 'audio/mpg', 'audio/mpeg3', 'audio/mp3'),\n\t'aif'\t=>\tarray('audio/x-aiff', 'audio/aiff'),\n\t'aiff'\t=>\tarray('audio/x-aiff', 'audio/aiff'),\n\t'aifc'\t=>\t'audio/x-aiff',\n\t'ram'\t=>\t'audio/x-pn-realaudio',\n\t'rm'\t=>\t'audio/x-pn-realaudio',\n\t'rpm'\t=>\t'audio/x-pn-realaudio-plugin',\n\t'ra'\t=>\t'audio/x-realaudio',\n\t'rv'\t=>\t'video/vnd.rn-realvideo',\n\t'wav'\t=>\tarray('audio/x-wav', 'audio/wave', 'audio/wav'),\n\t'bmp'\t=>\tarray('image/bmp', 'image/x-bmp', 'image/x-bitmap', 'image/x-xbitmap', 'image/x-win-bitmap', 'image/x-windows-bmp', 'image/ms-bmp', 'image/x-ms-bmp', 'application/bmp', 'application/x-bmp', 'application/x-win-bitmap'),\n\t'gif'\t=>\t'image/gif',\n\t'jpeg'\t=>\tarray('image/jpeg', 'image/pjpeg'),\n\t'jpg'\t=>\tarray('image/jpeg', 'image/pjpeg'),\n\t'jpe'\t=>\tarray('image/jpeg', 'image/pjpeg'),\n\t'jp2'\t=>\tarray('image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'),\n\t'j2k'\t=>\tarray('image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'),\n\t'jpf'\t=>\tarray('image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'),\n\t'jpg2'\t=>\tarray('image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'),\n\t'jpx'\t=>\tarray('image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'),\n\t'jpm'\t=>\tarray('image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'),\n\t'mj2'\t=>\tarray('image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'),\n\t'mjp2'\t=>\tarray('image/jp2', 'video/mj2', 'image/jpx', 'image/jpm'),\n\t'png'\t=>\tarray('image/png',  'image/x-png'),\n\t'tiff'\t=>\t'image/tiff',\n\t'tif'\t=>\t'image/tiff',\n\t'css'\t=>\tarray('text/css', 'text/plain'),\n\t'html'\t=>\tarray('text/html', 'text/plain'),\n\t'htm'\t=>\tarray('text/html', 'text/plain'),\n\t'shtml'\t=>\tarray('text/html', 'text/plain'),\n\t'txt'\t=>\t'text/plain',\n\t'text'\t=>\t'text/plain',\n\t'log'\t=>\tarray('text/plain', 'text/x-log'),\n\t'rtx'\t=>\t'text/richtext',\n\t'rtf'\t=>\t'text/rtf',\n\t'xml'\t=>\tarray('application/xml', 'text/xml', 'text/plain'),\n\t'xsl'\t=>\tarray('application/xml', 'text/xsl', 'text/xml'),\n\t'mpeg'\t=>\t'video/mpeg',\n\t'mpg'\t=>\t'video/mpeg',\n\t'mpe'\t=>\t'video/mpeg',\n\t'qt'\t=>\t'video/quicktime',\n\t'mov'\t=>\t'video/quicktime',\n\t'avi'\t=>\tarray('video/x-msvideo', 'video/msvideo', 'video/avi', 'application/x-troff-msvideo'),\n\t'movie'\t=>\t'video/x-sgi-movie',\n\t'doc'\t=>\tarray('application/msword', 'application/vnd.ms-office'),\n\t'docx'\t=>\tarray('application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/zip', 'application/msword', 'application/x-zip'),\n\t'dot'\t=>\tarray('application/msword', 'application/vnd.ms-office'),\n\t'dotx'\t=>\tarray('application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/zip', 'application/msword'),\n\t'xlsx'\t=>\tarray('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/zip', 'application/vnd.ms-excel', 'application/msword', 'application/x-zip'),\n\t'word'\t=>\tarray('application/msword', 'application/octet-stream'),\n\t'xl'\t=>\t'application/excel',\n\t'eml'\t=>\t'message/rfc822',\n\t'json'  =>\tarray('application/json', 'text/json'),\n\t'pem'   =>\tarray('application/x-x509-user-cert', 'application/x-pem-file', 'application/octet-stream'),\n\t'p10'   =>\tarray('application/x-pkcs10', 'application/pkcs10'),\n\t'p12'   =>\t'application/x-pkcs12',\n\t'p7a'   =>\t'application/x-pkcs7-signature',\n\t'p7c'   =>\tarray('application/pkcs7-mime', 'application/x-pkcs7-mime'),\n\t'p7m'   =>\tarray('application/pkcs7-mime', 'application/x-pkcs7-mime'),\n\t'p7r'   =>\t'application/x-pkcs7-certreqresp',\n\t'p7s'   =>\t'application/pkcs7-signature',\n\t'crt'   =>\tarray('application/x-x509-ca-cert', 'application/x-x509-user-cert', 'application/pkix-cert'),\n\t'crl'   =>\tarray('application/pkix-crl', 'application/pkcs-crl'),\n\t'der'   =>\t'application/x-x509-ca-cert',\n\t'kdb'   =>\t'application/octet-stream',\n\t'pgp'   =>\t'application/pgp',\n\t'gpg'   =>\t'application/gpg-keys',\n\t'sst'   =>\t'application/octet-stream',\n\t'csr'   =>\t'application/octet-stream',\n\t'rsa'   =>\t'application/x-pkcs7',\n\t'cer'   =>\tarray('application/pkix-cert', 'application/x-x509-ca-cert'),\n\t'3g2'   =>\t'video/3gpp2',\n\t'3gp'   =>\tarray('video/3gp', 'video/3gpp'),\n\t'mp4'   =>\t'video/mp4',\n\t'm4a'   =>\t'audio/x-m4a',\n\t'f4v'   =>\tarray('video/mp4', 'video/x-f4v'),\n\t'flv'\t=>\t'video/x-flv',\n\t'webm'\t=>\t'video/webm',\n\t'aac'   =>\t'audio/x-acc',\n\t'm4u'   =>\t'application/vnd.mpegurl',\n\t'm3u'   =>\t'text/plain',\n\t'xspf'  =>\t'application/xspf+xml',\n\t'vlc'   =>\t'application/videolan',\n\t'wmv'   =>\tarray('video/x-ms-wmv', 'video/x-ms-asf'),\n\t'au'    =>\t'audio/x-au',\n\t'ac3'   =>\t'audio/ac3',\n\t'flac'  =>\t'audio/x-flac',\n\t'ogg'   =>\tarray('audio/ogg', 'video/ogg', 'application/ogg'),\n\t'kmz'\t=>\tarray('application/vnd.google-earth.kmz', 'application/zip', 'application/x-zip'),\n\t'kml'\t=>\tarray('application/vnd.google-earth.kml+xml', 'application/xml', 'text/xml'),\n\t'ics'\t=>\t'text/calendar',\n\t'ical'\t=>\t'text/calendar',\n\t'zsh'\t=>\t'text/x-scriptzsh',\n\t'7zip'\t=>\tarray('application/x-compressed', 'application/x-zip-compressed', 'application/zip', 'multipart/x-zip'),\n\t'cdr'\t=>\tarray('application/cdr', 'application/coreldraw', 'application/x-cdr', 'application/x-coreldraw', 'image/cdr', 'image/x-cdr', 'zz-application/zz-winassoc-cdr'),\n\t'wma'\t=>\tarray('audio/x-ms-wma', 'video/x-ms-asf'),\n\t'jar'\t=>\tarray('application/java-archive', 'application/x-java-application', 'application/x-jar', 'application/x-compressed'),\n\t'svg'\t=>\tarray('image/svg+xml', 'application/xml', 'text/xml'),\n\t'vcf'\t=>\t'text/x-vcard',\n\t'srt'\t=>\tarray('text/srt', 'text/plain'),\n\t'vtt'\t=>\tarray('text/vtt', 'text/plain'),\n\t'ico'\t=>\tarray('image/x-icon', 'image/x-ico', 'image/vnd.microsoft.icon')\n);\n"
  },
  {
    "path": "application/config/profiler.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/*\n| -------------------------------------------------------------------------\n| Profiler Sections\n| -------------------------------------------------------------------------\n| This file lets you determine whether or not various sections of Profiler\n| data are displayed when the Profiler is enabled.\n| Please see the user guide for info:\n|\n|\thttps://codeigniter.com/user_guide/general/profiling.html\n|\n*/\n"
  },
  {
    "path": "application/config/routes.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/*\n| -------------------------------------------------------------------------\n| URI ROUTING\n| -------------------------------------------------------------------------\n| This file lets you re-map URI requests to specific controller functions.\n|\n| Typically there is a one-to-one relationship between a URL string\n| and its corresponding controller class/method. The segments in a\n| URL normally follow this pattern:\n|\n|\texample.com/class/method/id/\n|\n| In some instances, however, you may want to remap this relationship\n| so that a different class/function is called than the one\n| corresponding to the URL.\n|\n| Please see the user guide for complete details:\n|\n|\thttps://codeigniter.com/user_guide/general/routing.html\n|\n| -------------------------------------------------------------------------\n| RESERVED ROUTES\n| -------------------------------------------------------------------------\n|\n| There are three reserved routes:\n|\n|\t$route['default_controller'] = 'welcome';\n|\n| This route indicates which controller class should be loaded if the\n| URI contains no data. In the above example, the \"welcome\" class\n| would be loaded.\n|\n|\t$route['404_override'] = 'errors/page_missing';\n|\n| This route will tell the Router which controller/method to use if those\n| provided in the URL cannot be matched to a valid route.\n|\n|\t$route['translate_uri_dashes'] = FALSE;\n|\n| This is not exactly a route, but allows you to automatically route\n| controller and method names that contain dashes. '-' isn't a valid\n| class or method name character, so it requires translation.\n| When you set this option to TRUE, it will replace ALL dashes in the\n| controller and method URI segments.\n|\n| Examples:\tmy-controller/index\t-> my_controller/index\n|\t\tmy-controller/my-method\t-> my_controller/my_method\n*/\n$route['default_controller'] = 'welcome';\n$route['404_override'] = '';\n$route['translate_uri_dashes'] = FALSE;\n"
  },
  {
    "path": "application/config/smileys.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/*\n| -------------------------------------------------------------------\n| SMILEYS\n| -------------------------------------------------------------------\n| This file contains an array of smileys for use with the emoticon helper.\n| Individual images can be used to replace multiple smileys.  For example:\n| :-) and :) use the same image replacement.\n|\n| Please see user guide for more info:\n| https://codeigniter.com/user_guide/helpers/smiley_helper.html\n|\n*/\n$smileys = array(\n\n//\tsmiley\t\t\timage name\t\t\t\t\t\twidth\theight\talt\n\n\t':-)'\t\t\t=>\tarray('grin.gif',\t\t\t'19',\t'19',\t'grin'),\n\t':lol:'\t\t\t=>\tarray('lol.gif',\t\t\t'19',\t'19',\t'LOL'),\n\t':cheese:'\t\t=>\tarray('cheese.gif',\t\t\t'19',\t'19',\t'cheese'),\n\t':)'\t\t\t=>\tarray('smile.gif',\t\t\t'19',\t'19',\t'smile'),\n\t';-)'\t\t\t=>\tarray('wink.gif',\t\t\t'19',\t'19',\t'wink'),\n\t';)'\t\t\t=>\tarray('wink.gif',\t\t\t'19',\t'19',\t'wink'),\n\t':smirk:'\t\t=>\tarray('smirk.gif',\t\t\t'19',\t'19',\t'smirk'),\n\t':roll:'\t\t=>\tarray('rolleyes.gif',\t\t'19',\t'19',\t'rolleyes'),\n\t':-S'\t\t\t=>\tarray('confused.gif',\t\t'19',\t'19',\t'confused'),\n\t':wow:'\t\t\t=>\tarray('surprise.gif',\t\t'19',\t'19',\t'surprised'),\n\t':bug:'\t\t\t=>\tarray('bigsurprise.gif',\t'19',\t'19',\t'big surprise'),\n\t':-P'\t\t\t=>\tarray('tongue_laugh.gif',\t'19',\t'19',\t'tongue laugh'),\n\t'%-P'\t\t\t=>\tarray('tongue_rolleye.gif',\t'19',\t'19',\t'tongue rolleye'),\n\t';-P'\t\t\t=>\tarray('tongue_wink.gif',\t'19',\t'19',\t'tongue wink'),\n\t':P'\t\t\t=>\tarray('raspberry.gif',\t\t'19',\t'19',\t'raspberry'),\n\t':blank:'\t\t=>\tarray('blank.gif',\t\t\t'19',\t'19',\t'blank stare'),\n\t':long:'\t\t=>\tarray('longface.gif',\t\t'19',\t'19',\t'long face'),\n\t':ohh:'\t\t\t=>\tarray('ohh.gif',\t\t\t'19',\t'19',\t'ohh'),\n\t':grrr:'\t\t=>\tarray('grrr.gif',\t\t\t'19',\t'19',\t'grrr'),\n\t':gulp:'\t\t=>\tarray('gulp.gif',\t\t\t'19',\t'19',\t'gulp'),\n\t'8-/'\t\t\t=>\tarray('ohoh.gif',\t\t\t'19',\t'19',\t'oh oh'),\n\t':down:'\t\t=>\tarray('downer.gif',\t\t\t'19',\t'19',\t'downer'),\n\t':red:'\t\t\t=>\tarray('embarrassed.gif',\t'19',\t'19',\t'red face'),\n\t':sick:'\t\t=>\tarray('sick.gif',\t\t\t'19',\t'19',\t'sick'),\n\t':shut:'\t\t=>\tarray('shuteye.gif',\t\t'19',\t'19',\t'shut eye'),\n\t':-/'\t\t\t=>\tarray('hmm.gif',\t\t\t'19',\t'19',\t'hmmm'),\n\t'>:('\t\t\t=>\tarray('mad.gif',\t\t\t'19',\t'19',\t'mad'),\n\t':mad:'\t\t\t=>\tarray('mad.gif',\t\t\t'19',\t'19',\t'mad'),\n\t'>:-('\t\t\t=>\tarray('angry.gif',\t\t\t'19',\t'19',\t'angry'),\n\t':angry:'\t\t=>\tarray('angry.gif',\t\t\t'19',\t'19',\t'angry'),\n\t':zip:'\t\t\t=>\tarray('zip.gif',\t\t\t'19',\t'19',\t'zipper'),\n\t':kiss:'\t\t=>\tarray('kiss.gif',\t\t\t'19',\t'19',\t'kiss'),\n\t':ahhh:'\t\t=>\tarray('shock.gif',\t\t\t'19',\t'19',\t'shock'),\n\t':coolsmile:'\t=>\tarray('shade_smile.gif',\t'19',\t'19',\t'cool smile'),\n\t':coolsmirk:'\t=>\tarray('shade_smirk.gif',\t'19',\t'19',\t'cool smirk'),\n\t':coolgrin:'\t=>\tarray('shade_grin.gif',\t\t'19',\t'19',\t'cool grin'),\n\t':coolhmm:'\t\t=>\tarray('shade_hmm.gif',\t\t'19',\t'19',\t'cool hmm'),\n\t':coolmad:'\t\t=>\tarray('shade_mad.gif',\t\t'19',\t'19',\t'cool mad'),\n\t':coolcheese:'\t=>\tarray('shade_cheese.gif',\t'19',\t'19',\t'cool cheese'),\n\t':vampire:'\t\t=>\tarray('vampire.gif',\t\t'19',\t'19',\t'vampire'),\n\t':snake:'\t\t=>\tarray('snake.gif',\t\t\t'19',\t'19',\t'snake'),\n\t':exclaim:'\t\t=>\tarray('exclaim.gif',\t\t'19',\t'19',\t'exclaim'),\n\t':question:'\t=>\tarray('question.gif',\t\t'19',\t'19',\t'question')\n\n);\n"
  },
  {
    "path": "application/config/user_agents.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/*\n| -------------------------------------------------------------------\n| USER AGENT TYPES\n| -------------------------------------------------------------------\n| This file contains four arrays of user agent data. It is used by the\n| User Agent Class to help identify browser, platform, robot, and\n| mobile device data. The array keys are used to identify the device\n| and the array values are used to set the actual name of the item.\n*/\n$platforms = array(\n\t'windows nt 10.0'\t=> 'Windows 10',\n\t'windows nt 6.3'\t=> 'Windows 8.1',\n\t'windows nt 6.2'\t=> 'Windows 8',\n\t'windows nt 6.1'\t=> 'Windows 7',\n\t'windows nt 6.0'\t=> 'Windows Vista',\n\t'windows nt 5.2'\t=> 'Windows 2003',\n\t'windows nt 5.1'\t=> 'Windows XP',\n\t'windows nt 5.0'\t=> 'Windows 2000',\n\t'windows nt 4.0'\t=> 'Windows NT 4.0',\n\t'winnt4.0'\t\t\t=> 'Windows NT 4.0',\n\t'winnt 4.0'\t\t\t=> 'Windows NT',\n\t'winnt'\t\t\t\t=> 'Windows NT',\n\t'windows 98'\t\t=> 'Windows 98',\n\t'win98'\t\t\t\t=> 'Windows 98',\n\t'windows 95'\t\t=> 'Windows 95',\n\t'win95'\t\t\t\t=> 'Windows 95',\n\t'windows phone'\t\t\t=> 'Windows Phone',\n\t'windows'\t\t\t=> 'Unknown Windows OS',\n\t'android'\t\t\t=> 'Android',\n\t'blackberry'\t\t=> 'BlackBerry',\n\t'iphone'\t\t\t=> 'iOS',\n\t'ipad'\t\t\t\t=> 'iOS',\n\t'ipod'\t\t\t\t=> 'iOS',\n\t'os x'\t\t\t\t=> 'Mac OS X',\n\t'ppc mac'\t\t\t=> 'Power PC Mac',\n\t'freebsd'\t\t\t=> 'FreeBSD',\n\t'ppc'\t\t\t\t=> 'Macintosh',\n\t'linux'\t\t\t\t=> 'Linux',\n\t'debian'\t\t\t=> 'Debian',\n\t'sunos'\t\t\t\t=> 'Sun Solaris',\n\t'beos'\t\t\t\t=> 'BeOS',\n\t'apachebench'\t\t=> 'ApacheBench',\n\t'aix'\t\t\t\t=> 'AIX',\n\t'irix'\t\t\t\t=> 'Irix',\n\t'osf'\t\t\t\t=> 'DEC OSF',\n\t'hp-ux'\t\t\t\t=> 'HP-UX',\n\t'netbsd'\t\t\t=> 'NetBSD',\n\t'bsdi'\t\t\t\t=> 'BSDi',\n\t'openbsd'\t\t\t=> 'OpenBSD',\n\t'gnu'\t\t\t\t=> 'GNU/Linux',\n\t'unix'\t\t\t\t=> 'Unknown Unix OS',\n\t'symbian' \t\t\t=> 'Symbian OS'\n);\n\n\n// The order of this array should NOT be changed. Many browsers return\n// multiple browser types so we want to identify the sub-type first.\n$browsers = array(\n\t'OPR'\t\t\t=> 'Opera',\n\t'Flock'\t\t\t=> 'Flock',\n\t'Edge'\t\t\t=> 'Spartan',\n\t'Chrome'\t\t=> 'Chrome',\n\t// Opera 10+ always reports Opera/9.80 and appends Version/<real version> to the user agent string\n\t'Opera.*?Version'\t=> 'Opera',\n\t'Opera'\t\t\t=> 'Opera',\n\t'MSIE'\t\t\t=> 'Internet Explorer',\n\t'Internet Explorer'\t=> 'Internet Explorer',\n\t'Trident.* rv'\t=> 'Internet Explorer',\n\t'Shiira'\t\t=> 'Shiira',\n\t'Firefox'\t\t=> 'Firefox',\n\t'Chimera'\t\t=> 'Chimera',\n\t'Phoenix'\t\t=> 'Phoenix',\n\t'Firebird'\t\t=> 'Firebird',\n\t'Camino'\t\t=> 'Camino',\n\t'Netscape'\t\t=> 'Netscape',\n\t'OmniWeb'\t\t=> 'OmniWeb',\n\t'Safari'\t\t=> 'Safari',\n\t'Mozilla'\t\t=> 'Mozilla',\n\t'Konqueror'\t\t=> 'Konqueror',\n\t'icab'\t\t\t=> 'iCab',\n\t'Lynx'\t\t\t=> 'Lynx',\n\t'Links'\t\t\t=> 'Links',\n\t'hotjava'\t\t=> 'HotJava',\n\t'amaya'\t\t\t=> 'Amaya',\n\t'IBrowse'\t\t=> 'IBrowse',\n\t'Maxthon'\t\t=> 'Maxthon',\n\t'Ubuntu'\t\t=> 'Ubuntu Web Browser'\n);\n\n$mobiles = array(\n\t// legacy array, old values commented out\n\t'mobileexplorer'\t=> 'Mobile Explorer',\n//  'openwave'\t\t\t=> 'Open Wave',\n//\t'opera mini'\t\t=> 'Opera Mini',\n//\t'operamini'\t\t\t=> 'Opera Mini',\n//\t'elaine'\t\t\t=> 'Palm',\n\t'palmsource'\t\t=> 'Palm',\n//\t'digital paths'\t\t=> 'Palm',\n//\t'avantgo'\t\t\t=> 'Avantgo',\n//\t'xiino'\t\t\t\t=> 'Xiino',\n\t'palmscape'\t\t\t=> 'Palmscape',\n//\t'nokia'\t\t\t\t=> 'Nokia',\n//\t'ericsson'\t\t\t=> 'Ericsson',\n//\t'blackberry'\t\t=> 'BlackBerry',\n//\t'motorola'\t\t\t=> 'Motorola'\n\n\t// Phones and Manufacturers\n\t'motorola'\t\t=> 'Motorola',\n\t'nokia'\t\t\t=> 'Nokia',\n\t'palm'\t\t\t=> 'Palm',\n\t'iphone'\t\t=> 'Apple iPhone',\n\t'ipad'\t\t\t=> 'iPad',\n\t'ipod'\t\t\t=> 'Apple iPod Touch',\n\t'sony'\t\t\t=> 'Sony Ericsson',\n\t'ericsson'\t\t=> 'Sony Ericsson',\n\t'blackberry'\t=> 'BlackBerry',\n\t'cocoon'\t\t=> 'O2 Cocoon',\n\t'blazer'\t\t=> 'Treo',\n\t'lg'\t\t\t=> 'LG',\n\t'amoi'\t\t\t=> 'Amoi',\n\t'xda'\t\t\t=> 'XDA',\n\t'mda'\t\t\t=> 'MDA',\n\t'vario'\t\t\t=> 'Vario',\n\t'htc'\t\t\t=> 'HTC',\n\t'samsung'\t\t=> 'Samsung',\n\t'sharp'\t\t\t=> 'Sharp',\n\t'sie-'\t\t\t=> 'Siemens',\n\t'alcatel'\t\t=> 'Alcatel',\n\t'benq'\t\t\t=> 'BenQ',\n\t'ipaq'\t\t\t=> 'HP iPaq',\n\t'mot-'\t\t\t=> 'Motorola',\n\t'playstation portable'\t=> 'PlayStation Portable',\n\t'playstation 3'\t\t=> 'PlayStation 3',\n\t'playstation vita'  \t=> 'PlayStation Vita',\n\t'hiptop'\t\t=> 'Danger Hiptop',\n\t'nec-'\t\t\t=> 'NEC',\n\t'panasonic'\t\t=> 'Panasonic',\n\t'philips'\t\t=> 'Philips',\n\t'sagem'\t\t\t=> 'Sagem',\n\t'sanyo'\t\t\t=> 'Sanyo',\n\t'spv'\t\t\t=> 'SPV',\n\t'zte'\t\t\t=> 'ZTE',\n\t'sendo'\t\t\t=> 'Sendo',\n\t'nintendo dsi'\t=> 'Nintendo DSi',\n\t'nintendo ds'\t=> 'Nintendo DS',\n\t'nintendo 3ds'\t=> 'Nintendo 3DS',\n\t'wii'\t\t\t=> 'Nintendo Wii',\n\t'open web'\t\t=> 'Open Web',\n\t'openweb'\t\t=> 'OpenWeb',\n\n\t// Operating Systems\n\t'android'\t\t=> 'Android',\n\t'symbian'\t\t=> 'Symbian',\n\t'SymbianOS'\t\t=> 'SymbianOS',\n\t'elaine'\t\t=> 'Palm',\n\t'series60'\t\t=> 'Symbian S60',\n\t'windows ce'\t=> 'Windows CE',\n\n\t// Browsers\n\t'obigo'\t\t\t=> 'Obigo',\n\t'netfront'\t\t=> 'Netfront Browser',\n\t'openwave'\t\t=> 'Openwave Browser',\n\t'mobilexplorer'\t=> 'Mobile Explorer',\n\t'operamini'\t\t=> 'Opera Mini',\n\t'opera mini'\t=> 'Opera Mini',\n\t'opera mobi'\t=> 'Opera Mobile',\n\t'fennec'\t\t=> 'Firefox Mobile',\n\n\t// Other\n\t'digital paths'\t=> 'Digital Paths',\n\t'avantgo'\t\t=> 'AvantGo',\n\t'xiino'\t\t\t=> 'Xiino',\n\t'novarra'\t\t=> 'Novarra Transcoder',\n\t'vodafone'\t\t=> 'Vodafone',\n\t'docomo'\t\t=> 'NTT DoCoMo',\n\t'o2'\t\t\t=> 'O2',\n\n\t// Fallback\n\t'mobile'\t\t=> 'Generic Mobile',\n\t'wireless'\t\t=> 'Generic Mobile',\n\t'j2me'\t\t\t=> 'Generic Mobile',\n\t'midp'\t\t\t=> 'Generic Mobile',\n\t'cldc'\t\t\t=> 'Generic Mobile',\n\t'up.link'\t\t=> 'Generic Mobile',\n\t'up.browser'\t=> 'Generic Mobile',\n\t'smartphone'\t=> 'Generic Mobile',\n\t'cellphone'\t\t=> 'Generic Mobile'\n);\n\n// There are hundreds of bots but these are the most common.\n$robots = array(\n\t'googlebot'\t\t=> 'Googlebot',\n\t'msnbot'\t\t=> 'MSNBot',\n\t'baiduspider'\t\t=> 'Baiduspider',\n\t'bingbot'\t\t=> 'Bing',\n\t'slurp'\t\t\t=> 'Inktomi Slurp',\n\t'yahoo'\t\t\t=> 'Yahoo',\n\t'ask jeeves'\t\t=> 'Ask Jeeves',\n\t'fastcrawler'\t\t=> 'FastCrawler',\n\t'infoseek'\t\t=> 'InfoSeek Robot 1.0',\n\t'lycos'\t\t\t=> 'Lycos',\n\t'yandex'\t\t=> 'YandexBot',\n\t'mediapartners-google'\t=> 'MediaPartners Google',\n\t'CRAZYWEBCRAWLER'\t=> 'Crazy Webcrawler',\n\t'adsbot-google'\t\t=> 'AdsBot Google',\n\t'feedfetcher-google'\t=> 'Feedfetcher Google',\n\t'curious george'\t=> 'Curious George',\n\t'ia_archiver'\t\t=> 'Alexa Crawler',\n\t'MJ12bot'\t\t=> 'Majestic-12',\n\t'Uptimebot'\t\t=> 'Uptimebot'\n);\n"
  },
  {
    "path": "application/controllers/Login.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\nuse \\QCloud_WeApp_SDK\\Auth\\LoginService as LoginService;\n\nclass Login extends CI_Controller {\n    public function index() {\n        $result = LoginService::login();\n        // notes: do not echo anything\n    }\n}\n"
  },
  {
    "path": "application/controllers/Tunnel.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\nuse \\QCloud_WeApp_SDK\\Tunnel\\TunnelService as TunnelService;\n\nrequire APPPATH.'business/ChatTunnelHandler.php';\n\nclass Tunnel extends CI_Controller {\n    public function index() {\n        $handler = new ChatTunnelHandler();\n        TunnelService::handle($handler, array('checkLogin' => TRUE));\n    }\n}\n"
  },
  {
    "path": "application/controllers/User.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\nuse \\QCloud_WeApp_SDK\\Auth\\LoginService as LoginService;\n\nclass User extends CI_Controller {\n    public function index() {\n        $result = LoginService::check();\n\n        // check failed\n        if ($result['code'] !== 0) {\n            return;\n        }\n\n        $response = array(\n            'code' => 0,\n            'message' => 'ok',\n            'data' => array(\n                'userInfo' => $result['data']['userInfo'],\n            ),\n        );\n\n        echo json_encode($response, JSON_FORCE_OBJECT);\n    }\n}\n"
  },
  {
    "path": "application/controllers/Welcome.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\nclass Welcome extends CI_Controller {\n\n\t/**\n\t * Index Page for this controller.\n\t *\n\t * Maps to the following URL\n\t * \t\thttp://example.com/index.php/welcome\n\t *\t- or -\n\t * \t\thttp://example.com/index.php/welcome/index\n\t *\t- or -\n\t * Since this controller is set as the default controller in\n\t * config/routes.php, it's displayed at http://example.com/\n\t *\n\t * So any other public methods not prefixed with an underscore will\n\t * map to /index.php/welcome/<method_name>\n\t * @see https://codeigniter.com/user_guide/general/urls.html\n\t */\n\tpublic function index()\n\t{\n\t\t$this->load->view('welcome_message');\n\t}\n}\n"
  },
  {
    "path": "application/controllers/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "application/core/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "application/helpers/general_helper.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n\nif (!function_exists('debug')) {\n    /**\n     * 调试专用\n     */\n    function debug() {\n        $numargs = func_num_args();\n        $arg_list = func_get_args();\n        $messages = array();\n\n        for ($i = 0; $i < $numargs; $i += 1) {\n            $message = $arg_list[$i];\n\n            if (is_array($message)) {\n                if (version_compare(PHP_VERSION, '5.4.0') >= 0) {\n                    $message = json_encode($message, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);\n                } else {\n                    $message = json_encode($message);\n                }\n            }\n\n            if (is_string($message) || is_numeric($message)) {\n                $messages[] = $message;\n            }\n        }\n\n        log_message('debug', implode(' ', $messages) . \"\\n\");\n    }\n}\n"
  },
  {
    "path": "application/helpers/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "application/hooks/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "application/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "application/language/english/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "application/language/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "application/libraries/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "application/logs/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "application/models/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "application/third_party/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "application/views/errors/cli/error_404.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\necho \"\\nERROR: \",\n\t$heading,\n\t\"\\n\\n\",\n\t$message,\n\t\"\\n\\n\";"
  },
  {
    "path": "application/views/errors/cli/error_db.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\necho \"\\nDatabase error: \",\n\t$heading,\n\t\"\\n\\n\",\n\t$message,\n\t\"\\n\\n\";"
  },
  {
    "path": "application/views/errors/cli/error_exception.php",
    "content": "<?php defined('BASEPATH') OR exit('No direct script access allowed'); ?>\n\nAn uncaught Exception was encountered\n\nType:        <?php echo get_class($exception), \"\\n\"; ?>\nMessage:     <?php echo $message, \"\\n\"; ?>\nFilename:    <?php echo $exception->getFile(), \"\\n\"; ?>\nLine Number: <?php echo $exception->getLine(); ?>\n\n<?php if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE === TRUE): ?>\n\nBacktrace:\n<?php\tforeach ($exception->getTrace() as $error): ?>\n<?php\t\tif (isset($error['file']) && strpos($error['file'], realpath(BASEPATH)) !== 0): ?>\n\tFile: <?php echo $error['file'], \"\\n\"; ?>\n\tLine: <?php echo $error['line'], \"\\n\"; ?>\n\tFunction: <?php echo $error['function'], \"\\n\\n\"; ?>\n<?php\t\tendif ?>\n<?php\tendforeach ?>\n\n<?php endif ?>\n"
  },
  {
    "path": "application/views/errors/cli/error_general.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\necho \"\\nERROR: \",\n\t$heading,\n\t\"\\n\\n\",\n\t$message,\n\t\"\\n\\n\";"
  },
  {
    "path": "application/views/errors/cli/error_php.php",
    "content": "<?php defined('BASEPATH') OR exit('No direct script access allowed'); ?>\n\nA PHP Error was encountered\n\nSeverity:    <?php echo $severity, \"\\n\"; ?>\nMessage:     <?php echo $message, \"\\n\"; ?>\nFilename:    <?php echo $filepath, \"\\n\"; ?>\nLine Number: <?php echo $line; ?>\n\n<?php if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE === TRUE): ?>\n\nBacktrace:\n<?php\tforeach (debug_backtrace() as $error): ?>\n<?php\t\tif (isset($error['file']) && strpos($error['file'], realpath(BASEPATH)) !== 0): ?>\n\tFile: <?php echo $error['file'], \"\\n\"; ?>\n\tLine: <?php echo $error['line'], \"\\n\"; ?>\n\tFunction: <?php echo $error['function'], \"\\n\\n\"; ?>\n<?php\t\tendif ?>\n<?php\tendforeach ?>\n\n<?php endif ?>\n"
  },
  {
    "path": "application/views/errors/cli/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "application/views/errors/html/error_404.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n?><!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<title>404 Page Not Found</title>\n<style type=\"text/css\">\n\n::selection { background-color: #E13300; color: white; }\n::-moz-selection { background-color: #E13300; color: white; }\n\nbody {\n\tbackground-color: #fff;\n\tmargin: 40px;\n\tfont: 13px/20px normal Helvetica, Arial, sans-serif;\n\tcolor: #4F5155;\n}\n\na {\n\tcolor: #003399;\n\tbackground-color: transparent;\n\tfont-weight: normal;\n}\n\nh1 {\n\tcolor: #444;\n\tbackground-color: transparent;\n\tborder-bottom: 1px solid #D0D0D0;\n\tfont-size: 19px;\n\tfont-weight: normal;\n\tmargin: 0 0 14px 0;\n\tpadding: 14px 15px 10px 15px;\n}\n\ncode {\n\tfont-family: Consolas, Monaco, Courier New, Courier, monospace;\n\tfont-size: 12px;\n\tbackground-color: #f9f9f9;\n\tborder: 1px solid #D0D0D0;\n\tcolor: #002166;\n\tdisplay: block;\n\tmargin: 14px 0 14px 0;\n\tpadding: 12px 10px 12px 10px;\n}\n\n#container {\n\tmargin: 10px;\n\tborder: 1px solid #D0D0D0;\n\tbox-shadow: 0 0 8px #D0D0D0;\n}\n\np {\n\tmargin: 12px 15px 12px 15px;\n}\n</style>\n</head>\n<body>\n\t<div id=\"container\">\n\t\t<h1><?php echo $heading; ?></h1>\n\t\t<?php echo $message; ?>\n\t</div>\n</body>\n</html>"
  },
  {
    "path": "application/views/errors/html/error_db.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n?><!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<title>Database Error</title>\n<style type=\"text/css\">\n\n::selection { background-color: #E13300; color: white; }\n::-moz-selection { background-color: #E13300; color: white; }\n\nbody {\n\tbackground-color: #fff;\n\tmargin: 40px;\n\tfont: 13px/20px normal Helvetica, Arial, sans-serif;\n\tcolor: #4F5155;\n}\n\na {\n\tcolor: #003399;\n\tbackground-color: transparent;\n\tfont-weight: normal;\n}\n\nh1 {\n\tcolor: #444;\n\tbackground-color: transparent;\n\tborder-bottom: 1px solid #D0D0D0;\n\tfont-size: 19px;\n\tfont-weight: normal;\n\tmargin: 0 0 14px 0;\n\tpadding: 14px 15px 10px 15px;\n}\n\ncode {\n\tfont-family: Consolas, Monaco, Courier New, Courier, monospace;\n\tfont-size: 12px;\n\tbackground-color: #f9f9f9;\n\tborder: 1px solid #D0D0D0;\n\tcolor: #002166;\n\tdisplay: block;\n\tmargin: 14px 0 14px 0;\n\tpadding: 12px 10px 12px 10px;\n}\n\n#container {\n\tmargin: 10px;\n\tborder: 1px solid #D0D0D0;\n\tbox-shadow: 0 0 8px #D0D0D0;\n}\n\np {\n\tmargin: 12px 15px 12px 15px;\n}\n</style>\n</head>\n<body>\n\t<div id=\"container\">\n\t\t<h1><?php echo $heading; ?></h1>\n\t\t<?php echo $message; ?>\n\t</div>\n</body>\n</html>"
  },
  {
    "path": "application/views/errors/html/error_exception.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n?>\n\n<div style=\"border:1px solid #990000;padding-left:20px;margin:0 0 10px 0;\">\n\n<h4>An uncaught Exception was encountered</h4>\n\n<p>Type: <?php echo get_class($exception); ?></p>\n<p>Message: <?php echo $message; ?></p>\n<p>Filename: <?php echo $exception->getFile(); ?></p>\n<p>Line Number: <?php echo $exception->getLine(); ?></p>\n\n<?php if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE === TRUE): ?>\n\n\t<p>Backtrace:</p>\n\t<?php foreach ($exception->getTrace() as $error): ?>\n\n\t\t<?php if (isset($error['file']) && strpos($error['file'], realpath(BASEPATH)) !== 0): ?>\n\n\t\t\t<p style=\"margin-left:10px\">\n\t\t\tFile: <?php echo $error['file']; ?><br />\n\t\t\tLine: <?php echo $error['line']; ?><br />\n\t\t\tFunction: <?php echo $error['function']; ?>\n\t\t\t</p>\n\t\t<?php endif ?>\n\n\t<?php endforeach ?>\n\n<?php endif ?>\n\n</div>"
  },
  {
    "path": "application/views/errors/html/error_general.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n?><!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<title>Error</title>\n<style type=\"text/css\">\n\n::selection { background-color: #E13300; color: white; }\n::-moz-selection { background-color: #E13300; color: white; }\n\nbody {\n\tbackground-color: #fff;\n\tmargin: 40px;\n\tfont: 13px/20px normal Helvetica, Arial, sans-serif;\n\tcolor: #4F5155;\n}\n\na {\n\tcolor: #003399;\n\tbackground-color: transparent;\n\tfont-weight: normal;\n}\n\nh1 {\n\tcolor: #444;\n\tbackground-color: transparent;\n\tborder-bottom: 1px solid #D0D0D0;\n\tfont-size: 19px;\n\tfont-weight: normal;\n\tmargin: 0 0 14px 0;\n\tpadding: 14px 15px 10px 15px;\n}\n\ncode {\n\tfont-family: Consolas, Monaco, Courier New, Courier, monospace;\n\tfont-size: 12px;\n\tbackground-color: #f9f9f9;\n\tborder: 1px solid #D0D0D0;\n\tcolor: #002166;\n\tdisplay: block;\n\tmargin: 14px 0 14px 0;\n\tpadding: 12px 10px 12px 10px;\n}\n\n#container {\n\tmargin: 10px;\n\tborder: 1px solid #D0D0D0;\n\tbox-shadow: 0 0 8px #D0D0D0;\n}\n\np {\n\tmargin: 12px 15px 12px 15px;\n}\n</style>\n</head>\n<body>\n\t<div id=\"container\">\n\t\t<h1><?php echo $heading; ?></h1>\n\t\t<?php echo $message; ?>\n\t</div>\n</body>\n</html>"
  },
  {
    "path": "application/views/errors/html/error_php.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n?>\n\n<div style=\"border:1px solid #990000;padding-left:20px;margin:0 0 10px 0;\">\n\n<h4>A PHP Error was encountered</h4>\n\n<p>Severity: <?php echo $severity; ?></p>\n<p>Message:  <?php echo $message; ?></p>\n<p>Filename: <?php echo $filepath; ?></p>\n<p>Line Number: <?php echo $line; ?></p>\n\n<?php if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE === TRUE): ?>\n\n\t<p>Backtrace:</p>\n\t<?php foreach (debug_backtrace() as $error): ?>\n\n\t\t<?php if (isset($error['file']) && strpos($error['file'], realpath(BASEPATH)) !== 0): ?>\n\n\t\t\t<p style=\"margin-left:10px\">\n\t\t\tFile: <?php echo $error['file'] ?><br />\n\t\t\tLine: <?php echo $error['line'] ?><br />\n\t\t\tFunction: <?php echo $error['function'] ?>\n\t\t\t</p>\n\n\t\t<?php endif ?>\n\n\t<?php endforeach ?>\n\n<?php endif ?>\n\n</div>"
  },
  {
    "path": "application/views/errors/html/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "application/views/errors/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "application/views/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "application/views/welcome_message.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n?><!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"UTF-8\">\n    <title>腾讯云微信小程序服务器 Demo - PHP</title>\n    <style type=\"text/css\">\n\n    ::selection { background-color: #E13300; color: white; }\n    ::-moz-selection { background-color: #E13300; color: white; }\n\n    body {\n        background-color: #fff;\n        margin: 40px;\n        font: 13px/20px normal Helvetica, Arial, sans-serif;\n        color: #4F5155;\n    }\n\n    a {\n        color: #003399;\n        background-color: transparent;\n        font-weight: normal;\n        text-decoration: none;\n    }\n\n    h1 {\n        color: #444;\n        background-color: transparent;\n        border-bottom: 1px solid #D0D0D0;\n        font-size: 19px;\n        font-weight: normal;\n        margin: 0 0 14px 0;\n        padding: 14px 0;\n    }\n\n    p.footer {\n    \ttext-align: right;\n    \tfont-size: 11px;\n    \tborder-top: 1px solid #D0D0D0;\n    \tline-height: 32px;\n    \tpadding: 0 10px 0 10px;\n    \tmargin: 20px 0 0 0;\n    }\n\n    #container {\n        margin: 10px;\n        padding: 10px 20px;\n        border: 1px solid #D0D0D0;\n        box-shadow: 0 0 8px #D0D0D0;\n    }\n    </style>\n</head>\n<body>\n    <div id=\"container\">\n        <h1>腾讯云微信小程序服务端 Demo - PHP</h1>\n        <p>会话管理服务</p>\n        <ul>\n            <li><a href=\"/login\">登录服务</a></li>\n            <li><a href=\"/user\">检查登录</a></li>\n        </ul>\n        <p>信道服务</p>\n        <ul>\n            <li><a href=\"/tunnel\">获得信道地址</a></li>\n        </ul>\n\n        <p class=\"footer\">Page rendered in <strong>{elapsed_time}</strong> seconds. <?php echo  (ENVIRONMENT === 'development') ?  'CodeIgniter Version <strong>' . CI_VERSION . '</strong>' : '' ?></p>\n    </div>\n</body>\n</html>"
  },
  {
    "path": "composer.json",
    "content": "{\n    \"require\": {\n        \"qcloud/weapp-sdk\": \"v0.4.4\"\n    }\n}\n"
  },
  {
    "path": "index.php",
    "content": "<?php\n\n/**\n * 设置时区\n */\ndate_default_timezone_set('Asia/Shanghai');\n\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\n\n/*\n *---------------------------------------------------------------\n * APPLICATION ENVIRONMENT\n *---------------------------------------------------------------\n *\n * You can load different configurations depending on your\n * current environment. Setting the environment also influences\n * things like logging and error reporting.\n *\n * This can be set to anything, but default usage is:\n *\n *     development\n *     testing\n *     production\n *\n * NOTE: If you change these, also change the error_reporting() code below\n */\n\tdefine('ENVIRONMENT', isset($_SERVER['CI_ENV']) ? $_SERVER['CI_ENV'] : 'development');\n\n/*\n *---------------------------------------------------------------\n * ERROR REPORTING\n *---------------------------------------------------------------\n *\n * Different environments will require different levels of error reporting.\n * By default development will show errors but testing and live will hide them.\n */\nswitch (ENVIRONMENT)\n{\n\tcase 'development':\n\t\terror_reporting(-1);\n\t\tini_set('display_errors', 1);\n\tbreak;\n\n\tcase 'testing':\n\tcase 'production':\n\t\tini_set('display_errors', 0);\n\t\tif (version_compare(PHP_VERSION, '5.3', '>='))\n\t\t{\n\t\t\terror_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT & ~E_USER_NOTICE & ~E_USER_DEPRECATED);\n\t\t}\n\t\telse\n\t\t{\n\t\t\terror_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_USER_NOTICE);\n\t\t}\n\tbreak;\n\n\tdefault:\n\t\theader('HTTP/1.1 503 Service Unavailable.', TRUE, 503);\n\t\techo 'The application environment is not set correctly.';\n\t\texit(1); // EXIT_ERROR\n}\n\n/*\n *---------------------------------------------------------------\n * SYSTEM DIRECTORY NAME\n *---------------------------------------------------------------\n *\n * This variable must contain the name of your \"system\" directory.\n * Set the path if it is not in the same directory as this file.\n */\n\t$system_path = 'system';\n\n/*\n *---------------------------------------------------------------\n * APPLICATION DIRECTORY NAME\n *---------------------------------------------------------------\n *\n * If you want this front controller to use a different \"application\"\n * directory than the default one you can set its name here. The directory\n * can also be renamed or relocated anywhere on your server. If you do,\n * use an absolute (full) server path.\n * For more info please see the user guide:\n *\n * https://codeigniter.com/user_guide/general/managing_apps.html\n *\n * NO TRAILING SLASH!\n */\n\t$application_folder = 'application';\n\n/*\n *---------------------------------------------------------------\n * VIEW DIRECTORY NAME\n *---------------------------------------------------------------\n *\n * If you want to move the view directory out of the application\n * directory, set the path to it here. The directory can be renamed\n * and relocated anywhere on your server. If blank, it will default\n * to the standard location inside your application directory.\n * If you do move this, use an absolute (full) server path.\n *\n * NO TRAILING SLASH!\n */\n\t$view_folder = '';\n\n\n/*\n * --------------------------------------------------------------------\n * DEFAULT CONTROLLER\n * --------------------------------------------------------------------\n *\n * Normally you will set your default controller in the routes.php file.\n * You can, however, force a custom routing by hard-coding a\n * specific controller class/function here. For most applications, you\n * WILL NOT set your routing here, but it's an option for those\n * special instances where you might want to override the standard\n * routing in a specific front controller that shares a common CI installation.\n *\n * IMPORTANT: If you set the routing here, NO OTHER controller will be\n * callable. In essence, this preference limits your application to ONE\n * specific controller. Leave the function name blank if you need\n * to call functions dynamically via the URI.\n *\n * Un-comment the $routing array below to use this feature\n */\n\t// The directory name, relative to the \"controllers\" directory.  Leave blank\n\t// if your controller is not in a sub-directory within the \"controllers\" one\n\t// $routing['directory'] = '';\n\n\t// The controller class file name.  Example:  mycontroller\n\t// $routing['controller'] = '';\n\n\t// The controller function you wish to be called.\n\t// $routing['function']\t= '';\n\n\n/*\n * -------------------------------------------------------------------\n *  CUSTOM CONFIG VALUES\n * -------------------------------------------------------------------\n *\n * The $assign_to_config array below will be passed dynamically to the\n * config class when initialized. This allows you to set custom config\n * items or override any default config values found in the config.php file.\n * This can be handy as it permits you to share one application between\n * multiple front controller files, with each file containing different\n * config values.\n *\n * Un-comment the $assign_to_config array below to use this feature\n */\n\t// $assign_to_config['name_of_config_item'] = 'value of config item';\n\n\n\n// --------------------------------------------------------------------\n// END OF USER CONFIGURABLE SETTINGS.  DO NOT EDIT BELOW THIS LINE\n// --------------------------------------------------------------------\n\n/*\n * ---------------------------------------------------------------\n *  Resolve the system path for increased reliability\n * ---------------------------------------------------------------\n */\n\n\t// Set the current directory correctly for CLI requests\n\tif (defined('STDIN'))\n\t{\n\t\tchdir(dirname(__FILE__));\n\t}\n\n\tif (($_temp = realpath($system_path)) !== FALSE)\n\t{\n\t\t$system_path = $_temp.DIRECTORY_SEPARATOR;\n\t}\n\telse\n\t{\n\t\t// Ensure there's a trailing slash\n\t\t$system_path = strtr(\n\t\t\trtrim($system_path, '/\\\\'),\n\t\t\t'/\\\\',\n\t\t\tDIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR\n\t\t).DIRECTORY_SEPARATOR;\n\t}\n\n\t// Is the system path correct?\n\tif ( ! is_dir($system_path))\n\t{\n\t\theader('HTTP/1.1 503 Service Unavailable.', TRUE, 503);\n\t\techo 'Your system folder path does not appear to be set correctly. Please open the following file and correct this: '.pathinfo(__FILE__, PATHINFO_BASENAME);\n\t\texit(3); // EXIT_CONFIG\n\t}\n\n/*\n * -------------------------------------------------------------------\n *  Now that we know the path, set the main path constants\n * -------------------------------------------------------------------\n */\n\t// The name of THIS file\n\tdefine('SELF', pathinfo(__FILE__, PATHINFO_BASENAME));\n\n\t// Path to the system directory\n\tdefine('BASEPATH', $system_path);\n\n\t// Path to the front controller (this file) directory\n\tdefine('FCPATH', dirname(__FILE__).DIRECTORY_SEPARATOR);\n\n\t// Name of the \"system\" directory\n\tdefine('SYSDIR', basename(BASEPATH));\n\n\t// The path to the \"application\" directory\n\tif (is_dir($application_folder))\n\t{\n\t\tif (($_temp = realpath($application_folder)) !== FALSE)\n\t\t{\n\t\t\t$application_folder = $_temp;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$application_folder = strtr(\n\t\t\t\trtrim($application_folder, '/\\\\'),\n\t\t\t\t'/\\\\',\n\t\t\t\tDIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR\n\t\t\t);\n\t\t}\n\t}\n\telseif (is_dir(BASEPATH.$application_folder.DIRECTORY_SEPARATOR))\n\t{\n\t\t$application_folder = BASEPATH.strtr(\n\t\t\ttrim($application_folder, '/\\\\'),\n\t\t\t'/\\\\',\n\t\t\tDIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR\n\t\t);\n\t}\n\telse\n\t{\n\t\theader('HTTP/1.1 503 Service Unavailable.', TRUE, 503);\n\t\techo 'Your application folder path does not appear to be set correctly. Please open the following file and correct this: '.SELF;\n\t\texit(3); // EXIT_CONFIG\n\t}\n\n\tdefine('APPPATH', $application_folder.DIRECTORY_SEPARATOR);\n\n\t// The path to the \"views\" directory\n\tif ( ! isset($view_folder[0]) && is_dir(APPPATH.'views'.DIRECTORY_SEPARATOR))\n\t{\n\t\t$view_folder = APPPATH.'views';\n\t}\n\telseif (is_dir($view_folder))\n\t{\n\t\tif (($_temp = realpath($view_folder)) !== FALSE)\n\t\t{\n\t\t\t$view_folder = $_temp;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$view_folder = strtr(\n\t\t\t\trtrim($view_folder, '/\\\\'),\n\t\t\t\t'/\\\\',\n\t\t\t\tDIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR\n\t\t\t);\n\t\t}\n\t}\n\telseif (is_dir(APPPATH.$view_folder.DIRECTORY_SEPARATOR))\n\t{\n\t\t$view_folder = APPPATH.strtr(\n\t\t\ttrim($view_folder, '/\\\\'),\n\t\t\t'/\\\\',\n\t\t\tDIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR\n\t\t);\n\t}\n\telse\n\t{\n\t\theader('HTTP/1.1 503 Service Unavailable.', TRUE, 503);\n\t\techo 'Your view folder path does not appear to be set correctly. Please open the following file and correct this: '.SELF;\n\t\texit(3); // EXIT_CONFIG\n\t}\n\n\tdefine('VIEWPATH', $view_folder.DIRECTORY_SEPARATOR);\n\n/*\n * --------------------------------------------------------------------\n * LOAD and SETUP `QCLOUD SDK CONFIGURATION`\n * --------------------------------------------------------------------\n */\nrequire_once './install_qcloud_sdk.php';\n\n/*\n * --------------------------------------------------------------------\n * LOAD THE BOOTSTRAP FILE\n * --------------------------------------------------------------------\n *\n * And away we go...\n */\nrequire_once BASEPATH.'core/CodeIgniter.php';\n"
  },
  {
    "path": "install_qcloud_sdk.php",
    "content": "<?php\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n// 加载 SDK\nrequire_once './vendor/autoload.php';\n// require_once './weapp-sdk/AutoLoader.php';\n\nuse \\QCloud_WeApp_SDK\\Conf as Conf;\n\n// Windows\nif (PHP_OS === 'WINNT') {\n    $sdkConfig = 'C:\\qcloud\\sdk.config';\n\n// Linux\n} else {\n    $sdkConfig = '/etc/qcloud/sdk.config';\n}\n\nif (!file_exists($sdkConfig)) {\n    echo \"SDK 配置文件（{$sdkConfig}）不存在\";\n    die;\n}\n\n$config = json_decode(file_get_contents($sdkConfig), TRUE);\n\nif (!is_array($config)) {\n    echo \"SDK 配置文件（{$sdkConfig}）内容不合法\";\n    die;\n}\n\n/**\n * --------------------------------------------------------------------\n * 设置 SDK 基本配置\n * --------------------------------------------------------------------\n */\nConf::setup(array(\n    'ServerHost' => $config['serverHost'],\n    'AuthServerUrl' => $config['authServerUrl'],\n    'TunnelServerUrl' => $config['tunnelServerUrl'],\n    'TunnelSignatureKey' => $config['tunnelSignatureKey'],\n));\n\n/**\n * 也可以调用独立方法进行设置\n *\n * Conf::setServerHost($config['serverHost']);\n * Conf::setAuthServerUrl($config['authServerUrl']);\n * Conf::setTunnelServerUrl($config['tunnelServerUrl']);\n * Conf::setTunnelSignatureKey($config['tunnelSignatureKey']);\n */\n\n// 设置网络请求超时时长（可选，默认 30 秒）\nConf::setNetworkTimeout($config['networkTimeout']);\n\n\n/**\n * --------------------------------------------------------------------\n * 设置 SDK 日志输出配置（主要是方便调试）\n * --------------------------------------------------------------------\n */\n\n// 开启日志输出功能\nConf::setEnableOutputLog(TRUE);\n\n// 指定 SDK 日志输出目录（注意尾斜杠不能省略）\nConf::setLogPath(APPPATH.'logs/');\n\n// 设置日志输出级别\n// 1 => ERROR, 2 => DEBUG, 3 => INFO, 4 => ALL\nConf::setLogThresholdArray(array(2)); // output debug log only\n"
  },
  {
    "path": "system/.htaccess",
    "content": "<IfModule authz_core_module>\n\tRequire all denied\n</IfModule>\n<IfModule !authz_core_module>\n\tDeny from all\n</IfModule>"
  },
  {
    "path": "system/core/Benchmark.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Benchmark Class\n *\n * This class enables you to mark points and calculate the time difference\n * between them. Memory consumption can also be displayed.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/benchmark.html\n */\nclass CI_Benchmark {\n\n\t/**\n\t * List of all benchmark markers\n\t *\n\t * @var\tarray\n\t */\n\tpublic $marker = array();\n\n\t/**\n\t * Set a benchmark marker\n\t *\n\t * Multiple calls to this function can be made so that several\n\t * execution points can be timed.\n\t *\n\t * @param\tstring\t$name\tMarker name\n\t * @return\tvoid\n\t */\n\tpublic function mark($name)\n\t{\n\t\t$this->marker[$name] = microtime(TRUE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Elapsed time\n\t *\n\t * Calculates the time difference between two marked points.\n\t *\n\t * If the first parameter is empty this function instead returns the\n\t * {elapsed_time} pseudo-variable. This permits the full system\n\t * execution time to be shown in a template. The output class will\n\t * swap the real value for this variable.\n\t *\n\t * @param\tstring\t$point1\t\tA particular marked point\n\t * @param\tstring\t$point2\t\tA particular marked point\n\t * @param\tint\t$decimals\tNumber of decimal places\n\t *\n\t * @return\tstring\tCalculated elapsed time on success,\n\t *\t\t\tan '{elapsed_string}' if $point1 is empty\n\t *\t\t\tor an empty string if $point1 is not found.\n\t */\n\tpublic function elapsed_time($point1 = '', $point2 = '', $decimals = 4)\n\t{\n\t\tif ($point1 === '')\n\t\t{\n\t\t\treturn '{elapsed_time}';\n\t\t}\n\n\t\tif ( ! isset($this->marker[$point1]))\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\tif ( ! isset($this->marker[$point2]))\n\t\t{\n\t\t\t$this->marker[$point2] = microtime(TRUE);\n\t\t}\n\n\t\treturn number_format($this->marker[$point2] - $this->marker[$point1], $decimals);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Memory Usage\n\t *\n\t * Simply returns the {memory_usage} marker.\n\t *\n\t * This permits it to be put it anywhere in a template\n\t * without the memory being calculated until the end.\n\t * The output class will swap the real value for this variable.\n\t *\n\t * @return\tstring\t'{memory_usage}'\n\t */\n\tpublic function memory_usage()\n\t{\n\t\treturn '{memory_usage}';\n\t}\n\n}\n"
  },
  {
    "path": "system/core/CodeIgniter.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * System Initialization File\n *\n * Loads the base classes and executes the request.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tCodeIgniter\n * @category\tFront-controller\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/\n */\n\n/**\n * CodeIgniter Version\n *\n * @var\tstring\n *\n */\n\tdefine('CI_VERSION', '3.1.0');\n\n/*\n * ------------------------------------------------------\n *  Load the framework constants\n * ------------------------------------------------------\n */\n\tif (file_exists(APPPATH.'config/'.ENVIRONMENT.'/constants.php'))\n\t{\n\t\trequire_once(APPPATH.'config/'.ENVIRONMENT.'/constants.php');\n\t}\n\n\trequire_once(APPPATH.'config/constants.php');\n\n/*\n * ------------------------------------------------------\n *  Load the global functions\n * ------------------------------------------------------\n */\n\trequire_once(BASEPATH.'core/Common.php');\n\n\n/*\n * ------------------------------------------------------\n * Security procedures\n * ------------------------------------------------------\n */\n\nif ( ! is_php('5.4'))\n{\n\tini_set('magic_quotes_runtime', 0);\n\n\tif ((bool) ini_get('register_globals'))\n\t{\n\t\t$_protected = array(\n\t\t\t'_SERVER',\n\t\t\t'_GET',\n\t\t\t'_POST',\n\t\t\t'_FILES',\n\t\t\t'_REQUEST',\n\t\t\t'_SESSION',\n\t\t\t'_ENV',\n\t\t\t'_COOKIE',\n\t\t\t'GLOBALS',\n\t\t\t'HTTP_RAW_POST_DATA',\n\t\t\t'system_path',\n\t\t\t'application_folder',\n\t\t\t'view_folder',\n\t\t\t'_protected',\n\t\t\t'_registered'\n\t\t);\n\n\t\t$_registered = ini_get('variables_order');\n\t\tforeach (array('E' => '_ENV', 'G' => '_GET', 'P' => '_POST', 'C' => '_COOKIE', 'S' => '_SERVER') as $key => $superglobal)\n\t\t{\n\t\t\tif (strpos($_registered, $key) === FALSE)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tforeach (array_keys($$superglobal) as $var)\n\t\t\t{\n\t\t\t\tif (isset($GLOBALS[$var]) && ! in_array($var, $_protected, TRUE))\n\t\t\t\t{\n\t\t\t\t\t$GLOBALS[$var] = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\n\n/*\n * ------------------------------------------------------\n *  Define a custom error handler so we can log PHP errors\n * ------------------------------------------------------\n */\n\tset_error_handler('_error_handler');\n\tset_exception_handler('_exception_handler');\n\tregister_shutdown_function('_shutdown_handler');\n\n/*\n * ------------------------------------------------------\n *  Set the subclass_prefix\n * ------------------------------------------------------\n *\n * Normally the \"subclass_prefix\" is set in the config file.\n * The subclass prefix allows CI to know if a core class is\n * being extended via a library in the local application\n * \"libraries\" folder. Since CI allows config items to be\n * overridden via data set in the main index.php file,\n * before proceeding we need to know if a subclass_prefix\n * override exists. If so, we will set this value now,\n * before any classes are loaded\n * Note: Since the config file data is cached it doesn't\n * hurt to load it here.\n */\n\tif ( ! empty($assign_to_config['subclass_prefix']))\n\t{\n\t\tget_config(array('subclass_prefix' => $assign_to_config['subclass_prefix']));\n\t}\n\n/*\n * ------------------------------------------------------\n *  Should we use a Composer autoloader?\n * ------------------------------------------------------\n */\n\tif ($composer_autoload = config_item('composer_autoload'))\n\t{\n\t\tif ($composer_autoload === TRUE)\n\t\t{\n\t\t\tfile_exists(APPPATH.'vendor/autoload.php')\n\t\t\t\t? require_once(APPPATH.'vendor/autoload.php')\n\t\t\t\t: log_message('error', '$config[\\'composer_autoload\\'] is set to TRUE but '.APPPATH.'vendor/autoload.php was not found.');\n\t\t}\n\t\telseif (file_exists($composer_autoload))\n\t\t{\n\t\t\trequire_once($composer_autoload);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlog_message('error', 'Could not find the specified $config[\\'composer_autoload\\'] path: '.$composer_autoload);\n\t\t}\n\t}\n\n/*\n * ------------------------------------------------------\n *  Start the timer... tick tock tick tock...\n * ------------------------------------------------------\n */\n\t$BM =& load_class('Benchmark', 'core');\n\t$BM->mark('total_execution_time_start');\n\t$BM->mark('loading_time:_base_classes_start');\n\n/*\n * ------------------------------------------------------\n *  Instantiate the hooks class\n * ------------------------------------------------------\n */\n\t$EXT =& load_class('Hooks', 'core');\n\n/*\n * ------------------------------------------------------\n *  Is there a \"pre_system\" hook?\n * ------------------------------------------------------\n */\n\t$EXT->call_hook('pre_system');\n\n/*\n * ------------------------------------------------------\n *  Instantiate the config class\n * ------------------------------------------------------\n *\n * Note: It is important that Config is loaded first as\n * most other classes depend on it either directly or by\n * depending on another class that uses it.\n *\n */\n\t$CFG =& load_class('Config', 'core');\n\n\t// Do we have any manually set config items in the index.php file?\n\tif (isset($assign_to_config) && is_array($assign_to_config))\n\t{\n\t\tforeach ($assign_to_config as $key => $value)\n\t\t{\n\t\t\t$CFG->set_item($key, $value);\n\t\t}\n\t}\n\n/*\n * ------------------------------------------------------\n * Important charset-related stuff\n * ------------------------------------------------------\n *\n * Configure mbstring and/or iconv if they are enabled\n * and set MB_ENABLED and ICONV_ENABLED constants, so\n * that we don't repeatedly do extension_loaded() or\n * function_exists() calls.\n *\n * Note: UTF-8 class depends on this. It used to be done\n * in it's constructor, but it's _not_ class-specific.\n *\n */\n\t$charset = strtoupper(config_item('charset'));\n\tini_set('default_charset', $charset);\n\n\tif (extension_loaded('mbstring'))\n\t{\n\t\tdefine('MB_ENABLED', TRUE);\n\t\t// mbstring.internal_encoding is deprecated starting with PHP 5.6\n\t\t// and it's usage triggers E_DEPRECATED messages.\n\t\t@ini_set('mbstring.internal_encoding', $charset);\n\t\t// This is required for mb_convert_encoding() to strip invalid characters.\n\t\t// That's utilized by CI_Utf8, but it's also done for consistency with iconv.\n\t\tmb_substitute_character('none');\n\t}\n\telse\n\t{\n\t\tdefine('MB_ENABLED', FALSE);\n\t}\n\n\t// There's an ICONV_IMPL constant, but the PHP manual says that using\n\t// iconv's predefined constants is \"strongly discouraged\".\n\tif (extension_loaded('iconv'))\n\t{\n\t\tdefine('ICONV_ENABLED', TRUE);\n\t\t// iconv.internal_encoding is deprecated starting with PHP 5.6\n\t\t// and it's usage triggers E_DEPRECATED messages.\n\t\t@ini_set('iconv.internal_encoding', $charset);\n\t}\n\telse\n\t{\n\t\tdefine('ICONV_ENABLED', FALSE);\n\t}\n\n\tif (is_php('5.6'))\n\t{\n\t\tini_set('php.internal_encoding', $charset);\n\t}\n\n/*\n * ------------------------------------------------------\n *  Load compatibility features\n * ------------------------------------------------------\n */\n\n\trequire_once(BASEPATH.'core/compat/mbstring.php');\n\trequire_once(BASEPATH.'core/compat/hash.php');\n\trequire_once(BASEPATH.'core/compat/password.php');\n\trequire_once(BASEPATH.'core/compat/standard.php');\n\n/*\n * ------------------------------------------------------\n *  Instantiate the UTF-8 class\n * ------------------------------------------------------\n */\n\t$UNI =& load_class('Utf8', 'core');\n\n/*\n * ------------------------------------------------------\n *  Instantiate the URI class\n * ------------------------------------------------------\n */\n\t$URI =& load_class('URI', 'core');\n\n/*\n * ------------------------------------------------------\n *  Instantiate the routing class and set the routing\n * ------------------------------------------------------\n */\n\t$RTR =& load_class('Router', 'core', isset($routing) ? $routing : NULL);\n\n/*\n * ------------------------------------------------------\n *  Instantiate the output class\n * ------------------------------------------------------\n */\n\t$OUT =& load_class('Output', 'core');\n\n/*\n * ------------------------------------------------------\n *\tIs there a valid cache file? If so, we're done...\n * ------------------------------------------------------\n */\n\tif ($EXT->call_hook('cache_override') === FALSE && $OUT->_display_cache($CFG, $URI) === TRUE)\n\t{\n\t\texit;\n\t}\n\n/*\n * -----------------------------------------------------\n * Load the security class for xss and csrf support\n * -----------------------------------------------------\n */\n\t$SEC =& load_class('Security', 'core');\n\n/*\n * ------------------------------------------------------\n *  Load the Input class and sanitize globals\n * ------------------------------------------------------\n */\n\t$IN\t=& load_class('Input', 'core');\n\n/*\n * ------------------------------------------------------\n *  Load the Language class\n * ------------------------------------------------------\n */\n\t$LANG =& load_class('Lang', 'core');\n\n/*\n * ------------------------------------------------------\n *  Load the app controller and local controller\n * ------------------------------------------------------\n *\n */\n\t// Load the base controller class\n\trequire_once BASEPATH.'core/Controller.php';\n\n\t/**\n\t * Reference to the CI_Controller method.\n\t *\n\t * Returns current CI instance object\n\t *\n\t * @return CI_Controller\n\t */\n\tfunction &get_instance()\n\t{\n\t\treturn CI_Controller::get_instance();\n\t}\n\n\tif (file_exists(APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php'))\n\t{\n\t\trequire_once APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php';\n\t}\n\n\t// Set a mark point for benchmarking\n\t$BM->mark('loading_time:_base_classes_end');\n\n/*\n * ------------------------------------------------------\n *  Sanity checks\n * ------------------------------------------------------\n *\n *  The Router class has already validated the request,\n *  leaving us with 3 options here:\n *\n *\t1) an empty class name, if we reached the default\n *\t   controller, but it didn't exist;\n *\t2) a query string which doesn't go through a\n *\t   file_exists() check\n *\t3) a regular request for a non-existing page\n *\n *  We handle all of these as a 404 error.\n *\n *  Furthermore, none of the methods in the app controller\n *  or the loader class can be called via the URI, nor can\n *  controller methods that begin with an underscore.\n */\n\n\t$e404 = FALSE;\n\t$class = ucfirst($RTR->class);\n\t$method = $RTR->method;\n\n\tif (empty($class) OR ! file_exists(APPPATH.'controllers/'.$RTR->directory.$class.'.php'))\n\t{\n\t\t$e404 = TRUE;\n\t}\n\telse\n\t{\n\t\trequire_once(APPPATH.'controllers/'.$RTR->directory.$class.'.php');\n\n\t\tif ( ! class_exists($class, FALSE) OR $method[0] === '_' OR method_exists('CI_Controller', $method))\n\t\t{\n\t\t\t$e404 = TRUE;\n\t\t}\n\t\telseif (method_exists($class, '_remap'))\n\t\t{\n\t\t\t$params = array($method, array_slice($URI->rsegments, 2));\n\t\t\t$method = '_remap';\n\t\t}\n\t\t// WARNING: It appears that there are issues with is_callable() even in PHP 5.2!\n\t\t// Furthermore, there are bug reports and feature/change requests related to it\n\t\t// that make it unreliable to use in this context. Please, DO NOT change this\n\t\t// work-around until a better alternative is available.\n\t\telseif ( ! in_array(strtolower($method), array_map('strtolower', get_class_methods($class)), TRUE))\n\t\t{\n\t\t\t$e404 = TRUE;\n\t\t}\n\t}\n\n\tif ($e404)\n\t{\n\t\tif ( ! empty($RTR->routes['404_override']))\n\t\t{\n\t\t\tif (sscanf($RTR->routes['404_override'], '%[^/]/%s', $error_class, $error_method) !== 2)\n\t\t\t{\n\t\t\t\t$error_method = 'index';\n\t\t\t}\n\n\t\t\t$error_class = ucfirst($error_class);\n\n\t\t\tif ( ! class_exists($error_class, FALSE))\n\t\t\t{\n\t\t\t\tif (file_exists(APPPATH.'controllers/'.$RTR->directory.$error_class.'.php'))\n\t\t\t\t{\n\t\t\t\t\trequire_once(APPPATH.'controllers/'.$RTR->directory.$error_class.'.php');\n\t\t\t\t\t$e404 = ! class_exists($error_class, FALSE);\n\t\t\t\t}\n\t\t\t\t// Were we in a directory? If so, check for a global override\n\t\t\t\telseif ( ! empty($RTR->directory) && file_exists(APPPATH.'controllers/'.$error_class.'.php'))\n\t\t\t\t{\n\t\t\t\t\trequire_once(APPPATH.'controllers/'.$error_class.'.php');\n\t\t\t\t\tif (($e404 = ! class_exists($error_class, FALSE)) === FALSE)\n\t\t\t\t\t{\n\t\t\t\t\t\t$RTR->directory = '';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$e404 = FALSE;\n\t\t\t}\n\t\t}\n\n\t\t// Did we reset the $e404 flag? If so, set the rsegments, starting from index 1\n\t\tif ( ! $e404)\n\t\t{\n\t\t\t$class = $error_class;\n\t\t\t$method = $error_method;\n\n\t\t\t$URI->rsegments = array(\n\t\t\t\t1 => $class,\n\t\t\t\t2 => $method\n\t\t\t);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tshow_404($RTR->directory.$class.'/'.$method);\n\t\t}\n\t}\n\n\tif ($method !== '_remap')\n\t{\n\t\t$params = array_slice($URI->rsegments, 2);\n\t}\n\n/*\n * ------------------------------------------------------\n *  Is there a \"pre_controller\" hook?\n * ------------------------------------------------------\n */\n\t$EXT->call_hook('pre_controller');\n\n/*\n * ------------------------------------------------------\n *  Instantiate the requested controller\n * ------------------------------------------------------\n */\n\t// Mark a start point so we can benchmark the controller\n\t$BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_start');\n\n\t$CI = new $class();\n\n/*\n * ------------------------------------------------------\n *  Is there a \"post_controller_constructor\" hook?\n * ------------------------------------------------------\n */\n\t$EXT->call_hook('post_controller_constructor');\n\n/*\n * ------------------------------------------------------\n *  Call the requested method\n * ------------------------------------------------------\n */\n\tcall_user_func_array(array(&$CI, $method), $params);\n\n\t// Mark a benchmark end point\n\t$BM->mark('controller_execution_time_( '.$class.' / '.$method.' )_end');\n\n/*\n * ------------------------------------------------------\n *  Is there a \"post_controller\" hook?\n * ------------------------------------------------------\n */\n\t$EXT->call_hook('post_controller');\n\n/*\n * ------------------------------------------------------\n *  Send the final rendered output to the browser\n * ------------------------------------------------------\n */\n\tif ($EXT->call_hook('display_override') === FALSE)\n\t{\n\t\t$OUT->_display();\n\t}\n\n/*\n * ------------------------------------------------------\n *  Is there a \"post_system\" hook?\n * ------------------------------------------------------\n */\n\t$EXT->call_hook('post_system');\n"
  },
  {
    "path": "system/core/Common.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Common Functions\n *\n * Loads the base classes and executes the request.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tCodeIgniter\n * @category\tCommon Functions\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/\n */\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('is_php'))\n{\n\t/**\n\t * Determines if the current version of PHP is equal to or greater than the supplied value\n\t *\n\t * @param\tstring\n\t * @return\tbool\tTRUE if the current version is $version or higher\n\t */\n\tfunction is_php($version)\n\t{\n\t\tstatic $_is_php;\n\t\t$version = (string) $version;\n\n\t\tif ( ! isset($_is_php[$version]))\n\t\t{\n\t\t\t$_is_php[$version] = version_compare(PHP_VERSION, $version, '>=');\n\t\t}\n\n\t\treturn $_is_php[$version];\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('is_really_writable'))\n{\n\t/**\n\t * Tests for file writability\n\t *\n\t * is_writable() returns TRUE on Windows servers when you really can't write to\n\t * the file, based on the read-only attribute. is_writable() is also unreliable\n\t * on Unix servers if safe_mode is on.\n\t *\n\t * @link\thttps://bugs.php.net/bug.php?id=54709\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tfunction is_really_writable($file)\n\t{\n\t\t// If we're on a Unix server with safe_mode off we call is_writable\n\t\tif (DIRECTORY_SEPARATOR === '/' && (is_php('5.4') OR ! ini_get('safe_mode')))\n\t\t{\n\t\t\treturn is_writable($file);\n\t\t}\n\n\t\t/* For Windows servers and safe_mode \"on\" installations we'll actually\n\t\t * write a file then read it. Bah...\n\t\t */\n\t\tif (is_dir($file))\n\t\t{\n\t\t\t$file = rtrim($file, '/').'/'.md5(mt_rand());\n\t\t\tif (($fp = @fopen($file, 'ab')) === FALSE)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tfclose($fp);\n\t\t\t@chmod($file, 0777);\n\t\t\t@unlink($file);\n\t\t\treturn TRUE;\n\t\t}\n\t\telseif ( ! is_file($file) OR ($fp = @fopen($file, 'ab')) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tfclose($fp);\n\t\treturn TRUE;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('load_class'))\n{\n\t/**\n\t * Class registry\n\t *\n\t * This function acts as a singleton. If the requested class does not\n\t * exist it is instantiated and set to a static variable. If it has\n\t * previously been instantiated the variable is returned.\n\t *\n\t * @param\tstring\tthe class name being requested\n\t * @param\tstring\tthe directory where the class should be found\n\t * @param\tstring\tan optional argument to pass to the class constructor\n\t * @return\tobject\n\t */\n\tfunction &load_class($class, $directory = 'libraries', $param = NULL)\n\t{\n\t\tstatic $_classes = array();\n\n\t\t// Does the class exist? If so, we're done...\n\t\tif (isset($_classes[$class]))\n\t\t{\n\t\t\treturn $_classes[$class];\n\t\t}\n\n\t\t$name = FALSE;\n\n\t\t// Look for the class first in the local application/libraries folder\n\t\t// then in the native system/libraries folder\n\t\tforeach (array(APPPATH, BASEPATH) as $path)\n\t\t{\n\t\t\tif (file_exists($path.$directory.'/'.$class.'.php'))\n\t\t\t{\n\t\t\t\t$name = 'CI_'.$class;\n\n\t\t\t\tif (class_exists($name, FALSE) === FALSE)\n\t\t\t\t{\n\t\t\t\t\trequire_once($path.$directory.'/'.$class.'.php');\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// Is the request a class extension? If so we load it too\n\t\tif (file_exists(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php'))\n\t\t{\n\t\t\t$name = config_item('subclass_prefix').$class;\n\n\t\t\tif (class_exists($name, FALSE) === FALSE)\n\t\t\t{\n\t\t\t\trequire_once(APPPATH.$directory.'/'.$name.'.php');\n\t\t\t}\n\t\t}\n\n\t\t// Did we find the class?\n\t\tif ($name === FALSE)\n\t\t{\n\t\t\t// Note: We use exit() rather than show_error() in order to avoid a\n\t\t\t// self-referencing loop with the Exceptions class\n\t\t\tset_status_header(503);\n\t\t\techo 'Unable to locate the specified class: '.$class.'.php';\n\t\t\texit(5); // EXIT_UNK_CLASS\n\t\t}\n\n\t\t// Keep track of what we just loaded\n\t\tis_loaded($class);\n\n\t\t$_classes[$class] = isset($param)\n\t\t\t? new $name($param)\n\t\t\t: new $name();\n\t\treturn $_classes[$class];\n\t}\n}\n\n// --------------------------------------------------------------------\n\nif ( ! function_exists('is_loaded'))\n{\n\t/**\n\t * Keeps track of which libraries have been loaded. This function is\n\t * called by the load_class() function above\n\t *\n\t * @param\tstring\n\t * @return\tarray\n\t */\n\tfunction &is_loaded($class = '')\n\t{\n\t\tstatic $_is_loaded = array();\n\n\t\tif ($class !== '')\n\t\t{\n\t\t\t$_is_loaded[strtolower($class)] = $class;\n\t\t}\n\n\t\treturn $_is_loaded;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('get_config'))\n{\n\t/**\n\t * Loads the main config.php file\n\t *\n\t * This function lets us grab the config file even if the Config class\n\t * hasn't been instantiated yet\n\t *\n\t * @param\tarray\n\t * @return\tarray\n\t */\n\tfunction &get_config(Array $replace = array())\n\t{\n\t\tstatic $config;\n\n\t\tif (empty($config))\n\t\t{\n\t\t\t$file_path = APPPATH.'config/config.php';\n\t\t\t$found = FALSE;\n\t\t\tif (file_exists($file_path))\n\t\t\t{\n\t\t\t\t$found = TRUE;\n\t\t\t\trequire($file_path);\n\t\t\t}\n\n\t\t\t// Is the config file in the environment folder?\n\t\t\tif (file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config.php'))\n\t\t\t{\n\t\t\t\trequire($file_path);\n\t\t\t}\n\t\t\telseif ( ! $found)\n\t\t\t{\n\t\t\t\tset_status_header(503);\n\t\t\t\techo 'The configuration file does not exist.';\n\t\t\t\texit(3); // EXIT_CONFIG\n\t\t\t}\n\n\t\t\t// Does the $config array exist in the file?\n\t\t\tif ( ! isset($config) OR ! is_array($config))\n\t\t\t{\n\t\t\t\tset_status_header(503);\n\t\t\t\techo 'Your config file does not appear to be formatted correctly.';\n\t\t\t\texit(3); // EXIT_CONFIG\n\t\t\t}\n\t\t}\n\n\t\t// Are any values being dynamically added or replaced?\n\t\tforeach ($replace as $key => $val)\n\t\t{\n\t\t\t$config[$key] = $val;\n\t\t}\n\n\t\treturn $config;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('config_item'))\n{\n\t/**\n\t * Returns the specified config item\n\t *\n\t * @param\tstring\n\t * @return\tmixed\n\t */\n\tfunction config_item($item)\n\t{\n\t\tstatic $_config;\n\n\t\tif (empty($_config))\n\t\t{\n\t\t\t// references cannot be directly assigned to static variables, so we use an array\n\t\t\t$_config[0] =& get_config();\n\t\t}\n\n\t\treturn isset($_config[0][$item]) ? $_config[0][$item] : NULL;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('get_mimes'))\n{\n\t/**\n\t * Returns the MIME types array from config/mimes.php\n\t *\n\t * @return\tarray\n\t */\n\tfunction &get_mimes()\n\t{\n\t\tstatic $_mimes;\n\n\t\tif (empty($_mimes))\n\t\t{\n\t\t\tif (file_exists(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'))\n\t\t\t{\n\t\t\t\t$_mimes = include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php');\n\t\t\t}\n\t\t\telseif (file_exists(APPPATH.'config/mimes.php'))\n\t\t\t{\n\t\t\t\t$_mimes = include(APPPATH.'config/mimes.php');\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$_mimes = array();\n\t\t\t}\n\t\t}\n\n\t\treturn $_mimes;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('is_https'))\n{\n\t/**\n\t * Is HTTPS?\n\t *\n\t * Determines if the application is accessed via an encrypted\n\t * (HTTPS) connection.\n\t *\n\t * @return\tbool\n\t */\n\tfunction is_https()\n\t{\n\t\tif ( ! empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off')\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\t\telseif (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https')\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\t\telseif ( ! empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) !== 'off')\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('is_cli'))\n{\n\n\t/**\n\t * Is CLI?\n\t *\n\t * Test to see if a request was made from the command line.\n\t *\n\t * @return \tbool\n\t */\n\tfunction is_cli()\n\t{\n\t\treturn (PHP_SAPI === 'cli' OR defined('STDIN'));\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('show_error'))\n{\n\t/**\n\t * Error Handler\n\t *\n\t * This function lets us invoke the exception class and\n\t * display errors using the standard error template located\n\t * in application/views/errors/error_general.php\n\t * This function will send the error page directly to the\n\t * browser and exit.\n\t *\n\t * @param\tstring\n\t * @param\tint\n\t * @param\tstring\n\t * @return\tvoid\n\t */\n\tfunction show_error($message, $status_code = 500, $heading = 'An Error Was Encountered')\n\t{\n\t\t$status_code = abs($status_code);\n\t\tif ($status_code < 100)\n\t\t{\n\t\t\t$exit_status = $status_code + 9; // 9 is EXIT__AUTO_MIN\n\t\t\tif ($exit_status > 125) // 125 is EXIT__AUTO_MAX\n\t\t\t{\n\t\t\t\t$exit_status = 1; // EXIT_ERROR\n\t\t\t}\n\n\t\t\t$status_code = 500;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$exit_status = 1; // EXIT_ERROR\n\t\t}\n\n\t\t$_error =& load_class('Exceptions', 'core');\n\t\techo $_error->show_error($heading, $message, 'error_general', $status_code);\n\t\texit($exit_status);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('show_404'))\n{\n\t/**\n\t * 404 Page Handler\n\t *\n\t * This function is similar to the show_error() function above\n\t * However, instead of the standard error template it displays\n\t * 404 errors.\n\t *\n\t * @param\tstring\n\t * @param\tbool\n\t * @return\tvoid\n\t */\n\tfunction show_404($page = '', $log_error = TRUE)\n\t{\n\t\t$_error =& load_class('Exceptions', 'core');\n\t\t$_error->show_404($page, $log_error);\n\t\texit(4); // EXIT_UNKNOWN_FILE\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('log_message'))\n{\n\t/**\n\t * Error Logging Interface\n\t *\n\t * We use this as a simple mechanism to access the logging\n\t * class and send messages to be logged.\n\t *\n\t * @param\tstring\tthe error level: 'error', 'debug' or 'info'\n\t * @param\tstring\tthe error message\n\t * @return\tvoid\n\t */\n\tfunction log_message($level, $message)\n\t{\n\t\tstatic $_log;\n\n\t\tif ($_log === NULL)\n\t\t{\n\t\t\t// references cannot be directly assigned to static variables, so we use an array\n\t\t\t$_log[0] =& load_class('Log', 'core');\n\t\t}\n\n\t\t$_log[0]->write_log($level, $message);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('set_status_header'))\n{\n\t/**\n\t * Set HTTP Status Header\n\t *\n\t * @param\tint\tthe status code\n\t * @param\tstring\n\t * @return\tvoid\n\t */\n\tfunction set_status_header($code = 200, $text = '')\n\t{\n\t\tif (is_cli())\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tif (empty($code) OR ! is_numeric($code))\n\t\t{\n\t\t\tshow_error('Status codes must be numeric', 500);\n\t\t}\n\n\t\tif (empty($text))\n\t\t{\n\t\t\tis_int($code) OR $code = (int) $code;\n\t\t\t$stati = array(\n\t\t\t\t100\t=> 'Continue',\n\t\t\t\t101\t=> 'Switching Protocols',\n\n\t\t\t\t200\t=> 'OK',\n\t\t\t\t201\t=> 'Created',\n\t\t\t\t202\t=> 'Accepted',\n\t\t\t\t203\t=> 'Non-Authoritative Information',\n\t\t\t\t204\t=> 'No Content',\n\t\t\t\t205\t=> 'Reset Content',\n\t\t\t\t206\t=> 'Partial Content',\n\n\t\t\t\t300\t=> 'Multiple Choices',\n\t\t\t\t301\t=> 'Moved Permanently',\n\t\t\t\t302\t=> 'Found',\n\t\t\t\t303\t=> 'See Other',\n\t\t\t\t304\t=> 'Not Modified',\n\t\t\t\t305\t=> 'Use Proxy',\n\t\t\t\t307\t=> 'Temporary Redirect',\n\n\t\t\t\t400\t=> 'Bad Request',\n\t\t\t\t401\t=> 'Unauthorized',\n\t\t\t\t402\t=> 'Payment Required',\n\t\t\t\t403\t=> 'Forbidden',\n\t\t\t\t404\t=> 'Not Found',\n\t\t\t\t405\t=> 'Method Not Allowed',\n\t\t\t\t406\t=> 'Not Acceptable',\n\t\t\t\t407\t=> 'Proxy Authentication Required',\n\t\t\t\t408\t=> 'Request Timeout',\n\t\t\t\t409\t=> 'Conflict',\n\t\t\t\t410\t=> 'Gone',\n\t\t\t\t411\t=> 'Length Required',\n\t\t\t\t412\t=> 'Precondition Failed',\n\t\t\t\t413\t=> 'Request Entity Too Large',\n\t\t\t\t414\t=> 'Request-URI Too Long',\n\t\t\t\t415\t=> 'Unsupported Media Type',\n\t\t\t\t416\t=> 'Requested Range Not Satisfiable',\n\t\t\t\t417\t=> 'Expectation Failed',\n\t\t\t\t422\t=> 'Unprocessable Entity',\n\n\t\t\t\t500\t=> 'Internal Server Error',\n\t\t\t\t501\t=> 'Not Implemented',\n\t\t\t\t502\t=> 'Bad Gateway',\n\t\t\t\t503\t=> 'Service Unavailable',\n\t\t\t\t504\t=> 'Gateway Timeout',\n\t\t\t\t505\t=> 'HTTP Version Not Supported'\n\t\t\t);\n\n\t\t\tif (isset($stati[$code]))\n\t\t\t{\n\t\t\t\t$text = $stati[$code];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tshow_error('No status text available. Please check your status code number or supply your own message text.', 500);\n\t\t\t}\n\t\t}\n\n\t\tif (strpos(PHP_SAPI, 'cgi') === 0)\n\t\t{\n\t\t\theader('Status: '.$code.' '.$text, TRUE);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$server_protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1';\n\t\t\theader($server_protocol.' '.$code.' '.$text, TRUE, $code);\n\t\t}\n\t}\n}\n\n// --------------------------------------------------------------------\n\nif ( ! function_exists('_error_handler'))\n{\n\t/**\n\t * Error Handler\n\t *\n\t * This is the custom error handler that is declared at the (relative)\n\t * top of CodeIgniter.php. The main reason we use this is to permit\n\t * PHP errors to be logged in our own log files since the user may\n\t * not have access to server logs. Since this function effectively\n\t * intercepts PHP errors, however, we also need to display errors\n\t * based on the current error_reporting level.\n\t * We do that with the use of a PHP error template.\n\t *\n\t * @param\tint\t$severity\n\t * @param\tstring\t$message\n\t * @param\tstring\t$filepath\n\t * @param\tint\t$line\n\t * @return\tvoid\n\t */\n\tfunction _error_handler($severity, $message, $filepath, $line)\n\t{\n\t\t$is_error = (((E_ERROR | E_COMPILE_ERROR | E_CORE_ERROR | E_USER_ERROR) & $severity) === $severity);\n\n\t\t// When an error occurred, set the status header to '500 Internal Server Error'\n\t\t// to indicate to the client something went wrong.\n\t\t// This can't be done within the $_error->show_php_error method because\n\t\t// it is only called when the display_errors flag is set (which isn't usually\n\t\t// the case in a production environment) or when errors are ignored because\n\t\t// they are above the error_reporting threshold.\n\t\tif ($is_error)\n\t\t{\n\t\t\tset_status_header(500);\n\t\t}\n\n\t\t// Should we ignore the error? We'll get the current error_reporting\n\t\t// level and add its bits with the severity bits to find out.\n\t\tif (($severity & error_reporting()) !== $severity)\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\t$_error =& load_class('Exceptions', 'core');\n\t\t$_error->log_exception($severity, $message, $filepath, $line);\n\n\t\t// Should we display the error?\n\t\tif (str_ireplace(array('off', 'none', 'no', 'false', 'null'), '', ini_get('display_errors')))\n\t\t{\n\t\t\t$_error->show_php_error($severity, $message, $filepath, $line);\n\t\t}\n\n\t\t// If the error is fatal, the execution of the script should be stopped because\n\t\t// errors can't be recovered from. Halting the script conforms with PHP's\n\t\t// default error handling. See http://www.php.net/manual/en/errorfunc.constants.php\n\t\tif ($is_error)\n\t\t{\n\t\t\texit(1); // EXIT_ERROR\n\t\t}\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('_exception_handler'))\n{\n\t/**\n\t * Exception Handler\n\t *\n\t * Sends uncaught exceptions to the logger and displays them\n\t * only if display_errors is On so that they don't show up in\n\t * production environments.\n\t *\n\t * @param\tException\t$exception\n\t * @return\tvoid\n\t */\n\tfunction _exception_handler($exception)\n\t{\n\t\t$_error =& load_class('Exceptions', 'core');\n\t\t$_error->log_exception('error', 'Exception: '.$exception->getMessage(), $exception->getFile(), $exception->getLine());\n\n\t\t// Should we display the error?\n\t\tif (str_ireplace(array('off', 'none', 'no', 'false', 'null'), '', ini_get('display_errors')))\n\t\t{\n\t\t\t$_error->show_exception($exception);\n\t\t}\n\n\t\texit(1); // EXIT_ERROR\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('_shutdown_handler'))\n{\n\t/**\n\t * Shutdown Handler\n\t *\n\t * This is the shutdown handler that is declared at the top\n\t * of CodeIgniter.php. The main reason we use this is to simulate\n\t * a complete custom exception handler.\n\t *\n\t * E_STRICT is purposively neglected because such events may have\n\t * been caught. Duplication or none? None is preferred for now.\n\t *\n\t * @link\thttp://insomanic.me.uk/post/229851073/php-trick-catching-fatal-errors-e-error-with-a\n\t * @return\tvoid\n\t */\n\tfunction _shutdown_handler()\n\t{\n\t\t$last_error = error_get_last();\n\t\tif (isset($last_error) &&\n\t\t\t($last_error['type'] & (E_ERROR | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING)))\n\t\t{\n\t\t\t_error_handler($last_error['type'], $last_error['message'], $last_error['file'], $last_error['line']);\n\t\t}\n\t}\n}\n\n// --------------------------------------------------------------------\n\nif ( ! function_exists('remove_invisible_characters'))\n{\n\t/**\n\t * Remove Invisible Characters\n\t *\n\t * This prevents sandwiching null characters\n\t * between ascii characters, like Java\\0script.\n\t *\n\t * @param\tstring\n\t * @param\tbool\n\t * @return\tstring\n\t */\n\tfunction remove_invisible_characters($str, $url_encoded = TRUE)\n\t{\n\t\t$non_displayables = array();\n\n\t\t// every control character except newline (dec 10),\n\t\t// carriage return (dec 13) and horizontal tab (dec 09)\n\t\tif ($url_encoded)\n\t\t{\n\t\t\t$non_displayables[] = '/%0[0-8bcef]/i';\t// url encoded 00-08, 11, 12, 14, 15\n\t\t\t$non_displayables[] = '/%1[0-9a-f]/i';\t// url encoded 16-31\n\t\t}\n\n\t\t$non_displayables[] = '/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]+/S';\t// 00-08, 11, 12, 14-31, 127\n\n\t\tdo\n\t\t{\n\t\t\t$str = preg_replace($non_displayables, '', $str, -1, $count);\n\t\t}\n\t\twhile ($count);\n\n\t\treturn $str;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('html_escape'))\n{\n\t/**\n\t * Returns HTML escaped variable.\n\t *\n\t * @param\tmixed\t$var\t\tThe input string or array of strings to be escaped.\n\t * @param\tbool\t$double_encode\t$double_encode set to FALSE prevents escaping twice.\n\t * @return\tmixed\t\t\tThe escaped string or array of strings as a result.\n\t */\n\tfunction html_escape($var, $double_encode = TRUE)\n\t{\n\t\tif (empty($var))\n\t\t{\n\t\t\treturn $var;\n\t\t}\n\n\t\tif (is_array($var))\n\t\t{\n\t\t\tforeach (array_keys($var) as $key)\n\t\t\t{\n\t\t\t\t$var[$key] = html_escape($var[$key], $double_encode);\n\t\t\t}\n\n\t\t\treturn $var;\n\t\t}\n\n\t\treturn htmlspecialchars($var, ENT_QUOTES, config_item('charset'), $double_encode);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('_stringify_attributes'))\n{\n\t/**\n\t * Stringify attributes for use in HTML tags.\n\t *\n\t * Helper function used to convert a string, array, or object\n\t * of attributes to a string.\n\t *\n\t * @param\tmixed\tstring, array, object\n\t * @param\tbool\n\t * @return\tstring\n\t */\n\tfunction _stringify_attributes($attributes, $js = FALSE)\n\t{\n\t\t$atts = NULL;\n\n\t\tif (empty($attributes))\n\t\t{\n\t\t\treturn $atts;\n\t\t}\n\n\t\tif (is_string($attributes))\n\t\t{\n\t\t\treturn ' '.$attributes;\n\t\t}\n\n\t\t$attributes = (array) $attributes;\n\n\t\tforeach ($attributes as $key => $val)\n\t\t{\n\t\t\t$atts .= ($js) ? $key.'='.$val.',' : ' '.$key.'=\"'.$val.'\"';\n\t\t}\n\n\t\treturn rtrim($atts, ',');\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('function_usable'))\n{\n\t/**\n\t * Function usable\n\t *\n\t * Executes a function_exists() check, and if the Suhosin PHP\n\t * extension is loaded - checks whether the function that is\n\t * checked might be disabled in there as well.\n\t *\n\t * This is useful as function_exists() will return FALSE for\n\t * functions disabled via the *disable_functions* php.ini\n\t * setting, but not for *suhosin.executor.func.blacklist* and\n\t * *suhosin.executor.disable_eval*. These settings will just\n\t * terminate script execution if a disabled function is executed.\n\t *\n\t * The above described behavior turned out to be a bug in Suhosin,\n\t * but even though a fix was commited for 0.9.34 on 2012-02-12,\n\t * that version is yet to be released. This function will therefore\n\t * be just temporary, but would probably be kept for a few years.\n\t *\n\t * @link\thttp://www.hardened-php.net/suhosin/\n\t * @param\tstring\t$function_name\tFunction to check for\n\t * @return\tbool\tTRUE if the function exists and is safe to call,\n\t *\t\t\tFALSE otherwise.\n\t */\n\tfunction function_usable($function_name)\n\t{\n\t\tstatic $_suhosin_func_blacklist;\n\n\t\tif (function_exists($function_name))\n\t\t{\n\t\t\tif ( ! isset($_suhosin_func_blacklist))\n\t\t\t{\n\t\t\t\t$_suhosin_func_blacklist = extension_loaded('suhosin')\n\t\t\t\t\t? explode(',', trim(ini_get('suhosin.executor.func.blacklist')))\n\t\t\t\t\t: array();\n\t\t\t}\n\n\t\t\treturn ! in_array($function_name, $_suhosin_func_blacklist, TRUE);\n\t\t}\n\n\t\treturn FALSE;\n\t}\n}\n"
  },
  {
    "path": "system/core/Config.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Config Class\n *\n * This class contains functions that enable config files to be managed\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/config.html\n */\nclass CI_Config {\n\n\t/**\n\t * List of all loaded config values\n\t *\n\t * @var\tarray\n\t */\n\tpublic $config = array();\n\n\t/**\n\t * List of all loaded config files\n\t *\n\t * @var\tarray\n\t */\n\tpublic $is_loaded =\tarray();\n\n\t/**\n\t * List of paths to search when trying to load a config file.\n\t *\n\t * @used-by\tCI_Loader\n\t * @var\t\tarray\n\t */\n\tpublic $_config_paths =\tarray(APPPATH);\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Sets the $config data from the primary config.php file as a class variable.\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\t$this->config =& get_config();\n\n\t\t// Set the base_url automatically if none was provided\n\t\tif (empty($this->config['base_url']))\n\t\t{\n\t\t\tif (isset($_SERVER['SERVER_ADDR']))\n\t\t\t{\n\t\t\t\tif (strpos($_SERVER['SERVER_ADDR'], ':') !== FALSE)\n\t\t\t\t{\n\t\t\t\t\t$server_addr = '['.$_SERVER['SERVER_ADDR'].']';\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$server_addr = $_SERVER['SERVER_ADDR'];\n\t\t\t\t}\n\n\t\t\t\t$base_url = (is_https() ? 'https' : 'http').'://'.$server_addr\n\t\t\t\t\t.substr($_SERVER['SCRIPT_NAME'], 0, strpos($_SERVER['SCRIPT_NAME'], basename($_SERVER['SCRIPT_FILENAME'])));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$base_url = 'http://localhost/';\n\t\t\t}\n\n\t\t\t$this->set_item('base_url', $base_url);\n\t\t}\n\n\t\tlog_message('info', 'Config Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Load Config File\n\t *\n\t * @param\tstring\t$file\t\t\tConfiguration file name\n\t * @param\tbool\t$use_sections\t\tWhether configuration values should be loaded into their own section\n\t * @param\tbool\t$fail_gracefully\tWhether to just return FALSE or display an error message\n\t * @return\tbool\tTRUE if the file was loaded correctly or FALSE on failure\n\t */\n\tpublic function load($file = '', $use_sections = FALSE, $fail_gracefully = FALSE)\n\t{\n\t\t$file = ($file === '') ? 'config' : str_replace('.php', '', $file);\n\t\t$loaded = FALSE;\n\n\t\tforeach ($this->_config_paths as $path)\n\t\t{\n\t\t\tforeach (array($file, ENVIRONMENT.DIRECTORY_SEPARATOR.$file) as $location)\n\t\t\t{\n\t\t\t\t$file_path = $path.'config/'.$location.'.php';\n\t\t\t\tif (in_array($file_path, $this->is_loaded, TRUE))\n\t\t\t\t{\n\t\t\t\t\treturn TRUE;\n\t\t\t\t}\n\n\t\t\t\tif ( ! file_exists($file_path))\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tinclude($file_path);\n\n\t\t\t\tif ( ! isset($config) OR ! is_array($config))\n\t\t\t\t{\n\t\t\t\t\tif ($fail_gracefully === TRUE)\n\t\t\t\t\t{\n\t\t\t\t\t\treturn FALSE;\n\t\t\t\t\t}\n\n\t\t\t\t\tshow_error('Your '.$file_path.' file does not appear to contain a valid configuration array.');\n\t\t\t\t}\n\n\t\t\t\tif ($use_sections === TRUE)\n\t\t\t\t{\n\t\t\t\t\t$this->config[$file] = isset($this->config[$file])\n\t\t\t\t\t\t? array_merge($this->config[$file], $config)\n\t\t\t\t\t\t: $config;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$this->config = array_merge($this->config, $config);\n\t\t\t\t}\n\n\t\t\t\t$this->is_loaded[] = $file_path;\n\t\t\t\t$config = NULL;\n\t\t\t\t$loaded = TRUE;\n\t\t\t\tlog_message('debug', 'Config file loaded: '.$file_path);\n\t\t\t}\n\t\t}\n\n\t\tif ($loaded === TRUE)\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\t\telseif ($fail_gracefully === TRUE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tshow_error('The configuration file '.$file.'.php does not exist.');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch a config file item\n\t *\n\t * @param\tstring\t$item\tConfig item name\n\t * @param\tstring\t$index\tIndex name\n\t * @return\tstring|null\tThe configuration item or NULL if the item doesn't exist\n\t */\n\tpublic function item($item, $index = '')\n\t{\n\t\tif ($index == '')\n\t\t{\n\t\t\treturn isset($this->config[$item]) ? $this->config[$item] : NULL;\n\t\t}\n\n\t\treturn isset($this->config[$index], $this->config[$index][$item]) ? $this->config[$index][$item] : NULL;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch a config file item with slash appended (if not empty)\n\t *\n\t * @param\tstring\t\t$item\tConfig item name\n\t * @return\tstring|null\tThe configuration item or NULL if the item doesn't exist\n\t */\n\tpublic function slash_item($item)\n\t{\n\t\tif ( ! isset($this->config[$item]))\n\t\t{\n\t\t\treturn NULL;\n\t\t}\n\t\telseif (trim($this->config[$item]) === '')\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\treturn rtrim($this->config[$item], '/').'/';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Site URL\n\t *\n\t * Returns base_url . index_page [. uri_string]\n\t *\n\t * @uses\tCI_Config::_uri_string()\n\t *\n\t * @param\tstring|string[]\t$uri\tURI string or an array of segments\n\t * @param\tstring\t$protocol\n\t * @return\tstring\n\t */\n\tpublic function site_url($uri = '', $protocol = NULL)\n\t{\n\t\t$base_url = $this->slash_item('base_url');\n\n\t\tif (isset($protocol))\n\t\t{\n\t\t\t// For protocol-relative links\n\t\t\tif ($protocol === '')\n\t\t\t{\n\t\t\t\t$base_url = substr($base_url, strpos($base_url, '//'));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$base_url = $protocol.substr($base_url, strpos($base_url, '://'));\n\t\t\t}\n\t\t}\n\n\t\tif (empty($uri))\n\t\t{\n\t\t\treturn $base_url.$this->item('index_page');\n\t\t}\n\n\t\t$uri = $this->_uri_string($uri);\n\n\t\tif ($this->item('enable_query_strings') === FALSE)\n\t\t{\n\t\t\t$suffix = isset($this->config['url_suffix']) ? $this->config['url_suffix'] : '';\n\n\t\t\tif ($suffix !== '')\n\t\t\t{\n\t\t\t\tif (($offset = strpos($uri, '?')) !== FALSE)\n\t\t\t\t{\n\t\t\t\t\t$uri = substr($uri, 0, $offset).$suffix.substr($uri, $offset);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$uri .= $suffix;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn $base_url.$this->slash_item('index_page').$uri;\n\t\t}\n\t\telseif (strpos($uri, '?') === FALSE)\n\t\t{\n\t\t\t$uri = '?'.$uri;\n\t\t}\n\n\t\treturn $base_url.$this->item('index_page').$uri;\n\t}\n\n\t// -------------------------------------------------------------\n\n\t/**\n\t * Base URL\n\t *\n\t * Returns base_url [. uri_string]\n\t *\n\t * @uses\tCI_Config::_uri_string()\n\t *\n\t * @param\tstring|string[]\t$uri\tURI string or an array of segments\n\t * @param\tstring\t$protocol\n\t * @return\tstring\n\t */\n\tpublic function base_url($uri = '', $protocol = NULL)\n\t{\n\t\t$base_url = $this->slash_item('base_url');\n\n\t\tif (isset($protocol))\n\t\t{\n\t\t\t// For protocol-relative links\n\t\t\tif ($protocol === '')\n\t\t\t{\n\t\t\t\t$base_url = substr($base_url, strpos($base_url, '//'));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$base_url = $protocol.substr($base_url, strpos($base_url, '://'));\n\t\t\t}\n\t\t}\n\n\t\treturn $base_url.$this->_uri_string($uri);\n\t}\n\n\t// -------------------------------------------------------------\n\n\t/**\n\t * Build URI string\n\t *\n\t * @used-by\tCI_Config::site_url()\n\t * @used-by\tCI_Config::base_url()\n\t *\n\t * @param\tstring|string[]\t$uri\tURI string or an array of segments\n\t * @return\tstring\n\t */\n\tprotected function _uri_string($uri)\n\t{\n\t\tif ($this->item('enable_query_strings') === FALSE)\n\t\t{\n\t\t\tis_array($uri) && $uri = implode('/', $uri);\n\t\t\treturn ltrim($uri, '/');\n\t\t}\n\t\telseif (is_array($uri))\n\t\t{\n\t\t\treturn http_build_query($uri);\n\t\t}\n\n\t\treturn $uri;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * System URL\n\t *\n\t * @deprecated\t3.0.0\tEncourages insecure practices\n\t * @return\tstring\n\t */\n\tpublic function system_url()\n\t{\n\t\t$x = explode('/', preg_replace('|/*(.+?)/*$|', '\\\\1', BASEPATH));\n\t\treturn $this->slash_item('base_url').end($x).'/';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set a config file item\n\t *\n\t * @param\tstring\t$item\tConfig item key\n\t * @param\tstring\t$value\tConfig item value\n\t * @return\tvoid\n\t */\n\tpublic function set_item($item, $value)\n\t{\n\t\t$this->config[$item] = $value;\n\t}\n\n}\n"
  },
  {
    "path": "system/core/Controller.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Application Controller Class\n *\n * This class object is the super class that every library in\n * CodeIgniter will be assigned to.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/general/controllers.html\n */\nclass CI_Controller {\n\n\t/**\n\t * Reference to the CI singleton\n\t *\n\t * @var\tobject\n\t */\n\tprivate static $instance;\n\n\t/**\n\t * Class constructor\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\tself::$instance =& $this;\n\n\t\t// Assign all the class objects that were instantiated by the\n\t\t// bootstrap file (CodeIgniter.php) to local class variables\n\t\t// so that CI can run as one big super object.\n\t\tforeach (is_loaded() as $var => $class)\n\t\t{\n\t\t\t$this->$var =& load_class($class);\n\t\t}\n\n\t\t$this->load =& load_class('Loader', 'core');\n\t\t$this->load->initialize();\n\t\tlog_message('info', 'Controller Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get the CI singleton\n\t *\n\t * @static\n\t * @return\tobject\n\t */\n\tpublic static function &get_instance()\n\t{\n\t\treturn self::$instance;\n\t}\n\n}\n"
  },
  {
    "path": "system/core/Exceptions.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Exceptions Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tExceptions\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/exceptions.html\n */\nclass CI_Exceptions {\n\n\t/**\n\t * Nesting level of the output buffering mechanism\n\t *\n\t * @var\tint\n\t */\n\tpublic $ob_level;\n\n\t/**\n\t * List of available error levels\n\t *\n\t * @var\tarray\n\t */\n\tpublic $levels = array(\n\t\tE_ERROR\t\t\t=>\t'Error',\n\t\tE_WARNING\t\t=>\t'Warning',\n\t\tE_PARSE\t\t\t=>\t'Parsing Error',\n\t\tE_NOTICE\t\t=>\t'Notice',\n\t\tE_CORE_ERROR\t\t=>\t'Core Error',\n\t\tE_CORE_WARNING\t\t=>\t'Core Warning',\n\t\tE_COMPILE_ERROR\t\t=>\t'Compile Error',\n\t\tE_COMPILE_WARNING\t=>\t'Compile Warning',\n\t\tE_USER_ERROR\t\t=>\t'User Error',\n\t\tE_USER_WARNING\t\t=>\t'User Warning',\n\t\tE_USER_NOTICE\t\t=>\t'User Notice',\n\t\tE_STRICT\t\t=>\t'Runtime Notice'\n\t);\n\n\t/**\n\t * Class constructor\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\t$this->ob_level = ob_get_level();\n\t\t// Note: Do not log messages from this constructor.\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Exception Logger\n\t *\n\t * Logs PHP generated error messages\n\t *\n\t * @param\tint\t$severity\tLog level\n\t * @param\tstring\t$message\tError message\n\t * @param\tstring\t$filepath\tFile path\n\t * @param\tint\t$line\t\tLine number\n\t * @return\tvoid\n\t */\n\tpublic function log_exception($severity, $message, $filepath, $line)\n\t{\n\t\t$severity = isset($this->levels[$severity]) ? $this->levels[$severity] : $severity;\n\t\tlog_message('error', 'Severity: '.$severity.' --> '.$message.' '.$filepath.' '.$line);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * 404 Error Handler\n\t *\n\t * @uses\tCI_Exceptions::show_error()\n\t *\n\t * @param\tstring\t$page\t\tPage URI\n\t * @param \tbool\t$log_error\tWhether to log the error\n\t * @return\tvoid\n\t */\n\tpublic function show_404($page = '', $log_error = TRUE)\n\t{\n\t\tif (is_cli())\n\t\t{\n\t\t\t$heading = 'Not Found';\n\t\t\t$message = 'The controller/method pair you requested was not found.';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$heading = '404 Page Not Found';\n\t\t\t$message = 'The page you requested was not found.';\n\t\t}\n\n\t\t// By default we log this, but allow a dev to skip it\n\t\tif ($log_error)\n\t\t{\n\t\t\tlog_message('error', $heading.': '.$page);\n\t\t}\n\n\t\techo $this->show_error($heading, $message, 'error_404', 404);\n\t\texit(4); // EXIT_UNKNOWN_FILE\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * General Error Page\n\t *\n\t * Takes an error message as input (either as a string or an array)\n\t * and displays it using the specified template.\n\t *\n\t * @param\tstring\t\t$heading\tPage heading\n\t * @param\tstring|string[]\t$message\tError message\n\t * @param\tstring\t\t$template\tTemplate name\n\t * @param \tint\t\t$status_code\t(default: 500)\n\t *\n\t * @return\tstring\tError page output\n\t */\n\tpublic function show_error($heading, $message, $template = 'error_general', $status_code = 500)\n\t{\n\t\t$templates_path = config_item('error_views_path');\n\t\tif (empty($templates_path))\n\t\t{\n\t\t\t$templates_path = VIEWPATH.'errors'.DIRECTORY_SEPARATOR;\n\t\t}\n\n\t\tif (is_cli())\n\t\t{\n\t\t\t$message = \"\\t\".(is_array($message) ? implode(\"\\n\\t\", $message) : $message);\n\t\t\t$template = 'cli'.DIRECTORY_SEPARATOR.$template;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tset_status_header($status_code);\n\t\t\t$message = '<p>'.(is_array($message) ? implode('</p><p>', $message) : $message).'</p>';\n\t\t\t$template = 'html'.DIRECTORY_SEPARATOR.$template;\n\t\t}\n\n\t\tif (ob_get_level() > $this->ob_level + 1)\n\t\t{\n\t\t\tob_end_flush();\n\t\t}\n\t\tob_start();\n\t\tinclude($templates_path.$template.'.php');\n\t\t$buffer = ob_get_contents();\n\t\tob_end_clean();\n\t\treturn $buffer;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\tpublic function show_exception($exception)\n\t{\n\t\t$templates_path = config_item('error_views_path');\n\t\tif (empty($templates_path))\n\t\t{\n\t\t\t$templates_path = VIEWPATH.'errors'.DIRECTORY_SEPARATOR;\n\t\t}\n\n\t\t$message = $exception->getMessage();\n\t\tif (empty($message))\n\t\t{\n\t\t\t$message = '(null)';\n\t\t}\n\n\t\tif (is_cli())\n\t\t{\n\t\t\t$templates_path .= 'cli'.DIRECTORY_SEPARATOR;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tset_status_header(500);\n\t\t\t$templates_path .= 'html'.DIRECTORY_SEPARATOR;\n\t\t}\n\n\t\tif (ob_get_level() > $this->ob_level + 1)\n\t\t{\n\t\t\tob_end_flush();\n\t\t}\n\n\t\tob_start();\n\t\tinclude($templates_path.'error_exception.php');\n\t\t$buffer = ob_get_contents();\n\t\tob_end_clean();\n\t\techo $buffer;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Native PHP error handler\n\t *\n\t * @param\tint\t$severity\tError level\n\t * @param\tstring\t$message\tError message\n\t * @param\tstring\t$filepath\tFile path\n\t * @param\tint\t$line\t\tLine number\n\t * @return\tstring\tError page output\n\t */\n\tpublic function show_php_error($severity, $message, $filepath, $line)\n\t{\n\t\t$templates_path = config_item('error_views_path');\n\t\tif (empty($templates_path))\n\t\t{\n\t\t\t$templates_path = VIEWPATH.'errors'.DIRECTORY_SEPARATOR;\n\t\t}\n\n\t\t$severity = isset($this->levels[$severity]) ? $this->levels[$severity] : $severity;\n\n\t\t// For safety reasons we don't show the full file path in non-CLI requests\n\t\tif ( ! is_cli())\n\t\t{\n\t\t\t$filepath = str_replace('\\\\', '/', $filepath);\n\t\t\tif (FALSE !== strpos($filepath, '/'))\n\t\t\t{\n\t\t\t\t$x = explode('/', $filepath);\n\t\t\t\t$filepath = $x[count($x)-2].'/'.end($x);\n\t\t\t}\n\n\t\t\t$template = 'html'.DIRECTORY_SEPARATOR.'error_php';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$template = 'cli'.DIRECTORY_SEPARATOR.'error_php';\n\t\t}\n\n\t\tif (ob_get_level() > $this->ob_level + 1)\n\t\t{\n\t\t\tob_end_flush();\n\t\t}\n\t\tob_start();\n\t\tinclude($templates_path.$template.'.php');\n\t\t$buffer = ob_get_contents();\n\t\tob_end_clean();\n\t\techo $buffer;\n\t}\n\n}\n"
  },
  {
    "path": "system/core/Hooks.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Hooks Class\n *\n * Provides a mechanism to extend the base system without hacking.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/general/hooks.html\n */\nclass CI_Hooks {\n\n\t/**\n\t * Determines whether hooks are enabled\n\t *\n\t * @var\tbool\n\t */\n\tpublic $enabled = FALSE;\n\n\t/**\n\t * List of all hooks set in config/hooks.php\n\t *\n\t * @var\tarray\n\t */\n\tpublic $hooks =\tarray();\n\n\t/**\n\t * Array with class objects to use hooks methods\n\t *\n\t * @var array\n\t */\n\tprotected $_objects = array();\n\n\t/**\n\t * In progress flag\n\t *\n\t * Determines whether hook is in progress, used to prevent infinte loops\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_in_progress = FALSE;\n\n\t/**\n\t * Class constructor\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\t$CFG =& load_class('Config', 'core');\n\t\tlog_message('info', 'Hooks Class Initialized');\n\n\t\t// If hooks are not enabled in the config file\n\t\t// there is nothing else to do\n\t\tif ($CFG->item('enable_hooks') === FALSE)\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\t// Grab the \"hooks\" definition file.\n\t\tif (file_exists(APPPATH.'config/hooks.php'))\n\t\t{\n\t\t\tinclude(APPPATH.'config/hooks.php');\n\t\t}\n\n\t\tif (file_exists(APPPATH.'config/'.ENVIRONMENT.'/hooks.php'))\n\t\t{\n\t\t\tinclude(APPPATH.'config/'.ENVIRONMENT.'/hooks.php');\n\t\t}\n\n\t\t// If there are no hooks, we're done.\n\t\tif ( ! isset($hook) OR ! is_array($hook))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\t$this->hooks =& $hook;\n\t\t$this->enabled = TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Call Hook\n\t *\n\t * Calls a particular hook. Called by CodeIgniter.php.\n\t *\n\t * @uses\tCI_Hooks::_run_hook()\n\t *\n\t * @param\tstring\t$which\tHook name\n\t * @return\tbool\tTRUE on success or FALSE on failure\n\t */\n\tpublic function call_hook($which = '')\n\t{\n\t\tif ( ! $this->enabled OR ! isset($this->hooks[$which]))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (is_array($this->hooks[$which]) && ! isset($this->hooks[$which]['function']))\n\t\t{\n\t\t\tforeach ($this->hooks[$which] as $val)\n\t\t\t{\n\t\t\t\t$this->_run_hook($val);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->_run_hook($this->hooks[$which]);\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Run Hook\n\t *\n\t * Runs a particular hook\n\t *\n\t * @param\tarray\t$data\tHook details\n\t * @return\tbool\tTRUE on success or FALSE on failure\n\t */\n\tprotected function _run_hook($data)\n\t{\n\t\t// Closures/lambda functions and array($object, 'method') callables\n\t\tif (is_callable($data))\n\t\t{\n\t\t\tis_array($data)\n\t\t\t\t? $data[0]->{$data[1]}()\n\t\t\t\t: $data();\n\n\t\t\treturn TRUE;\n\t\t}\n\t\telseif ( ! is_array($data))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// -----------------------------------\n\t\t// Safety - Prevents run-away loops\n\t\t// -----------------------------------\n\n\t\t// If the script being called happens to have the same\n\t\t// hook call within it a loop can happen\n\t\tif ($this->_in_progress === TRUE)\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\t// -----------------------------------\n\t\t// Set file path\n\t\t// -----------------------------------\n\n\t\tif ( ! isset($data['filepath'], $data['filename']))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$filepath = APPPATH.$data['filepath'].'/'.$data['filename'];\n\n\t\tif ( ! file_exists($filepath))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Determine and class and/or function names\n\t\t$class\t\t= empty($data['class']) ? FALSE : $data['class'];\n\t\t$function\t= empty($data['function']) ? FALSE : $data['function'];\n\t\t$params\t\t= isset($data['params']) ? $data['params'] : '';\n\n\t\tif (empty($function))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Set the _in_progress flag\n\t\t$this->_in_progress = TRUE;\n\n\t\t// Call the requested class and/or function\n\t\tif ($class !== FALSE)\n\t\t{\n\t\t\t// The object is stored?\n\t\t\tif (isset($this->_objects[$class]))\n\t\t\t{\n\t\t\t\tif (method_exists($this->_objects[$class], $function))\n\t\t\t\t{\n\t\t\t\t\t$this->_objects[$class]->$function($params);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn $this->_in_progress = FALSE;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tclass_exists($class, FALSE) OR require_once($filepath);\n\n\t\t\t\tif ( ! class_exists($class, FALSE) OR ! method_exists($class, $function))\n\t\t\t\t{\n\t\t\t\t\treturn $this->_in_progress = FALSE;\n\t\t\t\t}\n\n\t\t\t\t// Store the object and execute the method\n\t\t\t\t$this->_objects[$class] = new $class();\n\t\t\t\t$this->_objects[$class]->$function($params);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfunction_exists($function) OR require_once($filepath);\n\n\t\t\tif ( ! function_exists($function))\n\t\t\t{\n\t\t\t\treturn $this->_in_progress = FALSE;\n\t\t\t}\n\n\t\t\t$function($params);\n\t\t}\n\n\t\t$this->_in_progress = FALSE;\n\t\treturn TRUE;\n\t}\n\n}\n"
  },
  {
    "path": "system/core/Input.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Input Class\n *\n * Pre-processes global input data for security\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tInput\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/input.html\n */\nclass CI_Input {\n\n\t/**\n\t * IP address of the current user\n\t *\n\t * @var\tstring\n\t */\n\tprotected $ip_address = FALSE;\n\n\t/**\n\t * Allow GET array flag\n\t *\n\t * If set to FALSE, then $_GET will be set to an empty array.\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_allow_get_array = TRUE;\n\n\t/**\n\t * Standardize new lines flag\n\t *\n\t * If set to TRUE, then newlines are standardized.\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_standardize_newlines;\n\n\t/**\n\t * Enable XSS flag\n\t *\n\t * Determines whether the XSS filter is always active when\n\t * GET, POST or COOKIE data is encountered.\n\t * Set automatically based on config setting.\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_enable_xss = FALSE;\n\n\t/**\n\t * Enable CSRF flag\n\t *\n\t * Enables a CSRF cookie token to be set.\n\t * Set automatically based on config setting.\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_enable_csrf = FALSE;\n\n\t/**\n\t * List of all HTTP request headers\n\t *\n\t * @var array\n\t */\n\tprotected $headers = array();\n\n\t/**\n\t * Raw input stream data\n\t *\n\t * Holds a cache of php://input contents\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_raw_input_stream;\n\n\t/**\n\t * Parsed input stream data\n\t *\n\t * Parsed from php://input at runtime\n\t *\n\t * @see\tCI_Input::input_stream()\n\t * @var\tarray\n\t */\n\tprotected $_input_stream;\n\n\tprotected $security;\n\tprotected $uni;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Determines whether to globally enable the XSS processing\n\t * and whether to allow the $_GET array.\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\t$this->_allow_get_array\t\t= (config_item('allow_get_array') === TRUE);\n\t\t$this->_enable_xss\t\t= (config_item('global_xss_filtering') === TRUE);\n\t\t$this->_enable_csrf\t\t= (config_item('csrf_protection') === TRUE);\n\t\t$this->_standardize_newlines\t= (bool) config_item('standardize_newlines');\n\n\t\t$this->security =& load_class('Security', 'core');\n\n\t\t// Do we need the UTF-8 class?\n\t\tif (UTF8_ENABLED === TRUE)\n\t\t{\n\t\t\t$this->uni =& load_class('Utf8', 'core');\n\t\t}\n\n\t\t// Sanitize global arrays\n\t\t$this->_sanitize_globals();\n\n\t\t// CSRF Protection check\n\t\tif ($this->_enable_csrf === TRUE && ! is_cli())\n\t\t{\n\t\t\t$this->security->csrf_verify();\n\t\t}\n\n\t\tlog_message('info', 'Input Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch from array\n\t *\n\t * Internal method used to retrieve values from global arrays.\n\t *\n\t * @param\tarray\t&$array\t\t$_GET, $_POST, $_COOKIE, $_SERVER, etc.\n\t * @param\tmixed\t$index\t\tIndex for item to be fetched from $array\n\t * @param\tbool\t$xss_clean\tWhether to apply XSS filtering\n\t * @return\tmixed\n\t */\n\tprotected function _fetch_from_array(&$array, $index = NULL, $xss_clean = NULL)\n\t{\n\t\tis_bool($xss_clean) OR $xss_clean = $this->_enable_xss;\n\n\t\t// If $index is NULL, it means that the whole $array is requested\n\t\tisset($index) OR $index = array_keys($array);\n\n\t\t// allow fetching multiple keys at once\n\t\tif (is_array($index))\n\t\t{\n\t\t\t$output = array();\n\t\t\tforeach ($index as $key)\n\t\t\t{\n\t\t\t\t$output[$key] = $this->_fetch_from_array($array, $key, $xss_clean);\n\t\t\t}\n\n\t\t\treturn $output;\n\t\t}\n\n\t\tif (isset($array[$index]))\n\t\t{\n\t\t\t$value = $array[$index];\n\t\t}\n\t\telseif (($count = preg_match_all('/(?:^[^\\[]+)|\\[[^]]*\\]/', $index, $matches)) > 1) // Does the index contain array notation\n\t\t{\n\t\t\t$value = $array;\n\t\t\tfor ($i = 0; $i < $count; $i++)\n\t\t\t{\n\t\t\t\t$key = trim($matches[0][$i], '[]');\n\t\t\t\tif ($key === '') // Empty notation will return the value as array\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (isset($value[$key]))\n\t\t\t\t{\n\t\t\t\t\t$value = $value[$key];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\treturn NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn NULL;\n\t\t}\n\n\t\treturn ($xss_clean === TRUE)\n\t\t\t? $this->security->xss_clean($value)\n\t\t\t: $value;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch an item from the GET array\n\t *\n\t * @param\tmixed\t$index\t\tIndex for item to be fetched from $_GET\n\t * @param\tbool\t$xss_clean\tWhether to apply XSS filtering\n\t * @return\tmixed\n\t */\n\tpublic function get($index = NULL, $xss_clean = NULL)\n\t{\n\t\treturn $this->_fetch_from_array($_GET, $index, $xss_clean);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch an item from the POST array\n\t *\n\t * @param\tmixed\t$index\t\tIndex for item to be fetched from $_POST\n\t * @param\tbool\t$xss_clean\tWhether to apply XSS filtering\n\t * @return\tmixed\n\t */\n\tpublic function post($index = NULL, $xss_clean = NULL)\n\t{\n\t\treturn $this->_fetch_from_array($_POST, $index, $xss_clean);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch an item from POST data with fallback to GET\n\t *\n\t * @param\tstring\t$index\t\tIndex for item to be fetched from $_POST or $_GET\n\t * @param\tbool\t$xss_clean\tWhether to apply XSS filtering\n\t * @return\tmixed\n\t */\n\tpublic function post_get($index, $xss_clean = NULL)\n\t{\n\t\treturn isset($_POST[$index])\n\t\t\t? $this->post($index, $xss_clean)\n\t\t\t: $this->get($index, $xss_clean);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch an item from GET data with fallback to POST\n\t *\n\t * @param\tstring\t$index\t\tIndex for item to be fetched from $_GET or $_POST\n\t * @param\tbool\t$xss_clean\tWhether to apply XSS filtering\n\t * @return\tmixed\n\t */\n\tpublic function get_post($index, $xss_clean = NULL)\n\t{\n\t\treturn isset($_GET[$index])\n\t\t\t? $this->get($index, $xss_clean)\n\t\t\t: $this->post($index, $xss_clean);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch an item from the COOKIE array\n\t *\n\t * @param\tmixed\t$index\t\tIndex for item to be fetched from $_COOKIE\n\t * @param\tbool\t$xss_clean\tWhether to apply XSS filtering\n\t * @return\tmixed\n\t */\n\tpublic function cookie($index = NULL, $xss_clean = NULL)\n\t{\n\t\treturn $this->_fetch_from_array($_COOKIE, $index, $xss_clean);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch an item from the SERVER array\n\t *\n\t * @param\tmixed\t$index\t\tIndex for item to be fetched from $_SERVER\n\t * @param\tbool\t$xss_clean\tWhether to apply XSS filtering\n\t * @return\tmixed\n\t */\n\tpublic function server($index, $xss_clean = NULL)\n\t{\n\t\treturn $this->_fetch_from_array($_SERVER, $index, $xss_clean);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Fetch an item from the php://input stream\n\t *\n\t * Useful when you need to access PUT, DELETE or PATCH request data.\n\t *\n\t * @param\tstring\t$index\t\tIndex for item to be fetched\n\t * @param\tbool\t$xss_clean\tWhether to apply XSS filtering\n\t * @return\tmixed\n\t */\n\tpublic function input_stream($index = NULL, $xss_clean = NULL)\n\t{\n\t\t// Prior to PHP 5.6, the input stream can only be read once,\n\t\t// so we'll need to check if we have already done that first.\n\t\tif ( ! is_array($this->_input_stream))\n\t\t{\n\t\t\t// $this->raw_input_stream will trigger __get().\n\t\t\tparse_str($this->raw_input_stream, $this->_input_stream);\n\t\t\tis_array($this->_input_stream) OR $this->_input_stream = array();\n\t\t}\n\n\t\treturn $this->_fetch_from_array($this->_input_stream, $index, $xss_clean);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Set cookie\n\t *\n\t * Accepts an arbitrary number of parameters (up to 7) or an associative\n\t * array in the first parameter containing all the values.\n\t *\n\t * @param\tstring|mixed[]\t$name\t\tCookie name or an array containing parameters\n\t * @param\tstring\t\t$value\t\tCookie value\n\t * @param\tint\t\t$expire\t\tCookie expiration time in seconds\n\t * @param\tstring\t\t$domain\t\tCookie domain (e.g.: '.yourdomain.com')\n\t * @param\tstring\t\t$path\t\tCookie path (default: '/')\n\t * @param\tstring\t\t$prefix\t\tCookie name prefix\n\t * @param\tbool\t\t$secure\t\tWhether to only transfer cookies via SSL\n\t * @param\tbool\t\t$httponly\tWhether to only makes the cookie accessible via HTTP (no javascript)\n\t * @return\tvoid\n\t */\n\tpublic function set_cookie($name, $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = FALSE, $httponly = FALSE)\n\t{\n\t\tif (is_array($name))\n\t\t{\n\t\t\t// always leave 'name' in last place, as the loop will break otherwise, due to $$item\n\t\t\tforeach (array('value', 'expire', 'domain', 'path', 'prefix', 'secure', 'httponly', 'name') as $item)\n\t\t\t{\n\t\t\t\tif (isset($name[$item]))\n\t\t\t\t{\n\t\t\t\t\t$$item = $name[$item];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ($prefix === '' && config_item('cookie_prefix') !== '')\n\t\t{\n\t\t\t$prefix = config_item('cookie_prefix');\n\t\t}\n\n\t\tif ($domain == '' && config_item('cookie_domain') != '')\n\t\t{\n\t\t\t$domain = config_item('cookie_domain');\n\t\t}\n\n\t\tif ($path === '/' && config_item('cookie_path') !== '/')\n\t\t{\n\t\t\t$path = config_item('cookie_path');\n\t\t}\n\n\t\tif ($secure === FALSE && config_item('cookie_secure') === TRUE)\n\t\t{\n\t\t\t$secure = config_item('cookie_secure');\n\t\t}\n\n\t\tif ($httponly === FALSE && config_item('cookie_httponly') !== FALSE)\n\t\t{\n\t\t\t$httponly = config_item('cookie_httponly');\n\t\t}\n\n\t\tif ( ! is_numeric($expire))\n\t\t{\n\t\t\t$expire = time() - 86500;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$expire = ($expire > 0) ? time() + $expire : 0;\n\t\t}\n\n\t\tsetcookie($prefix.$name, $value, $expire, $path, $domain, $secure, $httponly);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch the IP Address\n\t *\n\t * Determines and validates the visitor's IP address.\n\t *\n\t * @return\tstring\tIP address\n\t */\n\tpublic function ip_address()\n\t{\n\t\tif ($this->ip_address !== FALSE)\n\t\t{\n\t\t\treturn $this->ip_address;\n\t\t}\n\n\t\t$proxy_ips = config_item('proxy_ips');\n\t\tif ( ! empty($proxy_ips) && ! is_array($proxy_ips))\n\t\t{\n\t\t\t$proxy_ips = explode(',', str_replace(' ', '', $proxy_ips));\n\t\t}\n\n\t\t$this->ip_address = $this->server('REMOTE_ADDR');\n\n\t\tif ($proxy_ips)\n\t\t{\n\t\t\tforeach (array('HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'HTTP_X_CLIENT_IP', 'HTTP_X_CLUSTER_CLIENT_IP') as $header)\n\t\t\t{\n\t\t\t\tif (($spoof = $this->server($header)) !== NULL)\n\t\t\t\t{\n\t\t\t\t\t// Some proxies typically list the whole chain of IP\n\t\t\t\t\t// addresses through which the client has reached us.\n\t\t\t\t\t// e.g. client_ip, proxy_ip1, proxy_ip2, etc.\n\t\t\t\t\tsscanf($spoof, '%[^,]', $spoof);\n\n\t\t\t\t\tif ( ! $this->valid_ip($spoof))\n\t\t\t\t\t{\n\t\t\t\t\t\t$spoof = NULL;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ($spoof)\n\t\t\t{\n\t\t\t\tfor ($i = 0, $c = count($proxy_ips); $i < $c; $i++)\n\t\t\t\t{\n\t\t\t\t\t// Check if we have an IP address or a subnet\n\t\t\t\t\tif (strpos($proxy_ips[$i], '/') === FALSE)\n\t\t\t\t\t{\n\t\t\t\t\t\t// An IP address (and not a subnet) is specified.\n\t\t\t\t\t\t// We can compare right away.\n\t\t\t\t\t\tif ($proxy_ips[$i] === $this->ip_address)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$this->ip_address = $spoof;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t// We have a subnet ... now the heavy lifting begins\n\t\t\t\t\tisset($separator) OR $separator = $this->valid_ip($this->ip_address, 'ipv6') ? ':' : '.';\n\n\t\t\t\t\t// If the proxy entry doesn't match the IP protocol - skip it\n\t\t\t\t\tif (strpos($proxy_ips[$i], $separator) === FALSE)\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Convert the REMOTE_ADDR IP address to binary, if needed\n\t\t\t\t\tif ( ! isset($ip, $sprintf))\n\t\t\t\t\t{\n\t\t\t\t\t\tif ($separator === ':')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Make sure we're have the \"full\" IPv6 format\n\t\t\t\t\t\t\t$ip = explode(':',\n\t\t\t\t\t\t\t\tstr_replace('::',\n\t\t\t\t\t\t\t\t\tstr_repeat(':', 9 - substr_count($this->ip_address, ':')),\n\t\t\t\t\t\t\t\t\t$this->ip_address\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\tfor ($j = 0; $j < 8; $j++)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$ip[$j] = intval($ip[$j], 16);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t$sprintf = '%016b%016b%016b%016b%016b%016b%016b%016b';\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$ip = explode('.', $this->ip_address);\n\t\t\t\t\t\t\t$sprintf = '%08b%08b%08b%08b';\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$ip = vsprintf($sprintf, $ip);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Split the netmask length off the network address\n\t\t\t\t\tsscanf($proxy_ips[$i], '%[^/]/%d', $netaddr, $masklen);\n\n\t\t\t\t\t// Again, an IPv6 address is most likely in a compressed form\n\t\t\t\t\tif ($separator === ':')\n\t\t\t\t\t{\n\t\t\t\t\t\t$netaddr = explode(':', str_replace('::', str_repeat(':', 9 - substr_count($netaddr, ':')), $netaddr));\n\t\t\t\t\t\tfor ($j = 0; $j < 8; $j++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$netaddr[$i] = intval($netaddr[$j], 16);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$netaddr = explode('.', $netaddr);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Convert to binary and finally compare\n\t\t\t\t\tif (strncmp($ip, vsprintf($sprintf, $netaddr), $masklen) === 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->ip_address = $spoof;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( ! $this->valid_ip($this->ip_address))\n\t\t{\n\t\t\treturn $this->ip_address = '0.0.0.0';\n\t\t}\n\n\t\treturn $this->ip_address;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Validate IP Address\n\t *\n\t * @param\tstring\t$ip\tIP address\n\t * @param\tstring\t$which\tIP protocol: 'ipv4' or 'ipv6'\n\t * @return\tbool\n\t */\n\tpublic function valid_ip($ip, $which = '')\n\t{\n\t\tswitch (strtolower($which))\n\t\t{\n\t\t\tcase 'ipv4':\n\t\t\t\t$which = FILTER_FLAG_IPV4;\n\t\t\t\tbreak;\n\t\t\tcase 'ipv6':\n\t\t\t\t$which = FILTER_FLAG_IPV6;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t$which = NULL;\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn (bool) filter_var($ip, FILTER_VALIDATE_IP, $which);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch User Agent string\n\t *\n\t * @return\tstring|null\tUser Agent string or NULL if it doesn't exist\n\t */\n\tpublic function user_agent($xss_clean = NULL)\n\t{\n\t\treturn $this->_fetch_from_array($_SERVER, 'HTTP_USER_AGENT', $xss_clean);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Sanitize Globals\n\t *\n\t * Internal method serving for the following purposes:\n\t *\n\t *\t- Unsets $_GET data, if query strings are not enabled\n\t *\t- Cleans POST, COOKIE and SERVER data\n\t * \t- Standardizes newline characters to PHP_EOL\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _sanitize_globals()\n\t{\n\t\t// Is $_GET data allowed? If not we'll set the $_GET to an empty array\n\t\tif ($this->_allow_get_array === FALSE)\n\t\t{\n\t\t\t$_GET = array();\n\t\t}\n\t\telseif (is_array($_GET))\n\t\t{\n\t\t\tforeach ($_GET as $key => $val)\n\t\t\t{\n\t\t\t\t$_GET[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);\n\t\t\t}\n\t\t}\n\n\t\t// Clean $_POST Data\n\t\tif (is_array($_POST))\n\t\t{\n\t\t\tforeach ($_POST as $key => $val)\n\t\t\t{\n\t\t\t\t$_POST[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);\n\t\t\t}\n\t\t}\n\n\t\t// Clean $_COOKIE Data\n\t\tif (is_array($_COOKIE))\n\t\t{\n\t\t\t// Also get rid of specially treated cookies that might be set by a server\n\t\t\t// or silly application, that are of no use to a CI application anyway\n\t\t\t// but that when present will trip our 'Disallowed Key Characters' alarm\n\t\t\t// http://www.ietf.org/rfc/rfc2109.txt\n\t\t\t// note that the key names below are single quoted strings, and are not PHP variables\n\t\t\tunset(\n\t\t\t\t$_COOKIE['$Version'],\n\t\t\t\t$_COOKIE['$Path'],\n\t\t\t\t$_COOKIE['$Domain']\n\t\t\t);\n\n\t\t\tforeach ($_COOKIE as $key => $val)\n\t\t\t{\n\t\t\t\tif (($cookie_key = $this->_clean_input_keys($key)) !== FALSE)\n\t\t\t\t{\n\t\t\t\t\t$_COOKIE[$cookie_key] = $this->_clean_input_data($val);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tunset($_COOKIE[$key]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Sanitize PHP_SELF\n\t\t$_SERVER['PHP_SELF'] = strip_tags($_SERVER['PHP_SELF']);\n\n\t\tlog_message('debug', 'Global POST, GET and COOKIE data sanitized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Clean Input Data\n\t *\n\t * Internal method that aids in escaping data and\n\t * standardizing newline characters to PHP_EOL.\n\t *\n\t * @param\tstring|string[]\t$str\tInput string(s)\n\t * @return\tstring\n\t */\n\tprotected function _clean_input_data($str)\n\t{\n\t\tif (is_array($str))\n\t\t{\n\t\t\t$new_array = array();\n\t\t\tforeach (array_keys($str) as $key)\n\t\t\t{\n\t\t\t\t$new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($str[$key]);\n\t\t\t}\n\t\t\treturn $new_array;\n\t\t}\n\n\t\t/* We strip slashes if magic quotes is on to keep things consistent\n\n\t\t   NOTE: In PHP 5.4 get_magic_quotes_gpc() will always return 0 and\n\t\t         it will probably not exist in future versions at all.\n\t\t*/\n\t\tif ( ! is_php('5.4') && get_magic_quotes_gpc())\n\t\t{\n\t\t\t$str = stripslashes($str);\n\t\t}\n\n\t\t// Clean UTF-8 if supported\n\t\tif (UTF8_ENABLED === TRUE)\n\t\t{\n\t\t\t$str = $this->uni->clean_string($str);\n\t\t}\n\n\t\t// Remove control characters\n\t\t$str = remove_invisible_characters($str, FALSE);\n\n\t\t// Standardize newlines if needed\n\t\tif ($this->_standardize_newlines === TRUE)\n\t\t{\n\t\t\treturn preg_replace('/(?:\\r\\n|[\\r\\n])/', PHP_EOL, $str);\n\t\t}\n\n\t\treturn $str;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Clean Keys\n\t *\n\t * Internal method that helps to prevent malicious users\n\t * from trying to exploit keys we make sure that keys are\n\t * only named with alpha-numeric text and a few other items.\n\t *\n\t * @param\tstring\t$str\tInput string\n\t * @param\tbool\t$fatal\tWhether to terminate script exection\n\t *\t\t\t\tor to return FALSE if an invalid\n\t *\t\t\t\tkey is encountered\n\t * @return\tstring|bool\n\t */\n\tprotected function _clean_input_keys($str, $fatal = TRUE)\n\t{\n\t\tif ( ! preg_match('/^[a-z0-9:_\\/|-]+$/i', $str))\n\t\t{\n\t\t\tif ($fatal === TRUE)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tset_status_header(503);\n\t\t\t\techo 'Disallowed Key Characters.';\n\t\t\t\texit(7); // EXIT_USER_INPUT\n\t\t\t}\n\t\t}\n\n\t\t// Clean UTF-8 if supported\n\t\tif (UTF8_ENABLED === TRUE)\n\t\t{\n\t\t\treturn $this->uni->clean_string($str);\n\t\t}\n\n\t\treturn $str;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Request Headers\n\t *\n\t * @param\tbool\t$xss_clean\tWhether to apply XSS filtering\n\t * @return\tarray\n\t */\n\tpublic function request_headers($xss_clean = FALSE)\n\t{\n\t\t// If header is already defined, return it immediately\n\t\tif ( ! empty($this->headers))\n\t\t{\n\t\t\treturn $this->_fetch_from_array($this->headers, NULL, $xss_clean);\n\t\t}\n\n\t\t// In Apache, you can simply call apache_request_headers()\n\t\tif (function_exists('apache_request_headers'))\n\t\t{\n\t\t\t$this->headers = apache_request_headers();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tisset($_SERVER['CONTENT_TYPE']) && $this->headers['Content-Type'] = $_SERVER['CONTENT_TYPE'];\n\n\t\t\tforeach ($_SERVER as $key => $val)\n\t\t\t{\n\t\t\t\tif (sscanf($key, 'HTTP_%s', $header) === 1)\n\t\t\t\t{\n\t\t\t\t\t// take SOME_HEADER and turn it into Some-Header\n\t\t\t\t\t$header = str_replace('_', ' ', strtolower($header));\n\t\t\t\t\t$header = str_replace(' ', '-', ucwords($header));\n\n\t\t\t\t\t$this->headers[$header] = $_SERVER[$key];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn $this->_fetch_from_array($this->headers, NULL, $xss_clean);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Request Header\n\t *\n\t * Returns the value of a single member of the headers class member\n\t *\n\t * @param\tstring\t\t$index\t\tHeader name\n\t * @param\tbool\t\t$xss_clean\tWhether to apply XSS filtering\n\t * @return\tstring|null\tThe requested header on success or NULL on failure\n\t */\n\tpublic function get_request_header($index, $xss_clean = FALSE)\n\t{\n\t\tstatic $headers;\n\n\t\tif ( ! isset($headers))\n\t\t{\n\t\t\tempty($this->headers) && $this->request_headers();\n\t\t\tforeach ($this->headers as $key => $value)\n\t\t\t{\n\t\t\t\t$headers[strtolower($key)] = $value;\n\t\t\t}\n\t\t}\n\n\t\t$index = strtolower($index);\n\n\t\tif ( ! isset($headers[$index]))\n\t\t{\n\t\t\treturn NULL;\n\t\t}\n\n\t\treturn ($xss_clean === TRUE)\n\t\t\t? $this->security->xss_clean($headers[$index])\n\t\t\t: $headers[$index];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is AJAX request?\n\t *\n\t * Test to see if a request contains the HTTP_X_REQUESTED_WITH header.\n\t *\n\t * @return \tbool\n\t */\n\tpublic function is_ajax_request()\n\t{\n\t\treturn ( ! empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is CLI request?\n\t *\n\t * Test to see if a request was made from the command line.\n\t *\n\t * @deprecated\t3.0.0\tUse is_cli() instead\n\t * @return\tbool\n\t */\n\tpublic function is_cli_request()\n\t{\n\t\treturn is_cli();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Request Method\n\t *\n\t * Return the request method\n\t *\n\t * @param\tbool\t$upper\tWhether to return in upper or lower case\n\t *\t\t\t\t(default: FALSE)\n\t * @return \tstring\n\t */\n\tpublic function method($upper = FALSE)\n\t{\n\t\treturn ($upper)\n\t\t\t? strtoupper($this->server('REQUEST_METHOD'))\n\t\t\t: strtolower($this->server('REQUEST_METHOD'));\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Magic __get()\n\t *\n\t * Allows read access to protected properties\n\t *\n\t * @param\tstring\t$name\n\t * @return\tmixed\n\t */\n\tpublic function __get($name)\n\t{\n\t\tif ($name === 'raw_input_stream')\n\t\t{\n\t\t\tisset($this->_raw_input_stream) OR $this->_raw_input_stream = file_get_contents('php://input');\n\t\t\treturn $this->_raw_input_stream;\n\t\t}\n\t\telseif ($name === 'ip_address')\n\t\t{\n\t\t\treturn $this->ip_address;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "system/core/Lang.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Language Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLanguage\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/language.html\n */\nclass CI_Lang {\n\n\t/**\n\t * List of translations\n\t *\n\t * @var\tarray\n\t */\n\tpublic $language =\tarray();\n\n\t/**\n\t * List of loaded language files\n\t *\n\t * @var\tarray\n\t */\n\tpublic $is_loaded =\tarray();\n\n\t/**\n\t * Class constructor\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\tlog_message('info', 'Language Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Load a language file\n\t *\n\t * @param\tmixed\t$langfile\tLanguage file name\n\t * @param\tstring\t$idiom\t\tLanguage name (english, etc.)\n\t * @param\tbool\t$return\t\tWhether to return the loaded array of translations\n\t * @param \tbool\t$add_suffix\tWhether to add suffix to $langfile\n\t * @param \tstring\t$alt_path\tAlternative path to look for the language file\n\t *\n\t * @return\tvoid|string[]\tArray containing translations, if $return is set to TRUE\n\t */\n\tpublic function load($langfile, $idiom = '', $return = FALSE, $add_suffix = TRUE, $alt_path = '')\n\t{\n\t\tif (is_array($langfile))\n\t\t{\n\t\t\tforeach ($langfile as $value)\n\t\t\t{\n\t\t\t\t$this->load($value, $idiom, $return, $add_suffix, $alt_path);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t$langfile = str_replace('.php', '', $langfile);\n\n\t\tif ($add_suffix === TRUE)\n\t\t{\n\t\t\t$langfile = preg_replace('/_lang$/', '', $langfile).'_lang';\n\t\t}\n\n\t\t$langfile .= '.php';\n\n\t\tif (empty($idiom) OR ! preg_match('/^[a-z_-]+$/i', $idiom))\n\t\t{\n\t\t\t$config =& get_config();\n\t\t\t$idiom = empty($config['language']) ? 'english' : $config['language'];\n\t\t}\n\n\t\tif ($return === FALSE && isset($this->is_loaded[$langfile]) && $this->is_loaded[$langfile] === $idiom)\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\t// Load the base file, so any others found can override it\n\t\t$basepath = BASEPATH.'language/'.$idiom.'/'.$langfile;\n\t\tif (($found = file_exists($basepath)) === TRUE)\n\t\t{\n\t\t\tinclude($basepath);\n\t\t}\n\n\t\t// Do we have an alternative path to look in?\n\t\tif ($alt_path !== '')\n\t\t{\n\t\t\t$alt_path .= 'language/'.$idiom.'/'.$langfile;\n\t\t\tif (file_exists($alt_path))\n\t\t\t{\n\t\t\t\tinclude($alt_path);\n\t\t\t\t$found = TRUE;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tforeach (get_instance()->load->get_package_paths(TRUE) as $package_path)\n\t\t\t{\n\t\t\t\t$package_path .= 'language/'.$idiom.'/'.$langfile;\n\t\t\t\tif ($basepath !== $package_path && file_exists($package_path))\n\t\t\t\t{\n\t\t\t\t\tinclude($package_path);\n\t\t\t\t\t$found = TRUE;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ($found !== TRUE)\n\t\t{\n\t\t\tshow_error('Unable to load the requested language file: language/'.$idiom.'/'.$langfile);\n\t\t}\n\n\t\tif ( ! isset($lang) OR ! is_array($lang))\n\t\t{\n\t\t\tlog_message('error', 'Language file contains no data: language/'.$idiom.'/'.$langfile);\n\n\t\t\tif ($return === TRUE)\n\t\t\t{\n\t\t\t\treturn array();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif ($return === TRUE)\n\t\t{\n\t\t\treturn $lang;\n\t\t}\n\n\t\t$this->is_loaded[$langfile] = $idiom;\n\t\t$this->language = array_merge($this->language, $lang);\n\n\t\tlog_message('info', 'Language file loaded: language/'.$idiom.'/'.$langfile);\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Language line\n\t *\n\t * Fetches a single line of text from the language array\n\t *\n\t * @param\tstring\t$line\t\tLanguage line key\n\t * @param\tbool\t$log_errors\tWhether to log an error message if the line is not found\n\t * @return\tstring\tTranslation\n\t */\n\tpublic function line($line, $log_errors = TRUE)\n\t{\n\t\t$value = isset($this->language[$line]) ? $this->language[$line] : FALSE;\n\n\t\t// Because killer robots like unicorns!\n\t\tif ($value === FALSE && $log_errors === TRUE)\n\t\t{\n\t\t\tlog_message('error', 'Could not find the language line \"'.$line.'\"');\n\t\t}\n\n\t\treturn $value;\n\t}\n\n}\n"
  },
  {
    "path": "system/core/Loader.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Loader Class\n *\n * Loads framework components.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLoader\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/loader.html\n */\nclass CI_Loader {\n\n\t// All these are set automatically. Don't mess with them.\n\t/**\n\t * Nesting level of the output buffering mechanism\n\t *\n\t * @var\tint\n\t */\n\tprotected $_ci_ob_level;\n\n\t/**\n\t * List of paths to load views from\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_ci_view_paths =\tarray(VIEWPATH\t=> TRUE);\n\n\t/**\n\t * List of paths to load libraries from\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_ci_library_paths =\tarray(APPPATH, BASEPATH);\n\n\t/**\n\t * List of paths to load models from\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_ci_model_paths =\tarray(APPPATH);\n\n\t/**\n\t * List of paths to load helpers from\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_ci_helper_paths =\tarray(APPPATH, BASEPATH);\n\n\t/**\n\t * List of cached variables\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_ci_cached_vars =\tarray();\n\n\t/**\n\t * List of loaded classes\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_ci_classes =\tarray();\n\n\t/**\n\t * List of loaded models\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_ci_models =\tarray();\n\n\t/**\n\t * List of loaded helpers\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_ci_helpers =\tarray();\n\n\t/**\n\t * List of class name mappings\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_ci_varmap =\tarray(\n\t\t'unit_test' => 'unit',\n\t\t'user_agent' => 'agent'\n\t);\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Sets component load paths, gets the initial output buffering level.\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\t$this->_ci_ob_level = ob_get_level();\n\t\t$this->_ci_classes =& is_loaded();\n\n\t\tlog_message('info', 'Loader Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initializer\n\t *\n\t * @todo\tFigure out a way to move this to the constructor\n\t *\t\twithout breaking *package_path*() methods.\n\t * @uses\tCI_Loader::_ci_autoloader()\n\t * @used-by\tCI_Controller::__construct()\n\t * @return\tvoid\n\t */\n\tpublic function initialize()\n\t{\n\t\t$this->_ci_autoloader();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is Loaded\n\t *\n\t * A utility method to test if a class is in the self::$_ci_classes array.\n\t *\n\t * @used-by\tMainly used by Form Helper function _get_validation_object().\n\t *\n\t * @param \tstring\t\t$class\tClass name to check for\n\t * @return \tstring|bool\tClass object name if loaded or FALSE\n\t */\n\tpublic function is_loaded($class)\n\t{\n\t\treturn array_search(ucfirst($class), $this->_ci_classes, TRUE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Library Loader\n\t *\n\t * Loads and instantiates libraries.\n\t * Designed to be called from application controllers.\n\t *\n\t * @param\tstring\t$library\tLibrary name\n\t * @param\tarray\t$params\t\tOptional parameters to pass to the library class constructor\n\t * @param\tstring\t$object_name\tAn optional object name to assign to\n\t * @return\tobject\n\t */\n\tpublic function library($library, $params = NULL, $object_name = NULL)\n\t{\n\t\tif (empty($library))\n\t\t{\n\t\t\treturn $this;\n\t\t}\n\t\telseif (is_array($library))\n\t\t{\n\t\t\tforeach ($library as $key => $value)\n\t\t\t{\n\t\t\t\tif (is_int($key))\n\t\t\t\t{\n\t\t\t\t\t$this->library($value, $params);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$this->library($key, $params, $value);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn $this;\n\t\t}\n\n\t\tif ($params !== NULL && ! is_array($params))\n\t\t{\n\t\t\t$params = NULL;\n\t\t}\n\n\t\t$this->_ci_load_library($library, $params, $object_name);\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Model Loader\n\t *\n\t * Loads and instantiates models.\n\t *\n\t * @param\tstring\t$model\t\tModel name\n\t * @param\tstring\t$name\t\tAn optional object name to assign to\n\t * @param\tbool\t$db_conn\tAn optional database connection configuration to initialize\n\t * @return\tobject\n\t */\n\tpublic function model($model, $name = '', $db_conn = FALSE)\n\t{\n\t\tif (empty($model))\n\t\t{\n\t\t\treturn $this;\n\t\t}\n\t\telseif (is_array($model))\n\t\t{\n\t\t\tforeach ($model as $key => $value)\n\t\t\t{\n\t\t\t\tis_int($key) ? $this->model($value, '', $db_conn) : $this->model($key, $value, $db_conn);\n\t\t\t}\n\n\t\t\treturn $this;\n\t\t}\n\n\t\t$path = '';\n\n\t\t// Is the model in a sub-folder? If so, parse out the filename and path.\n\t\tif (($last_slash = strrpos($model, '/')) !== FALSE)\n\t\t{\n\t\t\t// The path is in front of the last slash\n\t\t\t$path = substr($model, 0, ++$last_slash);\n\n\t\t\t// And the model name behind it\n\t\t\t$model = substr($model, $last_slash);\n\t\t}\n\n\t\tif (empty($name))\n\t\t{\n\t\t\t$name = $model;\n\t\t}\n\n\t\tif (in_array($name, $this->_ci_models, TRUE))\n\t\t{\n\t\t\treturn $this;\n\t\t}\n\n\t\t$CI =& get_instance();\n\t\tif (isset($CI->$name))\n\t\t{\n\t\t\tthrow new RuntimeException('The model name you are loading is the name of a resource that is already being used: '.$name);\n\t\t}\n\n\t\tif ($db_conn !== FALSE && ! class_exists('CI_DB', FALSE))\n\t\t{\n\t\t\tif ($db_conn === TRUE)\n\t\t\t{\n\t\t\t\t$db_conn = '';\n\t\t\t}\n\n\t\t\t$this->database($db_conn, FALSE, TRUE);\n\t\t}\n\n\t\t// Note: All of the code under this condition used to be just:\n\t\t//\n\t\t//       load_class('Model', 'core');\n\t\t//\n\t\t//       However, load_class() instantiates classes\n\t\t//       to cache them for later use and that prevents\n\t\t//       MY_Model from being an abstract class and is\n\t\t//       sub-optimal otherwise anyway.\n\t\tif ( ! class_exists('CI_Model', FALSE))\n\t\t{\n\t\t\t$app_path = APPPATH.'core'.DIRECTORY_SEPARATOR;\n\t\t\tif (file_exists($app_path.'Model.php'))\n\t\t\t{\n\t\t\t\trequire_once($app_path.'Model.php');\n\t\t\t\tif ( ! class_exists('CI_Model', FALSE))\n\t\t\t\t{\n\t\t\t\t\tthrow new RuntimeException($app_path.\"Model.php exists, but doesn't declare class CI_Model\");\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ( ! class_exists('CI_Model', FALSE))\n\t\t\t{\n\t\t\t\trequire_once(BASEPATH.'core'.DIRECTORY_SEPARATOR.'Model.php');\n\t\t\t}\n\n\t\t\t$class = config_item('subclass_prefix').'Model';\n\t\t\tif (file_exists($app_path.$class.'.php'))\n\t\t\t{\n\t\t\t\trequire_once($app_path.$class.'.php');\n\t\t\t\tif ( ! class_exists($class, FALSE))\n\t\t\t\t{\n\t\t\t\t\tthrow new RuntimeException($app_path.$class.\".php exists, but doesn't declare class \".$class);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$model = ucfirst($model);\n\t\tif ( ! class_exists($model, FALSE))\n\t\t{\n\t\t\tforeach ($this->_ci_model_paths as $mod_path)\n\t\t\t{\n\t\t\t\tif ( ! file_exists($mod_path.'models/'.$path.$model.'.php'))\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\trequire_once($mod_path.'models/'.$path.$model.'.php');\n\t\t\t\tif ( ! class_exists($model, FALSE))\n\t\t\t\t{\n\t\t\t\t\tthrow new RuntimeException($mod_path.\"models/\".$path.$model.\".php exists, but doesn't declare class \".$model);\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif ( ! class_exists($model, FALSE))\n\t\t\t{\n\t\t\t\tthrow new RuntimeException('Unable to locate the model you have specified: '.$model);\n\t\t\t}\n\t\t}\n\t\telseif ( ! is_subclass_of($model, 'CI_Model'))\n\t\t{\n\t\t\tthrow new RuntimeException(\"Class \".$model.\" already exists and doesn't extend CI_Model\");\n\t\t}\n\n\t\t$this->_ci_models[] = $name;\n\t\t$CI->$name = new $model();\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Database Loader\n\t *\n\t * @param\tmixed\t$params\t\tDatabase configuration options\n\t * @param\tbool\t$return \tWhether to return the database object\n\t * @param\tbool\t$query_builder\tWhether to enable Query Builder\n\t *\t\t\t\t\t(overrides the configuration setting)\n\t *\n\t * @return\tobject|bool\tDatabase object if $return is set to TRUE,\n\t *\t\t\t\t\tFALSE on failure, CI_Loader instance in any other case\n\t */\n\tpublic function database($params = '', $return = FALSE, $query_builder = NULL)\n\t{\n\t\t// Grab the super object\n\t\t$CI =& get_instance();\n\n\t\t// Do we even need to load the database class?\n\t\tif ($return === FALSE && $query_builder === NULL && isset($CI->db) && is_object($CI->db) && ! empty($CI->db->conn_id))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\trequire_once(BASEPATH.'database/DB.php');\n\n\t\tif ($return === TRUE)\n\t\t{\n\t\t\treturn DB($params, $query_builder);\n\t\t}\n\n\t\t// Initialize the db variable. Needed to prevent\n\t\t// reference errors with some configurations\n\t\t$CI->db = '';\n\n\t\t// Load the DB class\n\t\t$CI->db =& DB($params, $query_builder);\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Load the Database Utilities Class\n\t *\n\t * @param\tobject\t$db\tDatabase object\n\t * @param\tbool\t$return\tWhether to return the DB Utilities class object or not\n\t * @return\tobject\n\t */\n\tpublic function dbutil($db = NULL, $return = FALSE)\n\t{\n\t\t$CI =& get_instance();\n\n\t\tif ( ! is_object($db) OR ! ($db instanceof CI_DB))\n\t\t{\n\t\t\tclass_exists('CI_DB', FALSE) OR $this->database();\n\t\t\t$db =& $CI->db;\n\t\t}\n\n\t\trequire_once(BASEPATH.'database/DB_utility.php');\n\t\trequire_once(BASEPATH.'database/drivers/'.$db->dbdriver.'/'.$db->dbdriver.'_utility.php');\n\t\t$class = 'CI_DB_'.$db->dbdriver.'_utility';\n\n\t\tif ($return === TRUE)\n\t\t{\n\t\t\treturn new $class($db);\n\t\t}\n\n\t\t$CI->dbutil = new $class($db);\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Load the Database Forge Class\n\t *\n\t * @param\tobject\t$db\tDatabase object\n\t * @param\tbool\t$return\tWhether to return the DB Forge class object or not\n\t * @return\tobject\n\t */\n\tpublic function dbforge($db = NULL, $return = FALSE)\n\t{\n\t\t$CI =& get_instance();\n\t\tif ( ! is_object($db) OR ! ($db instanceof CI_DB))\n\t\t{\n\t\t\tclass_exists('CI_DB', FALSE) OR $this->database();\n\t\t\t$db =& $CI->db;\n\t\t}\n\n\t\trequire_once(BASEPATH.'database/DB_forge.php');\n\t\trequire_once(BASEPATH.'database/drivers/'.$db->dbdriver.'/'.$db->dbdriver.'_forge.php');\n\n\t\tif ( ! empty($db->subdriver))\n\t\t{\n\t\t\t$driver_path = BASEPATH.'database/drivers/'.$db->dbdriver.'/subdrivers/'.$db->dbdriver.'_'.$db->subdriver.'_forge.php';\n\t\t\tif (file_exists($driver_path))\n\t\t\t{\n\t\t\t\trequire_once($driver_path);\n\t\t\t\t$class = 'CI_DB_'.$db->dbdriver.'_'.$db->subdriver.'_forge';\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$class = 'CI_DB_'.$db->dbdriver.'_forge';\n\t\t}\n\n\t\tif ($return === TRUE)\n\t\t{\n\t\t\treturn new $class($db);\n\t\t}\n\n\t\t$CI->dbforge = new $class($db);\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * View Loader\n\t *\n\t * Loads \"view\" files.\n\t *\n\t * @param\tstring\t$view\tView name\n\t * @param\tarray\t$vars\tAn associative array of data\n\t *\t\t\t\tto be extracted for use in the view\n\t * @param\tbool\t$return\tWhether to return the view output\n\t *\t\t\t\tor leave it to the Output class\n\t * @return\tobject|string\n\t */\n\tpublic function view($view, $vars = array(), $return = FALSE)\n\t{\n\t\treturn $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_return' => $return));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Generic File Loader\n\t *\n\t * @param\tstring\t$path\tFile path\n\t * @param\tbool\t$return\tWhether to return the file output\n\t * @return\tobject|string\n\t */\n\tpublic function file($path, $return = FALSE)\n\t{\n\t\treturn $this->_ci_load(array('_ci_path' => $path, '_ci_return' => $return));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Variables\n\t *\n\t * Once variables are set they become available within\n\t * the controller class and its \"view\" files.\n\t *\n\t * @param\tarray|object|string\t$vars\n\t *\t\t\t\t\tAn associative array or object containing values\n\t *\t\t\t\t\tto be set, or a value's name if string\n\t * @param \tstring\t$val\tValue to set, only used if $vars is a string\n\t * @return\tobject\n\t */\n\tpublic function vars($vars, $val = '')\n\t{\n\t\tif (is_string($vars))\n\t\t{\n\t\t\t$vars = array($vars => $val);\n\t\t}\n\n\t\t$vars = $this->_ci_object_to_array($vars);\n\n\t\tif (is_array($vars) && count($vars) > 0)\n\t\t{\n\t\t\tforeach ($vars as $key => $val)\n\t\t\t{\n\t\t\t\t$this->_ci_cached_vars[$key] = $val;\n\t\t\t}\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Clear Cached Variables\n\t *\n\t * Clears the cached variables.\n\t *\n\t * @return\tCI_Loader\n\t */\n\tpublic function clear_vars()\n\t{\n\t\t$this->_ci_cached_vars = array();\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Variable\n\t *\n\t * Check if a variable is set and retrieve it.\n\t *\n\t * @param\tstring\t$key\tVariable name\n\t * @return\tmixed\tThe variable or NULL if not found\n\t */\n\tpublic function get_var($key)\n\t{\n\t\treturn isset($this->_ci_cached_vars[$key]) ? $this->_ci_cached_vars[$key] : NULL;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Variables\n\t *\n\t * Retrieves all loaded variables.\n\t *\n\t * @return\tarray\n\t */\n\tpublic function get_vars()\n\t{\n\t\treturn $this->_ci_cached_vars;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Helper Loader\n\t *\n\t * @param\tstring|string[]\t$helpers\tHelper name(s)\n\t * @return\tobject\n\t */\n\tpublic function helper($helpers = array())\n\t{\n\t\tforeach ($this->_ci_prep_filename($helpers, '_helper') as $helper)\n\t\t{\n\t\t\tif (isset($this->_ci_helpers[$helper]))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Is this a helper extension request?\n\t\t\t$ext_helper = config_item('subclass_prefix').$helper;\n\t\t\t$ext_loaded = FALSE;\n\t\t\tforeach ($this->_ci_helper_paths as $path)\n\t\t\t{\n\t\t\t\tif (file_exists($path.'helpers/'.$ext_helper.'.php'))\n\t\t\t\t{\n\t\t\t\t\tinclude_once($path.'helpers/'.$ext_helper.'.php');\n\t\t\t\t\t$ext_loaded = TRUE;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If we have loaded extensions - check if the base one is here\n\t\t\tif ($ext_loaded === TRUE)\n\t\t\t{\n\t\t\t\t$base_helper = BASEPATH.'helpers/'.$helper.'.php';\n\t\t\t\tif ( ! file_exists($base_helper))\n\t\t\t\t{\n\t\t\t\t\tshow_error('Unable to load the requested file: helpers/'.$helper.'.php');\n\t\t\t\t}\n\n\t\t\t\tinclude_once($base_helper);\n\t\t\t\t$this->_ci_helpers[$helper] = TRUE;\n\t\t\t\tlog_message('info', 'Helper loaded: '.$helper);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// No extensions found ... try loading regular helpers and/or overrides\n\t\t\tforeach ($this->_ci_helper_paths as $path)\n\t\t\t{\n\t\t\t\tif (file_exists($path.'helpers/'.$helper.'.php'))\n\t\t\t\t{\n\t\t\t\t\tinclude_once($path.'helpers/'.$helper.'.php');\n\n\t\t\t\t\t$this->_ci_helpers[$helper] = TRUE;\n\t\t\t\t\tlog_message('info', 'Helper loaded: '.$helper);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// unable to load the helper\n\t\t\tif ( ! isset($this->_ci_helpers[$helper]))\n\t\t\t{\n\t\t\t\tshow_error('Unable to load the requested file: helpers/'.$helper.'.php');\n\t\t\t}\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Load Helpers\n\t *\n\t * An alias for the helper() method in case the developer has\n\t * written the plural form of it.\n\t *\n\t * @uses\tCI_Loader::helper()\n\t * @param\tstring|string[]\t$helpers\tHelper name(s)\n\t * @return\tobject\n\t */\n\tpublic function helpers($helpers = array())\n\t{\n\t\treturn $this->helper($helpers);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Language Loader\n\t *\n\t * Loads language files.\n\t *\n\t * @param\tstring|string[]\t$files\tList of language file names to load\n\t * @param\tstring\t\tLanguage name\n\t * @return\tobject\n\t */\n\tpublic function language($files, $lang = '')\n\t{\n\t\tget_instance()->lang->load($files, $lang);\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Config Loader\n\t *\n\t * Loads a config file (an alias for CI_Config::load()).\n\t *\n\t * @uses\tCI_Config::load()\n\t * @param\tstring\t$file\t\t\tConfiguration file name\n\t * @param\tbool\t$use_sections\t\tWhether configuration values should be loaded into their own section\n\t * @param\tbool\t$fail_gracefully\tWhether to just return FALSE or display an error message\n\t * @return\tbool\tTRUE if the file was loaded correctly or FALSE on failure\n\t */\n\tpublic function config($file, $use_sections = FALSE, $fail_gracefully = FALSE)\n\t{\n\t\treturn get_instance()->config->load($file, $use_sections, $fail_gracefully);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Driver Loader\n\t *\n\t * Loads a driver library.\n\t *\n\t * @param\tstring|string[]\t$library\tDriver name(s)\n\t * @param\tarray\t\t$params\t\tOptional parameters to pass to the driver\n\t * @param\tstring\t\t$object_name\tAn optional object name to assign to\n\t *\n\t * @return\tobject|bool\tObject or FALSE on failure if $library is a string\n\t *\t\t\t\tand $object_name is set. CI_Loader instance otherwise.\n\t */\n\tpublic function driver($library, $params = NULL, $object_name = NULL)\n\t{\n\t\tif (is_array($library))\n\t\t{\n\t\t\tforeach ($library as $key => $value)\n\t\t\t{\n\t\t\t\tif (is_int($key))\n\t\t\t\t{\n\t\t\t\t\t$this->driver($value, $params);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$this->driver($key, $params, $value);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn $this;\n\t\t}\n\t\telseif (empty($library))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ( ! class_exists('CI_Driver_Library', FALSE))\n\t\t{\n\t\t\t// We aren't instantiating an object here, just making the base class available\n\t\t\trequire BASEPATH.'libraries/Driver.php';\n\t\t}\n\n\t\t// We can save the loader some time since Drivers will *always* be in a subfolder,\n\t\t// and typically identically named to the library\n\t\tif ( ! strpos($library, '/'))\n\t\t{\n\t\t\t$library = ucfirst($library).'/'.$library;\n\t\t}\n\n\t\treturn $this->library($library, $params, $object_name);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add Package Path\n\t *\n\t * Prepends a parent path to the library, model, helper and config\n\t * path arrays.\n\t *\n\t * @see\tCI_Loader::$_ci_library_paths\n\t * @see\tCI_Loader::$_ci_model_paths\n\t * @see CI_Loader::$_ci_helper_paths\n\t * @see CI_Config::$_config_paths\n\t *\n\t * @param\tstring\t$path\t\tPath to add\n\t * @param \tbool\t$view_cascade\t(default: TRUE)\n\t * @return\tobject\n\t */\n\tpublic function add_package_path($path, $view_cascade = TRUE)\n\t{\n\t\t$path = rtrim($path, '/').'/';\n\n\t\tarray_unshift($this->_ci_library_paths, $path);\n\t\tarray_unshift($this->_ci_model_paths, $path);\n\t\tarray_unshift($this->_ci_helper_paths, $path);\n\n\t\t$this->_ci_view_paths = array($path.'views/' => $view_cascade) + $this->_ci_view_paths;\n\n\t\t// Add config file path\n\t\t$config =& $this->_ci_get_component('config');\n\t\t$config->_config_paths[] = $path;\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Package Paths\n\t *\n\t * Return a list of all package paths.\n\t *\n\t * @param\tbool\t$include_base\tWhether to include BASEPATH (default: FALSE)\n\t * @return\tarray\n\t */\n\tpublic function get_package_paths($include_base = FALSE)\n\t{\n\t\treturn ($include_base === TRUE) ? $this->_ci_library_paths : $this->_ci_model_paths;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Remove Package Path\n\t *\n\t * Remove a path from the library, model, helper and/or config\n\t * path arrays if it exists. If no path is provided, the most recently\n\t * added path will be removed removed.\n\t *\n\t * @param\tstring\t$path\tPath to remove\n\t * @return\tobject\n\t */\n\tpublic function remove_package_path($path = '')\n\t{\n\t\t$config =& $this->_ci_get_component('config');\n\n\t\tif ($path === '')\n\t\t{\n\t\t\tarray_shift($this->_ci_library_paths);\n\t\t\tarray_shift($this->_ci_model_paths);\n\t\t\tarray_shift($this->_ci_helper_paths);\n\t\t\tarray_shift($this->_ci_view_paths);\n\t\t\tarray_pop($config->_config_paths);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$path = rtrim($path, '/').'/';\n\t\t\tforeach (array('_ci_library_paths', '_ci_model_paths', '_ci_helper_paths') as $var)\n\t\t\t{\n\t\t\t\tif (($key = array_search($path, $this->{$var})) !== FALSE)\n\t\t\t\t{\n\t\t\t\t\tunset($this->{$var}[$key]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (isset($this->_ci_view_paths[$path.'views/']))\n\t\t\t{\n\t\t\t\tunset($this->_ci_view_paths[$path.'views/']);\n\t\t\t}\n\n\t\t\tif (($key = array_search($path, $config->_config_paths)) !== FALSE)\n\t\t\t{\n\t\t\t\tunset($config->_config_paths[$key]);\n\t\t\t}\n\t\t}\n\n\t\t// make sure the application default paths are still in the array\n\t\t$this->_ci_library_paths = array_unique(array_merge($this->_ci_library_paths, array(APPPATH, BASEPATH)));\n\t\t$this->_ci_helper_paths = array_unique(array_merge($this->_ci_helper_paths, array(APPPATH, BASEPATH)));\n\t\t$this->_ci_model_paths = array_unique(array_merge($this->_ci_model_paths, array(APPPATH)));\n\t\t$this->_ci_view_paths = array_merge($this->_ci_view_paths, array(APPPATH.'views/' => TRUE));\n\t\t$config->_config_paths = array_unique(array_merge($config->_config_paths, array(APPPATH)));\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Internal CI Data Loader\n\t *\n\t * Used to load views and files.\n\t *\n\t * Variables are prefixed with _ci_ to avoid symbol collision with\n\t * variables made available to view files.\n\t *\n\t * @used-by\tCI_Loader::view()\n\t * @used-by\tCI_Loader::file()\n\t * @param\tarray\t$_ci_data\tData to load\n\t * @return\tobject\n\t */\n\tprotected function _ci_load($_ci_data)\n\t{\n\t\t// Set the default data variables\n\t\tforeach (array('_ci_view', '_ci_vars', '_ci_path', '_ci_return') as $_ci_val)\n\t\t{\n\t\t\t$$_ci_val = isset($_ci_data[$_ci_val]) ? $_ci_data[$_ci_val] : FALSE;\n\t\t}\n\n\t\t$file_exists = FALSE;\n\n\t\t// Set the path to the requested file\n\t\tif (is_string($_ci_path) && $_ci_path !== '')\n\t\t{\n\t\t\t$_ci_x = explode('/', $_ci_path);\n\t\t\t$_ci_file = end($_ci_x);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$_ci_ext = pathinfo($_ci_view, PATHINFO_EXTENSION);\n\t\t\t$_ci_file = ($_ci_ext === '') ? $_ci_view.'.php' : $_ci_view;\n\n\t\t\tforeach ($this->_ci_view_paths as $_ci_view_file => $cascade)\n\t\t\t{\n\t\t\t\tif (file_exists($_ci_view_file.$_ci_file))\n\t\t\t\t{\n\t\t\t\t\t$_ci_path = $_ci_view_file.$_ci_file;\n\t\t\t\t\t$file_exists = TRUE;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( ! $cascade)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( ! $file_exists && ! file_exists($_ci_path))\n\t\t{\n\t\t\tshow_error('Unable to load the requested file: '.$_ci_file);\n\t\t}\n\n\t\t// This allows anything loaded using $this->load (views, files, etc.)\n\t\t// to become accessible from within the Controller and Model functions.\n\t\t$_ci_CI =& get_instance();\n\t\tforeach (get_object_vars($_ci_CI) as $_ci_key => $_ci_var)\n\t\t{\n\t\t\tif ( ! isset($this->$_ci_key))\n\t\t\t{\n\t\t\t\t$this->$_ci_key =& $_ci_CI->$_ci_key;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t * Extract and cache variables\n\t\t *\n\t\t * You can either set variables using the dedicated $this->load->vars()\n\t\t * function or via the second parameter of this function. We'll merge\n\t\t * the two types and cache them so that views that are embedded within\n\t\t * other views can have access to these variables.\n\t\t */\n\t\tif (is_array($_ci_vars))\n\t\t{\n\t\t\tforeach (array_keys($_ci_vars) as $key)\n\t\t\t{\n\t\t\t\tif (strncmp($key, '_ci_', 4) === 0)\n\t\t\t\t{\n\t\t\t\t\tunset($_ci_vars[$key]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars);\n\t\t}\n\t\textract($this->_ci_cached_vars);\n\n\t\t/*\n\t\t * Buffer the output\n\t\t *\n\t\t * We buffer the output for two reasons:\n\t\t * 1. Speed. You get a significant speed boost.\n\t\t * 2. So that the final rendered template can be post-processed by\n\t\t *\tthe output class. Why do we need post processing? For one thing,\n\t\t *\tin order to show the elapsed page load time. Unless we can\n\t\t *\tintercept the content right before it's sent to the browser and\n\t\t *\tthen stop the timer it won't be accurate.\n\t\t */\n\t\tob_start();\n\n\t\t// If the PHP installation does not support short tags we'll\n\t\t// do a little string replacement, changing the short tags\n\t\t// to standard PHP echo statements.\n\t\tif ( ! is_php('5.4') && ! ini_get('short_open_tag') && config_item('rewrite_short_tags') === TRUE)\n\t\t{\n\t\t\techo eval('?>'.preg_replace('/;*\\s*\\?>/', '; ?>', str_replace('<?=', '<?php echo ', file_get_contents($_ci_path))));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tinclude($_ci_path); // include() vs include_once() allows for multiple views with the same name\n\t\t}\n\n\t\tlog_message('info', 'File loaded: '.$_ci_path);\n\n\t\t// Return the file data if requested\n\t\tif ($_ci_return === TRUE)\n\t\t{\n\t\t\t$buffer = ob_get_contents();\n\t\t\t@ob_end_clean();\n\t\t\treturn $buffer;\n\t\t}\n\n\t\t/*\n\t\t * Flush the buffer... or buff the flusher?\n\t\t *\n\t\t * In order to permit views to be nested within\n\t\t * other views, we need to flush the content back out whenever\n\t\t * we are beyond the first level of output buffering so that\n\t\t * it can be seen and included properly by the first included\n\t\t * template and any subsequent ones. Oy!\n\t\t */\n\t\tif (ob_get_level() > $this->_ci_ob_level + 1)\n\t\t{\n\t\t\tob_end_flush();\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$_ci_CI->output->append_output(ob_get_contents());\n\t\t\t@ob_end_clean();\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Internal CI Library Loader\n\t *\n\t * @used-by\tCI_Loader::library()\n\t * @uses\tCI_Loader::_ci_init_library()\n\t *\n\t * @param\tstring\t$class\t\tClass name to load\n\t * @param\tmixed\t$params\t\tOptional parameters to pass to the class constructor\n\t * @param\tstring\t$object_name\tOptional object name to assign to\n\t * @return\tvoid\n\t */\n\tprotected function _ci_load_library($class, $params = NULL, $object_name = NULL)\n\t{\n\t\t// Get the class name, and while we're at it trim any slashes.\n\t\t// The directory path can be included as part of the class name,\n\t\t// but we don't want a leading slash\n\t\t$class = str_replace('.php', '', trim($class, '/'));\n\n\t\t// Was the path included with the class name?\n\t\t// We look for a slash to determine this\n\t\tif (($last_slash = strrpos($class, '/')) !== FALSE)\n\t\t{\n\t\t\t// Extract the path\n\t\t\t$subdir = substr($class, 0, ++$last_slash);\n\n\t\t\t// Get the filename from the path\n\t\t\t$class = substr($class, $last_slash);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$subdir = '';\n\t\t}\n\n\t\t$class = ucfirst($class);\n\n\t\t// Is this a stock library? There are a few special conditions if so ...\n\t\tif (file_exists(BASEPATH.'libraries/'.$subdir.$class.'.php'))\n\t\t{\n\t\t\treturn $this->_ci_load_stock_library($class, $subdir, $params, $object_name);\n\t\t}\n\n\t\t// Let's search for the requested library file and load it.\n\t\tforeach ($this->_ci_library_paths as $path)\n\t\t{\n\t\t\t// BASEPATH has already been checked for\n\t\t\tif ($path === BASEPATH)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t$filepath = $path.'libraries/'.$subdir.$class.'.php';\n\n\t\t\t// Safety: Was the class already loaded by a previous call?\n\t\t\tif (class_exists($class, FALSE))\n\t\t\t{\n\t\t\t\t// Before we deem this to be a duplicate request, let's see\n\t\t\t\t// if a custom object name is being supplied. If so, we'll\n\t\t\t\t// return a new instance of the object\n\t\t\t\tif ($object_name !== NULL)\n\t\t\t\t{\n\t\t\t\t\t$CI =& get_instance();\n\t\t\t\t\tif ( ! isset($CI->$object_name))\n\t\t\t\t\t{\n\t\t\t\t\t\treturn $this->_ci_init_library($class, '', $params, $object_name);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tlog_message('debug', $class.' class already loaded. Second attempt ignored.');\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// Does the file exist? No? Bummer...\n\t\t\telseif ( ! file_exists($filepath))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tinclude_once($filepath);\n\t\t\treturn $this->_ci_init_library($class, '', $params, $object_name);\n\t\t}\n\n\t\t// One last attempt. Maybe the library is in a subdirectory, but it wasn't specified?\n\t\tif ($subdir === '')\n\t\t{\n\t\t\treturn $this->_ci_load_library($class.'/'.$class, $params, $object_name);\n\t\t}\n\n\t\t// If we got this far we were unable to find the requested class.\n\t\tlog_message('error', 'Unable to load the requested class: '.$class);\n\t\tshow_error('Unable to load the requested class: '.$class);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Internal CI Stock Library Loader\n\t *\n\t * @used-by\tCI_Loader::_ci_load_library()\n\t * @uses\tCI_Loader::_ci_init_library()\n\t *\n\t * @param\tstring\t$library_name\tLibrary name to load\n\t * @param\tstring\t$file_path\tPath to the library filename, relative to libraries/\n\t * @param\tmixed\t$params\t\tOptional parameters to pass to the class constructor\n\t * @param\tstring\t$object_name\tOptional object name to assign to\n\t * @return\tvoid\n\t */\n\tprotected function _ci_load_stock_library($library_name, $file_path, $params, $object_name)\n\t{\n\t\t$prefix = 'CI_';\n\n\t\tif (class_exists($prefix.$library_name, FALSE))\n\t\t{\n\t\t\tif (class_exists(config_item('subclass_prefix').$library_name, FALSE))\n\t\t\t{\n\t\t\t\t$prefix = config_item('subclass_prefix');\n\t\t\t}\n\n\t\t\t// Before we deem this to be a duplicate request, let's see\n\t\t\t// if a custom object name is being supplied. If so, we'll\n\t\t\t// return a new instance of the object\n\t\t\tif ($object_name !== NULL)\n\t\t\t{\n\t\t\t\t$CI =& get_instance();\n\t\t\t\tif ( ! isset($CI->$object_name))\n\t\t\t\t{\n\t\t\t\t\treturn $this->_ci_init_library($library_name, $prefix, $params, $object_name);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlog_message('debug', $library_name.' class already loaded. Second attempt ignored.');\n\t\t\treturn;\n\t\t}\n\n\t\t$paths = $this->_ci_library_paths;\n\t\tarray_pop($paths); // BASEPATH\n\t\tarray_pop($paths); // APPPATH (needs to be the first path checked)\n\t\tarray_unshift($paths, APPPATH);\n\n\t\tforeach ($paths as $path)\n\t\t{\n\t\t\tif (file_exists($path = $path.'libraries/'.$file_path.$library_name.'.php'))\n\t\t\t{\n\t\t\t\t// Override\n\t\t\t\tinclude_once($path);\n\t\t\t\tif (class_exists($prefix.$library_name, FALSE))\n\t\t\t\t{\n\t\t\t\t\treturn $this->_ci_init_library($library_name, $prefix, $params, $object_name);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tlog_message('debug', $path.' exists, but does not declare '.$prefix.$library_name);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tinclude_once(BASEPATH.'libraries/'.$file_path.$library_name.'.php');\n\n\t\t// Check for extensions\n\t\t$subclass = config_item('subclass_prefix').$library_name;\n\t\tforeach ($paths as $path)\n\t\t{\n\t\t\tif (file_exists($path = $path.'libraries/'.$file_path.$subclass.'.php'))\n\t\t\t{\n\t\t\t\tinclude_once($path);\n\t\t\t\tif (class_exists($subclass, FALSE))\n\t\t\t\t{\n\t\t\t\t\t$prefix = config_item('subclass_prefix');\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tlog_message('debug', $path.' exists, but does not declare '.$subclass);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn $this->_ci_init_library($library_name, $prefix, $params, $object_name);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Internal CI Library Instantiator\n\t *\n\t * @used-by\tCI_Loader::_ci_load_stock_library()\n\t * @used-by\tCI_Loader::_ci_load_library()\n\t *\n\t * @param\tstring\t\t$class\t\tClass name\n\t * @param\tstring\t\t$prefix\t\tClass name prefix\n\t * @param\tarray|null|bool\t$config\t\tOptional configuration to pass to the class constructor:\n\t *\t\t\t\t\t\tFALSE to skip;\n\t *\t\t\t\t\t\tNULL to search in config paths;\n\t *\t\t\t\t\t\tarray containing configuration data\n\t * @param\tstring\t\t$object_name\tOptional object name to assign to\n\t * @return\tvoid\n\t */\n\tprotected function _ci_init_library($class, $prefix, $config = FALSE, $object_name = NULL)\n\t{\n\t\t// Is there an associated config file for this class? Note: these should always be lowercase\n\t\tif ($config === NULL)\n\t\t{\n\t\t\t// Fetch the config paths containing any package paths\n\t\t\t$config_component = $this->_ci_get_component('config');\n\n\t\t\tif (is_array($config_component->_config_paths))\n\t\t\t{\n\t\t\t\t$found = FALSE;\n\t\t\t\tforeach ($config_component->_config_paths as $path)\n\t\t\t\t{\n\t\t\t\t\t// We test for both uppercase and lowercase, for servers that\n\t\t\t\t\t// are case-sensitive with regard to file names. Load global first,\n\t\t\t\t\t// override with environment next\n\t\t\t\t\tif (file_exists($path.'config/'.strtolower($class).'.php'))\n\t\t\t\t\t{\n\t\t\t\t\t\tinclude($path.'config/'.strtolower($class).'.php');\n\t\t\t\t\t\t$found = TRUE;\n\t\t\t\t\t}\n\t\t\t\t\telseif (file_exists($path.'config/'.ucfirst(strtolower($class)).'.php'))\n\t\t\t\t\t{\n\t\t\t\t\t\tinclude($path.'config/'.ucfirst(strtolower($class)).'.php');\n\t\t\t\t\t\t$found = TRUE;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (file_exists($path.'config/'.ENVIRONMENT.'/'.strtolower($class).'.php'))\n\t\t\t\t\t{\n\t\t\t\t\t\tinclude($path.'config/'.ENVIRONMENT.'/'.strtolower($class).'.php');\n\t\t\t\t\t\t$found = TRUE;\n\t\t\t\t\t}\n\t\t\t\t\telseif (file_exists($path.'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php'))\n\t\t\t\t\t{\n\t\t\t\t\t\tinclude($path.'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php');\n\t\t\t\t\t\t$found = TRUE;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Break on the first found configuration, thus package\n\t\t\t\t\t// files are not overridden by default paths\n\t\t\t\t\tif ($found === TRUE)\n\t\t\t\t\t{\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$class_name = $prefix.$class;\n\n\t\t// Is the class name valid?\n\t\tif ( ! class_exists($class_name, FALSE))\n\t\t{\n\t\t\tlog_message('error', 'Non-existent class: '.$class_name);\n\t\t\tshow_error('Non-existent class: '.$class_name);\n\t\t}\n\n\t\t// Set the variable name we will assign the class to\n\t\t// Was a custom class name supplied? If so we'll use it\n\t\tif (empty($object_name))\n\t\t{\n\t\t\t$object_name = strtolower($class);\n\t\t\tif (isset($this->_ci_varmap[$object_name]))\n\t\t\t{\n\t\t\t\t$object_name = $this->_ci_varmap[$object_name];\n\t\t\t}\n\t\t}\n\n\t\t// Don't overwrite existing properties\n\t\t$CI =& get_instance();\n\t\tif (isset($CI->$object_name))\n\t\t{\n\t\t\tif ($CI->$object_name instanceof $class_name)\n\t\t\t{\n\t\t\t\tlog_message('debug', $class_name.\" has already been instantiated as '\".$object_name.\"'. Second attempt aborted.\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tshow_error(\"Resource '\".$object_name.\"' already exists and is not a \".$class_name.\" instance.\");\n\t\t}\n\n\t\t// Save the class name and object name\n\t\t$this->_ci_classes[$object_name] = $class;\n\n\t\t// Instantiate the class\n\t\t$CI->$object_name = isset($config)\n\t\t\t? new $class_name($config)\n\t\t\t: new $class_name();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * CI Autoloader\n\t *\n\t * Loads component listed in the config/autoload.php file.\n\t *\n\t * @used-by\tCI_Loader::initialize()\n\t * @return\tvoid\n\t */\n\tprotected function _ci_autoloader()\n\t{\n\t\tif (file_exists(APPPATH.'config/autoload.php'))\n\t\t{\n\t\t\tinclude(APPPATH.'config/autoload.php');\n\t\t}\n\n\t\tif (file_exists(APPPATH.'config/'.ENVIRONMENT.'/autoload.php'))\n\t\t{\n\t\t\tinclude(APPPATH.'config/'.ENVIRONMENT.'/autoload.php');\n\t\t}\n\n\t\tif ( ! isset($autoload))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\t// Autoload packages\n\t\tif (isset($autoload['packages']))\n\t\t{\n\t\t\tforeach ($autoload['packages'] as $package_path)\n\t\t\t{\n\t\t\t\t$this->add_package_path($package_path);\n\t\t\t}\n\t\t}\n\n\t\t// Load any custom config file\n\t\tif (count($autoload['config']) > 0)\n\t\t{\n\t\t\tforeach ($autoload['config'] as $val)\n\t\t\t{\n\t\t\t\t$this->config($val);\n\t\t\t}\n\t\t}\n\n\t\t// Autoload helpers and languages\n\t\tforeach (array('helper', 'language') as $type)\n\t\t{\n\t\t\tif (isset($autoload[$type]) && count($autoload[$type]) > 0)\n\t\t\t{\n\t\t\t\t$this->$type($autoload[$type]);\n\t\t\t}\n\t\t}\n\n\t\t// Autoload drivers\n\t\tif (isset($autoload['drivers']))\n\t\t{\n\t\t\t$this->driver($autoload['drivers']);\n\t\t}\n\n\t\t// Load libraries\n\t\tif (isset($autoload['libraries']) && count($autoload['libraries']) > 0)\n\t\t{\n\t\t\t// Load the database driver.\n\t\t\tif (in_array('database', $autoload['libraries']))\n\t\t\t{\n\t\t\t\t$this->database();\n\t\t\t\t$autoload['libraries'] = array_diff($autoload['libraries'], array('database'));\n\t\t\t}\n\n\t\t\t// Load all other libraries\n\t\t\t$this->library($autoload['libraries']);\n\t\t}\n\n\t\t// Autoload models\n\t\tif (isset($autoload['model']))\n\t\t{\n\t\t\t$this->model($autoload['model']);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * CI Object to Array translator\n\t *\n\t * Takes an object as input and converts the class variables to\n\t * an associative array with key/value pairs.\n\t *\n\t * @param\tobject\t$object\tObject data to translate\n\t * @return\tarray\n\t */\n\tprotected function _ci_object_to_array($object)\n\t{\n\t\treturn is_object($object) ? get_object_vars($object) : $object;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * CI Component getter\n\t *\n\t * Get a reference to a specific library or model.\n\t *\n\t * @param \tstring\t$component\tComponent name\n\t * @return\tbool\n\t */\n\tprotected function &_ci_get_component($component)\n\t{\n\t\t$CI =& get_instance();\n\t\treturn $CI->$component;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prep filename\n\t *\n\t * This function prepares filenames of various items to\n\t * make their loading more reliable.\n\t *\n\t * @param\tstring|string[]\t$filename\tFilename(s)\n\t * @param \tstring\t\t$extension\tFilename extension\n\t * @return\tarray\n\t */\n\tprotected function _ci_prep_filename($filename, $extension)\n\t{\n\t\tif ( ! is_array($filename))\n\t\t{\n\t\t\treturn array(strtolower(str_replace(array($extension, '.php'), '', $filename).$extension));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tforeach ($filename as $key => $val)\n\t\t\t{\n\t\t\t\t$filename[$key] = strtolower(str_replace(array($extension, '.php'), '', $val).$extension);\n\t\t\t}\n\n\t\t\treturn $filename;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "system/core/Log.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Logging Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLogging\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/general/errors.html\n */\nclass CI_Log {\n\n\t/**\n\t * Path to save log files\n\t *\n\t * @var string\n\t */\n\tprotected $_log_path;\n\n\t/**\n\t * File permissions\n\t *\n\t * @var\tint\n\t */\n\tprotected $_file_permissions = 0644;\n\n\t/**\n\t * Level of logging\n\t *\n\t * @var int\n\t */\n\tprotected $_threshold = 1;\n\n\t/**\n\t * Array of threshold levels to log\n\t *\n\t * @var array\n\t */\n\tprotected $_threshold_array = array();\n\n\t/**\n\t * Format of timestamp for log files\n\t *\n\t * @var string\n\t */\n\tprotected $_date_fmt = 'Y-m-d H:i:s';\n\n\t/**\n\t * Filename extension\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_file_ext;\n\n\t/**\n\t * Whether or not the logger can write to the log files\n\t *\n\t * @var bool\n\t */\n\tprotected $_enabled = TRUE;\n\n\t/**\n\t * Predefined logging levels\n\t *\n\t * @var array\n\t */\n\tprotected $_levels = array('ERROR' => 1, 'DEBUG' => 2, 'INFO' => 3, 'ALL' => 4);\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\t$config =& get_config();\n\n\t\t$this->_log_path = ($config['log_path'] !== '') ? $config['log_path'] : APPPATH.'logs/';\n\t\t$this->_file_ext = (isset($config['log_file_extension']) && $config['log_file_extension'] !== '')\n\t\t\t? ltrim($config['log_file_extension'], '.') : 'php';\n\n\t\tfile_exists($this->_log_path) OR mkdir($this->_log_path, 0755, TRUE);\n\n\t\tif ( ! is_dir($this->_log_path) OR ! is_really_writable($this->_log_path))\n\t\t{\n\t\t\t$this->_enabled = FALSE;\n\t\t}\n\n\t\tif (is_numeric($config['log_threshold']))\n\t\t{\n\t\t\t$this->_threshold = (int) $config['log_threshold'];\n\t\t}\n\t\telseif (is_array($config['log_threshold']))\n\t\t{\n\t\t\t$this->_threshold = 0;\n\t\t\t$this->_threshold_array = array_flip($config['log_threshold']);\n\t\t}\n\n\t\tif ( ! empty($config['log_date_format']))\n\t\t{\n\t\t\t$this->_date_fmt = $config['log_date_format'];\n\t\t}\n\n\t\tif ( ! empty($config['log_file_permissions']) && is_int($config['log_file_permissions']))\n\t\t{\n\t\t\t$this->_file_permissions = $config['log_file_permissions'];\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Write Log File\n\t *\n\t * Generally this function will be called using the global log_message() function\n\t *\n\t * @param\tstring\t$level \tThe error level: 'error', 'debug' or 'info'\n\t * @param\tstring\t$msg \tThe error message\n\t * @return\tbool\n\t */\n\tpublic function write_log($level, $msg)\n\t{\n\t\tif ($this->_enabled === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$level = strtoupper($level);\n\n\t\tif (( ! isset($this->_levels[$level]) OR ($this->_levels[$level] > $this->_threshold))\n\t\t\t&& ! isset($this->_threshold_array[$this->_levels[$level]]))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$filepath = $this->_log_path.'log-'.date('Y-m-d').'.'.$this->_file_ext;\n\t\t$message = '';\n\n\t\tif ( ! file_exists($filepath))\n\t\t{\n\t\t\t$newfile = TRUE;\n\t\t\t// Only add protection to php files\n\t\t\tif ($this->_file_ext === 'php')\n\t\t\t{\n\t\t\t\t$message .= \"<?php defined('BASEPATH') OR exit('No direct script access allowed'); ?>\\n\\n\";\n\t\t\t}\n\t\t}\n\n\t\tif ( ! $fp = @fopen($filepath, 'ab'))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tflock($fp, LOCK_EX);\n\n\t\t// Instantiating DateTime with microseconds appended to initial date is needed for proper support of this format\n\t\tif (strpos($this->_date_fmt, 'u') !== FALSE)\n\t\t{\n\t\t\t$microtime_full = microtime(TRUE);\n\t\t\t$microtime_short = sprintf(\"%06d\", ($microtime_full - floor($microtime_full)) * 1000000);\n\t\t\t$date = new DateTime(date('Y-m-d H:i:s.'.$microtime_short, $microtime_full));\n\t\t\t$date = $date->format($this->_date_fmt);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$date = date($this->_date_fmt);\n\t\t}\n\n\t\t$message .= $this->_format_line($level, $date, $msg);\n\n\t\tfor ($written = 0, $length = strlen($message); $written < $length; $written += $result)\n\t\t{\n\t\t\tif (($result = fwrite($fp, substr($message, $written))) === FALSE)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tflock($fp, LOCK_UN);\n\t\tfclose($fp);\n\n\t\tif (isset($newfile) && $newfile === TRUE)\n\t\t{\n\t\t\tchmod($filepath, $this->_file_permissions);\n\t\t}\n\n\t\treturn is_int($result);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Format the log line.\n\t *\n\t * This is for extensibility of log formatting\n\t * If you want to change the log format, extend the CI_Log class and override this method\n\t *\n\t * @param\tstring\t$level \tThe error level\n\t * @param\tstring\t$date \tFormatted date string\n\t * @param\tstring\t$message \tThe log message\n\t * @return\tstring\tFormatted log line with a new line character '\\n' at the end\n\t */\n\tprotected function _format_line($level, $date, $message)\n\t{\n\t\treturn $level.' - '.$date.' --> '.$message.\"\\n\";\n\t}\n}\n"
  },
  {
    "path": "system/core/Model.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Model Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/config.html\n */\nclass CI_Model {\n\n\t/**\n\t * Class constructor\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\tlog_message('info', 'Model Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * __get magic\n\t *\n\t * Allows models to access CI's loaded classes using the same\n\t * syntax as controllers.\n\t *\n\t * @param\tstring\t$key\n\t */\n\tpublic function __get($key)\n\t{\n\t\t// Debugging note:\n\t\t//\tIf you're here because you're getting an error message\n\t\t//\tsaying 'Undefined Property: system/core/Model.php', it's\n\t\t//\tmost likely a typo in your model code.\n\t\treturn get_instance()->$key;\n\t}\n\n}\n"
  },
  {
    "path": "system/core/Output.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Output Class\n *\n * Responsible for sending final output to the browser.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tOutput\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/output.html\n */\nclass CI_Output {\n\n\t/**\n\t * Final output string\n\t *\n\t * @var\tstring\n\t */\n\tpublic $final_output;\n\n\t/**\n\t * Cache expiration time\n\t *\n\t * @var\tint\n\t */\n\tpublic $cache_expiration = 0;\n\n\t/**\n\t * List of server headers\n\t *\n\t * @var\tarray\n\t */\n\tpublic $headers = array();\n\n\t/**\n\t * List of mime types\n\t *\n\t * @var\tarray\n\t */\n\tpublic $mimes =\tarray();\n\n\t/**\n\t * Mime-type for the current page\n\t *\n\t * @var\tstring\n\t */\n\tprotected $mime_type = 'text/html';\n\n\t/**\n\t * Enable Profiler flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $enable_profiler = FALSE;\n\n\t/**\n\t * php.ini zlib.output_compression flag\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_zlib_oc = FALSE;\n\n\t/**\n\t * CI output compression flag\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_compress_output = FALSE;\n\n\t/**\n\t * List of profiler sections\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_profiler_sections =\tarray();\n\n\t/**\n\t * Parse markers flag\n\t *\n\t * Whether or not to parse variables like {elapsed_time} and {memory_usage}.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $parse_exec_vars = TRUE;\n\n\t/**\n\t * Class constructor\n\t *\n\t * Determines whether zLib output compression will be used.\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\t$this->_zlib_oc = (bool) ini_get('zlib.output_compression');\n\t\t$this->_compress_output = (\n\t\t\t$this->_zlib_oc === FALSE\n\t\t\t&& config_item('compress_output') === TRUE\n\t\t\t&& extension_loaded('zlib')\n\t\t);\n\n\t\t// Get mime types for later\n\t\t$this->mimes =& get_mimes();\n\n\t\tlog_message('info', 'Output Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Output\n\t *\n\t * Returns the current output string.\n\t *\n\t * @return\tstring\n\t */\n\tpublic function get_output()\n\t{\n\t\treturn $this->final_output;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Output\n\t *\n\t * Sets the output string.\n\t *\n\t * @param\tstring\t$output\tOutput data\n\t * @return\tCI_Output\n\t */\n\tpublic function set_output($output)\n\t{\n\t\t$this->final_output = $output;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Append Output\n\t *\n\t * Appends data onto the output string.\n\t *\n\t * @param\tstring\t$output\tData to append\n\t * @return\tCI_Output\n\t */\n\tpublic function append_output($output)\n\t{\n\t\t$this->final_output .= $output;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Header\n\t *\n\t * Lets you set a server header which will be sent with the final output.\n\t *\n\t * Note: If a file is cached, headers will not be sent.\n\t * @todo\tWe need to figure out how to permit headers to be cached.\n\t *\n\t * @param\tstring\t$header\t\tHeader\n\t * @param\tbool\t$replace\tWhether to replace the old header value, if already set\n\t * @return\tCI_Output\n\t */\n\tpublic function set_header($header, $replace = TRUE)\n\t{\n\t\t// If zlib.output_compression is enabled it will compress the output,\n\t\t// but it will not modify the content-length header to compensate for\n\t\t// the reduction, causing the browser to hang waiting for more data.\n\t\t// We'll just skip content-length in those cases.\n\t\tif ($this->_zlib_oc && strncasecmp($header, 'content-length', 14) === 0)\n\t\t{\n\t\t\treturn $this;\n\t\t}\n\n\t\t$this->headers[] = array($header, $replace);\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Content-Type Header\n\t *\n\t * @param\tstring\t$mime_type\tExtension of the file we're outputting\n\t * @param\tstring\t$charset\tCharacter set (default: NULL)\n\t * @return\tCI_Output\n\t */\n\tpublic function set_content_type($mime_type, $charset = NULL)\n\t{\n\t\tif (strpos($mime_type, '/') === FALSE)\n\t\t{\n\t\t\t$extension = ltrim($mime_type, '.');\n\n\t\t\t// Is this extension supported?\n\t\t\tif (isset($this->mimes[$extension]))\n\t\t\t{\n\t\t\t\t$mime_type =& $this->mimes[$extension];\n\n\t\t\t\tif (is_array($mime_type))\n\t\t\t\t{\n\t\t\t\t\t$mime_type = current($mime_type);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$this->mime_type = $mime_type;\n\n\t\tif (empty($charset))\n\t\t{\n\t\t\t$charset = config_item('charset');\n\t\t}\n\n\t\t$header = 'Content-Type: '.$mime_type\n\t\t\t.(empty($charset) ? '' : '; charset='.$charset);\n\n\t\t$this->headers[] = array($header, TRUE);\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Current Content-Type Header\n\t *\n\t * @return\tstring\t'text/html', if not already set\n\t */\n\tpublic function get_content_type()\n\t{\n\t\tfor ($i = 0, $c = count($this->headers); $i < $c; $i++)\n\t\t{\n\t\t\tif (sscanf($this->headers[$i][0], 'Content-Type: %[^;]', $content_type) === 1)\n\t\t\t{\n\t\t\t\treturn $content_type;\n\t\t\t}\n\t\t}\n\n\t\treturn 'text/html';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Header\n\t *\n\t * @param\tstring\t$header\n\t * @return\tstring\n\t */\n\tpublic function get_header($header)\n\t{\n\t\t// Combine headers already sent with our batched headers\n\t\t$headers = array_merge(\n\t\t\t// We only need [x][0] from our multi-dimensional array\n\t\t\tarray_map('array_shift', $this->headers),\n\t\t\theaders_list()\n\t\t);\n\n\t\tif (empty($headers) OR empty($header))\n\t\t{\n\t\t\treturn NULL;\n\t\t}\n\n\t\tfor ($i = 0, $c = count($headers); $i < $c; $i++)\n\t\t{\n\t\t\tif (strncasecmp($header, $headers[$i], $l = strlen($header)) === 0)\n\t\t\t{\n\t\t\t\treturn trim(substr($headers[$i], $l+1));\n\t\t\t}\n\t\t}\n\n\t\treturn NULL;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set HTTP Status Header\n\t *\n\t * As of version 1.7.2, this is an alias for common function\n\t * set_status_header().\n\t *\n\t * @param\tint\t$code\tStatus code (default: 200)\n\t * @param\tstring\t$text\tOptional message\n\t * @return\tCI_Output\n\t */\n\tpublic function set_status_header($code = 200, $text = '')\n\t{\n\t\tset_status_header($code, $text);\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Enable/disable Profiler\n\t *\n\t * @param\tbool\t$val\tTRUE to enable or FALSE to disable\n\t * @return\tCI_Output\n\t */\n\tpublic function enable_profiler($val = TRUE)\n\t{\n\t\t$this->enable_profiler = is_bool($val) ? $val : TRUE;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Profiler Sections\n\t *\n\t * Allows override of default/config settings for\n\t * Profiler section display.\n\t *\n\t * @param\tarray\t$sections\tProfiler sections\n\t * @return\tCI_Output\n\t */\n\tpublic function set_profiler_sections($sections)\n\t{\n\t\tif (isset($sections['query_toggle_count']))\n\t\t{\n\t\t\t$this->_profiler_sections['query_toggle_count'] = (int) $sections['query_toggle_count'];\n\t\t\tunset($sections['query_toggle_count']);\n\t\t}\n\n\t\tforeach ($sections as $section => $enable)\n\t\t{\n\t\t\t$this->_profiler_sections[$section] = ($enable !== FALSE);\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Cache\n\t *\n\t * @param\tint\t$time\tCache expiration time in minutes\n\t * @return\tCI_Output\n\t */\n\tpublic function cache($time)\n\t{\n\t\t$this->cache_expiration = is_numeric($time) ? $time : 0;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Display Output\n\t *\n\t * Processes and sends finalized output data to the browser along\n\t * with any server headers and profile data. It also stops benchmark\n\t * timers so the page rendering speed and memory usage can be shown.\n\t *\n\t * Note: All \"view\" data is automatically put into $this->final_output\n\t *\t by controller class.\n\t *\n\t * @uses\tCI_Output::$final_output\n\t * @param\tstring\t$output\tOutput data override\n\t * @return\tvoid\n\t */\n\tpublic function _display($output = '')\n\t{\n\t\t// Note:  We use load_class() because we can't use $CI =& get_instance()\n\t\t// since this function is sometimes called by the caching mechanism,\n\t\t// which happens before the CI super object is available.\n\t\t$BM =& load_class('Benchmark', 'core');\n\t\t$CFG =& load_class('Config', 'core');\n\n\t\t// Grab the super object if we can.\n\t\tif (class_exists('CI_Controller', FALSE))\n\t\t{\n\t\t\t$CI =& get_instance();\n\t\t}\n\n\t\t// --------------------------------------------------------------------\n\n\t\t// Set the output data\n\t\tif ($output === '')\n\t\t{\n\t\t\t$output =& $this->final_output;\n\t\t}\n\n\t\t// --------------------------------------------------------------------\n\n\t\t// Do we need to write a cache file? Only if the controller does not have its\n\t\t// own _output() method and we are not dealing with a cache file, which we\n\t\t// can determine by the existence of the $CI object above\n\t\tif ($this->cache_expiration > 0 && isset($CI) && ! method_exists($CI, '_output'))\n\t\t{\n\t\t\t$this->_write_cache($output);\n\t\t}\n\n\t\t// --------------------------------------------------------------------\n\n\t\t// Parse out the elapsed time and memory usage,\n\t\t// then swap the pseudo-variables with the data\n\n\t\t$elapsed = $BM->elapsed_time('total_execution_time_start', 'total_execution_time_end');\n\n\t\tif ($this->parse_exec_vars === TRUE)\n\t\t{\n\t\t\t$memory\t= round(memory_get_usage() / 1024 / 1024, 2).'MB';\n\t\t\t$output = str_replace(array('{elapsed_time}', '{memory_usage}'), array($elapsed, $memory), $output);\n\t\t}\n\n\t\t// --------------------------------------------------------------------\n\n\t\t// Is compression requested?\n\t\tif (isset($CI) // This means that we're not serving a cache file, if we were, it would already be compressed\n\t\t\t&& $this->_compress_output === TRUE\n\t\t\t&& isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE)\n\t\t{\n\t\t\tob_start('ob_gzhandler');\n\t\t}\n\n\t\t// --------------------------------------------------------------------\n\n\t\t// Are there any server headers to send?\n\t\tif (count($this->headers) > 0)\n\t\t{\n\t\t\tforeach ($this->headers as $header)\n\t\t\t{\n\t\t\t\t@header($header[0], $header[1]);\n\t\t\t}\n\t\t}\n\n\t\t// --------------------------------------------------------------------\n\n\t\t// Does the $CI object exist?\n\t\t// If not we know we are dealing with a cache file so we'll\n\t\t// simply echo out the data and exit.\n\t\tif ( ! isset($CI))\n\t\t{\n\t\t\tif ($this->_compress_output === TRUE)\n\t\t\t{\n\t\t\t\tif (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE)\n\t\t\t\t{\n\t\t\t\t\theader('Content-Encoding: gzip');\n\t\t\t\t\theader('Content-Length: '.strlen($output));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// User agent doesn't support gzip compression,\n\t\t\t\t\t// so we'll have to decompress our cache\n\t\t\t\t\t$output = gzinflate(substr($output, 10, -8));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\techo $output;\n\t\t\tlog_message('info', 'Final output sent to browser');\n\t\t\tlog_message('debug', 'Total execution time: '.$elapsed);\n\t\t\treturn;\n\t\t}\n\n\t\t// --------------------------------------------------------------------\n\n\t\t// Do we need to generate profile data?\n\t\t// If so, load the Profile class and run it.\n\t\tif ($this->enable_profiler === TRUE)\n\t\t{\n\t\t\t$CI->load->library('profiler');\n\t\t\tif ( ! empty($this->_profiler_sections))\n\t\t\t{\n\t\t\t\t$CI->profiler->set_sections($this->_profiler_sections);\n\t\t\t}\n\n\t\t\t// If the output data contains closing </body> and </html> tags\n\t\t\t// we will remove them and add them back after we insert the profile data\n\t\t\t$output = preg_replace('|</body>.*?</html>|is', '', $output, -1, $count).$CI->profiler->run();\n\t\t\tif ($count > 0)\n\t\t\t{\n\t\t\t\t$output .= '</body></html>';\n\t\t\t}\n\t\t}\n\n\t\t// Does the controller contain a function named _output()?\n\t\t// If so send the output there.  Otherwise, echo it.\n\t\tif (method_exists($CI, '_output'))\n\t\t{\n\t\t\t$CI->_output($output);\n\t\t}\n\t\telse\n\t\t{\n\t\t\techo $output; // Send it to the browser!\n\t\t}\n\n\t\tlog_message('info', 'Final output sent to browser');\n\t\tlog_message('debug', 'Total execution time: '.$elapsed);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Write Cache\n\t *\n\t * @param\tstring\t$output\tOutput data to cache\n\t * @return\tvoid\n\t */\n\tpublic function _write_cache($output)\n\t{\n\t\t$CI =& get_instance();\n\t\t$path = $CI->config->item('cache_path');\n\t\t$cache_path = ($path === '') ? APPPATH.'cache/' : $path;\n\n\t\tif ( ! is_dir($cache_path) OR ! is_really_writable($cache_path))\n\t\t{\n\t\t\tlog_message('error', 'Unable to write cache file: '.$cache_path);\n\t\t\treturn;\n\t\t}\n\n\t\t$uri = $CI->config->item('base_url')\n\t\t\t.$CI->config->item('index_page')\n\t\t\t.$CI->uri->uri_string();\n\n\t\tif (($cache_query_string = $CI->config->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))\n\t\t{\n\t\t\tif (is_array($cache_query_string))\n\t\t\t{\n\t\t\t\t$uri .= '?'.http_build_query(array_intersect_key($_GET, array_flip($cache_query_string)));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$uri .= '?'.$_SERVER['QUERY_STRING'];\n\t\t\t}\n\t\t}\n\n\t\t$cache_path .= md5($uri);\n\n\t\tif ( ! $fp = @fopen($cache_path, 'w+b'))\n\t\t{\n\t\t\tlog_message('error', 'Unable to write cache file: '.$cache_path);\n\t\t\treturn;\n\t\t}\n\n\t\tif (flock($fp, LOCK_EX))\n\t\t{\n\t\t\t// If output compression is enabled, compress the cache\n\t\t\t// itself, so that we don't have to do that each time\n\t\t\t// we're serving it\n\t\t\tif ($this->_compress_output === TRUE)\n\t\t\t{\n\t\t\t\t$output = gzencode($output);\n\n\t\t\t\tif ($this->get_header('content-type') === NULL)\n\t\t\t\t{\n\t\t\t\t\t$this->set_content_type($this->mime_type);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$expire = time() + ($this->cache_expiration * 60);\n\n\t\t\t// Put together our serialized info.\n\t\t\t$cache_info = serialize(array(\n\t\t\t\t'expire'\t=> $expire,\n\t\t\t\t'headers'\t=> $this->headers\n\t\t\t));\n\n\t\t\t$output = $cache_info.'ENDCI--->'.$output;\n\n\t\t\tfor ($written = 0, $length = strlen($output); $written < $length; $written += $result)\n\t\t\t{\n\t\t\t\tif (($result = fwrite($fp, substr($output, $written))) === FALSE)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tflock($fp, LOCK_UN);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlog_message('error', 'Unable to secure a file lock for file at: '.$cache_path);\n\t\t\treturn;\n\t\t}\n\n\t\tfclose($fp);\n\n\t\tif (is_int($result))\n\t\t{\n\t\t\tchmod($cache_path, 0640);\n\t\t\tlog_message('debug', 'Cache file written: '.$cache_path);\n\n\t\t\t// Send HTTP cache-control headers to browser to match file cache settings.\n\t\t\t$this->set_cache_header($_SERVER['REQUEST_TIME'], $expire);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t@unlink($cache_path);\n\t\t\tlog_message('error', 'Unable to write the complete cache content at: '.$cache_path);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update/serve cached output\n\t *\n\t * @uses\tCI_Config\n\t * @uses\tCI_URI\n\t *\n\t * @param\tobject\t&$CFG\tCI_Config class instance\n\t * @param\tobject\t&$URI\tCI_URI class instance\n\t * @return\tbool\tTRUE on success or FALSE on failure\n\t */\n\tpublic function _display_cache(&$CFG, &$URI)\n\t{\n\t\t$cache_path = ($CFG->item('cache_path') === '') ? APPPATH.'cache/' : $CFG->item('cache_path');\n\n\t\t// Build the file path. The file name is an MD5 hash of the full URI\n\t\t$uri = $CFG->item('base_url').$CFG->item('index_page').$URI->uri_string;\n\n\t\tif (($cache_query_string = $CFG->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))\n\t\t{\n\t\t\tif (is_array($cache_query_string))\n\t\t\t{\n\t\t\t\t$uri .= '?'.http_build_query(array_intersect_key($_GET, array_flip($cache_query_string)));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$uri .= '?'.$_SERVER['QUERY_STRING'];\n\t\t\t}\n\t\t}\n\n\t\t$filepath = $cache_path.md5($uri);\n\n\t\tif ( ! file_exists($filepath) OR ! $fp = @fopen($filepath, 'rb'))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tflock($fp, LOCK_SH);\n\n\t\t$cache = (filesize($filepath) > 0) ? fread($fp, filesize($filepath)) : '';\n\n\t\tflock($fp, LOCK_UN);\n\t\tfclose($fp);\n\n\t\t// Look for embedded serialized file info.\n\t\tif ( ! preg_match('/^(.*)ENDCI--->/', $cache, $match))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$cache_info = unserialize($match[1]);\n\t\t$expire = $cache_info['expire'];\n\n\t\t$last_modified = filemtime($filepath);\n\n\t\t// Has the file expired?\n\t\tif ($_SERVER['REQUEST_TIME'] >= $expire && is_really_writable($cache_path))\n\t\t{\n\t\t\t// If so we'll delete it.\n\t\t\t@unlink($filepath);\n\t\t\tlog_message('debug', 'Cache file has expired. File deleted.');\n\t\t\treturn FALSE;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Or else send the HTTP cache control headers.\n\t\t\t$this->set_cache_header($last_modified, $expire);\n\t\t}\n\n\t\t// Add headers from cache file.\n\t\tforeach ($cache_info['headers'] as $header)\n\t\t{\n\t\t\t$this->set_header($header[0], $header[1]);\n\t\t}\n\n\t\t// Display the cache\n\t\t$this->_display(substr($cache, strlen($match[0])));\n\t\tlog_message('debug', 'Cache file is current. Sending it to browser.');\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Delete cache\n\t *\n\t * @param\tstring\t$uri\tURI string\n\t * @return\tbool\n\t */\n\tpublic function delete_cache($uri = '')\n\t{\n\t\t$CI =& get_instance();\n\t\t$cache_path = $CI->config->item('cache_path');\n\t\tif ($cache_path === '')\n\t\t{\n\t\t\t$cache_path = APPPATH.'cache/';\n\t\t}\n\n\t\tif ( ! is_dir($cache_path))\n\t\t{\n\t\t\tlog_message('error', 'Unable to find cache path: '.$cache_path);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (empty($uri))\n\t\t{\n\t\t\t$uri = $CI->uri->uri_string();\n\n\t\t\tif (($cache_query_string = $CI->config->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))\n\t\t\t{\n\t\t\t\tif (is_array($cache_query_string))\n\t\t\t\t{\n\t\t\t\t\t$uri .= '?'.http_build_query(array_intersect_key($_GET, array_flip($cache_query_string)));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$uri .= '?'.$_SERVER['QUERY_STRING'];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$cache_path .= md5($CI->config->item('base_url').$CI->config->item('index_page').ltrim($uri, '/'));\n\n\t\tif ( ! @unlink($cache_path))\n\t\t{\n\t\t\tlog_message('error', 'Unable to delete cache file for '.$uri);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Cache Header\n\t *\n\t * Set the HTTP headers to match the server-side file cache settings\n\t * in order to reduce bandwidth.\n\t *\n\t * @param\tint\t$last_modified\tTimestamp of when the page was last modified\n\t * @param\tint\t$expiration\tTimestamp of when should the requested page expire from cache\n\t * @return\tvoid\n\t */\n\tpublic function set_cache_header($last_modified, $expiration)\n\t{\n\t\t$max_age = $expiration - $_SERVER['REQUEST_TIME'];\n\n\t\tif (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $last_modified <= strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']))\n\t\t{\n\t\t\t$this->set_status_header(304);\n\t\t\texit;\n\t\t}\n\t\telse\n\t\t{\n\t\t\theader('Pragma: public');\n\t\t\theader('Cache-Control: max-age='.$max_age.', public');\n\t\t\theader('Expires: '.gmdate('D, d M Y H:i:s', $expiration).' GMT');\n\t\t\theader('Last-modified: '.gmdate('D, d M Y H:i:s', $last_modified).' GMT');\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "system/core/Router.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Router Class\n *\n * Parses URIs and determines routing\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/general/routing.html\n */\nclass CI_Router {\n\n\t/**\n\t * CI_Config class object\n\t *\n\t * @var\tobject\n\t */\n\tpublic $config;\n\n\t/**\n\t * List of routes\n\t *\n\t * @var\tarray\n\t */\n\tpublic $routes =\tarray();\n\n\t/**\n\t * Current class name\n\t *\n\t * @var\tstring\n\t */\n\tpublic $class =\t\t'';\n\n\t/**\n\t * Current method name\n\t *\n\t * @var\tstring\n\t */\n\tpublic $method =\t'index';\n\n\t/**\n\t * Sub-directory that contains the requested controller class\n\t *\n\t * @var\tstring\n\t */\n\tpublic $directory;\n\n\t/**\n\t * Default controller (and method if specific)\n\t *\n\t * @var\tstring\n\t */\n\tpublic $default_controller;\n\n\t/**\n\t * Translate URI dashes\n\t *\n\t * Determines whether dashes in controller & method segments\n\t * should be automatically replaced by underscores.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $translate_uri_dashes = FALSE;\n\n\t/**\n\t * Enable query strings flag\n\t *\n\t * Determines whether to use GET parameters or segment URIs\n\t *\n\t * @var\tbool\n\t */\n\tpublic $enable_query_strings = FALSE;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Runs the route mapping function.\n\t *\n\t * @param\tarray\t$routing\n\t * @return\tvoid\n\t */\n\tpublic function __construct($routing = NULL)\n\t{\n\t\t$this->config =& load_class('Config', 'core');\n\t\t$this->uri =& load_class('URI', 'core');\n\n\t\t$this->enable_query_strings = ( ! is_cli() && $this->config->item('enable_query_strings') === TRUE);\n\n\t\t// If a directory override is configured, it has to be set before any dynamic routing logic\n\t\tis_array($routing) && isset($routing['directory']) && $this->set_directory($routing['directory']);\n\t\t$this->_set_routing();\n\n\t\t// Set any routing overrides that may exist in the main index file\n\t\tif (is_array($routing))\n\t\t{\n\t\t\tempty($routing['controller']) OR $this->set_class($routing['controller']);\n\t\t\tempty($routing['function'])   OR $this->set_method($routing['function']);\n\t\t}\n\n\t\tlog_message('info', 'Router Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set route mapping\n\t *\n\t * Determines what should be served based on the URI request,\n\t * as well as any \"routes\" that have been set in the routing config file.\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _set_routing()\n\t{\n\t\t// Load the routes.php file. It would be great if we could\n\t\t// skip this for enable_query_strings = TRUE, but then\n\t\t// default_controller would be empty ...\n\t\tif (file_exists(APPPATH.'config/routes.php'))\n\t\t{\n\t\t\tinclude(APPPATH.'config/routes.php');\n\t\t}\n\n\t\tif (file_exists(APPPATH.'config/'.ENVIRONMENT.'/routes.php'))\n\t\t{\n\t\t\tinclude(APPPATH.'config/'.ENVIRONMENT.'/routes.php');\n\t\t}\n\n\t\t// Validate & get reserved routes\n\t\tif (isset($route) && is_array($route))\n\t\t{\n\t\t\tisset($route['default_controller']) && $this->default_controller = $route['default_controller'];\n\t\t\tisset($route['translate_uri_dashes']) && $this->translate_uri_dashes = $route['translate_uri_dashes'];\n\t\t\tunset($route['default_controller'], $route['translate_uri_dashes']);\n\t\t\t$this->routes = $route;\n\t\t}\n\n\t\t// Are query strings enabled in the config file? Normally CI doesn't utilize query strings\n\t\t// since URI segments are more search-engine friendly, but they can optionally be used.\n\t\t// If this feature is enabled, we will gather the directory/class/method a little differently\n\t\tif ($this->enable_query_strings)\n\t\t{\n\t\t\t// If the directory is set at this time, it means an override exists, so skip the checks\n\t\t\tif ( ! isset($this->directory))\n\t\t\t{\n\t\t\t\t$_d = $this->config->item('directory_trigger');\n\t\t\t\t$_d = isset($_GET[$_d]) ? trim($_GET[$_d], \" \\t\\n\\r\\0\\x0B/\") : '';\n\n\t\t\t\tif ($_d !== '')\n\t\t\t\t{\n\t\t\t\t\t$this->uri->filter_uri($_d);\n\t\t\t\t\t$this->set_directory($_d);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$_c = trim($this->config->item('controller_trigger'));\n\t\t\tif ( ! empty($_GET[$_c]))\n\t\t\t{\n\t\t\t\t$this->uri->filter_uri($_GET[$_c]);\n\t\t\t\t$this->set_class($_GET[$_c]);\n\n\t\t\t\t$_f = trim($this->config->item('function_trigger'));\n\t\t\t\tif ( ! empty($_GET[$_f]))\n\t\t\t\t{\n\t\t\t\t\t$this->uri->filter_uri($_GET[$_f]);\n\t\t\t\t\t$this->set_method($_GET[$_f]);\n\t\t\t\t}\n\n\t\t\t\t$this->uri->rsegments = array(\n\t\t\t\t\t1 => $this->class,\n\t\t\t\t\t2 => $this->method\n\t\t\t\t);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->_set_default_controller();\n\t\t\t}\n\n\t\t\t// Routing rules don't apply to query strings and we don't need to detect\n\t\t\t// directories, so we're done here\n\t\t\treturn;\n\t\t}\n\n\t\t// Is there anything to parse?\n\t\tif ($this->uri->uri_string !== '')\n\t\t{\n\t\t\t$this->_parse_routes();\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->_set_default_controller();\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set request route\n\t *\n\t * Takes an array of URI segments as input and sets the class/method\n\t * to be called.\n\t *\n\t * @used-by\tCI_Router::_parse_routes()\n\t * @param\tarray\t$segments\tURI segments\n\t * @return\tvoid\n\t */\n\tprotected function _set_request($segments = array())\n\t{\n\t\t$segments = $this->_validate_request($segments);\n\t\t// If we don't have any segments left - try the default controller;\n\t\t// WARNING: Directories get shifted out of the segments array!\n\t\tif (empty($segments))\n\t\t{\n\t\t\t$this->_set_default_controller();\n\t\t\treturn;\n\t\t}\n\n\t\tif ($this->translate_uri_dashes === TRUE)\n\t\t{\n\t\t\t$segments[0] = str_replace('-', '_', $segments[0]);\n\t\t\tif (isset($segments[1]))\n\t\t\t{\n\t\t\t\t$segments[1] = str_replace('-', '_', $segments[1]);\n\t\t\t}\n\t\t}\n\n\t\t$this->set_class($segments[0]);\n\t\tif (isset($segments[1]))\n\t\t{\n\t\t\t$this->set_method($segments[1]);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$segments[1] = 'index';\n\t\t}\n\n\t\tarray_unshift($segments, NULL);\n\t\tunset($segments[0]);\n\t\t$this->uri->rsegments = $segments;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set default controller\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _set_default_controller()\n\t{\n\t\tif (empty($this->default_controller))\n\t\t{\n\t\t\tshow_error('Unable to determine what should be displayed. A default route has not been specified in the routing file.');\n\t\t}\n\n\t\t// Is the method being specified?\n\t\tif (sscanf($this->default_controller, '%[^/]/%s', $class, $method) !== 2)\n\t\t{\n\t\t\t$method = 'index';\n\t\t}\n\n\t\tif ( ! file_exists(APPPATH.'controllers/'.$this->directory.ucfirst($class).'.php'))\n\t\t{\n\t\t\t// This will trigger 404 later\n\t\t\treturn;\n\t\t}\n\n\t\t$this->set_class($class);\n\t\t$this->set_method($method);\n\n\t\t// Assign routed segments, index starting from 1\n\t\t$this->uri->rsegments = array(\n\t\t\t1 => $class,\n\t\t\t2 => $method\n\t\t);\n\n\t\tlog_message('debug', 'No URI present. Default controller set.');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Validate request\n\t *\n\t * Attempts validate the URI request and determine the controller path.\n\t *\n\t * @used-by\tCI_Router::_set_request()\n\t * @param\tarray\t$segments\tURI segments\n\t * @return\tmixed\tURI segments\n\t */\n\tprotected function _validate_request($segments)\n\t{\n\t\t$c = count($segments);\n\t\t$directory_override = isset($this->directory);\n\n\t\t// Loop through our segments and return as soon as a controller\n\t\t// is found or when such a directory doesn't exist\n\t\twhile ($c-- > 0)\n\t\t{\n\t\t\t$test = $this->directory\n\t\t\t\t.ucfirst($this->translate_uri_dashes === TRUE ? str_replace('-', '_', $segments[0]) : $segments[0]);\n\n\t\t\tif ( ! file_exists(APPPATH.'controllers/'.$test.'.php')\n\t\t\t\t&& $directory_override === FALSE\n\t\t\t\t&& is_dir(APPPATH.'controllers/'.$this->directory.$segments[0])\n\t\t\t)\n\t\t\t{\n\t\t\t\t$this->set_directory(array_shift($segments), TRUE);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\treturn $segments;\n\t\t}\n\n\t\t// This means that all segments were actually directories\n\t\treturn $segments;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse Routes\n\t *\n\t * Matches any routes that may exist in the config/routes.php file\n\t * against the URI to determine if the class/method need to be remapped.\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _parse_routes()\n\t{\n\t\t// Turn the segment array into a URI string\n\t\t$uri = implode('/', $this->uri->segments);\n\n\t\t// Get HTTP verb\n\t\t$http_verb = isset($_SERVER['REQUEST_METHOD']) ? strtolower($_SERVER['REQUEST_METHOD']) : 'cli';\n\n\t\t// Loop through the route array looking for wildcards\n\t\tforeach ($this->routes as $key => $val)\n\t\t{\n\t\t\t// Check if route format is using HTTP verbs\n\t\t\tif (is_array($val))\n\t\t\t{\n\t\t\t\t$val = array_change_key_case($val, CASE_LOWER);\n\t\t\t\tif (isset($val[$http_verb]))\n\t\t\t\t{\n\t\t\t\t\t$val = $val[$http_verb];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Convert wildcards to RegEx\n\t\t\t$key = str_replace(array(':any', ':num'), array('[^/]+', '[0-9]+'), $key);\n\n\t\t\t// Does the RegEx match?\n\t\t\tif (preg_match('#^'.$key.'$#', $uri, $matches))\n\t\t\t{\n\t\t\t\t// Are we using callbacks to process back-references?\n\t\t\t\tif ( ! is_string($val) && is_callable($val))\n\t\t\t\t{\n\t\t\t\t\t// Remove the original string from the matches array.\n\t\t\t\t\tarray_shift($matches);\n\n\t\t\t\t\t// Execute the callback using the values in matches as its parameters.\n\t\t\t\t\t$val = call_user_func_array($val, $matches);\n\t\t\t\t}\n\t\t\t\t// Are we using the default routing method for back-references?\n\t\t\t\telseif (strpos($val, '$') !== FALSE && strpos($key, '(') !== FALSE)\n\t\t\t\t{\n\t\t\t\t\t$val = preg_replace('#^'.$key.'$#', $val, $uri);\n\t\t\t\t}\n\n\t\t\t\t$this->_set_request(explode('/', $val));\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// If we got this far it means we didn't encounter a\n\t\t// matching route so we'll set the site default route\n\t\t$this->_set_request(array_values($this->uri->segments));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set class name\n\t *\n\t * @param\tstring\t$class\tClass name\n\t * @return\tvoid\n\t */\n\tpublic function set_class($class)\n\t{\n\t\t$this->class = str_replace(array('/', '.'), '', $class);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch the current class\n\t *\n\t * @deprecated\t3.0.0\tRead the 'class' property instead\n\t * @return\tstring\n\t */\n\tpublic function fetch_class()\n\t{\n\t\treturn $this->class;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set method name\n\t *\n\t * @param\tstring\t$method\tMethod name\n\t * @return\tvoid\n\t */\n\tpublic function set_method($method)\n\t{\n\t\t$this->method = $method;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch the current method\n\t *\n\t * @deprecated\t3.0.0\tRead the 'method' property instead\n\t * @return\tstring\n\t */\n\tpublic function fetch_method()\n\t{\n\t\treturn $this->method;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set directory name\n\t *\n\t * @param\tstring\t$dir\tDirectory name\n\t * @param\tbool\t$append\tWhether we're appending rather than setting the full value\n\t * @return\tvoid\n\t */\n\tpublic function set_directory($dir, $append = FALSE)\n\t{\n\t\tif ($append !== TRUE OR empty($this->directory))\n\t\t{\n\t\t\t$this->directory = str_replace('.', '', trim($dir, '/')).'/';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->directory .= str_replace('.', '', trim($dir, '/')).'/';\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch directory\n\t *\n\t * Feches the sub-directory (if any) that contains the requested\n\t * controller class.\n\t *\n\t * @deprecated\t3.0.0\tRead the 'directory' property instead\n\t * @return\tstring\n\t */\n\tpublic function fetch_directory()\n\t{\n\t\treturn $this->directory;\n\t}\n\n}\n"
  },
  {
    "path": "system/core/Security.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Security Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tSecurity\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/security.html\n */\nclass CI_Security {\n\n\t/**\n\t * List of sanitize filename strings\n\t *\n\t * @var\tarray\n\t */\n\tpublic $filename_bad_chars =\tarray(\n\t\t'../', '<!--', '-->', '<', '>',\n\t\t\"'\", '\"', '&', '$', '#',\n\t\t'{', '}', '[', ']', '=',\n\t\t';', '?', '%20', '%22',\n\t\t'%3c',\t\t// <\n\t\t'%253c',\t// <\n\t\t'%3e',\t\t// >\n\t\t'%0e',\t\t// >\n\t\t'%28',\t\t// (\n\t\t'%29',\t\t// )\n\t\t'%2528',\t// (\n\t\t'%26',\t\t// &\n\t\t'%24',\t\t// $\n\t\t'%3f',\t\t// ?\n\t\t'%3b',\t\t// ;\n\t\t'%3d'\t\t// =\n\t);\n\n\t/**\n\t * Character set\n\t *\n\t * Will be overridden by the constructor.\n\t *\n\t * @var\tstring\n\t */\n\tpublic $charset = 'UTF-8';\n\n\t/**\n\t * XSS Hash\n\t *\n\t * Random Hash for protecting URLs.\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_xss_hash;\n\n\t/**\n\t * CSRF Hash\n\t *\n\t * Random hash for Cross Site Request Forgery protection cookie\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_csrf_hash;\n\n\t/**\n\t * CSRF Expire time\n\t *\n\t * Expiration time for Cross Site Request Forgery protection cookie.\n\t * Defaults to two hours (in seconds).\n\t *\n\t * @var\tint\n\t */\n\tprotected $_csrf_expire =\t7200;\n\n\t/**\n\t * CSRF Token name\n\t *\n\t * Token name for Cross Site Request Forgery protection cookie.\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_csrf_token_name =\t'ci_csrf_token';\n\n\t/**\n\t * CSRF Cookie name\n\t *\n\t * Cookie name for Cross Site Request Forgery protection cookie.\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_csrf_cookie_name =\t'ci_csrf_token';\n\n\t/**\n\t * List of never allowed strings\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_never_allowed_str =\tarray(\n\t\t'document.cookie'\t=> '[removed]',\n\t\t'document.write'\t=> '[removed]',\n\t\t'.parentNode'\t\t=> '[removed]',\n\t\t'.innerHTML'\t\t=> '[removed]',\n\t\t'-moz-binding'\t\t=> '[removed]',\n\t\t'<!--'\t\t\t\t=> '&lt;!--',\n\t\t'-->'\t\t\t\t=> '--&gt;',\n\t\t'<![CDATA['\t\t\t=> '&lt;![CDATA[',\n\t\t'<comment>'\t\t\t=> '&lt;comment&gt;'\n\t);\n\n\t/**\n\t * List of never allowed regex replacements\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_never_allowed_regex = array(\n\t\t'javascript\\s*:',\n\t\t'(document|(document\\.)?window)\\.(location|on\\w*)',\n\t\t'expression\\s*(\\(|&\\#40;)', // CSS and IE\n\t\t'vbscript\\s*:', // IE, surprise!\n\t\t'wscript\\s*:', // IE\n\t\t'jscript\\s*:', // IE\n\t\t'vbs\\s*:', // IE\n\t\t'Redirect\\s+30\\d',\n\t\t\"([\\\"'])?data\\s*:[^\\\\1]*?base64[^\\\\1]*?,[^\\\\1]*?\\\\1?\"\n\t);\n\n\t/**\n\t * Class constructor\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\t// Is CSRF protection enabled?\n\t\tif (config_item('csrf_protection'))\n\t\t{\n\t\t\t// CSRF config\n\t\t\tforeach (array('csrf_expire', 'csrf_token_name', 'csrf_cookie_name') as $key)\n\t\t\t{\n\t\t\t\tif (NULL !== ($val = config_item($key)))\n\t\t\t\t{\n\t\t\t\t\t$this->{'_'.$key} = $val;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Append application specific cookie prefix\n\t\t\tif ($cookie_prefix = config_item('cookie_prefix'))\n\t\t\t{\n\t\t\t\t$this->_csrf_cookie_name = $cookie_prefix.$this->_csrf_cookie_name;\n\t\t\t}\n\n\t\t\t// Set the CSRF hash\n\t\t\t$this->_csrf_set_hash();\n\t\t}\n\n\t\t$this->charset = strtoupper(config_item('charset'));\n\n\t\tlog_message('info', 'Security Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * CSRF Verify\n\t *\n\t * @return\tCI_Security\n\t */\n\tpublic function csrf_verify()\n\t{\n\t\t// If it's not a POST request we will set the CSRF cookie\n\t\tif (strtoupper($_SERVER['REQUEST_METHOD']) !== 'POST')\n\t\t{\n\t\t\treturn $this->csrf_set_cookie();\n\t\t}\n\n\t\t// Check if URI has been whitelisted from CSRF checks\n\t\tif ($exclude_uris = config_item('csrf_exclude_uris'))\n\t\t{\n\t\t\t$uri = load_class('URI', 'core');\n\t\t\tforeach ($exclude_uris as $excluded)\n\t\t\t{\n\t\t\t\tif (preg_match('#^'.$excluded.'$#i'.(UTF8_ENABLED ? 'u' : ''), $uri->uri_string()))\n\t\t\t\t{\n\t\t\t\t\treturn $this;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Do the tokens exist in both the _POST and _COOKIE arrays?\n\t\tif ( ! isset($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name])\n\t\t\tOR $_POST[$this->_csrf_token_name] !== $_COOKIE[$this->_csrf_cookie_name]) // Do the tokens match?\n\t\t{\n\t\t\t$this->csrf_show_error();\n\t\t}\n\n\t\t// We kill this since we're done and we don't want to polute the _POST array\n\t\tunset($_POST[$this->_csrf_token_name]);\n\n\t\t// Regenerate on every submission?\n\t\tif (config_item('csrf_regenerate'))\n\t\t{\n\t\t\t// Nothing should last forever\n\t\t\tunset($_COOKIE[$this->_csrf_cookie_name]);\n\t\t\t$this->_csrf_hash = NULL;\n\t\t}\n\n\t\t$this->_csrf_set_hash();\n\t\t$this->csrf_set_cookie();\n\n\t\tlog_message('info', 'CSRF token verified');\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * CSRF Set Cookie\n\t *\n\t * @codeCoverageIgnore\n\t * @return\tCI_Security\n\t */\n\tpublic function csrf_set_cookie()\n\t{\n\t\t$expire = time() + $this->_csrf_expire;\n\t\t$secure_cookie = (bool) config_item('cookie_secure');\n\n\t\tif ($secure_cookie && ! is_https())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tsetcookie(\n\t\t\t$this->_csrf_cookie_name,\n\t\t\t$this->_csrf_hash,\n\t\t\t$expire,\n\t\t\tconfig_item('cookie_path'),\n\t\t\tconfig_item('cookie_domain'),\n\t\t\t$secure_cookie,\n\t\t\tconfig_item('cookie_httponly')\n\t\t);\n\t\tlog_message('info', 'CSRF cookie sent');\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show CSRF Error\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function csrf_show_error()\n\t{\n\t\tshow_error('The action you have requested is not allowed.', 403);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get CSRF Hash\n\t *\n\t * @see\t\tCI_Security::$_csrf_hash\n\t * @return \tstring\tCSRF hash\n\t */\n\tpublic function get_csrf_hash()\n\t{\n\t\treturn $this->_csrf_hash;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get CSRF Token Name\n\t *\n\t * @see\t\tCI_Security::$_csrf_token_name\n\t * @return\tstring\tCSRF token name\n\t */\n\tpublic function get_csrf_token_name()\n\t{\n\t\treturn $this->_csrf_token_name;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * XSS Clean\n\t *\n\t * Sanitizes data so that Cross Site Scripting Hacks can be\n\t * prevented.  This method does a fair amount of work but\n\t * it is extremely thorough, designed to prevent even the\n\t * most obscure XSS attempts.  Nothing is ever 100% foolproof,\n\t * of course, but I haven't been able to get anything passed\n\t * the filter.\n\t *\n\t * Note: Should only be used to deal with data upon submission.\n\t *\t It's not something that should be used for general\n\t *\t runtime processing.\n\t *\n\t * @link\thttp://channel.bitflux.ch/wiki/XSS_Prevention\n\t * \t\tBased in part on some code and ideas from Bitflux.\n\t *\n\t * @link\thttp://ha.ckers.org/xss.html\n\t * \t\tTo help develop this script I used this great list of\n\t *\t\tvulnerabilities along with a few other hacks I've\n\t *\t\tharvested from examining vulnerabilities in other programs.\n\t *\n\t * @param\tstring|string[]\t$str\t\tInput data\n\t * @param \tbool\t\t$is_image\tWhether the input is an image\n\t * @return\tstring\n\t */\n\tpublic function xss_clean($str, $is_image = FALSE)\n\t{\n\t\t// Is the string an array?\n\t\tif (is_array($str))\n\t\t{\n\t\t\twhile (list($key) = each($str))\n\t\t\t{\n\t\t\t\t$str[$key] = $this->xss_clean($str[$key]);\n\t\t\t}\n\n\t\t\treturn $str;\n\t\t}\n\n\t\t// Remove Invisible Characters\n\t\t$str = remove_invisible_characters($str);\n\n\t\t/*\n\t\t * URL Decode\n\t\t *\n\t\t * Just in case stuff like this is submitted:\n\t\t *\n\t\t * <a href=\"http://%77%77%77%2E%67%6F%6F%67%6C%65%2E%63%6F%6D\">Google</a>\n\t\t *\n\t\t * Note: Use rawurldecode() so it does not remove plus signs\n\t\t */\n\t\tdo\n\t\t{\n\t\t\t$str = rawurldecode($str);\n\t\t}\n\t\twhile (preg_match('/%[0-9a-f]{2,}/i', $str));\n\n\t\t/*\n\t\t * Convert character entities to ASCII\n\t\t *\n\t\t * This permits our tests below to work reliably.\n\t\t * We only convert entities that are within tags since\n\t\t * these are the ones that will pose security problems.\n\t\t */\n\t\t$str = preg_replace_callback(\"/[^a-z0-9>]+[a-z0-9]+=([\\'\\\"]).*?\\\\1/si\", array($this, '_convert_attribute'), $str);\n\t\t$str = preg_replace_callback('/<\\w+.*/si', array($this, '_decode_entity'), $str);\n\n\t\t// Remove Invisible Characters Again!\n\t\t$str = remove_invisible_characters($str);\n\n\t\t/*\n\t\t * Convert all tabs to spaces\n\t\t *\n\t\t * This prevents strings like this: ja\tvascript\n\t\t * NOTE: we deal with spaces between characters later.\n\t\t * NOTE: preg_replace was found to be amazingly slow here on\n\t\t * large blocks of data, so we use str_replace.\n\t\t */\n\t\t$str = str_replace(\"\\t\", ' ', $str);\n\n\t\t// Capture converted string for later comparison\n\t\t$converted_string = $str;\n\n\t\t// Remove Strings that are never allowed\n\t\t$str = $this->_do_never_allowed($str);\n\n\t\t/*\n\t\t * Makes PHP tags safe\n\t\t *\n\t\t * Note: XML tags are inadvertently replaced too:\n\t\t *\n\t\t * <?xml\n\t\t *\n\t\t * But it doesn't seem to pose a problem.\n\t\t */\n\t\tif ($is_image === TRUE)\n\t\t{\n\t\t\t// Images have a tendency to have the PHP short opening and\n\t\t\t// closing tags every so often so we skip those and only\n\t\t\t// do the long opening tags.\n\t\t\t$str = preg_replace('/<\\?(php)/i', '&lt;?\\\\1', $str);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$str = str_replace(array('<?', '?'.'>'), array('&lt;?', '?&gt;'), $str);\n\t\t}\n\n\t\t/*\n\t\t * Compact any exploded words\n\t\t *\n\t\t * This corrects words like:  j a v a s c r i p t\n\t\t * These words are compacted back to their correct state.\n\t\t */\n\t\t$words = array(\n\t\t\t'javascript', 'expression', 'vbscript', 'jscript', 'wscript',\n\t\t\t'vbs', 'script', 'base64', 'applet', 'alert', 'document',\n\t\t\t'write', 'cookie', 'window', 'confirm', 'prompt', 'eval'\n\t\t);\n\n\t\tforeach ($words as $word)\n\t\t{\n\t\t\t$word = implode('\\s*', str_split($word)).'\\s*';\n\n\t\t\t// We only want to do this when it is followed by a non-word character\n\t\t\t// That way valid stuff like \"dealer to\" does not become \"dealerto\"\n\t\t\t$str = preg_replace_callback('#('.substr($word, 0, -3).')(\\W)#is', array($this, '_compact_exploded_words'), $str);\n\t\t}\n\n\t\t/*\n\t\t * Remove disallowed Javascript in links or img tags\n\t\t * We used to do some version comparisons and use of stripos(),\n\t\t * but it is dog slow compared to these simplified non-capturing\n\t\t * preg_match(), especially if the pattern exists in the string\n\t\t *\n\t\t * Note: It was reported that not only space characters, but all in\n\t\t * the following pattern can be parsed as separators between a tag name\n\t\t * and its attributes: [\\d\\s\"\\'`;,\\/\\=\\(\\x00\\x0B\\x09\\x0C]\n\t\t * ... however, remove_invisible_characters() above already strips the\n\t\t * hex-encoded ones, so we'll skip them below.\n\t\t */\n\t\tdo\n\t\t{\n\t\t\t$original = $str;\n\n\t\t\tif (preg_match('/<a/i', $str))\n\t\t\t{\n\t\t\t\t$str = preg_replace_callback('#<a[^a-z0-9>]+([^>]*?)(?:>|$)#si', array($this, '_js_link_removal'), $str);\n\t\t\t}\n\n\t\t\tif (preg_match('/<img/i', $str))\n\t\t\t{\n\t\t\t\t$str = preg_replace_callback('#<img[^a-z0-9]+([^>]*?)(?:\\s?/?>|$)#si', array($this, '_js_img_removal'), $str);\n\t\t\t}\n\n\t\t\tif (preg_match('/script|xss/i', $str))\n\t\t\t{\n\t\t\t\t$str = preg_replace('#</*(?:script|xss).*?>#si', '[removed]', $str);\n\t\t\t}\n\t\t}\n\t\twhile ($original !== $str);\n\t\tunset($original);\n\n\t\t/*\n\t\t * Sanitize naughty HTML elements\n\t\t *\n\t\t * If a tag containing any of the words in the list\n\t\t * below is found, the tag gets converted to entities.\n\t\t *\n\t\t * So this: <blink>\n\t\t * Becomes: &lt;blink&gt;\n\t\t */\n\t\t$pattern = '#'\n\t\t\t.'<((?<slash>/*\\s*)(?<tagName>[a-z0-9]+)(?=[^a-z0-9]|$)' // tag start and name, followed by a non-tag character\n\t\t\t.'[^\\s\\042\\047a-z0-9>/=]*' // a valid attribute character immediately after the tag would count as a separator\n\t\t\t// optional attributes\n\t\t\t.'(?<attributes>(?:[\\s\\042\\047/=]*' // non-attribute characters, excluding > (tag close) for obvious reasons\n\t\t\t.'[^\\s\\042\\047>/=]+' // attribute characters\n\t\t\t// optional attribute-value\n\t\t\t\t.'(?:\\s*=' // attribute-value separator\n\t\t\t\t\t.'(?:[^\\s\\042\\047=><`]+|\\s*\\042[^\\042]*\\042|\\s*\\047[^\\047]*\\047|\\s*(?U:[^\\s\\042\\047=><`]*))' // single, double or non-quoted value\n\t\t\t\t.')?' // end optional attribute-value group\n\t\t\t.')*)' // end optional attributes group\n\t\t\t.'[^>]*)(?<closeTag>\\>)?#isS';\n\n\t\t// Note: It would be nice to optimize this for speed, BUT\n\t\t//       only matching the naughty elements here results in\n\t\t//       false positives and in turn - vulnerabilities!\n\t\tdo\n\t\t{\n\t\t\t$old_str = $str;\n\t\t\t$str = preg_replace_callback($pattern, array($this, '_sanitize_naughty_html'), $str);\n\t\t}\n\t\twhile ($old_str !== $str);\n\t\tunset($old_str);\n\n\t\t/*\n\t\t * Sanitize naughty scripting elements\n\t\t *\n\t\t * Similar to above, only instead of looking for\n\t\t * tags it looks for PHP and JavaScript commands\n\t\t * that are disallowed. Rather than removing the\n\t\t * code, it simply converts the parenthesis to entities\n\t\t * rendering the code un-executable.\n\t\t *\n\t\t * For example:\teval('some code')\n\t\t * Becomes:\teval&#40;'some code'&#41;\n\t\t */\n\t\t$str = preg_replace(\n\t\t\t'#(alert|prompt|confirm|cmd|passthru|eval|exec|expression|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(\\s*)\\((.*?)\\)#si',\n\t\t\t'\\\\1\\\\2&#40;\\\\3&#41;',\n\t\t\t$str\n\t\t);\n\n\t\t// Final clean up\n\t\t// This adds a bit of extra precaution in case\n\t\t// something got through the above filters\n\t\t$str = $this->_do_never_allowed($str);\n\n\t\t/*\n\t\t * Images are Handled in a Special Way\n\t\t * - Essentially, we want to know that after all of the character\n\t\t * conversion is done whether any unwanted, likely XSS, code was found.\n\t\t * If not, we return TRUE, as the image is clean.\n\t\t * However, if the string post-conversion does not matched the\n\t\t * string post-removal of XSS, then it fails, as there was unwanted XSS\n\t\t * code found and removed/changed during processing.\n\t\t */\n\t\tif ($is_image === TRUE)\n\t\t{\n\t\t\treturn ($str === $converted_string);\n\t\t}\n\n\t\treturn $str;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * XSS Hash\n\t *\n\t * Generates the XSS hash if needed and returns it.\n\t *\n\t * @see\t\tCI_Security::$_xss_hash\n\t * @return\tstring\tXSS hash\n\t */\n\tpublic function xss_hash()\n\t{\n\t\tif ($this->_xss_hash === NULL)\n\t\t{\n\t\t\t$rand = $this->get_random_bytes(16);\n\t\t\t$this->_xss_hash = ($rand === FALSE)\n\t\t\t\t? md5(uniqid(mt_rand(), TRUE))\n\t\t\t\t: bin2hex($rand);\n\t\t}\n\n\t\treturn $this->_xss_hash;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get random bytes\n\t *\n\t * @param\tint\t$length\tOutput length\n\t * @return\tstring\n\t */\n\tpublic function get_random_bytes($length)\n\t{\n\t\tif (empty($length) OR ! ctype_digit((string) $length))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (function_exists('random_bytes'))\n\t\t{\n\t\t\ttry\n\t\t\t{\n\t\t\t\t// The cast is required to avoid TypeError\n\t\t\t\treturn random_bytes((int) $length);\n\t\t\t}\n\t\t\tcatch (Exception $e)\n\t\t\t{\n\t\t\t\t// If random_bytes() can't do the job, we can't either ...\n\t\t\t\t// There's no point in using fallbacks.\n\t\t\t\tlog_message('error', $e->getMessage());\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\t// Unfortunately, none of the following PRNGs is guaranteed to exist ...\n\t\tif (defined('MCRYPT_DEV_URANDOM') && ($output = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM)) !== FALSE)\n\t\t{\n\t\t\treturn $output;\n\t\t}\n\n\n\t\tif (is_readable('/dev/urandom') && ($fp = fopen('/dev/urandom', 'rb')) !== FALSE)\n\t\t{\n\t\t\t// Try not to waste entropy ...\n\t\t\tis_php('5.4') && stream_set_chunk_size($fp, $length);\n\t\t\t$output = fread($fp, $length);\n\t\t\tfclose($fp);\n\t\t\tif ($output !== FALSE)\n\t\t\t{\n\t\t\t\treturn $output;\n\t\t\t}\n\t\t}\n\n\t\tif (function_exists('openssl_random_pseudo_bytes'))\n\t\t{\n\t\t\treturn openssl_random_pseudo_bytes($length);\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * HTML Entities Decode\n\t *\n\t * A replacement for html_entity_decode()\n\t *\n\t * The reason we are not using html_entity_decode() by itself is because\n\t * while it is not technically correct to leave out the semicolon\n\t * at the end of an entity most browsers will still interpret the entity\n\t * correctly. html_entity_decode() does not convert entities without\n\t * semicolons, so we are left with our own little solution here. Bummer.\n\t *\n\t * @link\thttp://php.net/html-entity-decode\n\t *\n\t * @param\tstring\t$str\t\tInput\n\t * @param\tstring\t$charset\tCharacter set\n\t * @return\tstring\n\t */\n\tpublic function entity_decode($str, $charset = NULL)\n\t{\n\t\tif (strpos($str, '&') === FALSE)\n\t\t{\n\t\t\treturn $str;\n\t\t}\n\n\t\tstatic $_entities;\n\n\t\tisset($charset) OR $charset = $this->charset;\n\t\t$flag = is_php('5.4')\n\t\t\t? ENT_COMPAT | ENT_HTML5\n\t\t\t: ENT_COMPAT;\n\n\t\tdo\n\t\t{\n\t\t\t$str_compare = $str;\n\n\t\t\t// Decode standard entities, avoiding false positives\n\t\t\tif (preg_match_all('/&[a-z]{2,}(?![a-z;])/i', $str, $matches))\n\t\t\t{\n\t\t\t\tif ( ! isset($_entities))\n\t\t\t\t{\n\t\t\t\t\t$_entities = array_map(\n\t\t\t\t\t\t'strtolower',\n\t\t\t\t\t\tis_php('5.3.4')\n\t\t\t\t\t\t\t? get_html_translation_table(HTML_ENTITIES, $flag, $charset)\n\t\t\t\t\t\t\t: get_html_translation_table(HTML_ENTITIES, $flag)\n\t\t\t\t\t);\n\n\t\t\t\t\t// If we're not on PHP 5.4+, add the possibly dangerous HTML 5\n\t\t\t\t\t// entities to the array manually\n\t\t\t\t\tif ($flag === ENT_COMPAT)\n\t\t\t\t\t{\n\t\t\t\t\t\t$_entities[':'] = '&colon;';\n\t\t\t\t\t\t$_entities['('] = '&lpar;';\n\t\t\t\t\t\t$_entities[')'] = '&rpar;';\n\t\t\t\t\t\t$_entities[\"\\n\"] = '&newline;';\n\t\t\t\t\t\t$_entities[\"\\t\"] = '&tab;';\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t$replace = array();\n\t\t\t\t$matches = array_unique(array_map('strtolower', $matches[0]));\n\t\t\t\tforeach ($matches as &$match)\n\t\t\t\t{\n\t\t\t\t\tif (($char = array_search($match.';', $_entities, TRUE)) !== FALSE)\n\t\t\t\t\t{\n\t\t\t\t\t\t$replace[$match] = $char;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t$str = str_ireplace(array_keys($replace), array_values($replace), $str);\n\t\t\t}\n\n\t\t\t// Decode numeric & UTF16 two byte entities\n\t\t\t$str = html_entity_decode(\n\t\t\t\tpreg_replace('/(&#(?:x0*[0-9a-f]{2,5}(?![0-9a-f;])|(?:0*\\d{2,4}(?![0-9;]))))/iS', '$1;', $str),\n\t\t\t\t$flag,\n\t\t\t\t$charset\n\t\t\t);\n\t\t}\n\t\twhile ($str_compare !== $str);\n\t\treturn $str;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Sanitize Filename\n\t *\n\t * @param\tstring\t$str\t\tInput file name\n\t * @param \tbool\t$relative_path\tWhether to preserve paths\n\t * @return\tstring\n\t */\n\tpublic function sanitize_filename($str, $relative_path = FALSE)\n\t{\n\t\t$bad = $this->filename_bad_chars;\n\n\t\tif ( ! $relative_path)\n\t\t{\n\t\t\t$bad[] = './';\n\t\t\t$bad[] = '/';\n\t\t}\n\n\t\t$str = remove_invisible_characters($str, FALSE);\n\n\t\tdo\n\t\t{\n\t\t\t$old = $str;\n\t\t\t$str = str_replace($bad, '', $str);\n\t\t}\n\t\twhile ($old !== $str);\n\n\t\treturn stripslashes($str);\n\t}\n\n\t// ----------------------------------------------------------------\n\n\t/**\n\t * Strip Image Tags\n\t *\n\t * @param\tstring\t$str\n\t * @return\tstring\n\t */\n\tpublic function strip_image_tags($str)\n\t{\n\t\treturn preg_replace(\n\t\t\tarray(\n\t\t\t\t'#<img[\\s/]+.*?src\\s*=\\s*([\"\\'])([^\\\\1]+?)\\\\1.*?\\>#i',\n\t\t\t\t'#<img[\\s/]+.*?src\\s*=\\s*?(([^\\s\"\\'=<>`]+)).*?\\>#i'\n\t\t\t),\n\t\t\t'\\\\2',\n\t\t\t$str\n\t\t);\n\t}\n\n\t// ----------------------------------------------------------------\n\n\t/**\n\t * Compact Exploded Words\n\t *\n\t * Callback method for xss_clean() to remove whitespace from\n\t * things like 'j a v a s c r i p t'.\n\t *\n\t * @used-by\tCI_Security::xss_clean()\n\t * @param\tarray\t$matches\n\t * @return\tstring\n\t */\n\tprotected function _compact_exploded_words($matches)\n\t{\n\t\treturn preg_replace('/\\s+/s', '', $matches[1]).$matches[2];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Sanitize Naughty HTML\n\t *\n\t * Callback method for xss_clean() to remove naughty HTML elements.\n\t *\n\t * @used-by\tCI_Security::xss_clean()\n\t * @param\tarray\t$matches\n\t * @return\tstring\n\t */\n\tprotected function _sanitize_naughty_html($matches)\n\t{\n\t\tstatic $naughty_tags    = array(\n\t\t\t'alert', 'prompt', 'confirm', 'applet', 'audio', 'basefont', 'base', 'behavior', 'bgsound',\n\t\t\t'blink', 'body', 'embed', 'expression', 'form', 'frameset', 'frame', 'head', 'html', 'ilayer',\n\t\t\t'iframe', 'input', 'button', 'select', 'isindex', 'layer', 'link', 'meta', 'keygen', 'object',\n\t\t\t'plaintext', 'style', 'script', 'textarea', 'title', 'math', 'video', 'svg', 'xml', 'xss'\n\t\t);\n\n\t\tstatic $evil_attributes = array(\n\t\t\t'on\\w+', 'style', 'xmlns', 'formaction', 'form', 'xlink:href', 'FSCommand', 'seekSegmentTime'\n\t\t);\n\n\t\t// First, escape unclosed tags\n\t\tif (empty($matches['closeTag']))\n\t\t{\n\t\t\treturn '&lt;'.$matches[1];\n\t\t}\n\t\t// Is the element that we caught naughty? If so, escape it\n\t\telseif (in_array(strtolower($matches['tagName']), $naughty_tags, TRUE))\n\t\t{\n\t\t\treturn '&lt;'.$matches[1].'&gt;';\n\t\t}\n\t\t// For other tags, see if their attributes are \"evil\" and strip those\n\t\telseif (isset($matches['attributes']))\n\t\t{\n\t\t\t// We'll store the already fitlered attributes here\n\t\t\t$attributes = array();\n\n\t\t\t// Attribute-catching pattern\n\t\t\t$attributes_pattern = '#'\n\t\t\t\t.'(?<name>[^\\s\\042\\047>/=]+)' // attribute characters\n\t\t\t\t// optional attribute-value\n\t\t\t\t.'(?:\\s*=(?<value>[^\\s\\042\\047=><`]+|\\s*\\042[^\\042]*\\042|\\s*\\047[^\\047]*\\047|\\s*(?U:[^\\s\\042\\047=><`]*)))' // attribute-value separator\n\t\t\t\t.'#i';\n\n\t\t\t// Blacklist pattern for evil attribute names\n\t\t\t$is_evil_pattern = '#^('.implode('|', $evil_attributes).')$#i';\n\n\t\t\t// Each iteration filters a single attribute\n\t\t\tdo\n\t\t\t{\n\t\t\t\t// Strip any non-alpha characters that may preceed an attribute.\n\t\t\t\t// Browsers often parse these incorrectly and that has been a\n\t\t\t\t// of numerous XSS issues we've had.\n\t\t\t\t$matches['attributes'] = preg_replace('#^[^a-z]+#i', '', $matches['attributes']);\n\n\t\t\t\tif ( ! preg_match($attributes_pattern, $matches['attributes'], $attribute, PREG_OFFSET_CAPTURE))\n\t\t\t\t{\n\t\t\t\t\t// No (valid) attribute found? Discard everything else inside the tag\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\t// Is it indeed an \"evil\" attribute?\n\t\t\t\t\tpreg_match($is_evil_pattern, $attribute['name'][0])\n\t\t\t\t\t// Or does it have an equals sign, but no value and not quoted? Strip that too!\n\t\t\t\t\tOR (trim($attribute['value'][0]) === '')\n\t\t\t\t)\n\t\t\t\t{\n\t\t\t\t\t$attributes[] = 'xss=removed';\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$attributes[] = $attribute[0][0];\n\t\t\t\t}\n\n\t\t\t\t$matches['attributes'] = substr($matches['attributes'], $attribute[0][1] + strlen($attribute[0][0]));\n\t\t\t}\n\t\t\twhile ($matches['attributes'] !== '');\n\n\t\t\t$attributes = empty($attributes)\n\t\t\t\t? ''\n\t\t\t\t: ' '.implode(' ', $attributes);\n\t\t\treturn '<'.$matches['slash'].$matches['tagName'].$attributes.'>';\n\t\t}\n\n\t\treturn $matches[0];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * JS Link Removal\n\t *\n\t * Callback method for xss_clean() to sanitize links.\n\t *\n\t * This limits the PCRE backtracks, making it more performance friendly\n\t * and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in\n\t * PHP 5.2+ on link-heavy strings.\n\t *\n\t * @used-by\tCI_Security::xss_clean()\n\t * @param\tarray\t$match\n\t * @return\tstring\n\t */\n\tprotected function _js_link_removal($match)\n\t{\n\t\treturn str_replace(\n\t\t\t$match[1],\n\t\t\tpreg_replace(\n\t\t\t\t'#href=.*?(?:(?:alert|prompt|confirm)(?:\\(|&\\#40;)|javascript:|livescript:|mocha:|charset=|window\\.|document\\.|\\.cookie|<script|<xss|data\\s*:)#si',\n\t\t\t\t'',\n\t\t\t\t$this->_filter_attributes($match[1])\n\t\t\t),\n\t\t\t$match[0]\n\t\t);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * JS Image Removal\n\t *\n\t * Callback method for xss_clean() to sanitize image tags.\n\t *\n\t * This limits the PCRE backtracks, making it more performance friendly\n\t * and prevents PREG_BACKTRACK_LIMIT_ERROR from being triggered in\n\t * PHP 5.2+ on image tag heavy strings.\n\t *\n\t * @used-by\tCI_Security::xss_clean()\n\t * @param\tarray\t$match\n\t * @return\tstring\n\t */\n\tprotected function _js_img_removal($match)\n\t{\n\t\treturn str_replace(\n\t\t\t$match[1],\n\t\t\tpreg_replace(\n\t\t\t\t'#src=.*?(?:(?:alert|prompt|confirm|eval)(?:\\(|&\\#40;)|javascript:|livescript:|mocha:|charset=|window\\.|document\\.|\\.cookie|<script|<xss|base64\\s*,)#si',\n\t\t\t\t'',\n\t\t\t\t$this->_filter_attributes($match[1])\n\t\t\t),\n\t\t\t$match[0]\n\t\t);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Attribute Conversion\n\t *\n\t * @used-by\tCI_Security::xss_clean()\n\t * @param\tarray\t$match\n\t * @return\tstring\n\t */\n\tprotected function _convert_attribute($match)\n\t{\n\t\treturn str_replace(array('>', '<', '\\\\'), array('&gt;', '&lt;', '\\\\\\\\'), $match[0]);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Filter Attributes\n\t *\n\t * Filters tag attributes for consistency and safety.\n\t *\n\t * @used-by\tCI_Security::_js_img_removal()\n\t * @used-by\tCI_Security::_js_link_removal()\n\t * @param\tstring\t$str\n\t * @return\tstring\n\t */\n\tprotected function _filter_attributes($str)\n\t{\n\t\t$out = '';\n\t\tif (preg_match_all('#\\s*[a-z\\-]+\\s*=\\s*(\\042|\\047)([^\\\\1]*?)\\\\1#is', $str, $matches))\n\t\t{\n\t\t\tforeach ($matches[0] as $match)\n\t\t\t{\n\t\t\t\t$out .= preg_replace('#/\\*.*?\\*/#s', '', $match);\n\t\t\t}\n\t\t}\n\n\t\treturn $out;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * HTML Entity Decode Callback\n\t *\n\t * @used-by\tCI_Security::xss_clean()\n\t * @param\tarray\t$match\n\t * @return\tstring\n\t */\n\tprotected function _decode_entity($match)\n\t{\n\t\t// Protect GET variables in URLs\n\t\t// 901119URL5918AMP18930PROTECT8198\n\t\t$match = preg_replace('|\\&([a-z\\_0-9\\-]+)\\=([a-z\\_0-9\\-/]+)|i', $this->xss_hash().'\\\\1=\\\\2', $match[0]);\n\n\t\t// Decode, then un-protect URL GET vars\n\t\treturn str_replace(\n\t\t\t$this->xss_hash(),\n\t\t\t'&',\n\t\t\t$this->entity_decode($match, $this->charset)\n\t\t);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Do Never Allowed\n\t *\n\t * @used-by\tCI_Security::xss_clean()\n\t * @param \tstring\n\t * @return \tstring\n\t */\n\tprotected function _do_never_allowed($str)\n\t{\n\t\t$str = str_replace(array_keys($this->_never_allowed_str), $this->_never_allowed_str, $str);\n\n\t\tforeach ($this->_never_allowed_regex as $regex)\n\t\t{\n\t\t\t$str = preg_replace('#'.$regex.'#is', '[removed]', $str);\n\t\t}\n\n\t\treturn $str;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set CSRF Hash and Cookie\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _csrf_set_hash()\n\t{\n\t\tif ($this->_csrf_hash === NULL)\n\t\t{\n\t\t\t// If the cookie exists we will use its value.\n\t\t\t// We don't necessarily want to regenerate it with\n\t\t\t// each page load since a page could contain embedded\n\t\t\t// sub-pages causing this feature to fail\n\t\t\tif (isset($_COOKIE[$this->_csrf_cookie_name]) && is_string($_COOKIE[$this->_csrf_cookie_name])\n\t\t\t\t&& preg_match('#^[0-9a-f]{32}$#iS', $_COOKIE[$this->_csrf_cookie_name]) === 1)\n\t\t\t{\n\t\t\t\treturn $this->_csrf_hash = $_COOKIE[$this->_csrf_cookie_name];\n\t\t\t}\n\n\t\t\t$rand = $this->get_random_bytes(16);\n\t\t\t$this->_csrf_hash = ($rand === FALSE)\n\t\t\t\t? md5(uniqid(mt_rand(), TRUE))\n\t\t\t\t: bin2hex($rand);\n\t\t}\n\n\t\treturn $this->_csrf_hash;\n\t}\n\n}\n"
  },
  {
    "path": "system/core/URI.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * URI Class\n *\n * Parses URIs and determines routing\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tURI\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/uri.html\n */\nclass CI_URI {\n\n\t/**\n\t * List of cached URI segments\n\t *\n\t * @var\tarray\n\t */\n\tpublic $keyval = array();\n\n\t/**\n\t * Current URI string\n\t *\n\t * @var\tstring\n\t */\n\tpublic $uri_string = '';\n\n\t/**\n\t * List of URI segments\n\t *\n\t * Starts at 1 instead of 0.\n\t *\n\t * @var\tarray\n\t */\n\tpublic $segments = array();\n\n\t/**\n\t * List of routed URI segments\n\t *\n\t * Starts at 1 instead of 0.\n\t *\n\t * @var\tarray\n\t */\n\tpublic $rsegments = array();\n\n\t/**\n\t * Permitted URI chars\n\t *\n\t * PCRE character group allowed in URI segments\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_permitted_uri_chars;\n\n\t/**\n\t * Class constructor\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\t$this->config =& load_class('Config', 'core');\n\n\t\t// If query strings are enabled, we don't need to parse any segments.\n\t\t// However, they don't make sense under CLI.\n\t\tif (is_cli() OR $this->config->item('enable_query_strings') !== TRUE)\n\t\t{\n\t\t\t$this->_permitted_uri_chars = $this->config->item('permitted_uri_chars');\n\n\t\t\t// If it's a CLI request, ignore the configuration\n\t\t\tif (is_cli())\n\t\t\t{\n\t\t\t\t$uri = $this->_parse_argv();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$protocol = $this->config->item('uri_protocol');\n\t\t\t\tempty($protocol) && $protocol = 'REQUEST_URI';\n\n\t\t\t\tswitch ($protocol)\n\t\t\t\t{\n\t\t\t\t\tcase 'AUTO': // For BC purposes only\n\t\t\t\t\tcase 'REQUEST_URI':\n\t\t\t\t\t\t$uri = $this->_parse_request_uri();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'QUERY_STRING':\n\t\t\t\t\t\t$uri = $this->_parse_query_string();\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'PATH_INFO':\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t$uri = isset($_SERVER[$protocol])\n\t\t\t\t\t\t\t? $_SERVER[$protocol]\n\t\t\t\t\t\t\t: $this->_parse_request_uri();\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$this->_set_uri_string($uri);\n\t\t}\n\n\t\tlog_message('info', 'URI Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set URI String\n\t *\n\t * @param \tstring\t$str\n\t * @return\tvoid\n\t */\n\tprotected function _set_uri_string($str)\n\t{\n\t\t// Filter out control characters and trim slashes\n\t\t$this->uri_string = trim(remove_invisible_characters($str, FALSE), '/');\n\n\t\tif ($this->uri_string !== '')\n\t\t{\n\t\t\t// Remove the URL suffix, if present\n\t\t\tif (($suffix = (string) $this->config->item('url_suffix')) !== '')\n\t\t\t{\n\t\t\t\t$slen = strlen($suffix);\n\n\t\t\t\tif (substr($this->uri_string, -$slen) === $suffix)\n\t\t\t\t{\n\t\t\t\t\t$this->uri_string = substr($this->uri_string, 0, -$slen);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$this->segments[0] = NULL;\n\t\t\t// Populate the segments array\n\t\t\tforeach (explode('/', trim($this->uri_string, '/')) as $val)\n\t\t\t{\n\t\t\t\t$val = trim($val);\n\t\t\t\t// Filter segments for security\n\t\t\t\t$this->filter_uri($val);\n\n\t\t\t\tif ($val !== '')\n\t\t\t\t{\n\t\t\t\t\t$this->segments[] = $val;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tunset($this->segments[0]);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse REQUEST_URI\n\t *\n\t * Will parse REQUEST_URI and automatically detect the URI from it,\n\t * while fixing the query string if necessary.\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _parse_request_uri()\n\t{\n\t\tif ( ! isset($_SERVER['REQUEST_URI'], $_SERVER['SCRIPT_NAME']))\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\t// parse_url() returns false if no host is present, but the path or query string\n\t\t// contains a colon followed by a number\n\t\t$uri = parse_url('http://dummy'.$_SERVER['REQUEST_URI']);\n\t\t$query = isset($uri['query']) ? $uri['query'] : '';\n\t\t$uri = isset($uri['path']) ? $uri['path'] : '';\n\n\t\tif (isset($_SERVER['SCRIPT_NAME'][0]))\n\t\t{\n\t\t\tif (strpos($uri, $_SERVER['SCRIPT_NAME']) === 0)\n\t\t\t{\n\t\t\t\t$uri = (string) substr($uri, strlen($_SERVER['SCRIPT_NAME']));\n\t\t\t}\n\t\t\telseif (strpos($uri, dirname($_SERVER['SCRIPT_NAME'])) === 0)\n\t\t\t{\n\t\t\t\t$uri = (string) substr($uri, strlen(dirname($_SERVER['SCRIPT_NAME'])));\n\t\t\t}\n\t\t}\n\n\t\t// This section ensures that even on servers that require the URI to be in the query string (Nginx) a correct\n\t\t// URI is found, and also fixes the QUERY_STRING server var and $_GET array.\n\t\tif (trim($uri, '/') === '' && strncmp($query, '/', 1) === 0)\n\t\t{\n\t\t\t$query = explode('?', $query, 2);\n\t\t\t$uri = $query[0];\n\t\t\t$_SERVER['QUERY_STRING'] = isset($query[1]) ? $query[1] : '';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$_SERVER['QUERY_STRING'] = $query;\n\t\t}\n\n\t\tparse_str($_SERVER['QUERY_STRING'], $_GET);\n\n\t\tif ($uri === '/' OR $uri === '')\n\t\t{\n\t\t\treturn '/';\n\t\t}\n\n\t\t// Do some final cleaning of the URI and return it\n\t\treturn $this->_remove_relative_directory($uri);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse QUERY_STRING\n\t *\n\t * Will parse QUERY_STRING and automatically detect the URI from it.\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _parse_query_string()\n\t{\n\t\t$uri = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING');\n\n\t\tif (trim($uri, '/') === '')\n\t\t{\n\t\t\treturn '';\n\t\t}\n\t\telseif (strncmp($uri, '/', 1) === 0)\n\t\t{\n\t\t\t$uri = explode('?', $uri, 2);\n\t\t\t$_SERVER['QUERY_STRING'] = isset($uri[1]) ? $uri[1] : '';\n\t\t\t$uri = $uri[0];\n\t\t}\n\n\t\tparse_str($_SERVER['QUERY_STRING'], $_GET);\n\n\t\treturn $this->_remove_relative_directory($uri);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse CLI arguments\n\t *\n\t * Take each command line argument and assume it is a URI segment.\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _parse_argv()\n\t{\n\t\t$args = array_slice($_SERVER['argv'], 1);\n\t\treturn $args ? implode('/', $args) : '';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Remove relative directory (../) and multi slashes (///)\n\t *\n\t * Do some final cleaning of the URI and return it, currently only used in self::_parse_request_uri()\n\t *\n\t * @param\tstring\t$uri\n\t * @return\tstring\n\t */\n\tprotected function _remove_relative_directory($uri)\n\t{\n\t\t$uris = array();\n\t\t$tok = strtok($uri, '/');\n\t\twhile ($tok !== FALSE)\n\t\t{\n\t\t\tif (( ! empty($tok) OR $tok === '0') && $tok !== '..')\n\t\t\t{\n\t\t\t\t$uris[] = $tok;\n\t\t\t}\n\t\t\t$tok = strtok('/');\n\t\t}\n\n\t\treturn implode('/', $uris);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Filter URI\n\t *\n\t * Filters segments for malicious characters.\n\t *\n\t * @param\tstring\t$str\n\t * @return\tvoid\n\t */\n\tpublic function filter_uri(&$str)\n\t{\n\t\tif ( ! empty($str) && ! empty($this->_permitted_uri_chars) && ! preg_match('/^['.$this->_permitted_uri_chars.']+$/i'.(UTF8_ENABLED ? 'u' : ''), $str))\n\t\t{\n\t\t\tshow_error('The URI you submitted has disallowed characters.', 400);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch URI Segment\n\t *\n\t * @see\t\tCI_URI::$segments\n\t * @param\tint\t\t$n\t\tIndex\n\t * @param\tmixed\t\t$no_result\tWhat to return if the segment index is not found\n\t * @return\tmixed\n\t */\n\tpublic function segment($n, $no_result = NULL)\n\t{\n\t\treturn isset($this->segments[$n]) ? $this->segments[$n] : $no_result;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch URI \"routed\" Segment\n\t *\n\t * Returns the re-routed URI segment (assuming routing rules are used)\n\t * based on the index provided. If there is no routing, will return\n\t * the same result as CI_URI::segment().\n\t *\n\t * @see\t\tCI_URI::$rsegments\n\t * @see\t\tCI_URI::segment()\n\t * @param\tint\t\t$n\t\tIndex\n\t * @param\tmixed\t\t$no_result\tWhat to return if the segment index is not found\n\t * @return\tmixed\n\t */\n\tpublic function rsegment($n, $no_result = NULL)\n\t{\n\t\treturn isset($this->rsegments[$n]) ? $this->rsegments[$n] : $no_result;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * URI to assoc\n\t *\n\t * Generates an associative array of URI data starting at the supplied\n\t * segment index. For example, if this is your URI:\n\t *\n\t *\texample.com/user/search/name/joe/location/UK/gender/male\n\t *\n\t * You can use this method to generate an array with this prototype:\n\t *\n\t *\tarray (\n\t *\t\tname => joe\n\t *\t\tlocation => UK\n\t *\t\tgender => male\n\t *\t )\n\t *\n\t * @param\tint\t$n\t\tIndex (default: 3)\n\t * @param\tarray\t$default\tDefault values\n\t * @return\tarray\n\t */\n\tpublic function uri_to_assoc($n = 3, $default = array())\n\t{\n\t\treturn $this->_uri_to_assoc($n, $default, 'segment');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Routed URI to assoc\n\t *\n\t * Identical to CI_URI::uri_to_assoc(), only it uses the re-routed\n\t * segment array.\n\t *\n\t * @see\t\tCI_URI::uri_to_assoc()\n\t * @param \tint\t$n\t\tIndex (default: 3)\n\t * @param \tarray\t$default\tDefault values\n\t * @return \tarray\n\t */\n\tpublic function ruri_to_assoc($n = 3, $default = array())\n\t{\n\t\treturn $this->_uri_to_assoc($n, $default, 'rsegment');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Internal URI-to-assoc\n\t *\n\t * Generates a key/value pair from the URI string or re-routed URI string.\n\t *\n\t * @used-by\tCI_URI::uri_to_assoc()\n\t * @used-by\tCI_URI::ruri_to_assoc()\n\t * @param\tint\t$n\t\tIndex (default: 3)\n\t * @param\tarray\t$default\tDefault values\n\t * @param\tstring\t$which\t\tArray name ('segment' or 'rsegment')\n\t * @return\tarray\n\t */\n\tprotected function _uri_to_assoc($n = 3, $default = array(), $which = 'segment')\n\t{\n\t\tif ( ! is_numeric($n))\n\t\t{\n\t\t\treturn $default;\n\t\t}\n\n\t\tif (isset($this->keyval[$which], $this->keyval[$which][$n]))\n\t\t{\n\t\t\treturn $this->keyval[$which][$n];\n\t\t}\n\n\t\t$total_segments = \"total_{$which}s\";\n\t\t$segment_array = \"{$which}_array\";\n\n\t\tif ($this->$total_segments() < $n)\n\t\t{\n\t\t\treturn (count($default) === 0)\n\t\t\t\t? array()\n\t\t\t\t: array_fill_keys($default, NULL);\n\t\t}\n\n\t\t$segments = array_slice($this->$segment_array(), ($n - 1));\n\t\t$i = 0;\n\t\t$lastval = '';\n\t\t$retval = array();\n\t\tforeach ($segments as $seg)\n\t\t{\n\t\t\tif ($i % 2)\n\t\t\t{\n\t\t\t\t$retval[$lastval] = $seg;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$retval[$seg] = NULL;\n\t\t\t\t$lastval = $seg;\n\t\t\t}\n\n\t\t\t$i++;\n\t\t}\n\n\t\tif (count($default) > 0)\n\t\t{\n\t\t\tforeach ($default as $val)\n\t\t\t{\n\t\t\t\tif ( ! array_key_exists($val, $retval))\n\t\t\t\t{\n\t\t\t\t\t$retval[$val] = NULL;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Cache the array for reuse\n\t\tisset($this->keyval[$which]) OR $this->keyval[$which] = array();\n\t\t$this->keyval[$which][$n] = $retval;\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Assoc to URI\n\t *\n\t * Generates a URI string from an associative array.\n\t *\n\t * @param\tarray\t$array\tInput array of key/value pairs\n\t * @return\tstring\tURI string\n\t */\n\tpublic function assoc_to_uri($array)\n\t{\n\t\t$temp = array();\n\t\tforeach ((array) $array as $key => $val)\n\t\t{\n\t\t\t$temp[] = $key;\n\t\t\t$temp[] = $val;\n\t\t}\n\n\t\treturn implode('/', $temp);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Slash segment\n\t *\n\t * Fetches an URI segment with a slash.\n\t *\n\t * @param\tint\t$n\tIndex\n\t * @param\tstring\t$where\tWhere to add the slash ('trailing' or 'leading')\n\t * @return\tstring\n\t */\n\tpublic function slash_segment($n, $where = 'trailing')\n\t{\n\t\treturn $this->_slash_segment($n, $where, 'segment');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Slash routed segment\n\t *\n\t * Fetches an URI routed segment with a slash.\n\t *\n\t * @param\tint\t$n\tIndex\n\t * @param\tstring\t$where\tWhere to add the slash ('trailing' or 'leading')\n\t * @return\tstring\n\t */\n\tpublic function slash_rsegment($n, $where = 'trailing')\n\t{\n\t\treturn $this->_slash_segment($n, $where, 'rsegment');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Internal Slash segment\n\t *\n\t * Fetches an URI Segment and adds a slash to it.\n\t *\n\t * @used-by\tCI_URI::slash_segment()\n\t * @used-by\tCI_URI::slash_rsegment()\n\t *\n\t * @param\tint\t$n\tIndex\n\t * @param\tstring\t$where\tWhere to add the slash ('trailing' or 'leading')\n\t * @param\tstring\t$which\tArray name ('segment' or 'rsegment')\n\t * @return\tstring\n\t */\n\tprotected function _slash_segment($n, $where = 'trailing', $which = 'segment')\n\t{\n\t\t$leading = $trailing = '/';\n\n\t\tif ($where === 'trailing')\n\t\t{\n\t\t\t$leading\t= '';\n\t\t}\n\t\telseif ($where === 'leading')\n\t\t{\n\t\t\t$trailing\t= '';\n\t\t}\n\n\t\treturn $leading.$this->$which($n).$trailing;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Segment Array\n\t *\n\t * @return\tarray\tCI_URI::$segments\n\t */\n\tpublic function segment_array()\n\t{\n\t\treturn $this->segments;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Routed Segment Array\n\t *\n\t * @return\tarray\tCI_URI::$rsegments\n\t */\n\tpublic function rsegment_array()\n\t{\n\t\treturn $this->rsegments;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Total number of segments\n\t *\n\t * @return\tint\n\t */\n\tpublic function total_segments()\n\t{\n\t\treturn count($this->segments);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Total number of routed segments\n\t *\n\t * @return\tint\n\t */\n\tpublic function total_rsegments()\n\t{\n\t\treturn count($this->rsegments);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch URI string\n\t *\n\t * @return\tstring\tCI_URI::$uri_string\n\t */\n\tpublic function uri_string()\n\t{\n\t\treturn $this->uri_string;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch Re-routed URI string\n\t *\n\t * @return\tstring\n\t */\n\tpublic function ruri_string()\n\t{\n\t\treturn ltrim(load_class('Router', 'core')->directory, '/').implode('/', $this->rsegments);\n\t}\n\n}\n"
  },
  {
    "path": "system/core/Utf8.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 2.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Utf8 Class\n *\n * Provides support for UTF-8 environments\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tUTF-8\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/utf8.html\n */\nclass CI_Utf8 {\n\n\t/**\n\t * Class constructor\n\t *\n\t * Determines if UTF-8 support is to be enabled.\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\tif (\n\t\t\tdefined('PREG_BAD_UTF8_ERROR')\t\t\t\t// PCRE must support UTF-8\n\t\t\t&& (ICONV_ENABLED === TRUE OR MB_ENABLED === TRUE)\t// iconv or mbstring must be installed\n\t\t\t&& strtoupper(config_item('charset')) === 'UTF-8'\t// Application charset must be UTF-8\n\t\t\t)\n\t\t{\n\t\t\tdefine('UTF8_ENABLED', TRUE);\n\t\t\tlog_message('debug', 'UTF-8 Support Enabled');\n\t\t}\n\t\telse\n\t\t{\n\t\t\tdefine('UTF8_ENABLED', FALSE);\n\t\t\tlog_message('debug', 'UTF-8 Support Disabled');\n\t\t}\n\n\t\tlog_message('info', 'Utf8 Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Clean UTF-8 strings\n\t *\n\t * Ensures strings contain only valid UTF-8 characters.\n\t *\n\t * @param\tstring\t$str\tString to clean\n\t * @return\tstring\n\t */\n\tpublic function clean_string($str)\n\t{\n\t\tif ($this->is_ascii($str) === FALSE)\n\t\t{\n\t\t\tif (MB_ENABLED)\n\t\t\t{\n\t\t\t\t$str = mb_convert_encoding($str, 'UTF-8', 'UTF-8');\n\t\t\t}\n\t\t\telseif (ICONV_ENABLED)\n\t\t\t{\n\t\t\t\t$str = @iconv('UTF-8', 'UTF-8//IGNORE', $str);\n\t\t\t}\n\t\t}\n\n\t\treturn $str;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Remove ASCII control characters\n\t *\n\t * Removes all ASCII control characters except horizontal tabs,\n\t * line feeds, and carriage returns, as all others can cause\n\t * problems in XML.\n\t *\n\t * @param\tstring\t$str\tString to clean\n\t * @return\tstring\n\t */\n\tpublic function safe_ascii_for_xml($str)\n\t{\n\t\treturn remove_invisible_characters($str, FALSE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Convert to UTF-8\n\t *\n\t * Attempts to convert a string to UTF-8.\n\t *\n\t * @param\tstring\t$str\t\tInput string\n\t * @param\tstring\t$encoding\tInput encoding\n\t * @return\tstring\t$str encoded in UTF-8 or FALSE on failure\n\t */\n\tpublic function convert_to_utf8($str, $encoding)\n\t{\n\t\tif (MB_ENABLED)\n\t\t{\n\t\t\treturn mb_convert_encoding($str, 'UTF-8', $encoding);\n\t\t}\n\t\telseif (ICONV_ENABLED)\n\t\t{\n\t\t\treturn @iconv($encoding, 'UTF-8', $str);\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is ASCII?\n\t *\n\t * Tests if a string is standard 7-bit ASCII or not.\n\t *\n\t * @param\tstring\t$str\tString to check\n\t * @return\tbool\n\t */\n\tpublic function is_ascii($str)\n\t{\n\t\treturn (preg_match('/[^\\x00-\\x7F]/S', $str) === 0);\n\t}\n\n}\n"
  },
  {
    "path": "system/core/compat/hash.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PHP ext/hash compatibility package\n *\n * @package\t\tCodeIgniter\n * @subpackage\tCodeIgniter\n * @category\tCompatibility\n * @author\t\tAndrey Andreev\n * @link\t\thttps://codeigniter.com/user_guide/\n * @link\t\thttp://php.net/hash\n */\n\n// ------------------------------------------------------------------------\n\nif (is_php('5.6'))\n{\n\treturn;\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('hash_equals'))\n{\n\t/**\n\t * hash_equals()\n\t *\n\t * @link\thttp://php.net/hash_equals\n\t * @param\tstring\t$known_string\n\t * @param\tstring\t$user_string\n\t * @return\tbool\n\t */\n\tfunction hash_equals($known_string, $user_string)\n\t{\n\t\tif ( ! is_string($known_string))\n\t\t{\n\t\t\ttrigger_error('hash_equals(): Expected known_string to be a string, '.strtolower(gettype($known_string)).' given', E_USER_WARNING);\n\t\t\treturn FALSE;\n\t\t}\n\t\telseif ( ! is_string($user_string))\n\t\t{\n\t\t\ttrigger_error('hash_equals(): Expected user_string to be a string, '.strtolower(gettype($user_string)).' given', E_USER_WARNING);\n\t\t\treturn FALSE;\n\t\t}\n\t\telseif (($length = strlen($known_string)) !== strlen($user_string))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$diff = 0;\n\t\tfor ($i = 0; $i < $length; $i++)\n\t\t{\n\t\t\t$diff |= ord($known_string[$i]) ^ ord($user_string[$i]);\n\t\t}\n\n\t\treturn ($diff === 0);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif (is_php('5.5'))\n{\n\treturn;\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('hash_pbkdf2'))\n{\n\t/**\n\t * hash_pbkdf2()\n\t *\n\t * @link\thttp://php.net/hash_pbkdf2\n\t * @param\tstring\t$algo\n\t * @param\tstring\t$password\n\t * @param\tstring\t$salt\n\t * @param\tint\t$iterations\n\t * @param\tint\t$length\n\t * @param\tbool\t$raw_output\n\t * @return\tstring\n\t */\n\tfunction hash_pbkdf2($algo, $password, $salt, $iterations, $length = 0, $raw_output = FALSE)\n\t{\n\t\tif ( ! in_array($algo, hash_algos(), TRUE))\n\t\t{\n\t\t\ttrigger_error('hash_pbkdf2(): Unknown hashing algorithm: '.$algo, E_USER_WARNING);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (($type = gettype($iterations)) !== 'integer')\n\t\t{\n\t\t\tif ($type === 'object' && method_exists($iterations, '__toString'))\n\t\t\t{\n\t\t\t\t$iterations = (string) $iterations;\n\t\t\t}\n\n\t\t\tif (is_string($iterations) && is_numeric($iterations))\n\t\t\t{\n\t\t\t\t$iterations = (int) $iterations;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ttrigger_error('hash_pbkdf2() expects parameter 4 to be long, '.$type.' given', E_USER_WARNING);\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t}\n\n\t\tif ($iterations < 1)\n\t\t{\n\t\t\ttrigger_error('hash_pbkdf2(): Iterations must be a positive integer: '.$iterations, E_USER_WARNING);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (($type = gettype($length)) !== 'integer')\n\t\t{\n\t\t\tif ($type === 'object' && method_exists($length, '__toString'))\n\t\t\t{\n\t\t\t\t$length = (string) $length;\n\t\t\t}\n\n\t\t\tif (is_string($length) && is_numeric($length))\n\t\t\t{\n\t\t\t\t$length = (int) $length;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ttrigger_error('hash_pbkdf2() expects parameter 5 to be long, '.$type.' given', E_USER_WARNING);\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t}\n\n\t\tif ($length < 0)\n\t\t{\n\t\t\ttrigger_error('hash_pbkdf2(): Length must be greater than or equal to 0: '.$length, E_USER_WARNING);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$hash_length = strlen(hash($algo, NULL, TRUE));\n\t\tempty($length) && $length = $hash_length;\n\n\t\t// Pre-hash password inputs longer than the algorithm's block size\n\t\t// (i.e. prepare HMAC key) to mitigate potential DoS attacks.\n\t\tstatic $block_sizes;\n\t\tempty($block_sizes) && $block_sizes = array(\n\t\t\t'gost' => 32,\n\t\t\t'haval128,3' => 128,\n\t\t\t'haval160,3' => 128,\n\t\t\t'haval192,3' => 128,\n\t\t\t'haval224,3' => 128,\n\t\t\t'haval256,3' => 128,\n\t\t\t'haval128,4' => 128,\n\t\t\t'haval160,4' => 128,\n\t\t\t'haval192,4' => 128,\n\t\t\t'haval224,4' => 128,\n\t\t\t'haval256,4' => 128,\n\t\t\t'haval128,5' => 128,\n\t\t\t'haval160,5' => 128,\n\t\t\t'haval192,5' => 128,\n\t\t\t'haval224,5' => 128,\n\t\t\t'haval256,5' => 128,\n\t\t\t'md2' => 16,\n\t\t\t'md4' => 64,\n\t\t\t'md5' => 64,\n\t\t\t'ripemd128' => 64,\n\t\t\t'ripemd160' => 64,\n\t\t\t'ripemd256' => 64,\n\t\t\t'ripemd320' => 64,\n\t\t\t'salsa10' => 64,\n\t\t\t'salsa20' => 64,\n\t\t\t'sha1' => 64,\n\t\t\t'sha224' => 64,\n\t\t\t'sha256' => 64,\n\t\t\t'sha384' => 128,\n\t\t\t'sha512' => 128,\n\t\t\t'snefru' => 32,\n\t\t\t'snefru256' => 32,\n\t\t\t'tiger128,3' => 64,\n\t\t\t'tiger160,3' => 64,\n\t\t\t'tiger192,3' => 64,\n\t\t\t'tiger128,4' => 64,\n\t\t\t'tiger160,4' => 64,\n\t\t\t'tiger192,4' => 64,\n\t\t\t'whirlpool' => 64\n\t\t);\n\n\t\tif (isset($block_sizes[$algo]) && strlen($password) > $block_sizes[$algo])\n\t\t{\n\t\t\t$password = hash($algo, $password, TRUE);\n\t\t}\n\n\t\t$hash = '';\n\t\t// Note: Blocks are NOT 0-indexed\n\t\tfor ($bc = ceil($length / $hash_length), $bi = 1; $bi <= $bc; $bi++)\n\t\t{\n\t\t\t$key = $derived_key = hash_hmac($algo, $salt.pack('N', $bi), $password, TRUE);\n\t\t\tfor ($i = 1; $i < $iterations; $i++)\n\t\t\t{\n\t\t\t\t$derived_key ^= $key = hash_hmac($algo, $key, $password, TRUE);\n\t\t\t}\n\n\t\t\t$hash .= $derived_key;\n\t\t}\n\n\t\t// This is not RFC-compatible, but we're aiming for natural PHP compatibility\n\t\treturn substr($raw_output ? $hash : bin2hex($hash), 0, $length);\n\t}\n}\n"
  },
  {
    "path": "system/core/compat/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/core/compat/mbstring.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PHP ext/mbstring compatibility package\n *\n * @package\t\tCodeIgniter\n * @subpackage\tCodeIgniter\n * @category\tCompatibility\n * @author\t\tAndrey Andreev\n * @link\t\thttps://codeigniter.com/user_guide/\n * @link\t\thttp://php.net/mbstring\n */\n\n// ------------------------------------------------------------------------\n\nif (MB_ENABLED === TRUE)\n{\n\treturn;\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('mb_strlen'))\n{\n\t/**\n\t * mb_strlen()\n\t *\n\t * WARNING: This function WILL fall-back to strlen()\n\t * if iconv is not available!\n\t *\n\t * @link\thttp://php.net/mb_strlen\n\t * @param\tstring\t$str\n\t * @param\tstring\t$encoding\n\t * @return\tstring\n\t */\n\tfunction mb_strlen($str, $encoding = NULL)\n\t{\n\t\tif (ICONV_ENABLED === TRUE)\n\t\t{\n\t\t\treturn iconv_strlen($str, isset($encoding) ? $encoding : config_item('charset'));\n\t\t}\n\n\t\tlog_message('debug', 'Compatibility (mbstring): iconv_strlen() is not available, falling back to strlen().');\n\t\treturn strlen($str);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('mb_strpos'))\n{\n\t/**\n\t * mb_strpos()\n\t *\n\t * WARNING: This function WILL fall-back to strpos()\n\t * if iconv is not available!\n\t *\n\t * @link\thttp://php.net/mb_strpos\n\t * @param\tstring\t$haystack\n\t * @param\tstring\t$needle\n\t * @param\tint\t$offset\n\t * @param\tstring\t$encoding\n\t * @return\tmixed\n\t */\n\tfunction mb_strpos($haystack, $needle, $offset = 0, $encoding = NULL)\n\t{\n\t\tif (ICONV_ENABLED === TRUE)\n\t\t{\n\t\t\treturn iconv_strpos($haystack, $needle, $offset, isset($encoding) ? $encoding : config_item('charset'));\n\t\t}\n\n\t\tlog_message('debug', 'Compatibility (mbstring): iconv_strpos() is not available, falling back to strpos().');\n\t\treturn strpos($haystack, $needle, $offset);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('mb_substr'))\n{\n\t/**\n\t * mb_substr()\n\t *\n\t * WARNING: This function WILL fall-back to substr()\n\t * if iconv is not available.\n\t *\n\t * @link\thttp://php.net/mb_substr\n\t * @param\tstring\t$str\n\t * @param\tint\t$start\n\t * @param\tint \t$length\n\t * @param\tstring\t$encoding\n\t * @return\tstring\n\t */\n\tfunction mb_substr($str, $start, $length = NULL, $encoding = NULL)\n\t{\n\t\tif (ICONV_ENABLED === TRUE)\n\t\t{\n\t\t\tisset($encoding) OR $encoding = config_item('charset');\n\t\t\treturn iconv_substr(\n\t\t\t\t$str,\n\t\t\t\t$start,\n\t\t\t\tisset($length) ? $length : iconv_strlen($str, $encoding), // NULL doesn't work\n\t\t\t\t$encoding\n\t\t\t);\n\t\t}\n\n\t\tlog_message('debug', 'Compatibility (mbstring): iconv_substr() is not available, falling back to substr().');\n\t\treturn isset($length)\n\t\t\t? substr($str, $start, $length)\n\t\t\t: substr($str, $start);\n\t}\n}\n"
  },
  {
    "path": "system/core/compat/password.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PHP ext/standard/password compatibility package\n *\n * @package\t\tCodeIgniter\n * @subpackage\tCodeIgniter\n * @category\tCompatibility\n * @author\t\tAndrey Andreev\n * @link\t\thttps://codeigniter.com/user_guide/\n * @link\t\thttp://php.net/password\n */\n\n// ------------------------------------------------------------------------\n\nif (is_php('5.5') OR ! is_php('5.3.7') OR ! defined('CRYPT_BLOWFISH') OR CRYPT_BLOWFISH !== 1 OR defined('HHVM_VERSION'))\n{\n\treturn;\n}\n\n// ------------------------------------------------------------------------\n\ndefined('PASSWORD_BCRYPT') OR define('PASSWORD_BCRYPT', 1);\ndefined('PASSWORD_DEFAULT') OR define('PASSWORD_DEFAULT', PASSWORD_BCRYPT);\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('password_get_info'))\n{\n\t/**\n\t * password_get_info()\n\t *\n\t * @link\thttp://php.net/password_get_info\n\t * @param\tstring\t$hash\n\t * @return\tarray\n\t */\n\tfunction password_get_info($hash)\n\t{\n\t\treturn (strlen($hash) < 60 OR sscanf($hash, '$2y$%d', $hash) !== 1)\n\t\t\t? array('algo' => 0, 'algoName' => 'unknown', 'options' => array())\n\t\t\t: array('algo' => 1, 'algoName' => 'bcrypt', 'options' => array('cost' => $hash));\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('password_hash'))\n{\n\t/**\n\t * password_hash()\n\t *\n\t * @link\thttp://php.net/password_hash\n\t * @param\tstring\t$password\n\t * @param\tint\t$algo\n\t * @param\tarray\t$options\n\t * @return\tmixed\n\t */\n\tfunction password_hash($password, $algo, array $options = array())\n\t{\n\t\tstatic $func_override;\n\t\tisset($func_override) OR $func_override = (extension_loaded('mbstring') && ini_get('mbstring.func_override'));\n\n\t\tif ($algo !== 1)\n\t\t{\n\t\t\ttrigger_error('password_hash(): Unknown hashing algorithm: '.(int) $algo, E_USER_WARNING);\n\t\t\treturn NULL;\n\t\t}\n\n\t\tif (isset($options['cost']) && ($options['cost'] < 4 OR $options['cost'] > 31))\n\t\t{\n\t\t\ttrigger_error('password_hash(): Invalid bcrypt cost parameter specified: '.(int) $options['cost'], E_USER_WARNING);\n\t\t\treturn NULL;\n\t\t}\n\n\t\tif (isset($options['salt']) && ($saltlen = ($func_override ? mb_strlen($options['salt'], '8bit') : strlen($options['salt']))) < 22)\n\t\t{\n\t\t\ttrigger_error('password_hash(): Provided salt is too short: '.$saltlen.' expecting 22', E_USER_WARNING);\n\t\t\treturn NULL;\n\t\t}\n\t\telseif ( ! isset($options['salt']))\n\t\t{\n\t\t\tif (function_exists('random_bytes'))\n\t\t\t{\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\t$options['salt'] = random_bytes(16);\n\t\t\t\t}\n\t\t\t\tcatch (Exception $e)\n\t\t\t\t{\n\t\t\t\t\tlog_message('error', 'compat/password: Error while trying to use random_bytes(): '.$e->getMessage());\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif (defined('MCRYPT_DEV_URANDOM'))\n\t\t\t{\n\t\t\t\t$options['salt'] = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM);\n\t\t\t}\n\t\t\telseif (DIRECTORY_SEPARATOR === '/' && (is_readable($dev = '/dev/arandom') OR is_readable($dev = '/dev/urandom')))\n\t\t\t{\n\t\t\t\tif (($fp = fopen($dev, 'rb')) === FALSE)\n\t\t\t\t{\n\t\t\t\t\tlog_message('error', 'compat/password: Unable to open '.$dev.' for reading.');\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\n\t\t\t\t// Try not to waste entropy ...\n\t\t\t\tis_php('5.4') && stream_set_chunk_size($fp, 16);\n\n\t\t\t\t$options['salt'] = '';\n\t\t\t\tfor ($read = 0; $read < 16; $read = ($func_override) ? mb_strlen($options['salt'], '8bit') : strlen($options['salt']))\n\t\t\t\t{\n\t\t\t\t\tif (($read = fread($fp, 16 - $read)) === FALSE)\n\t\t\t\t\t{\n\t\t\t\t\t\tlog_message('error', 'compat/password: Error while reading from '.$dev.'.');\n\t\t\t\t\t\treturn FALSE;\n\t\t\t\t\t}\n\t\t\t\t\t$options['salt'] .= $read;\n\t\t\t\t}\n\n\t\t\t\tfclose($fp);\n\t\t\t}\n\t\t\telseif (function_exists('openssl_random_pseudo_bytes'))\n\t\t\t{\n\t\t\t\t$is_secure = NULL;\n\t\t\t\t$options['salt'] = openssl_random_pseudo_bytes(16, $is_secure);\n\t\t\t\tif ($is_secure !== TRUE)\n\t\t\t\t{\n\t\t\t\t\tlog_message('error', 'compat/password: openssl_random_pseudo_bytes() set the $cryto_strong flag to FALSE');\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tlog_message('error', 'compat/password: No CSPRNG available.');\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$options['salt'] = str_replace('+', '.', rtrim(base64_encode($options['salt']), '='));\n\t\t}\n\t\telseif ( ! preg_match('#^[a-zA-Z0-9./]+$#D', $options['salt']))\n\t\t{\n\t\t\t$options['salt'] = str_replace('+', '.', rtrim(base64_encode($options['salt']), '='));\n\t\t}\n\n\t\tisset($options['cost']) OR $options['cost'] = 10;\n\n\t\treturn (strlen($password = crypt($password, sprintf('$2y$%02d$%s', $options['cost'], $options['salt']))) === 60)\n\t\t\t? $password\n\t\t\t: FALSE;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('password_needs_rehash'))\n{\n\t/**\n\t * password_needs_rehash()\n\t *\n\t * @link\thttp://php.net/password_needs_rehash\n\t * @param\tstring\t$hash\n\t * @param\tint\t$algo\n\t * @param\tarray\t$options\n\t * @return\tbool\n\t */\n\tfunction password_needs_rehash($hash, $algo, array $options = array())\n\t{\n\t\t$info = password_get_info($hash);\n\n\t\tif ($algo !== $info['algo'])\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\t\telseif ($algo === 1)\n\t\t{\n\t\t\t$options['cost'] = isset($options['cost']) ? (int) $options['cost'] : 10;\n\t\t\treturn ($info['options']['cost'] !== $options['cost']);\n\t\t}\n\n\t\t// Odd at first glance, but according to a comment in PHP's own unit tests,\n\t\t// because it is an unknown algorithm - it's valid and therefore doesn't\n\t\t// need rehashing.\n\t\treturn FALSE;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('password_verify'))\n{\n\t/**\n\t * password_verify()\n\t *\n\t * @link\thttp://php.net/password_verify\n\t * @param\tstring\t$password\n\t * @param\tstring\t$hash\n\t * @return\tbool\n\t */\n\tfunction password_verify($password, $hash)\n\t{\n\t\tif (strlen($hash) !== 60 OR strlen($password = crypt($password, $hash)) !== 60)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$compare = 0;\n\t\tfor ($i = 0; $i < 60; $i++)\n\t\t{\n\t\t\t$compare |= (ord($password[$i]) ^ ord($hash[$i]));\n\t\t}\n\n\t\treturn ($compare === 0);\n\t}\n}\n"
  },
  {
    "path": "system/core/compat/standard.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PHP ext/standard compatibility package\n *\n * @package\t\tCodeIgniter\n * @subpackage\tCodeIgniter\n * @category\tCompatibility\n * @author\t\tAndrey Andreev\n * @link\t\thttps://codeigniter.com/user_guide/\n */\n\n// ------------------------------------------------------------------------\n\nif (is_php('5.5'))\n{\n\treturn;\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('array_column'))\n{\n\t/**\n\t * array_column()\n\t *\n\t * @link\thttp://php.net/array_column\n\t * @param\tarray\t$array\n\t * @param\tmixed\t$column_key\n\t * @param\tmixed\t$index_key\n\t * @return\tarray\n\t */\n\tfunction array_column(array $array, $column_key, $index_key = NULL)\n\t{\n\t\tif ( ! in_array($type = gettype($column_key), array('integer', 'string', 'NULL'), TRUE))\n\t\t{\n\t\t\tif ($type === 'double')\n\t\t\t{\n\t\t\t\t$column_key = (int) $column_key;\n\t\t\t}\n\t\t\telseif ($type === 'object' && method_exists($column_key, '__toString'))\n\t\t\t{\n\t\t\t\t$column_key = (string) $column_key;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ttrigger_error('array_column(): The column key should be either a string or an integer', E_USER_WARNING);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\tif ( ! in_array($type = gettype($index_key), array('integer', 'string', 'NULL'), TRUE))\n\t\t{\n\t\t\tif ($type === 'double')\n\t\t\t{\n\t\t\t\t$index_key = (int) $index_key;\n\t\t\t}\n\t\t\telseif ($type === 'object' && method_exists($index_key, '__toString'))\n\t\t\t{\n\t\t\t\t$index_key = (string) $index_key;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ttrigger_error('array_column(): The index key should be either a string or an integer', E_USER_WARNING);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\t$result = array();\n\t\tforeach ($array as &$a)\n\t\t{\n\t\t\tif ($column_key === NULL)\n\t\t\t{\n\t\t\t\t$value = $a;\n\t\t\t}\n\t\t\telseif (is_array($a) && array_key_exists($column_key, $a))\n\t\t\t{\n\t\t\t\t$value = $a[$column_key];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ($index_key === NULL OR ! array_key_exists($index_key, $a))\n\t\t\t{\n\t\t\t\t$result[] = $value;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$result[$a[$index_key]] = $value;\n\t\t\t}\n\t\t}\n\n\t\treturn $result;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif (is_php('5.4'))\n{\n\treturn;\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('hex2bin'))\n{\n\t/**\n\t * hex2bin()\n\t *\n\t * @link\thttp://php.net/hex2bin\n\t * @param\tstring\t$data\n\t * @return\tstring\n\t */\n\tfunction hex2bin($data)\n\t{\n\t\tif (in_array($type = gettype($data), array('array', 'double', 'object'), TRUE))\n\t\t{\n\t\t\tif ($type === 'object' && method_exists($data, '__toString'))\n\t\t\t{\n\t\t\t\t$data = (string) $data;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ttrigger_error('hex2bin() expects parameter 1 to be string, '.$type.' given', E_USER_WARNING);\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t}\n\n\t\tif (strlen($data) % 2 !== 0)\n\t\t{\n\t\t\ttrigger_error('Hexadecimal input string must have an even length', E_USER_WARNING);\n\t\t\treturn FALSE;\n\t\t}\n\t\telseif ( ! preg_match('/^[0-9a-f]*$/i', $data))\n\t\t{\n\t\t\ttrigger_error('Input string must be hexadecimal string', E_USER_WARNING);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn pack('H*', $data);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif (is_php('5.3'))\n{\n\treturn;\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('array_replace'))\n{\n\t/**\n\t * array_replace()\n\t *\n\t * @link\thttp://php.net/array_replace\n\t * @return\tarray\n\t */\n\tfunction array_replace()\n\t{\n\t\t$arrays = func_get_args();\n\n\t\tif (($c = count($arrays)) === 0)\n\t\t{\n\t\t\ttrigger_error('array_replace() expects at least 1 parameter, 0 given', E_USER_WARNING);\n\t\t\treturn NULL;\n\t\t}\n\t\telseif ($c === 1)\n\t\t{\n\t\t\tif ( ! is_array($arrays[0]))\n\t\t\t{\n\t\t\t\ttrigger_error('array_replace(): Argument #1 is not an array', E_USER_WARNING);\n\t\t\t\treturn NULL;\n\t\t\t}\n\n\t\t\treturn $arrays[0];\n\t\t}\n\n\t\t$array = array_shift($arrays);\n\t\t$c--;\n\n\t\tfor ($i = 0; $i < $c; $i++)\n\t\t{\n\t\t\tif ( ! is_array($arrays[$i]))\n\t\t\t{\n\t\t\t\ttrigger_error('array_replace(): Argument #'.($i + 2).' is not an array', E_USER_WARNING);\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t\telseif (empty($arrays[$i]))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tforeach (array_keys($arrays[$i]) as $key)\n\t\t\t{\n\t\t\t\t$array[$key] = $arrays[$i][$key];\n\t\t\t}\n\t\t}\n\n\t\treturn $array;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('array_replace_recursive'))\n{\n\t/**\n\t * array_replace_recursive()\n\t *\n\t * @link\thttp://php.net/array_replace_recursive\n\t * @return\tarray\n\t */\n\tfunction array_replace_recursive()\n\t{\n\t\t$arrays = func_get_args();\n\n\t\tif (($c = count($arrays)) === 0)\n\t\t{\n\t\t\ttrigger_error('array_replace_recursive() expects at least 1 parameter, 0 given', E_USER_WARNING);\n\t\t\treturn NULL;\n\t\t}\n\t\telseif ($c === 1)\n\t\t{\n\t\t\tif ( ! is_array($arrays[0]))\n\t\t\t{\n\t\t\t\ttrigger_error('array_replace_recursive(): Argument #1 is not an array', E_USER_WARNING);\n\t\t\t\treturn NULL;\n\t\t\t}\n\n\t\t\treturn $arrays[0];\n\t\t}\n\n\t\t$array = array_shift($arrays);\n\t\t$c--;\n\n\t\tfor ($i = 0; $i < $c; $i++)\n\t\t{\n\t\t\tif ( ! is_array($arrays[$i]))\n\t\t\t{\n\t\t\t\ttrigger_error('array_replace_recursive(): Argument #'.($i + 2).' is not an array', E_USER_WARNING);\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t\telseif (empty($arrays[$i]))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tforeach (array_keys($arrays[$i]) as $key)\n\t\t\t{\n\t\t\t\t$array[$key] = (is_array($arrays[$i][$key]) && isset($array[$key]) && is_array($array[$key]))\n\t\t\t\t\t? array_replace_recursive($array[$key], $arrays[$i][$key])\n\t\t\t\t\t: $arrays[$i][$key];\n\t\t\t}\n\t\t}\n\n\t\treturn $array;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('quoted_printable_encode'))\n{\n\t/**\n\t * quoted_printable_encode()\n\t *\n\t * @link\thttp://php.net/quoted_printable_encode\n\t * @param\tstring\t$str\n\t * @return\tstring\n\t */\n\tfunction quoted_printable_encode($str)\n\t{\n\t\tif (strlen($str) === 0)\n\t\t{\n\t\t\treturn '';\n\t\t}\n\t\telseif (in_array($type = gettype($str), array('array', 'object'), TRUE))\n\t\t{\n\t\t\tif ($type === 'object' && method_exists($str, '__toString'))\n\t\t\t{\n\t\t\t\t$str = (string) $str;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\ttrigger_error('quoted_printable_encode() expects parameter 1 to be string, '.$type.' given', E_USER_WARNING);\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t}\n\n\t\tif (function_exists('imap_8bit'))\n\t\t{\n\t\t\treturn imap_8bit($str);\n\t\t}\n\n\t\t$i = $lp = 0;\n\t\t$output = '';\n\t\t$hex = '0123456789ABCDEF';\n\t\t$length = (extension_loaded('mbstring') && ini_get('mbstring.func_overload'))\n\t\t\t? mb_strlen($str, '8bit')\n\t\t\t: strlen($str);\n\n\t\twhile ($length--)\n\t\t{\n\t\t\tif ((($c = $str[$i++]) === \"\\015\") && isset($str[$i]) && ($str[$i] === \"\\012\") && $length > 0)\n\t\t\t{\n\t\t\t\t$output .= \"\\015\".$str[$i++];\n\t\t\t\t$length--;\n\t\t\t\t$lp = 0;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tctype_cntrl($c)\n\t\t\t\tOR (ord($c) === 0x7f)\n\t\t\t\tOR (ord($c) & 0x80)\n\t\t\t\tOR ($c === '=')\n\t\t\t\tOR ($c === ' ' && isset($str[$i]) && $str[$i] === \"\\015\")\n\t\t\t)\n\t\t\t{\n\t\t\t\tif (\n\t\t\t\t\t(($lp += 3) > 75 && ord($c) <= 0x7f)\n\t\t\t\t\tOR (ord($c) > 0x7f && ord($c) <= 0xdf && ($lp + 3) > 75)\n\t\t\t\t\tOR (ord($c) > 0xdf && ord($c) <= 0xef && ($lp + 6) > 75)\n\t\t\t\t\tOR (ord($c) > 0xef && ord($c) <= 0xf4 && ($lp + 9) > 75)\n\t\t\t\t)\n\t\t\t\t{\n\t\t\t\t\t$output .= \"=\\015\\012\";\n\t\t\t\t\t$lp = 3;\n\t\t\t\t}\n\n\t\t\t\t$output .= '='.$hex[ord($c) >> 4].$hex[ord($c) & 0xf];\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ((++$lp) > 75)\n\t\t\t{\n\t\t\t\t$output .= \"=\\015\\012\";\n\t\t\t\t$lp = 1;\n\t\t\t}\n\n\t\t\t$output .= $c;\n\t\t}\n\n\t\treturn $output;\n\t}\n}\n"
  },
  {
    "path": "system/core/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/database/DB.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Initialize the database\n *\n * @category\tDatabase\n * @author\tEllisLab Dev Team\n * @link\thttps://codeigniter.com/user_guide/database/\n *\n * @param \tstring|string[]\t$params\n * @param \tbool\t\t$query_builder_override\n *\t\t\t\tDetermines if query builder should be used or not\n */\nfunction &DB($params = '', $query_builder_override = NULL)\n{\n\t// Load the DB config file if a DSN string wasn't passed\n\tif (is_string($params) && strpos($params, '://') === FALSE)\n\t{\n\t\t// Is the config file in the environment folder?\n\t\tif ( ! file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/database.php')\n\t\t\t&& ! file_exists($file_path = APPPATH.'config/database.php'))\n\t\t{\n\t\t\tshow_error('The configuration file database.php does not exist.');\n\t\t}\n\n\t\tinclude($file_path);\n\n\t\t// Make packages contain database config files,\n\t\t// given that the controller instance already exists\n\t\tif (class_exists('CI_Controller', FALSE))\n\t\t{\n\t\t\tforeach (get_instance()->load->get_package_paths() as $path)\n\t\t\t{\n\t\t\t\tif ($path !== APPPATH)\n\t\t\t\t{\n\t\t\t\t\tif (file_exists($file_path = $path.'config/'.ENVIRONMENT.'/database.php'))\n\t\t\t\t\t{\n\t\t\t\t\t\tinclude($file_path);\n\t\t\t\t\t}\n\t\t\t\t\telseif (file_exists($file_path = $path.'config/database.php'))\n\t\t\t\t\t{\n\t\t\t\t\t\tinclude($file_path);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( ! isset($db) OR count($db) === 0)\n\t\t{\n\t\t\tshow_error('No database connection settings were found in the database config file.');\n\t\t}\n\n\t\tif ($params !== '')\n\t\t{\n\t\t\t$active_group = $params;\n\t\t}\n\n\t\tif ( ! isset($active_group))\n\t\t{\n\t\t\tshow_error('You have not specified a database connection group via $active_group in your config/database.php file.');\n\t\t}\n\t\telseif ( ! isset($db[$active_group]))\n\t\t{\n\t\t\tshow_error('You have specified an invalid database connection group ('.$active_group.') in your config/database.php file.');\n\t\t}\n\n\t\t$params = $db[$active_group];\n\t}\n\telseif (is_string($params))\n\t{\n\t\t/**\n\t\t * Parse the URL from the DSN string\n\t\t * Database settings can be passed as discreet\n\t\t * parameters or as a data source name in the first\n\t\t * parameter. DSNs must have this prototype:\n\t\t * $dsn = 'driver://username:password@hostname/database';\n\t\t */\n\t\tif (($dsn = @parse_url($params)) === FALSE)\n\t\t{\n\t\t\tshow_error('Invalid DB Connection String');\n\t\t}\n\n\t\t$params = array(\n\t\t\t'dbdriver'\t=> $dsn['scheme'],\n\t\t\t'hostname'\t=> isset($dsn['host']) ? rawurldecode($dsn['host']) : '',\n\t\t\t'port'\t\t=> isset($dsn['port']) ? rawurldecode($dsn['port']) : '',\n\t\t\t'username'\t=> isset($dsn['user']) ? rawurldecode($dsn['user']) : '',\n\t\t\t'password'\t=> isset($dsn['pass']) ? rawurldecode($dsn['pass']) : '',\n\t\t\t'database'\t=> isset($dsn['path']) ? rawurldecode(substr($dsn['path'], 1)) : ''\n\t\t);\n\n\t\t// Were additional config items set?\n\t\tif (isset($dsn['query']))\n\t\t{\n\t\t\tparse_str($dsn['query'], $extra);\n\n\t\t\tforeach ($extra as $key => $val)\n\t\t\t{\n\t\t\t\tif (is_string($val) && in_array(strtoupper($val), array('TRUE', 'FALSE', 'NULL')))\n\t\t\t\t{\n\t\t\t\t\t$val = var_export($val, TRUE);\n\t\t\t\t}\n\n\t\t\t\t$params[$key] = $val;\n\t\t\t}\n\t\t}\n\t}\n\n\t// No DB specified yet? Beat them senseless...\n\tif (empty($params['dbdriver']))\n\t{\n\t\tshow_error('You have not selected a database type to connect to.');\n\t}\n\n\t// Load the DB classes. Note: Since the query builder class is optional\n\t// we need to dynamically create a class that extends proper parent class\n\t// based on whether we're using the query builder class or not.\n\tif ($query_builder_override !== NULL)\n\t{\n\t\t$query_builder = $query_builder_override;\n\t}\n\t// Backwards compatibility work-around for keeping the\n\t// $active_record config variable working. Should be\n\t// removed in v3.1\n\telseif ( ! isset($query_builder) && isset($active_record))\n\t{\n\t\t$query_builder = $active_record;\n\t}\n\n\trequire_once(BASEPATH.'database/DB_driver.php');\n\n\tif ( ! isset($query_builder) OR $query_builder === TRUE)\n\t{\n\t\trequire_once(BASEPATH.'database/DB_query_builder.php');\n\t\tif ( ! class_exists('CI_DB', FALSE))\n\t\t{\n\t\t\t/**\n\t\t\t * CI_DB\n\t\t\t *\n\t\t\t * Acts as an alias for both CI_DB_driver and CI_DB_query_builder.\n\t\t\t *\n\t\t\t * @see\tCI_DB_query_builder\n\t\t\t * @see\tCI_DB_driver\n\t\t\t */\n\t\t\tclass CI_DB extends CI_DB_query_builder { }\n\t\t}\n\t}\n\telseif ( ! class_exists('CI_DB', FALSE))\n\t{\n\t\t/**\n\t \t * @ignore\n\t\t */\n\t\tclass CI_DB extends CI_DB_driver { }\n\t}\n\n\t// Load the DB driver\n\t$driver_file = BASEPATH.'database/drivers/'.$params['dbdriver'].'/'.$params['dbdriver'].'_driver.php';\n\n\tfile_exists($driver_file) OR show_error('Invalid DB driver');\n\trequire_once($driver_file);\n\n\t// Instantiate the DB adapter\n\t$driver = 'CI_DB_'.$params['dbdriver'].'_driver';\n\t$DB = new $driver($params);\n\n\t// Check for a subdriver\n\tif ( ! empty($DB->subdriver))\n\t{\n\t\t$driver_file = BASEPATH.'database/drivers/'.$DB->dbdriver.'/subdrivers/'.$DB->dbdriver.'_'.$DB->subdriver.'_driver.php';\n\n\t\tif (file_exists($driver_file))\n\t\t{\n\t\t\trequire_once($driver_file);\n\t\t\t$driver = 'CI_DB_'.$DB->dbdriver.'_'.$DB->subdriver.'_driver';\n\t\t\t$DB = new $driver($params);\n\t\t}\n\t}\n\n\t$DB->initialize();\n\treturn $DB;\n}\n"
  },
  {
    "path": "system/database/DB_cache.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Database Cache Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_Cache {\n\n\t/**\n\t * CI Singleton\n\t *\n\t * @var\tobject\n\t */\n\tpublic $CI;\n\n\t/**\n\t * Database object\n\t *\n\t * Allows passing of DB object so that multiple database connections\n\t * and returned DB objects can be supported.\n\t *\n\t * @var\tobject\n\t */\n\tpublic $db;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @param\tobject\t&$db\n\t * @return\tvoid\n\t */\n\tpublic function __construct(&$db)\n\t{\n\t\t// Assign the main CI object to $this->CI and load the file helper since we use it a lot\n\t\t$this->CI =& get_instance();\n\t\t$this->db =& $db;\n\t\t$this->CI->load->helper('file');\n\n\t\t$this->check_path();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Cache Directory Path\n\t *\n\t * @param\tstring\t$path\tPath to the cache directory\n\t * @return\tbool\n\t */\n\tpublic function check_path($path = '')\n\t{\n\t\tif ($path === '')\n\t\t{\n\t\t\tif ($this->db->cachedir === '')\n\t\t\t{\n\t\t\t\treturn $this->db->cache_off();\n\t\t\t}\n\n\t\t\t$path = $this->db->cachedir;\n\t\t}\n\n\t\t// Add a trailing slash to the path if needed\n\t\t$path = realpath($path)\n\t\t\t? rtrim(realpath($path), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR\n\t\t\t: rtrim($path, '/').'/';\n\n\t\tif ( ! is_dir($path))\n\t\t{\n\t\t\tlog_message('debug', 'DB cache path error: '.$path);\n\n\t\t\t// If the path is wrong we'll turn off caching\n\t\t\treturn $this->db->cache_off();\n\t\t}\n\n\t\tif ( ! is_really_writable($path))\n\t\t{\n\t\t\tlog_message('debug', 'DB cache dir not writable: '.$path);\n\n\t\t\t// If the path is not really writable we'll turn off caching\n\t\t\treturn $this->db->cache_off();\n\t\t}\n\n\t\t$this->db->cachedir = $path;\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Retrieve a cached query\n\t *\n\t * The URI being requested will become the name of the cache sub-folder.\n\t * An MD5 hash of the SQL statement will become the cache file name.\n\t *\n\t * @param\tstring\t$sql\n\t * @return\tstring\n\t */\n\tpublic function read($sql)\n\t{\n\t\t$segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1);\n\t\t$segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2);\n\t\t$filepath = $this->db->cachedir.$segment_one.'+'.$segment_two.'/'.md5($sql);\n\n\t\tif (FALSE === ($cachedata = @file_get_contents($filepath)))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn unserialize($cachedata);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Write a query to a cache file\n\t *\n\t * @param\tstring\t$sql\n\t * @param\tobject\t$object\n\t * @return\tbool\n\t */\n\tpublic function write($sql, $object)\n\t{\n\t\t$segment_one = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1);\n\t\t$segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2);\n\t\t$dir_path = $this->db->cachedir.$segment_one.'+'.$segment_two.'/';\n\t\t$filename = md5($sql);\n\n\t\tif ( ! is_dir($dir_path) && ! @mkdir($dir_path, 0750))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (write_file($dir_path.$filename, serialize($object)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tchmod($dir_path.$filename, 0640);\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Delete cache files within a particular directory\n\t *\n\t * @param\tstring\t$segment_one\n\t * @param\tstring\t$segment_two\n\t * @return\tvoid\n\t */\n\tpublic function delete($segment_one = '', $segment_two = '')\n\t{\n\t\tif ($segment_one === '')\n\t\t{\n\t\t\t$segment_one  = ($this->CI->uri->segment(1) == FALSE) ? 'default' : $this->CI->uri->segment(1);\n\t\t}\n\n\t\tif ($segment_two === '')\n\t\t{\n\t\t\t$segment_two = ($this->CI->uri->segment(2) == FALSE) ? 'index' : $this->CI->uri->segment(2);\n\t\t}\n\n\t\t$dir_path = $this->db->cachedir.$segment_one.'+'.$segment_two.'/';\n\t\tdelete_files($dir_path, TRUE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Delete all existing cache files\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function delete_all()\n\t{\n\t\tdelete_files($this->db->cachedir, TRUE, TRUE);\n\t}\n\n}\n"
  },
  {
    "path": "system/database/DB_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Database Driver Class\n *\n * This is the platform-independent base DB implementation class.\n * This class will not be called directly. Rather, the adapter\n * class for the specific database will extend and instantiate it.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nabstract class CI_DB_driver {\n\n\t/**\n\t * Data Source Name / Connect string\n\t *\n\t * @var\tstring\n\t */\n\tpublic $dsn;\n\n\t/**\n\t * Username\n\t *\n\t * @var\tstring\n\t */\n\tpublic $username;\n\n\t/**\n\t * Password\n\t *\n\t * @var\tstring\n\t */\n\tpublic $password;\n\n\t/**\n\t * Hostname\n\t *\n\t * @var\tstring\n\t */\n\tpublic $hostname;\n\n\t/**\n\t * Database name\n\t *\n\t * @var\tstring\n\t */\n\tpublic $database;\n\n\t/**\n\t * Database driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $dbdriver\t\t= 'mysqli';\n\n\t/**\n\t * Sub-driver\n\t *\n\t * @used-by\tCI_DB_pdo_driver\n\t * @var\tstring\n\t */\n\tpublic $subdriver;\n\n\t/**\n\t * Table prefix\n\t *\n\t * @var\tstring\n\t */\n\tpublic $dbprefix\t\t= '';\n\n\t/**\n\t * Character set\n\t *\n\t * @var\tstring\n\t */\n\tpublic $char_set\t\t= 'utf8';\n\n\t/**\n\t * Collation\n\t *\n\t * @var\tstring\n\t */\n\tpublic $dbcollat\t\t= 'utf8_general_ci';\n\n\t/**\n\t * Encryption flag/data\n\t *\n\t * @var\tmixed\n\t */\n\tpublic $encrypt\t\t\t= FALSE;\n\n\t/**\n\t * Swap Prefix\n\t *\n\t * @var\tstring\n\t */\n\tpublic $swap_pre\t\t= '';\n\n\t/**\n\t * Database port\n\t *\n\t * @var\tint\n\t */\n\tpublic $port\t\t\t= '';\n\n\t/**\n\t * Persistent connection flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $pconnect\t\t= FALSE;\n\n\t/**\n\t * Connection ID\n\t *\n\t * @var\tobject|resource\n\t */\n\tpublic $conn_id\t\t\t= FALSE;\n\n\t/**\n\t * Result ID\n\t *\n\t * @var\tobject|resource\n\t */\n\tpublic $result_id\t\t= FALSE;\n\n\t/**\n\t * Debug flag\n\t *\n\t * Whether to display error messages.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $db_debug\t\t= FALSE;\n\n\t/**\n\t * Benchmark time\n\t *\n\t * @var\tint\n\t */\n\tpublic $benchmark\t\t= 0;\n\n\t/**\n\t * Executed queries count\n\t *\n\t * @var\tint\n\t */\n\tpublic $query_count\t\t= 0;\n\n\t/**\n\t * Bind marker\n\t *\n\t * Character used to identify values in a prepared statement.\n\t *\n\t * @var\tstring\n\t */\n\tpublic $bind_marker\t\t= '?';\n\n\t/**\n\t * Save queries flag\n\t *\n\t * Whether to keep an in-memory history of queries for debugging purposes.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $save_queries\t\t= TRUE;\n\n\t/**\n\t * Queries list\n\t *\n\t * @see\tCI_DB_driver::$save_queries\n\t * @var\tstring[]\n\t */\n\tpublic $queries\t\t\t= array();\n\n\t/**\n\t * Query times\n\t *\n\t * A list of times that queries took to execute.\n\t *\n\t * @var\tarray\n\t */\n\tpublic $query_times\t\t= array();\n\n\t/**\n\t * Data cache\n\t *\n\t * An internal generic value cache.\n\t *\n\t * @var\tarray\n\t */\n\tpublic $data_cache\t\t= array();\n\n\t/**\n\t * Transaction enabled flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $trans_enabled\t\t= TRUE;\n\n\t/**\n\t * Strict transaction mode flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $trans_strict\t\t= TRUE;\n\n\t/**\n\t * Transaction depth level\n\t *\n\t * @var\tint\n\t */\n\tprotected $_trans_depth\t\t= 0;\n\n\t/**\n\t * Transaction status flag\n\t *\n\t * Used with transactions to determine if a rollback should occur.\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_trans_status\t= TRUE;\n\n\t/**\n\t * Transaction failure flag\n\t *\n\t * Used with transactions to determine if a transaction has failed.\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_trans_failure\t= FALSE;\n\n\t/**\n\t * Cache On flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $cache_on\t\t= FALSE;\n\n\t/**\n\t * Cache directory path\n\t *\n\t * @var\tbool\n\t */\n\tpublic $cachedir\t\t= '';\n\n\t/**\n\t * Cache auto-delete flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $cache_autodel\t\t= FALSE;\n\n\t/**\n\t * DB Cache object\n\t *\n\t * @see\tCI_DB_cache\n\t * @var\tobject\n\t */\n\tpublic $CACHE;\n\n\t/**\n\t * Protect identifiers flag\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_protect_identifiers\t\t= TRUE;\n\n\t/**\n\t * List of reserved identifiers\n\t *\n\t * Identifiers that must NOT be escaped.\n\t *\n\t * @var\tstring[]\n\t */\n\tprotected $_reserved_identifiers\t= array('*');\n\n\t/**\n\t * Identifier escape character\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_escape_char = '\"';\n\n\t/**\n\t * ESCAPE statement string\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_like_escape_str = \" ESCAPE '%s' \";\n\n\t/**\n\t * ESCAPE character\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_like_escape_chr = '!';\n\n\t/**\n\t * ORDER BY random keyword\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_random_keyword = array('RAND()', 'RAND(%d)');\n\n\t/**\n\t * COUNT string\n\t *\n\t * @used-by\tCI_DB_driver::count_all()\n\t * @used-by\tCI_DB_query_builder::count_all_results()\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_count_string = 'SELECT COUNT(*) AS ';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\tif (is_array($params))\n\t\t{\n\t\t\tforeach ($params as $key => $val)\n\t\t\t{\n\t\t\t\t$this->$key = $val;\n\t\t\t}\n\t\t}\n\n\t\tlog_message('info', 'Database Driver Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize Database Settings\n\t *\n\t * @return\tbool\n\t */\n\tpublic function initialize()\n\t{\n\t\t/* If an established connection is available, then there's\n\t\t * no need to connect and select the database.\n\t\t *\n\t\t * Depending on the database driver, conn_id can be either\n\t\t * boolean TRUE, a resource or an object.\n\t\t */\n\t\tif ($this->conn_id)\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\t// ----------------------------------------------------------------\n\n\t\t// Connect to the database and set the connection ID\n\t\t$this->conn_id = $this->db_connect($this->pconnect);\n\n\t\t// No connection resource? Check if there is a failover else throw an error\n\t\tif ( ! $this->conn_id)\n\t\t{\n\t\t\t// Check if there is a failover set\n\t\t\tif ( ! empty($this->failover) && is_array($this->failover))\n\t\t\t{\n\t\t\t\t// Go over all the failovers\n\t\t\t\tforeach ($this->failover as $failover)\n\t\t\t\t{\n\t\t\t\t\t// Replace the current settings with those of the failover\n\t\t\t\t\tforeach ($failover as $key => $val)\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->$key = $val;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Try to connect\n\t\t\t\t\t$this->conn_id = $this->db_connect($this->pconnect);\n\n\t\t\t\t\t// If a connection is made break the foreach loop\n\t\t\t\t\tif ($this->conn_id)\n\t\t\t\t\t{\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// We still don't have a connection?\n\t\t\tif ( ! $this->conn_id)\n\t\t\t{\n\t\t\t\tlog_message('error', 'Unable to connect to the database');\n\n\t\t\t\tif ($this->db_debug)\n\t\t\t\t{\n\t\t\t\t\t$this->display_error('db_unable_to_connect');\n\t\t\t\t}\n\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\t// Now we set the character set and that's all\n\t\treturn $this->db_set_charset($this->char_set);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * DB connect\n\t *\n\t * This is just a dummy method that all drivers will override.\n\t *\n\t * @return\tmixed\n\t */\n\tpublic function db_connect()\n\t{\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Persistent database connection\n\t *\n\t * @return\tmixed\n\t */\n\tpublic function db_pconnect()\n\t{\n\t\treturn $this->db_connect(TRUE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Reconnect\n\t *\n\t * Keep / reestablish the db connection if no queries have been\n\t * sent for a length of time exceeding the server's idle timeout.\n\t *\n\t * This is just a dummy method to allow drivers without such\n\t * functionality to not declare it, while others will override it.\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function reconnect()\n\t{\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Select database\n\t *\n\t * This is just a dummy method to allow drivers without such\n\t * functionality to not declare it, while others will override it.\n\t *\n\t * @return\tbool\n\t */\n\tpublic function db_select()\n\t{\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Last error\n\t *\n\t * @return\tarray\n\t */\n\tpublic function error()\n\t{\n\t\treturn array('code' => NULL, 'message' => NULL);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set client character set\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function db_set_charset($charset)\n\t{\n\t\tif (method_exists($this, '_db_set_charset') && ! $this->_db_set_charset($charset))\n\t\t{\n\t\t\tlog_message('error', 'Unable to set database connection charset: '.$charset);\n\n\t\t\tif ($this->db_debug)\n\t\t\t{\n\t\t\t\t$this->display_error('db_unable_to_set_charset', $charset);\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * The name of the platform in use (mysql, mssql, etc...)\n\t *\n\t * @return\tstring\n\t */\n\tpublic function platform()\n\t{\n\t\treturn $this->dbdriver;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Database version number\n\t *\n\t * Returns a string containing the version of the database being used.\n\t * Most drivers will override this method.\n\t *\n\t * @return\tstring\n\t */\n\tpublic function version()\n\t{\n\t\tif (isset($this->data_cache['version']))\n\t\t{\n\t\t\treturn $this->data_cache['version'];\n\t\t}\n\n\t\tif (FALSE === ($sql = $this->_version()))\n\t\t{\n\t\t\treturn ($this->db_debug) ? $this->display_error('db_unsupported_function') : FALSE;\n\t\t}\n\n\t\t$query = $this->query($sql)->row();\n\t\treturn $this->data_cache['version'] = $query->ver;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Version number query string\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _version()\n\t{\n\t\treturn 'SELECT VERSION() AS ver';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Execute the query\n\t *\n\t * Accepts an SQL string as input and returns a result object upon\n\t * successful execution of a \"read\" type query. Returns boolean TRUE\n\t * upon successful execution of a \"write\" type query. Returns boolean\n\t * FALSE upon failure, and if the $db_debug variable is set to TRUE\n\t * will raise an error.\n\t *\n\t * @param\tstring\t$sql\n\t * @param\tarray\t$binds = FALSE\t\tAn array of binding data\n\t * @param\tbool\t$return_object = NULL\n\t * @return\tmixed\n\t */\n\tpublic function query($sql, $binds = FALSE, $return_object = NULL)\n\t{\n\t\tif ($sql === '')\n\t\t{\n\t\t\tlog_message('error', 'Invalid query: '.$sql);\n\t\t\treturn ($this->db_debug) ? $this->display_error('db_invalid_query') : FALSE;\n\t\t}\n\t\telseif ( ! is_bool($return_object))\n\t\t{\n\t\t\t$return_object = ! $this->is_write_type($sql);\n\t\t}\n\n\t\t// Verify table prefix and replace if necessary\n\t\tif ($this->dbprefix !== '' && $this->swap_pre !== '' && $this->dbprefix !== $this->swap_pre)\n\t\t{\n\t\t\t$sql = preg_replace('/(\\W)'.$this->swap_pre.'(\\S+?)/', '\\\\1'.$this->dbprefix.'\\\\2', $sql);\n\t\t}\n\n\t\t// Compile binds if needed\n\t\tif ($binds !== FALSE)\n\t\t{\n\t\t\t$sql = $this->compile_binds($sql, $binds);\n\t\t}\n\n\t\t// Is query caching enabled? If the query is a \"read type\"\n\t\t// we will load the caching class and return the previously\n\t\t// cached query if it exists\n\t\tif ($this->cache_on === TRUE && $return_object === TRUE && $this->_cache_init())\n\t\t{\n\t\t\t$this->load_rdriver();\n\t\t\tif (FALSE !== ($cache = $this->CACHE->read($sql)))\n\t\t\t{\n\t\t\t\treturn $cache;\n\t\t\t}\n\t\t}\n\n\t\t// Save the query for debugging\n\t\tif ($this->save_queries === TRUE)\n\t\t{\n\t\t\t$this->queries[] = $sql;\n\t\t}\n\n\t\t// Start the Query Timer\n\t\t$time_start = microtime(TRUE);\n\n\t\t// Run the Query\n\t\tif (FALSE === ($this->result_id = $this->simple_query($sql)))\n\t\t{\n\t\t\tif ($this->save_queries === TRUE)\n\t\t\t{\n\t\t\t\t$this->query_times[] = 0;\n\t\t\t}\n\n\t\t\t// This will trigger a rollback if transactions are being used\n\t\t\tif ($this->_trans_depth !== 0)\n\t\t\t{\n\t\t\t\t$this->_trans_status = FALSE;\n\t\t\t}\n\n\t\t\t// Grab the error now, as we might run some additional queries before displaying the error\n\t\t\t$error = $this->error();\n\n\t\t\t// Log errors\n\t\t\tlog_message('error', 'Query error: '.$error['message'].' - Invalid query: '.$sql);\n\n\t\t\tif ($this->db_debug)\n\t\t\t{\n\t\t\t\t// We call this function in order to roll-back queries\n\t\t\t\t// if transactions are enabled. If we don't call this here\n\t\t\t\t// the error message will trigger an exit, causing the\n\t\t\t\t// transactions to remain in limbo.\n\t\t\t\twhile ($this->_trans_depth !== 0)\n\t\t\t\t{\n\t\t\t\t\t$trans_depth = $this->_trans_depth;\n\t\t\t\t\t$this->trans_complete();\n\t\t\t\t\tif ($trans_depth === $this->_trans_depth)\n\t\t\t\t\t{\n\t\t\t\t\t\tlog_message('error', 'Database: Failure during an automated transaction commit/rollback!');\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Display errors\n\t\t\t\treturn $this->display_error(array('Error Number: '.$error['code'], $error['message'], $sql));\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Stop and aggregate the query time results\n\t\t$time_end = microtime(TRUE);\n\t\t$this->benchmark += $time_end - $time_start;\n\n\t\tif ($this->save_queries === TRUE)\n\t\t{\n\t\t\t$this->query_times[] = $time_end - $time_start;\n\t\t}\n\n\t\t// Increment the query counter\n\t\t$this->query_count++;\n\n\t\t// Will we have a result object instantiated? If not - we'll simply return TRUE\n\t\tif ($return_object !== TRUE)\n\t\t{\n\t\t\t// If caching is enabled we'll auto-cleanup any existing files related to this particular URI\n\t\t\tif ($this->cache_on === TRUE && $this->cache_autodel === TRUE && $this->_cache_init())\n\t\t\t{\n\t\t\t\t$this->CACHE->delete();\n\t\t\t}\n\n\t\t\treturn TRUE;\n\t\t}\n\n\t\t// Load and instantiate the result driver\n\t\t$driver\t\t= $this->load_rdriver();\n\t\t$RES\t\t= new $driver($this);\n\n\t\t// Is query caching enabled? If so, we'll serialize the\n\t\t// result object and save it to a cache file.\n\t\tif ($this->cache_on === TRUE && $this->_cache_init())\n\t\t{\n\t\t\t// We'll create a new instance of the result object\n\t\t\t// only without the platform specific driver since\n\t\t\t// we can't use it with cached data (the query result\n\t\t\t// resource ID won't be any good once we've cached the\n\t\t\t// result object, so we'll have to compile the data\n\t\t\t// and save it)\n\t\t\t$CR = new CI_DB_result($this);\n\t\t\t$CR->result_object\t= $RES->result_object();\n\t\t\t$CR->result_array\t= $RES->result_array();\n\t\t\t$CR->num_rows\t\t= $RES->num_rows();\n\n\t\t\t// Reset these since cached objects can not utilize resource IDs.\n\t\t\t$CR->conn_id\t\t= NULL;\n\t\t\t$CR->result_id\t\t= NULL;\n\n\t\t\t$this->CACHE->write($sql, $CR);\n\t\t}\n\n\t\treturn $RES;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Load the result drivers\n\t *\n\t * @return\tstring\tthe name of the result class\n\t */\n\tpublic function load_rdriver()\n\t{\n\t\t$driver = 'CI_DB_'.$this->dbdriver.'_result';\n\n\t\tif ( ! class_exists($driver, FALSE))\n\t\t{\n\t\t\trequire_once(BASEPATH.'database/DB_result.php');\n\t\t\trequire_once(BASEPATH.'database/drivers/'.$this->dbdriver.'/'.$this->dbdriver.'_result.php');\n\t\t}\n\n\t\treturn $driver;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Simple Query\n\t * This is a simplified version of the query() function. Internally\n\t * we only use it when running transaction commands since they do\n\t * not require all the features of the main query() function.\n\t *\n\t * @param\tstring\tthe sql query\n\t * @return\tmixed\n\t */\n\tpublic function simple_query($sql)\n\t{\n\t\tif ( ! $this->conn_id)\n\t\t{\n\t\t\tif ( ! $this->initialize())\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\treturn $this->_execute($sql);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Disable Transactions\n\t * This permits transactions to be disabled at run-time.\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function trans_off()\n\t{\n\t\t$this->trans_enabled = FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Enable/disable Transaction Strict Mode\n\t *\n\t * When strict mode is enabled, if you are running multiple groups of\n\t * transactions, if one group fails all subsequent groups will be\n\t * rolled back.\n\t *\n\t * If strict mode is disabled, each group is treated autonomously,\n\t * meaning a failure of one group will not affect any others\n\t *\n\t * @param\tbool\t$mode = TRUE\n\t * @return\tvoid\n\t */\n\tpublic function trans_strict($mode = TRUE)\n\t{\n\t\t$this->trans_strict = is_bool($mode) ? $mode : TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Start Transaction\n\t *\n\t * @param\tbool\t$test_mode = FALSE\n\t * @return\tbool\n\t */\n\tpublic function trans_start($test_mode = FALSE)\n\t{\n\t\tif ( ! $this->trans_enabled)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn $this->trans_begin($test_mode);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Complete Transaction\n\t *\n\t * @return\tbool\n\t */\n\tpublic function trans_complete()\n\t{\n\t\tif ( ! $this->trans_enabled)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// The query() function will set this flag to FALSE in the event that a query failed\n\t\tif ($this->_trans_status === FALSE OR $this->_trans_failure === TRUE)\n\t\t{\n\t\t\t$this->trans_rollback();\n\n\t\t\t// If we are NOT running in strict mode, we will reset\n\t\t\t// the _trans_status flag so that subsequent groups of\n\t\t\t// transactions will be permitted.\n\t\t\tif ($this->trans_strict === FALSE)\n\t\t\t{\n\t\t\t\t$this->_trans_status = TRUE;\n\t\t\t}\n\n\t\t\tlog_message('debug', 'DB Transaction Failure');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn $this->trans_commit();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Lets you retrieve the transaction flag to determine if it has failed\n\t *\n\t * @return\tbool\n\t */\n\tpublic function trans_status()\n\t{\n\t\treturn $this->_trans_status;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Begin Transaction\n\t *\n\t * @param\tbool\t$test_mode\n\t * @return\tbool\n\t */\n\tpublic function trans_begin($test_mode = FALSE)\n\t{\n\t\tif ( ! $this->trans_enabled)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\t// When transactions are nested we only begin/commit/rollback the outermost ones\n\t\telseif ($this->_trans_depth > 0)\n\t\t{\n\t\t\t$this->_trans_depth++;\n\t\t\treturn TRUE;\n\t\t}\n\n\t\t// Reset the transaction failure flag.\n\t\t// If the $test_mode flag is set to TRUE transactions will be rolled back\n\t\t// even if the queries produce a successful result.\n\t\t$this->_trans_failure = ($test_mode === TRUE);\n\n\t\tif ($this->_trans_begin())\n\t\t{\n\t\t\t$this->_trans_depth++;\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Commit Transaction\n\t *\n\t * @return\tbool\n\t */\n\tpublic function trans_commit()\n\t{\n\t\tif ( ! $this->trans_enabled OR $this->_trans_depth === 0)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\t// When transactions are nested we only begin/commit/rollback the outermost ones\n\t\telseif ($this->_trans_depth > 1 OR $this->_trans_commit())\n\t\t{\n\t\t\t$this->_trans_depth--;\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Rollback Transaction\n\t *\n\t * @return\tbool\n\t */\n\tpublic function trans_rollback()\n\t{\n\t\tif ( ! $this->trans_enabled OR $this->_trans_depth === 0)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\t// When transactions are nested we only begin/commit/rollback the outermost ones\n\t\telseif ($this->_trans_depth > 1 OR $this->_trans_rollback())\n\t\t{\n\t\t\t$this->_trans_depth--;\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile Bindings\n\t *\n\t * @param\tstring\tthe sql statement\n\t * @param\tarray\tan array of bind data\n\t * @return\tstring\n\t */\n\tpublic function compile_binds($sql, $binds)\n\t{\n\t\tif (empty($binds) OR empty($this->bind_marker) OR strpos($sql, $this->bind_marker) === FALSE)\n\t\t{\n\t\t\treturn $sql;\n\t\t}\n\t\telseif ( ! is_array($binds))\n\t\t{\n\t\t\t$binds = array($binds);\n\t\t\t$bind_count = 1;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Make sure we're using numeric keys\n\t\t\t$binds = array_values($binds);\n\t\t\t$bind_count = count($binds);\n\t\t}\n\n\t\t// We'll need the marker length later\n\t\t$ml = strlen($this->bind_marker);\n\n\t\t// Make sure not to replace a chunk inside a string that happens to match the bind marker\n\t\tif ($c = preg_match_all(\"/'[^']*'/i\", $sql, $matches))\n\t\t{\n\t\t\t$c = preg_match_all('/'.preg_quote($this->bind_marker, '/').'/i',\n\t\t\t\tstr_replace($matches[0],\n\t\t\t\t\tstr_replace($this->bind_marker, str_repeat(' ', $ml), $matches[0]),\n\t\t\t\t\t$sql, $c),\n\t\t\t\t$matches, PREG_OFFSET_CAPTURE);\n\n\t\t\t// Bind values' count must match the count of markers in the query\n\t\t\tif ($bind_count !== $c)\n\t\t\t{\n\t\t\t\treturn $sql;\n\t\t\t}\n\t\t}\n\t\telseif (($c = preg_match_all('/'.preg_quote($this->bind_marker, '/').'/i', $sql, $matches, PREG_OFFSET_CAPTURE)) !== $bind_count)\n\t\t{\n\t\t\treturn $sql;\n\t\t}\n\n\t\tdo\n\t\t{\n\t\t\t$c--;\n\t\t\t$escaped_value = $this->escape($binds[$c]);\n\t\t\tif (is_array($escaped_value))\n\t\t\t{\n\t\t\t\t$escaped_value = '('.implode(',', $escaped_value).')';\n\t\t\t}\n\t\t\t$sql = substr_replace($sql, $escaped_value, $matches[0][$c][1], $ml);\n\t\t}\n\t\twhile ($c !== 0);\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Determines if a query is a \"write\" type.\n\t *\n\t * @param\tstring\tAn SQL query string\n\t * @return\tbool\n\t */\n\tpublic function is_write_type($sql)\n\t{\n\t\treturn (bool) preg_match('/^\\s*\"?(SET|INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX)\\s/i', $sql);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Calculate the aggregate query elapsed time\n\t *\n\t * @param\tint\tThe number of decimal places\n\t * @return\tstring\n\t */\n\tpublic function elapsed_time($decimals = 6)\n\t{\n\t\treturn number_format($this->benchmark, $decimals);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns the total number of queries\n\t *\n\t * @return\tint\n\t */\n\tpublic function total_queries()\n\t{\n\t\treturn $this->query_count;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns the last query that was executed\n\t *\n\t * @return\tstring\n\t */\n\tpublic function last_query()\n\t{\n\t\treturn end($this->queries);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * \"Smart\" Escape String\n\t *\n\t * Escapes data based on type\n\t * Sets boolean and null types\n\t *\n\t * @param\tstring\n\t * @return\tmixed\n\t */\n\tpublic function escape($str)\n\t{\n\t\tif (is_array($str))\n\t\t{\n\t\t\t$str = array_map(array(&$this, 'escape'), $str);\n\t\t\treturn $str;\n\t\t}\n\t\telseif (is_string($str) OR (is_object($str) && method_exists($str, '__toString')))\n\t\t{\n\t\t\treturn \"'\".$this->escape_str($str).\"'\";\n\t\t}\n\t\telseif (is_bool($str))\n\t\t{\n\t\t\treturn ($str === FALSE) ? 0 : 1;\n\t\t}\n\t\telseif ($str === NULL)\n\t\t{\n\t\t\treturn 'NULL';\n\t\t}\n\n\t\treturn $str;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Escape String\n\t *\n\t * @param\tstring|string[]\t$str\tInput string\n\t * @param\tbool\t$like\tWhether or not the string will be used in a LIKE condition\n\t * @return\tstring\n\t */\n\tpublic function escape_str($str, $like = FALSE)\n\t{\n\t\tif (is_array($str))\n\t\t{\n\t\t\tforeach ($str as $key => $val)\n\t\t\t{\n\t\t\t\t$str[$key] = $this->escape_str($val, $like);\n\t\t\t}\n\n\t\t\treturn $str;\n\t\t}\n\n\t\t$str = $this->_escape_str($str);\n\n\t\t// escape LIKE condition wildcards\n\t\tif ($like === TRUE)\n\t\t{\n\t\t\treturn str_replace(\n\t\t\t\tarray($this->_like_escape_chr, '%', '_'),\n\t\t\t\tarray($this->_like_escape_chr.$this->_like_escape_chr, $this->_like_escape_chr.'%', $this->_like_escape_chr.'_'),\n\t\t\t\t$str\n\t\t\t);\n\t\t}\n\n\t\treturn $str;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Escape LIKE String\n\t *\n\t * Calls the individual driver for platform\n\t * specific escaping for LIKE conditions\n\t *\n\t * @param\tstring|string[]\n\t * @return\tmixed\n\t */\n\tpublic function escape_like_str($str)\n\t{\n\t\treturn $this->escape_str($str, TRUE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Platform-dependant string escape\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _escape_str($str)\n\t{\n\t\treturn str_replace(\"'\", \"''\", remove_invisible_characters($str));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Primary\n\t *\n\t * Retrieves the primary key. It assumes that the row in the first\n\t * position is the primary key\n\t *\n\t * @param\tstring\t$table\tTable name\n\t * @return\tstring\n\t */\n\tpublic function primary($table)\n\t{\n\t\t$fields = $this->list_fields($table);\n\t\treturn is_array($fields) ? current($fields) : FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * \"Count All\" query\n\t *\n\t * Generates a platform-specific query string that counts all records in\n\t * the specified database\n\t *\n\t * @param\tstring\n\t * @return\tint\n\t */\n\tpublic function count_all($table = '')\n\t{\n\t\tif ($table === '')\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\n\t\t$query = $this->query($this->_count_string.$this->escape_identifiers('numrows').' FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE));\n\t\tif ($query->num_rows() === 0)\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\n\t\t$query = $query->row();\n\t\t$this->_reset_select();\n\t\treturn (int) $query->numrows;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an array of table names\n\t *\n\t * @param\tstring\t$constrain_by_prefix = FALSE\n\t * @return\tarray\n\t */\n\tpublic function list_tables($constrain_by_prefix = FALSE)\n\t{\n\t\t// Is there a cached result?\n\t\tif (isset($this->data_cache['table_names']))\n\t\t{\n\t\t\treturn $this->data_cache['table_names'];\n\t\t}\n\n\t\tif (FALSE === ($sql = $this->_list_tables($constrain_by_prefix)))\n\t\t{\n\t\t\treturn ($this->db_debug) ? $this->display_error('db_unsupported_function') : FALSE;\n\t\t}\n\n\t\t$this->data_cache['table_names'] = array();\n\t\t$query = $this->query($sql);\n\n\t\tforeach ($query->result_array() as $row)\n\t\t{\n\t\t\t// Do we know from which column to get the table name?\n\t\t\tif ( ! isset($key))\n\t\t\t{\n\t\t\t\tif (isset($row['table_name']))\n\t\t\t\t{\n\t\t\t\t\t$key = 'table_name';\n\t\t\t\t}\n\t\t\t\telseif (isset($row['TABLE_NAME']))\n\t\t\t\t{\n\t\t\t\t\t$key = 'TABLE_NAME';\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t/* We have no other choice but to just get the first element's key.\n\t\t\t\t\t * Due to array_shift() accepting its argument by reference, if\n\t\t\t\t\t * E_STRICT is on, this would trigger a warning. So we'll have to\n\t\t\t\t\t * assign it first.\n\t\t\t\t\t */\n\t\t\t\t\t$key = array_keys($row);\n\t\t\t\t\t$key = array_shift($key);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$this->data_cache['table_names'][] = $row[$key];\n\t\t}\n\n\t\treturn $this->data_cache['table_names'];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Determine if a particular table exists\n\t *\n\t * @param\tstring\t$table_name\n\t * @return\tbool\n\t */\n\tpublic function table_exists($table_name)\n\t{\n\t\treturn in_array($this->protect_identifiers($table_name, TRUE, FALSE, FALSE), $this->list_tables());\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch Field Names\n\t *\n\t * @param\tstring\t$table\tTable name\n\t * @return\tarray\n\t */\n\tpublic function list_fields($table)\n\t{\n\t\t// Is there a cached result?\n\t\tif (isset($this->data_cache['field_names'][$table]))\n\t\t{\n\t\t\treturn $this->data_cache['field_names'][$table];\n\t\t}\n\n\t\tif (FALSE === ($sql = $this->_list_columns($table)))\n\t\t{\n\t\t\treturn ($this->db_debug) ? $this->display_error('db_unsupported_function') : FALSE;\n\t\t}\n\n\t\t$query = $this->query($sql);\n\t\t$this->data_cache['field_names'][$table] = array();\n\n\t\tforeach ($query->result_array() as $row)\n\t\t{\n\t\t\t// Do we know from where to get the column's name?\n\t\t\tif ( ! isset($key))\n\t\t\t{\n\t\t\t\tif (isset($row['column_name']))\n\t\t\t\t{\n\t\t\t\t\t$key = 'column_name';\n\t\t\t\t}\n\t\t\t\telseif (isset($row['COLUMN_NAME']))\n\t\t\t\t{\n\t\t\t\t\t$key = 'COLUMN_NAME';\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// We have no other choice but to just get the first element's key.\n\t\t\t\t\t$key = key($row);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$this->data_cache['field_names'][$table][] = $row[$key];\n\t\t}\n\n\t\treturn $this->data_cache['field_names'][$table];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Determine if a particular field exists\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function field_exists($field_name, $table_name)\n\t{\n\t\treturn in_array($field_name, $this->list_fields($table_name));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an object with field data\n\t *\n\t * @param\tstring\t$table\tthe table name\n\t * @return\tarray\n\t */\n\tpublic function field_data($table)\n\t{\n\t\t$query = $this->query($this->_field_data($this->protect_identifiers($table, TRUE, NULL, FALSE)));\n\t\treturn ($query) ? $query->field_data() : FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Escape the SQL Identifiers\n\t *\n\t * This function escapes column and table names\n\t *\n\t * @param\tmixed\n\t * @return\tmixed\n\t */\n\tpublic function escape_identifiers($item)\n\t{\n\t\tif ($this->_escape_char === '' OR empty($item) OR in_array($item, $this->_reserved_identifiers))\n\t\t{\n\t\t\treturn $item;\n\t\t}\n\t\telseif (is_array($item))\n\t\t{\n\t\t\tforeach ($item as $key => $value)\n\t\t\t{\n\t\t\t\t$item[$key] = $this->escape_identifiers($value);\n\t\t\t}\n\n\t\t\treturn $item;\n\t\t}\n\t\t// Avoid breaking functions and literal values inside queries\n\t\telseif (ctype_digit($item) OR $item[0] === \"'\" OR ($this->_escape_char !== '\"' && $item[0] === '\"') OR strpos($item, '(') !== FALSE)\n\t\t{\n\t\t\treturn $item;\n\t\t}\n\n\t\tstatic $preg_ec = array();\n\n\t\tif (empty($preg_ec))\n\t\t{\n\t\t\tif (is_array($this->_escape_char))\n\t\t\t{\n\t\t\t\t$preg_ec = array(\n\t\t\t\t\tpreg_quote($this->_escape_char[0], '/'),\n\t\t\t\t\tpreg_quote($this->_escape_char[1], '/'),\n\t\t\t\t\t$this->_escape_char[0],\n\t\t\t\t\t$this->_escape_char[1]\n\t\t\t\t);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$preg_ec[0] = $preg_ec[1] = preg_quote($this->_escape_char, '/');\n\t\t\t\t$preg_ec[2] = $preg_ec[3] = $this->_escape_char;\n\t\t\t}\n\t\t}\n\n\t\tforeach ($this->_reserved_identifiers as $id)\n\t\t{\n\t\t\tif (strpos($item, '.'.$id) !== FALSE)\n\t\t\t{\n\t\t\t\treturn preg_replace('/'.$preg_ec[0].'?([^'.$preg_ec[1].'\\.]+)'.$preg_ec[1].'?\\./i', $preg_ec[2].'$1'.$preg_ec[3].'.', $item);\n\t\t\t}\n\t\t}\n\n\t\treturn preg_replace('/'.$preg_ec[0].'?([^'.$preg_ec[1].'\\.]+)'.$preg_ec[1].'?(\\.)?/i', $preg_ec[2].'$1'.$preg_ec[3].'$2', $item);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Generate an insert string\n\t *\n\t * @param\tstring\tthe table upon which the query will be performed\n\t * @param\tarray\tan associative array data of key/values\n\t * @return\tstring\n\t */\n\tpublic function insert_string($table, $data)\n\t{\n\t\t$fields = $values = array();\n\n\t\tforeach ($data as $key => $val)\n\t\t{\n\t\t\t$fields[] = $this->escape_identifiers($key);\n\t\t\t$values[] = $this->escape($val);\n\t\t}\n\n\t\treturn $this->_insert($this->protect_identifiers($table, TRUE, NULL, FALSE), $fields, $values);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert statement\n\t *\n\t * Generates a platform-specific insert string from the supplied data\n\t *\n\t * @param\tstring\tthe table name\n\t * @param\tarray\tthe insert keys\n\t * @param\tarray\tthe insert values\n\t * @return\tstring\n\t */\n\tprotected function _insert($table, $keys, $values)\n\t{\n\t\treturn 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Generate an update string\n\t *\n\t * @param\tstring\tthe table upon which the query will be performed\n\t * @param\tarray\tan associative array data of key/values\n\t * @param\tmixed\tthe \"where\" statement\n\t * @return\tstring\n\t */\n\tpublic function update_string($table, $data, $where)\n\t{\n\t\tif (empty($where))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->where($where);\n\n\t\t$fields = array();\n\t\tforeach ($data as $key => $val)\n\t\t{\n\t\t\t$fields[$this->protect_identifiers($key)] = $this->escape($val);\n\t\t}\n\n\t\t$sql = $this->_update($this->protect_identifiers($table, TRUE, NULL, FALSE), $fields);\n\t\t$this->_reset_write();\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update statement\n\t *\n\t * Generates a platform-specific update string from the supplied data\n\t *\n\t * @param\tstring\tthe table name\n\t * @param\tarray\tthe update data\n\t * @return\tstring\n\t */\n\tprotected function _update($table, $values)\n\t{\n\t\tforeach ($values as $key => $val)\n\t\t{\n\t\t\t$valstr[] = $key.' = '.$val;\n\t\t}\n\n\t\treturn 'UPDATE '.$table.' SET '.implode(', ', $valstr)\n\t\t\t.$this->_compile_wh('qb_where')\n\t\t\t.$this->_compile_order_by()\n\t\t\t.($this->qb_limit ? ' LIMIT '.$this->qb_limit : '');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Tests whether the string has an SQL operator\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tprotected function _has_operator($str)\n\t{\n\t\treturn (bool) preg_match('/(<|>|!|=|\\sIS NULL|\\sIS NOT NULL|\\sEXISTS|\\sBETWEEN|\\sLIKE|\\sIN\\s*\\(|\\s)/i', trim($str));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns the SQL string operator\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _get_operator($str)\n\t{\n\t\tstatic $_operators;\n\n\t\tif (empty($_operators))\n\t\t{\n\t\t\t$_les = ($this->_like_escape_str !== '')\n\t\t\t\t? '\\s+'.preg_quote(trim(sprintf($this->_like_escape_str, $this->_like_escape_chr)), '/')\n\t\t\t\t: '';\n\t\t\t$_operators = array(\n\t\t\t\t'\\s*(?:<|>|!)?=\\s*',             // =, <=, >=, !=\n\t\t\t\t'\\s*<>?\\s*',                     // <, <>\n\t\t\t\t'\\s*>\\s*',                       // >\n\t\t\t\t'\\s+IS NULL',                    // IS NULL\n\t\t\t\t'\\s+IS NOT NULL',                // IS NOT NULL\n\t\t\t\t'\\s+EXISTS\\s*\\(.*\\)',        // EXISTS(sql)\n\t\t\t\t'\\s+NOT EXISTS\\s*\\(.*\\)',    // NOT EXISTS(sql)\n\t\t\t\t'\\s+BETWEEN\\s+',                 // BETWEEN value AND value\n\t\t\t\t'\\s+IN\\s*\\(.*\\)',            // IN(list)\n\t\t\t\t'\\s+NOT IN\\s*\\(.*\\)',        // NOT IN (list)\n\t\t\t\t'\\s+LIKE\\s+\\S.*('.$_les.')?',    // LIKE 'expr'[ ESCAPE '%s']\n\t\t\t\t'\\s+NOT LIKE\\s+\\S.*('.$_les.')?' // NOT LIKE 'expr'[ ESCAPE '%s']\n\t\t\t);\n\n\t\t}\n\n\t\treturn preg_match('/'.implode('|', $_operators).'/i', $str, $match)\n\t\t\t? $match[0] : FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Enables a native PHP function to be run, using a platform agnostic wrapper.\n\t *\n\t * @param\tstring\t$function\tFunction name\n\t * @return\tmixed\n\t */\n\tpublic function call_function($function)\n\t{\n\t\t$driver = ($this->dbdriver === 'postgre') ? 'pg_' : $this->dbdriver.'_';\n\n\t\tif (FALSE === strpos($driver, $function))\n\t\t{\n\t\t\t$function = $driver.$function;\n\t\t}\n\n\t\tif ( ! function_exists($function))\n\t\t{\n\t\t\treturn ($this->db_debug) ? $this->display_error('db_unsupported_function') : FALSE;\n\t\t}\n\n\t\treturn (func_num_args() > 1)\n\t\t\t? call_user_func_array($function, array_slice(func_get_args(), 1))\n\t\t\t: call_user_func($function);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Cache Directory Path\n\t *\n\t * @param\tstring\tthe path to the cache directory\n\t * @return\tvoid\n\t */\n\tpublic function cache_set_path($path = '')\n\t{\n\t\t$this->cachedir = $path;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Enable Query Caching\n\t *\n\t * @return\tbool\tcache_on value\n\t */\n\tpublic function cache_on()\n\t{\n\t\treturn $this->cache_on = TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Disable Query Caching\n\t *\n\t * @return\tbool\tcache_on value\n\t */\n\tpublic function cache_off()\n\t{\n\t\treturn $this->cache_on = FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Delete the cache files associated with a particular URI\n\t *\n\t * @param\tstring\t$segment_one = ''\n\t * @param\tstring\t$segment_two = ''\n\t * @return\tbool\n\t */\n\tpublic function cache_delete($segment_one = '', $segment_two = '')\n\t{\n\t\treturn $this->_cache_init()\n\t\t\t? $this->CACHE->delete($segment_one, $segment_two)\n\t\t\t: FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Delete All cache files\n\t *\n\t * @return\tbool\n\t */\n\tpublic function cache_delete_all()\n\t{\n\t\treturn $this->_cache_init()\n\t\t\t? $this->CACHE->delete_all()\n\t\t\t: FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize the Cache Class\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _cache_init()\n\t{\n\t\tif ( ! class_exists('CI_DB_Cache', FALSE))\n\t\t{\n\t\t\trequire_once(BASEPATH.'database/DB_cache.php');\n\t\t}\n\t\telseif (is_object($this->CACHE))\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\t$this->CACHE = new CI_DB_Cache($this); // pass db object to support multiple db connections and returned db objects\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Close DB Connection\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function close()\n\t{\n\t\tif ($this->conn_id)\n\t\t{\n\t\t\t$this->_close();\n\t\t\t$this->conn_id = FALSE;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Close DB Connection\n\t *\n\t * This method would be overridden by most of the drivers.\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _close()\n\t{\n\t\t$this->conn_id = FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Display an error message\n\t *\n\t * @param\tstring\tthe error message\n\t * @param\tstring\tany \"swap\" values\n\t * @param\tbool\twhether to localize the message\n\t * @return\tstring\tsends the application/views/errors/error_db.php template\n\t */\n\tpublic function display_error($error = '', $swap = '', $native = FALSE)\n\t{\n\t\t$LANG =& load_class('Lang', 'core');\n\t\t$LANG->load('db');\n\n\t\t$heading = $LANG->line('db_error_heading');\n\n\t\tif ($native === TRUE)\n\t\t{\n\t\t\t$message = (array) $error;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$message = is_array($error) ? $error : array(str_replace('%s', $swap, $LANG->line($error)));\n\t\t}\n\n\t\t// Find the most likely culprit of the error by going through\n\t\t// the backtrace until the source file is no longer in the\n\t\t// database folder.\n\t\t$trace = debug_backtrace();\n\t\tforeach ($trace as $call)\n\t\t{\n\t\t\tif (isset($call['file'], $call['class']))\n\t\t\t{\n\t\t\t\t// We'll need this on Windows, as APPPATH and BASEPATH will always use forward slashes\n\t\t\t\tif (DIRECTORY_SEPARATOR !== '/')\n\t\t\t\t{\n\t\t\t\t\t$call['file'] = str_replace('\\\\', '/', $call['file']);\n\t\t\t\t}\n\n\t\t\t\tif (strpos($call['file'], BASEPATH.'database') === FALSE && strpos($call['class'], 'Loader') === FALSE)\n\t\t\t\t{\n\t\t\t\t\t// Found it - use a relative path for safety\n\t\t\t\t\t$message[] = 'Filename: '.str_replace(array(APPPATH, BASEPATH), '', $call['file']);\n\t\t\t\t\t$message[] = 'Line Number: '.$call['line'];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$error =& load_class('Exceptions', 'core');\n\t\techo $error->show_error($heading, $message, 'error_db');\n\t\texit(8); // EXIT_DATABASE\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Protect Identifiers\n\t *\n\t * This function is used extensively by the Query Builder class, and by\n\t * a couple functions in this class.\n\t * It takes a column or table name (optionally with an alias) and inserts\n\t * the table prefix onto it. Some logic is necessary in order to deal with\n\t * column names that include the path. Consider a query like this:\n\t *\n\t * SELECT hostname.database.table.column AS c FROM hostname.database.table\n\t *\n\t * Or a query with aliasing:\n\t *\n\t * SELECT m.member_id, m.member_name FROM members AS m\n\t *\n\t * Since the column name can include up to four segments (host, DB, table, column)\n\t * or also have an alias prefix, we need to do a bit of work to figure this out and\n\t * insert the table prefix (if it exists) in the proper position, and escape only\n\t * the correct identifiers.\n\t *\n\t * @param\tstring\n\t * @param\tbool\n\t * @param\tmixed\n\t * @param\tbool\n\t * @return\tstring\n\t */\n\tpublic function protect_identifiers($item, $prefix_single = FALSE, $protect_identifiers = NULL, $field_exists = TRUE)\n\t{\n\t\tif ( ! is_bool($protect_identifiers))\n\t\t{\n\t\t\t$protect_identifiers = $this->_protect_identifiers;\n\t\t}\n\n\t\tif (is_array($item))\n\t\t{\n\t\t\t$escaped_array = array();\n\t\t\tforeach ($item as $k => $v)\n\t\t\t{\n\t\t\t\t$escaped_array[$this->protect_identifiers($k)] = $this->protect_identifiers($v, $prefix_single, $protect_identifiers, $field_exists);\n\t\t\t}\n\n\t\t\treturn $escaped_array;\n\t\t}\n\n\t\t// This is basically a bug fix for queries that use MAX, MIN, etc.\n\t\t// If a parenthesis is found we know that we do not need to\n\t\t// escape the data or add a prefix. There's probably a more graceful\n\t\t// way to deal with this, but I'm not thinking of it -- Rick\n\t\t//\n\t\t// Added exception for single quotes as well, we don't want to alter\n\t\t// literal strings. -- Narf\n\t\tif (strcspn($item, \"()'\") !== strlen($item))\n\t\t{\n\t\t\treturn $item;\n\t\t}\n\n\t\t// Convert tabs or multiple spaces into single spaces\n\t\t$item = preg_replace('/\\s+/', ' ', trim($item));\n\n\t\t// If the item has an alias declaration we remove it and set it aside.\n\t\t// Note: strripos() is used in order to support spaces in table names\n\t\tif ($offset = strripos($item, ' AS '))\n\t\t{\n\t\t\t$alias = ($protect_identifiers)\n\t\t\t\t? substr($item, $offset, 4).$this->escape_identifiers(substr($item, $offset + 4))\n\t\t\t\t: substr($item, $offset);\n\t\t\t$item = substr($item, 0, $offset);\n\t\t}\n\t\telseif ($offset = strrpos($item, ' '))\n\t\t{\n\t\t\t$alias = ($protect_identifiers)\n\t\t\t\t? ' '.$this->escape_identifiers(substr($item, $offset + 1))\n\t\t\t\t: substr($item, $offset);\n\t\t\t$item = substr($item, 0, $offset);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$alias = '';\n\t\t}\n\n\t\t// Break the string apart if it contains periods, then insert the table prefix\n\t\t// in the correct location, assuming the period doesn't indicate that we're dealing\n\t\t// with an alias. While we're at it, we will escape the components\n\t\tif (strpos($item, '.') !== FALSE)\n\t\t{\n\t\t\t$parts = explode('.', $item);\n\n\t\t\t// Does the first segment of the exploded item match\n\t\t\t// one of the aliases previously identified? If so,\n\t\t\t// we have nothing more to do other than escape the item\n\t\t\t//\n\t\t\t// NOTE: The ! empty() condition prevents this method\n\t\t\t//       from breaking when QB isn't enabled.\n\t\t\tif ( ! empty($this->qb_aliased_tables) && in_array($parts[0], $this->qb_aliased_tables))\n\t\t\t{\n\t\t\t\tif ($protect_identifiers === TRUE)\n\t\t\t\t{\n\t\t\t\t\tforeach ($parts as $key => $val)\n\t\t\t\t\t{\n\t\t\t\t\t\tif ( ! in_array($val, $this->_reserved_identifiers))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$parts[$key] = $this->escape_identifiers($val);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t$item = implode('.', $parts);\n\t\t\t\t}\n\n\t\t\t\treturn $item.$alias;\n\t\t\t}\n\n\t\t\t// Is there a table prefix defined in the config file? If not, no need to do anything\n\t\t\tif ($this->dbprefix !== '')\n\t\t\t{\n\t\t\t\t// We now add the table prefix based on some logic.\n\t\t\t\t// Do we have 4 segments (hostname.database.table.column)?\n\t\t\t\t// If so, we add the table prefix to the column name in the 3rd segment.\n\t\t\t\tif (isset($parts[3]))\n\t\t\t\t{\n\t\t\t\t\t$i = 2;\n\t\t\t\t}\n\t\t\t\t// Do we have 3 segments (database.table.column)?\n\t\t\t\t// If so, we add the table prefix to the column name in 2nd position\n\t\t\t\telseif (isset($parts[2]))\n\t\t\t\t{\n\t\t\t\t\t$i = 1;\n\t\t\t\t}\n\t\t\t\t// Do we have 2 segments (table.column)?\n\t\t\t\t// If so, we add the table prefix to the column name in 1st segment\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$i = 0;\n\t\t\t\t}\n\n\t\t\t\t// This flag is set when the supplied $item does not contain a field name.\n\t\t\t\t// This can happen when this function is being called from a JOIN.\n\t\t\t\tif ($field_exists === FALSE)\n\t\t\t\t{\n\t\t\t\t\t$i++;\n\t\t\t\t}\n\n\t\t\t\t// Verify table prefix and replace if necessary\n\t\t\t\tif ($this->swap_pre !== '' && strpos($parts[$i], $this->swap_pre) === 0)\n\t\t\t\t{\n\t\t\t\t\t$parts[$i] = preg_replace('/^'.$this->swap_pre.'(\\S+?)/', $this->dbprefix.'\\\\1', $parts[$i]);\n\t\t\t\t}\n\t\t\t\t// We only add the table prefix if it does not already exist\n\t\t\t\telseif (strpos($parts[$i], $this->dbprefix) !== 0)\n\t\t\t\t{\n\t\t\t\t\t$parts[$i] = $this->dbprefix.$parts[$i];\n\t\t\t\t}\n\n\t\t\t\t// Put the parts back together\n\t\t\t\t$item = implode('.', $parts);\n\t\t\t}\n\n\t\t\tif ($protect_identifiers === TRUE)\n\t\t\t{\n\t\t\t\t$item = $this->escape_identifiers($item);\n\t\t\t}\n\n\t\t\treturn $item.$alias;\n\t\t}\n\n\t\t// Is there a table prefix? If not, no need to insert it\n\t\tif ($this->dbprefix !== '')\n\t\t{\n\t\t\t// Verify table prefix and replace if necessary\n\t\t\tif ($this->swap_pre !== '' && strpos($item, $this->swap_pre) === 0)\n\t\t\t{\n\t\t\t\t$item = preg_replace('/^'.$this->swap_pre.'(\\S+?)/', $this->dbprefix.'\\\\1', $item);\n\t\t\t}\n\t\t\t// Do we prefix an item with no segments?\n\t\t\telseif ($prefix_single === TRUE && strpos($item, $this->dbprefix) !== 0)\n\t\t\t{\n\t\t\t\t$item = $this->dbprefix.$item;\n\t\t\t}\n\t\t}\n\n\t\tif ($protect_identifiers === TRUE && ! in_array($item, $this->_reserved_identifiers))\n\t\t{\n\t\t\t$item = $this->escape_identifiers($item);\n\t\t}\n\n\t\treturn $item.$alias;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Dummy method that allows Query Builder class to be disabled\n\t * and keep count_all() working.\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _reset_select()\n\t{\n\t}\n\n}\n"
  },
  {
    "path": "system/database/DB_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Database Forge Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nabstract class CI_DB_forge {\n\n\t/**\n\t * Database object\n\t *\n\t * @var\tobject\n\t */\n\tprotected $db;\n\n\t/**\n\t * Fields data\n\t *\n\t * @var\tarray\n\t */\n\tpublic $fields\t\t= array();\n\n\t/**\n\t * Keys data\n\t *\n\t * @var\tarray\n\t */\n\tpublic $keys\t\t= array();\n\n\t/**\n\t * Primary Keys data\n\t *\n\t * @var\tarray\n\t */\n\tpublic $primary_keys\t= array();\n\n\t/**\n\t * Database character set\n\t *\n\t * @var\tstring\n\t */\n\tpublic $db_char_set\t= '';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * CREATE DATABASE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_database\t= 'CREATE DATABASE %s';\n\n\t/**\n\t * DROP DATABASE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_drop_database\t= 'DROP DATABASE %s';\n\n\t/**\n\t * CREATE TABLE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_table\t= \"%s %s (%s\\n)\";\n\n\t/**\n\t * CREATE TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_table_if\t= 'CREATE TABLE IF NOT EXISTS';\n\n\t/**\n\t * CREATE TABLE keys flag\n\t *\n\t * Whether table keys are created from within the\n\t * CREATE TABLE statement.\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_create_table_keys\t= FALSE;\n\n\t/**\n\t * DROP TABLE IF EXISTS statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_drop_table_if\t= 'DROP TABLE IF EXISTS';\n\n\t/**\n\t * RENAME TABLE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_rename_table\t= 'ALTER TABLE %s RENAME TO %s;';\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tbool|array\n\t */\n\tprotected $_unsigned\t\t= TRUE;\n\n\t/**\n\t * NULL value representation in CREATE/ALTER TABLE statements\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_null\t\t= '';\n\n\t/**\n\t * DEFAULT value representation in CREATE/ALTER TABLE statements\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_default\t\t= ' DEFAULT ';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tobject\t&$db\tDatabase object\n\t * @return\tvoid\n\t */\n\tpublic function __construct(&$db)\n\t{\n\t\t$this->db =& $db;\n\t\tlog_message('info', 'Database Forge Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Create database\n\t *\n\t * @param\tstring\t$db_name\n\t * @return\tbool\n\t */\n\tpublic function create_database($db_name)\n\t{\n\t\tif ($this->_create_database === FALSE)\n\t\t{\n\t\t\treturn ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;\n\t\t}\n\t\telseif ( ! $this->db->query(sprintf($this->_create_database, $db_name, $this->db->char_set, $this->db->dbcollat)))\n\t\t{\n\t\t\treturn ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE;\n\t\t}\n\n\t\tif ( ! empty($this->db->data_cache['db_names']))\n\t\t{\n\t\t\t$this->db->data_cache['db_names'][] = $db_name;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Drop database\n\t *\n\t * @param\tstring\t$db_name\n\t * @return\tbool\n\t */\n\tpublic function drop_database($db_name)\n\t{\n\t\tif ($this->_drop_database === FALSE)\n\t\t{\n\t\t\treturn ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;\n\t\t}\n\t\telseif ( ! $this->db->query(sprintf($this->_drop_database, $db_name)))\n\t\t{\n\t\t\treturn ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE;\n\t\t}\n\n\t\tif ( ! empty($this->db->data_cache['db_names']))\n\t\t{\n\t\t\t$key = array_search(strtolower($db_name), array_map('strtolower', $this->db->data_cache['db_names']), TRUE);\n\t\t\tif ($key !== FALSE)\n\t\t\t{\n\t\t\t\tunset($this->db->data_cache['db_names'][$key]);\n\t\t\t}\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add Key\n\t *\n\t * @param\tstring\t$key\n\t * @param\tbool\t$primary\n\t * @return\tCI_DB_forge\n\t */\n\tpublic function add_key($key, $primary = FALSE)\n\t{\n\t\t// DO NOT change this! This condition is only applicable\n\t\t// for PRIMARY keys because you can only have one such,\n\t\t// and therefore all fields you add to it will be included\n\t\t// in the same, composite PRIMARY KEY.\n\t\t//\n\t\t// It's not the same for regular indexes.\n\t\tif ($primary === TRUE && is_array($key))\n\t\t{\n\t\t\tforeach ($key as $one)\n\t\t\t{\n\t\t\t\t$this->add_key($one, $primary);\n\t\t\t}\n\n\t\t\treturn $this;\n\t\t}\n\n\t\tif ($primary === TRUE)\n\t\t{\n\t\t\t$this->primary_keys[] = $key;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->keys[] = $key;\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add Field\n\t *\n\t * @param\tarray\t$field\n\t * @return\tCI_DB_forge\n\t */\n\tpublic function add_field($field)\n\t{\n\t\tif (is_string($field))\n\t\t{\n\t\t\tif ($field === 'id')\n\t\t\t{\n\t\t\t\t$this->add_field(array(\n\t\t\t\t\t'id' => array(\n\t\t\t\t\t\t'type' => 'INT',\n\t\t\t\t\t\t'constraint' => 9,\n\t\t\t\t\t\t'auto_increment' => TRUE\n\t\t\t\t\t)\n\t\t\t\t));\n\t\t\t\t$this->add_key('id', TRUE);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (strpos($field, ' ') === FALSE)\n\t\t\t\t{\n\t\t\t\t\tshow_error('Field information is required for that operation.');\n\t\t\t\t}\n\n\t\t\t\t$this->fields[] = $field;\n\t\t\t}\n\t\t}\n\n\t\tif (is_array($field))\n\t\t{\n\t\t\t$this->fields = array_merge($this->fields, $field);\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Create Table\n\t *\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tbool\t$if_not_exists\tWhether to add IF NOT EXISTS condition\n\t * @param\tarray\t$attributes\tAssociative array of table attributes\n\t * @return\tbool\n\t */\n\tpublic function create_table($table, $if_not_exists = FALSE, array $attributes = array())\n\t{\n\t\tif ($table === '')\n\t\t{\n\t\t\tshow_error('A table name is required for that operation.');\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$table = $this->db->dbprefix.$table;\n\t\t}\n\n\t\tif (count($this->fields) === 0)\n\t\t{\n\t\t\tshow_error('Field information is required.');\n\t\t}\n\n\t\t$sql = $this->_create_table($table, $if_not_exists, $attributes);\n\n\t\tif (is_bool($sql))\n\t\t{\n\t\t\t$this->_reset();\n\t\t\tif ($sql === FALSE)\n\t\t\t{\n\t\t\t\treturn ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;\n\t\t\t}\n\t\t}\n\n\t\tif (($result = $this->db->query($sql)) !== FALSE)\n\t\t{\n\t\t\tempty($this->db->data_cache['table_names']) OR $this->db->data_cache['table_names'][] = $table;\n\n\t\t\t// Most databases don't support creating indexes from within the CREATE TABLE statement\n\t\t\tif ( ! empty($this->keys))\n\t\t\t{\n\t\t\t\tfor ($i = 0, $sqls = $this->_process_indexes($table), $c = count($sqls); $i < $c; $i++)\n\t\t\t\t{\n\t\t\t\t\t$this->db->query($sqls[$i]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$this->_reset();\n\t\treturn $result;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Create Table\n\t *\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tbool\t$if_not_exists\tWhether to add 'IF NOT EXISTS' condition\n\t * @param\tarray\t$attributes\tAssociative array of table attributes\n\t * @return\tmixed\n\t */\n\tprotected function _create_table($table, $if_not_exists, $attributes)\n\t{\n\t\tif ($if_not_exists === TRUE && $this->_create_table_if === FALSE)\n\t\t{\n\t\t\tif ($this->db->table_exists($table))\n\t\t\t{\n\t\t\t\treturn TRUE;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$if_not_exists = FALSE;\n\t\t\t}\n\t\t}\n\n\t\t$sql = ($if_not_exists)\n\t\t\t? sprintf($this->_create_table_if, $this->db->escape_identifiers($table))\n\t\t\t: 'CREATE TABLE';\n\n\t\t$columns = $this->_process_fields(TRUE);\n\t\tfor ($i = 0, $c = count($columns); $i < $c; $i++)\n\t\t{\n\t\t\t$columns[$i] = ($columns[$i]['_literal'] !== FALSE)\n\t\t\t\t\t? \"\\n\\t\".$columns[$i]['_literal']\n\t\t\t\t\t: \"\\n\\t\".$this->_process_column($columns[$i]);\n\t\t}\n\n\t\t$columns = implode(',', $columns)\n\t\t\t\t.$this->_process_primary_keys($table);\n\n\t\t// Are indexes created from within the CREATE TABLE statement? (e.g. in MySQL)\n\t\tif ($this->_create_table_keys === TRUE)\n\t\t{\n\t\t\t$columns .= $this->_process_indexes($table);\n\t\t}\n\n\t\t// _create_table will usually have the following format: \"%s %s (%s\\n)\"\n\t\t$sql = sprintf($this->_create_table.'%s',\n\t\t\t$sql,\n\t\t\t$this->db->escape_identifiers($table),\n\t\t\t$columns,\n\t\t\t$this->_create_table_attr($attributes)\n\t\t);\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * CREATE TABLE attributes\n\t *\n\t * @param\tarray\t$attributes\tAssociative array of table attributes\n\t * @return\tstring\n\t */\n\tprotected function _create_table_attr($attributes)\n\t{\n\t\t$sql = '';\n\n\t\tforeach (array_keys($attributes) as $key)\n\t\t{\n\t\t\tif (is_string($key))\n\t\t\t{\n\t\t\t\t$sql .= ' '.strtoupper($key).' '.$attributes[$key];\n\t\t\t}\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Drop Table\n\t *\n\t * @param\tstring\t$table_name\tTable name\n\t * @param\tbool\t$if_exists\tWhether to add an IF EXISTS condition\n\t * @return\tbool\n\t */\n\tpublic function drop_table($table_name, $if_exists = FALSE)\n\t{\n\t\tif ($table_name === '')\n\t\t{\n\t\t\treturn ($this->db->db_debug) ? $this->db->display_error('db_table_name_required') : FALSE;\n\t\t}\n\n\t\tif (($query = $this->_drop_table($this->db->dbprefix.$table_name, $if_exists)) === TRUE)\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\t$query = $this->db->query($query);\n\n\t\t// Update table list cache\n\t\tif ($query && ! empty($this->db->data_cache['table_names']))\n\t\t{\n\t\t\t$key = array_search(strtolower($this->db->dbprefix.$table_name), array_map('strtolower', $this->db->data_cache['table_names']), TRUE);\n\t\t\tif ($key !== FALSE)\n\t\t\t{\n\t\t\t\tunset($this->db->data_cache['table_names'][$key]);\n\t\t\t}\n\t\t}\n\n\t\treturn $query;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Drop Table\n\t *\n\t * Generates a platform-specific DROP TABLE string\n\t *\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tbool\t$if_exists\tWhether to add an IF EXISTS condition\n\t * @return\tstring\n\t */\n\tprotected function _drop_table($table, $if_exists)\n\t{\n\t\t$sql = 'DROP TABLE';\n\n\t\tif ($if_exists)\n\t\t{\n\t\t\tif ($this->_drop_table_if === FALSE)\n\t\t\t{\n\t\t\t\tif ( ! $this->db->table_exists($table))\n\t\t\t\t{\n\t\t\t\t\treturn TRUE;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$sql = sprintf($this->_drop_table_if, $this->db->escape_identifiers($table));\n\t\t\t}\n\t\t}\n\n\t\treturn $sql.' '.$this->db->escape_identifiers($table);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Rename Table\n\t *\n\t * @param\tstring\t$table_name\tOld table name\n\t * @param\tstring\t$new_table_name\tNew table name\n\t * @return\tbool\n\t */\n\tpublic function rename_table($table_name, $new_table_name)\n\t{\n\t\tif ($table_name === '' OR $new_table_name === '')\n\t\t{\n\t\t\tshow_error('A table name is required for that operation.');\n\t\t\treturn FALSE;\n\t\t}\n\t\telseif ($this->_rename_table === FALSE)\n\t\t{\n\t\t\treturn ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;\n\t\t}\n\n\t\t$result = $this->db->query(sprintf($this->_rename_table,\n\t\t\t\t\t\t$this->db->escape_identifiers($this->db->dbprefix.$table_name),\n\t\t\t\t\t\t$this->db->escape_identifiers($this->db->dbprefix.$new_table_name))\n\t\t\t\t\t);\n\n\t\tif ($result && ! empty($this->db->data_cache['table_names']))\n\t\t{\n\t\t\t$key = array_search(strtolower($this->db->dbprefix.$table_name), array_map('strtolower', $this->db->data_cache['table_names']), TRUE);\n\t\t\tif ($key !== FALSE)\n\t\t\t{\n\t\t\t\t$this->db->data_cache['table_names'][$key] = $this->db->dbprefix.$new_table_name;\n\t\t\t}\n\t\t}\n\n\t\treturn $result;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Column Add\n\t *\n\t * @todo\tRemove deprecated $_after option in 3.1+\n\t * @param\tstring\t$table\tTable name\n\t * @param\tarray\t$field\tColumn definition\n\t * @param\tstring\t$_after\tColumn for AFTER clause (deprecated)\n\t * @return\tbool\n\t */\n\tpublic function add_column($table, $field, $_after = NULL)\n\t{\n\t\t// Work-around for literal column definitions\n\t\tis_array($field) OR $field = array($field);\n\n\t\tforeach (array_keys($field) as $k)\n\t\t{\n\t\t\t// Backwards-compatibility work-around for MySQL/CUBRID AFTER clause (remove in 3.1+)\n\t\t\tif ($_after !== NULL && is_array($field[$k]) && ! isset($field[$k]['after']))\n\t\t\t{\n\t\t\t\t$field[$k]['after'] = $_after;\n\t\t\t}\n\n\t\t\t$this->add_field(array($k => $field[$k]));\n\t\t}\n\n\t\t$sqls = $this->_alter_table('ADD', $this->db->dbprefix.$table, $this->_process_fields());\n\t\t$this->_reset();\n\t\tif ($sqls === FALSE)\n\t\t{\n\t\t\treturn ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;\n\t\t}\n\n\t\tfor ($i = 0, $c = count($sqls); $i < $c; $i++)\n\t\t{\n\t\t\tif ($this->db->query($sqls[$i]) === FALSE)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Column Drop\n\t *\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tstring\t$column_name\tColumn name\n\t * @return\tbool\n\t */\n\tpublic function drop_column($table, $column_name)\n\t{\n\t\t$sql = $this->_alter_table('DROP', $this->db->dbprefix.$table, $column_name);\n\t\tif ($sql === FALSE)\n\t\t{\n\t\t\treturn ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;\n\t\t}\n\n\t\treturn $this->db->query($sql);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Column Modify\n\t *\n\t * @param\tstring\t$table\tTable name\n\t * @param\tstring\t$field\tColumn definition\n\t * @return\tbool\n\t */\n\tpublic function modify_column($table, $field)\n\t{\n\t\t// Work-around for literal column definitions\n\t\tis_array($field) OR $field = array($field);\n\n\t\tforeach (array_keys($field) as $k)\n\t\t{\n\t\t\t$this->add_field(array($k => $field[$k]));\n\t\t}\n\n\t\tif (count($this->fields) === 0)\n\t\t{\n\t\t\tshow_error('Field information is required.');\n\t\t}\n\n\t\t$sqls = $this->_alter_table('CHANGE', $this->db->dbprefix.$table, $this->_process_fields());\n\t\t$this->_reset();\n\t\tif ($sqls === FALSE)\n\t\t{\n\t\t\treturn ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;\n\t\t}\n\n\t\tfor ($i = 0, $c = count($sqls); $i < $c; $i++)\n\t\t{\n\t\t\tif ($this->db->query($sqls[$i]) === FALSE)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ALTER TABLE\n\t *\n\t * @param\tstring\t$alter_type\tALTER type\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tmixed\t$field\t\tColumn definition\n\t * @return\tstring|string[]\n\t */\n\tprotected function _alter_table($alter_type, $table, $field)\n\t{\n\t\t$sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ';\n\n\t\t// DROP has everything it needs now.\n\t\tif ($alter_type === 'DROP')\n\t\t{\n\t\t\treturn $sql.'DROP COLUMN '.$this->db->escape_identifiers($field);\n\t\t}\n\n\t\t$sql .= ($alter_type === 'ADD')\n\t\t\t? 'ADD '\n\t\t\t: $alter_type.' COLUMN ';\n\n\t\t$sqls = array();\n\t\tfor ($i = 0, $c = count($field); $i < $c; $i++)\n\t\t{\n\t\t\t$sqls[] = $sql\n\t\t\t\t.($field[$i]['_literal'] !== FALSE ? $field[$i]['_literal'] : $this->_process_column($field[$i]));\n\t\t}\n\n\t\treturn $sqls;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Process fields\n\t *\n\t * @param\tbool\t$create_table\n\t * @return\tarray\n\t */\n\tprotected function _process_fields($create_table = FALSE)\n\t{\n\t\t$fields = array();\n\n\t\tforeach ($this->fields as $key => $attributes)\n\t\t{\n\t\t\tif (is_int($key) && ! is_array($attributes))\n\t\t\t{\n\t\t\t\t$fields[] = array('_literal' => $attributes);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t$attributes = array_change_key_case($attributes, CASE_UPPER);\n\n\t\t\tif ($create_table === TRUE && empty($attributes['TYPE']))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tisset($attributes['TYPE']) && $this->_attr_type($attributes);\n\n\t\t\t$field = array(\n\t\t\t\t'name'\t\t\t=> $key,\n\t\t\t\t'new_name'\t\t=> isset($attributes['NAME']) ? $attributes['NAME'] : NULL,\n\t\t\t\t'type'\t\t\t=> isset($attributes['TYPE']) ? $attributes['TYPE'] : NULL,\n\t\t\t\t'length'\t\t=> '',\n\t\t\t\t'unsigned'\t\t=> '',\n\t\t\t\t'null'\t\t\t=> '',\n\t\t\t\t'unique'\t\t=> '',\n\t\t\t\t'default'\t\t=> '',\n\t\t\t\t'auto_increment'\t=> '',\n\t\t\t\t'_literal'\t\t=> FALSE\n\t\t\t);\n\n\t\t\tisset($attributes['TYPE']) && $this->_attr_unsigned($attributes, $field);\n\n\t\t\tif ($create_table === FALSE)\n\t\t\t{\n\t\t\t\tif (isset($attributes['AFTER']))\n\t\t\t\t{\n\t\t\t\t\t$field['after'] = $attributes['AFTER'];\n\t\t\t\t}\n\t\t\t\telseif (isset($attributes['FIRST']))\n\t\t\t\t{\n\t\t\t\t\t$field['first'] = (bool) $attributes['FIRST'];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$this->_attr_default($attributes, $field);\n\n\t\t\tif (isset($attributes['NULL']))\n\t\t\t{\n\t\t\t\tif ($attributes['NULL'] === TRUE)\n\t\t\t\t{\n\t\t\t\t\t$field['null'] = empty($this->_null) ? '' : ' '.$this->_null;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$field['null'] = ' NOT NULL';\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ($create_table === TRUE)\n\t\t\t{\n\t\t\t\t$field['null'] = ' NOT NULL';\n\t\t\t}\n\n\t\t\t$this->_attr_auto_increment($attributes, $field);\n\t\t\t$this->_attr_unique($attributes, $field);\n\n\t\t\tif (isset($attributes['COMMENT']))\n\t\t\t{\n\t\t\t\t$field['comment'] = $this->db->escape($attributes['COMMENT']);\n\t\t\t}\n\n\t\t\tif (isset($attributes['TYPE']) && ! empty($attributes['CONSTRAINT']))\n\t\t\t{\n\t\t\t\tswitch (strtoupper($attributes['TYPE']))\n\t\t\t\t{\n\t\t\t\t\tcase 'ENUM':\n\t\t\t\t\tcase 'SET':\n\t\t\t\t\t\t$attributes['CONSTRAINT'] = $this->db->escape($attributes['CONSTRAINT']);\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t$field['length'] = is_array($attributes['CONSTRAINT'])\n\t\t\t\t\t\t\t? '('.implode(',', $attributes['CONSTRAINT']).')'\n\t\t\t\t\t\t\t: '('.$attributes['CONSTRAINT'].')';\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$fields[] = $field;\n\t\t}\n\n\t\treturn $fields;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Process column\n\t *\n\t * @param\tarray\t$field\n\t * @return\tstring\n\t */\n\tprotected function _process_column($field)\n\t{\n\t\treturn $this->db->escape_identifiers($field['name'])\n\t\t\t.' '.$field['type'].$field['length']\n\t\t\t.$field['unsigned']\n\t\t\t.$field['default']\n\t\t\t.$field['null']\n\t\t\t.$field['auto_increment']\n\t\t\t.$field['unique'];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute TYPE\n\t *\n\t * Performs a data type mapping between different databases.\n\t *\n\t * @param\tarray\t&$attributes\n\t * @return\tvoid\n\t */\n\tprotected function _attr_type(&$attributes)\n\t{\n\t\t// Usually overridden by drivers\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute UNSIGNED\n\t *\n\t * Depending on the _unsigned property value:\n\t *\n\t *\t- TRUE will always set $field['unsigned'] to 'UNSIGNED'\n\t *\t- FALSE will always set $field['unsigned'] to ''\n\t *\t- array(TYPE) will set $field['unsigned'] to 'UNSIGNED',\n\t *\t\tif $attributes['TYPE'] is found in the array\n\t *\t- array(TYPE => UTYPE) will change $field['type'],\n\t *\t\tfrom TYPE to UTYPE in case of a match\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_unsigned(&$attributes, &$field)\n\t{\n\t\tif (empty($attributes['UNSIGNED']) OR $attributes['UNSIGNED'] !== TRUE)\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\t// Reset the attribute in order to avoid issues if we do type conversion\n\t\t$attributes['UNSIGNED'] = FALSE;\n\n\t\tif (is_array($this->_unsigned))\n\t\t{\n\t\t\tforeach (array_keys($this->_unsigned) as $key)\n\t\t\t{\n\t\t\t\tif (is_int($key) && strcasecmp($attributes['TYPE'], $this->_unsigned[$key]) === 0)\n\t\t\t\t{\n\t\t\t\t\t$field['unsigned'] = ' UNSIGNED';\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\telseif (is_string($key) && strcasecmp($attributes['TYPE'], $key) === 0)\n\t\t\t\t{\n\t\t\t\t\t$field['type'] = $key;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t$field['unsigned'] = ($this->_unsigned === TRUE) ? ' UNSIGNED' : '';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute DEFAULT\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_default(&$attributes, &$field)\n\t{\n\t\tif ($this->_default === FALSE)\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tif (array_key_exists('DEFAULT', $attributes))\n\t\t{\n\t\t\tif ($attributes['DEFAULT'] === NULL)\n\t\t\t{\n\t\t\t\t$field['default'] = empty($this->_null) ? '' : $this->_default.$this->_null;\n\n\t\t\t\t// Override the NULL attribute if that's our default\n\t\t\t\t$attributes['NULL'] = TRUE;\n\t\t\t\t$field['null'] = empty($this->_null) ? '' : ' '.$this->_null;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$field['default'] = $this->_default.$this->db->escape($attributes['DEFAULT']);\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute UNIQUE\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_unique(&$attributes, &$field)\n\t{\n\t\tif ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE)\n\t\t{\n\t\t\t$field['unique'] = ' UNIQUE';\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute AUTO_INCREMENT\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_auto_increment(&$attributes, &$field)\n\t{\n\t\tif ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)\n\t\t{\n\t\t\t$field['auto_increment'] = ' AUTO_INCREMENT';\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Process primary keys\n\t *\n\t * @param\tstring\t$table\tTable name\n\t * @return\tstring\n\t */\n\tprotected function _process_primary_keys($table)\n\t{\n\t\t$sql = '';\n\n\t\tfor ($i = 0, $c = count($this->primary_keys); $i < $c; $i++)\n\t\t{\n\t\t\tif ( ! isset($this->fields[$this->primary_keys[$i]]))\n\t\t\t{\n\t\t\t\tunset($this->primary_keys[$i]);\n\t\t\t}\n\t\t}\n\n\t\tif (count($this->primary_keys) > 0)\n\t\t{\n\t\t\t$sql .= \",\\n\\tCONSTRAINT \".$this->db->escape_identifiers('pk_'.$table)\n\t\t\t\t.' PRIMARY KEY('.implode(', ', $this->db->escape_identifiers($this->primary_keys)).')';\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Process indexes\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _process_indexes($table)\n\t{\n\t\t$sqls = array();\n\n\t\tfor ($i = 0, $c = count($this->keys); $i < $c; $i++)\n\t\t{\n\t\t\tif (is_array($this->keys[$i]))\n\t\t\t{\n\t\t\t\tfor ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++)\n\t\t\t\t{\n\t\t\t\t\tif ( ! isset($this->fields[$this->keys[$i][$i2]]))\n\t\t\t\t\t{\n\t\t\t\t\t\tunset($this->keys[$i][$i2]);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ( ! isset($this->fields[$this->keys[$i]]))\n\t\t\t{\n\t\t\t\tunset($this->keys[$i]);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tis_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);\n\n\t\t\t$sqls[] = 'CREATE INDEX '.$this->db->escape_identifiers($table.'_'.implode('_', $this->keys[$i]))\n\t\t\t\t.' ON '.$this->db->escape_identifiers($table)\n\t\t\t\t.' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).');';\n\t\t}\n\n\t\treturn $sqls;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Reset\n\t *\n\t * Resets table creation vars\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _reset()\n\t{\n\t\t$this->fields = $this->keys = $this->primary_keys = array();\n\t}\n\n}\n"
  },
  {
    "path": "system/database/DB_query_builder.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Query Builder Class\n *\n * This is the platform-independent base Query Builder implementation class.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\n\nabstract class CI_DB_query_builder extends CI_DB_driver {\n\n\t/**\n\t * Return DELETE SQL flag\n\t *\n\t * @var\tbool\n\t */\n\tprotected $return_delete_sql\t\t= FALSE;\n\n\t/**\n\t * Reset DELETE data flag\n\t *\n\t * @var\tbool\n\t */\n\tprotected $reset_delete_data\t\t= FALSE;\n\n\t/**\n\t * QB SELECT data\n\t *\n\t * @var\tarray\n\t */\n\tprotected $qb_select\t\t\t= array();\n\n\t/**\n\t * QB DISTINCT flag\n\t *\n\t * @var\tbool\n\t */\n\tprotected $qb_distinct\t\t\t= FALSE;\n\n\t/**\n\t * QB FROM data\n\t *\n\t * @var\tarray\n\t */\n\tprotected $qb_from\t\t\t= array();\n\n\t/**\n\t * QB JOIN data\n\t *\n\t * @var\tarray\n\t */\n\tprotected $qb_join\t\t\t= array();\n\n\t/**\n\t * QB WHERE data\n\t *\n\t * @var\tarray\n\t */\n\tprotected $qb_where\t\t\t= array();\n\n\t/**\n\t * QB GROUP BY data\n\t *\n\t * @var\tarray\n\t */\n\tprotected $qb_groupby\t\t\t= array();\n\n\t/**\n\t * QB HAVING data\n\t *\n\t * @var\tarray\n\t */\n\tprotected $qb_having\t\t\t= array();\n\n\t/**\n\t * QB keys\n\t *\n\t * @var\tarray\n\t */\n\tprotected $qb_keys\t\t\t= array();\n\n\t/**\n\t * QB LIMIT data\n\t *\n\t * @var\tint\n\t */\n\tprotected $qb_limit\t\t\t= FALSE;\n\n\t/**\n\t * QB OFFSET data\n\t *\n\t * @var\tint\n\t */\n\tprotected $qb_offset\t\t\t= FALSE;\n\n\t/**\n\t * QB ORDER BY data\n\t *\n\t * @var\tarray\n\t */\n\tprotected $qb_orderby\t\t\t= array();\n\n\t/**\n\t * QB data sets\n\t *\n\t * @var\tarray\n\t */\n\tprotected $qb_set\t\t\t= array();\n\n\t/**\n\t * QB aliased tables list\n\t *\n\t * @var\tarray\n\t */\n\tprotected $qb_aliased_tables\t\t= array();\n\n\t/**\n\t * QB WHERE group started flag\n\t *\n\t * @var\tbool\n\t */\n\tprotected $qb_where_group_started\t= FALSE;\n\n\t/**\n\t * QB WHERE group count\n\t *\n\t * @var\tint\n\t */\n\tprotected $qb_where_group_count\t\t= 0;\n\n\t// Query Builder Caching variables\n\n\t/**\n\t * QB Caching flag\n\t *\n\t * @var\tbool\n\t */\n\tprotected $qb_caching\t\t\t\t= FALSE;\n\n\t/**\n\t * QB Cache exists list\n\t *\n\t * @var\tarray\n\t */\n\tprotected $qb_cache_exists\t\t\t= array();\n\n\t/**\n\t * QB Cache SELECT data\n\t *\n\t * @var\tarray\n\t */\n\tprotected $qb_cache_select\t\t\t= array();\n\n\t/**\n\t * QB Cache FROM data\n\t *\n\t * @var\tarray\n\t */\n\tprotected $qb_cache_from\t\t\t= array();\n\n\t/**\n\t * QB Cache JOIN data\n\t *\n\t * @var\tarray\n\t */\n\tprotected $qb_cache_join\t\t\t= array();\n\n\t/**\n\t * QB Cache WHERE data\n\t *\n\t * @var\tarray\n\t */\n\tprotected $qb_cache_where\t\t\t= array();\n\n\t/**\n\t * QB Cache GROUP BY data\n\t *\n\t * @var\tarray\n\t */\n\tprotected $qb_cache_groupby\t\t\t= array();\n\n\t/**\n\t * QB Cache HAVING data\n\t *\n\t * @var\tarray\n\t */\n\tprotected $qb_cache_having\t\t\t= array();\n\n\t/**\n\t * QB Cache ORDER BY data\n\t *\n\t * @var\tarray\n\t */\n\tprotected $qb_cache_orderby\t\t\t= array();\n\n\t/**\n\t * QB Cache data sets\n\t *\n\t * @var\tarray\n\t */\n\tprotected $qb_cache_set\t\t\t\t= array();\n\n\t/**\n\t * QB No Escape data\n\t *\n\t * @var\tarray\n\t */\n\tprotected $qb_no_escape \t\t\t= array();\n\n\t/**\n\t * QB Cache No Escape data\n\t *\n\t * @var\tarray\n\t */\n\tprotected $qb_cache_no_escape\t\t\t= array();\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Select\n\t *\n\t * Generates the SELECT portion of the query\n\t *\n\t * @param\tstring\n\t * @param\tmixed\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function select($select = '*', $escape = NULL)\n\t{\n\t\tif (is_string($select))\n\t\t{\n\t\t\t$select = explode(',', $select);\n\t\t}\n\n\t\t// If the escape value was not set, we will base it on the global setting\n\t\tis_bool($escape) OR $escape = $this->_protect_identifiers;\n\n\t\tforeach ($select as $val)\n\t\t{\n\t\t\t$val = trim($val);\n\n\t\t\tif ($val !== '')\n\t\t\t{\n\t\t\t\t$this->qb_select[] = $val;\n\t\t\t\t$this->qb_no_escape[] = $escape;\n\n\t\t\t\tif ($this->qb_caching === TRUE)\n\t\t\t\t{\n\t\t\t\t\t$this->qb_cache_select[] = $val;\n\t\t\t\t\t$this->qb_cache_exists[] = 'select';\n\t\t\t\t\t$this->qb_cache_no_escape[] = $escape;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Select Max\n\t *\n\t * Generates a SELECT MAX(field) portion of a query\n\t *\n\t * @param\tstring\tthe field\n\t * @param\tstring\tan alias\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function select_max($select = '', $alias = '')\n\t{\n\t\treturn $this->_max_min_avg_sum($select, $alias, 'MAX');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Select Min\n\t *\n\t * Generates a SELECT MIN(field) portion of a query\n\t *\n\t * @param\tstring\tthe field\n\t * @param\tstring\tan alias\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function select_min($select = '', $alias = '')\n\t{\n\t\treturn $this->_max_min_avg_sum($select, $alias, 'MIN');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Select Average\n\t *\n\t * Generates a SELECT AVG(field) portion of a query\n\t *\n\t * @param\tstring\tthe field\n\t * @param\tstring\tan alias\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function select_avg($select = '', $alias = '')\n\t{\n\t\treturn $this->_max_min_avg_sum($select, $alias, 'AVG');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Select Sum\n\t *\n\t * Generates a SELECT SUM(field) portion of a query\n\t *\n\t * @param\tstring\tthe field\n\t * @param\tstring\tan alias\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function select_sum($select = '', $alias = '')\n\t{\n\t\treturn $this->_max_min_avg_sum($select, $alias, 'SUM');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * SELECT [MAX|MIN|AVG|SUM]()\n\t *\n\t * @used-by\tselect_max()\n\t * @used-by\tselect_min()\n\t * @used-by\tselect_avg()\n\t * @used-by\tselect_sum()\n\t *\n\t * @param\tstring\t$select\tField name\n\t * @param\tstring\t$alias\n\t * @param\tstring\t$type\n\t * @return\tCI_DB_query_builder\n\t */\n\tprotected function _max_min_avg_sum($select = '', $alias = '', $type = 'MAX')\n\t{\n\t\tif ( ! is_string($select) OR $select === '')\n\t\t{\n\t\t\t$this->display_error('db_invalid_query');\n\t\t}\n\n\t\t$type = strtoupper($type);\n\n\t\tif ( ! in_array($type, array('MAX', 'MIN', 'AVG', 'SUM')))\n\t\t{\n\t\t\tshow_error('Invalid function type: '.$type);\n\t\t}\n\n\t\tif ($alias === '')\n\t\t{\n\t\t\t$alias = $this->_create_alias_from_table(trim($select));\n\t\t}\n\n\t\t$sql = $type.'('.$this->protect_identifiers(trim($select)).') AS '.$this->escape_identifiers(trim($alias));\n\n\t\t$this->qb_select[] = $sql;\n\t\t$this->qb_no_escape[] = NULL;\n\n\t\tif ($this->qb_caching === TRUE)\n\t\t{\n\t\t\t$this->qb_cache_select[] = $sql;\n\t\t\t$this->qb_cache_exists[] = 'select';\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Determines the alias name based on the table\n\t *\n\t * @param\tstring\t$item\n\t * @return\tstring\n\t */\n\tprotected function _create_alias_from_table($item)\n\t{\n\t\tif (strpos($item, '.') !== FALSE)\n\t\t{\n\t\t\t$item = explode('.', $item);\n\t\t\treturn end($item);\n\t\t}\n\n\t\treturn $item;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * DISTINCT\n\t *\n\t * Sets a flag which tells the query string compiler to add DISTINCT\n\t *\n\t * @param\tbool\t$val\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function distinct($val = TRUE)\n\t{\n\t\t$this->qb_distinct = is_bool($val) ? $val : TRUE;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * From\n\t *\n\t * Generates the FROM portion of the query\n\t *\n\t * @param\tmixed\t$from\tcan be a string or array\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function from($from)\n\t{\n\t\tforeach ((array) $from as $val)\n\t\t{\n\t\t\tif (strpos($val, ',') !== FALSE)\n\t\t\t{\n\t\t\t\tforeach (explode(',', $val) as $v)\n\t\t\t\t{\n\t\t\t\t\t$v = trim($v);\n\t\t\t\t\t$this->_track_aliases($v);\n\n\t\t\t\t\t$this->qb_from[] = $v = $this->protect_identifiers($v, TRUE, NULL, FALSE);\n\n\t\t\t\t\tif ($this->qb_caching === TRUE)\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->qb_cache_from[] = $v;\n\t\t\t\t\t\t$this->qb_cache_exists[] = 'from';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$val = trim($val);\n\n\t\t\t\t// Extract any aliases that might exist. We use this information\n\t\t\t\t// in the protect_identifiers to know whether to add a table prefix\n\t\t\t\t$this->_track_aliases($val);\n\n\t\t\t\t$this->qb_from[] = $val = $this->protect_identifiers($val, TRUE, NULL, FALSE);\n\n\t\t\t\tif ($this->qb_caching === TRUE)\n\t\t\t\t{\n\t\t\t\t\t$this->qb_cache_from[] = $val;\n\t\t\t\t\t$this->qb_cache_exists[] = 'from';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * JOIN\n\t *\n\t * Generates the JOIN portion of the query\n\t *\n\t * @param\tstring\n\t * @param\tstring\tthe join condition\n\t * @param\tstring\tthe type of join\n\t * @param\tstring\twhether not to try to escape identifiers\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function join($table, $cond, $type = '', $escape = NULL)\n\t{\n\t\tif ($type !== '')\n\t\t{\n\t\t\t$type = strtoupper(trim($type));\n\n\t\t\tif ( ! in_array($type, array('LEFT', 'RIGHT', 'OUTER', 'INNER', 'LEFT OUTER', 'RIGHT OUTER'), TRUE))\n\t\t\t{\n\t\t\t\t$type = '';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$type .= ' ';\n\t\t\t}\n\t\t}\n\n\t\t// Extract any aliases that might exist. We use this information\n\t\t// in the protect_identifiers to know whether to add a table prefix\n\t\t$this->_track_aliases($table);\n\n\t\tis_bool($escape) OR $escape = $this->_protect_identifiers;\n\n\t\tif ( ! $this->_has_operator($cond))\n\t\t{\n\t\t\t$cond = ' USING ('.($escape ? $this->escape_identifiers($cond) : $cond).')';\n\t\t}\n\t\telseif ($escape === FALSE)\n\t\t{\n\t\t\t$cond = ' ON '.$cond;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Split multiple conditions\n\t\t\tif (preg_match_all('/\\sAND\\s|\\sOR\\s/i', $cond, $joints, PREG_OFFSET_CAPTURE))\n\t\t\t{\n\t\t\t\t$conditions = array();\n\t\t\t\t$joints = $joints[0];\n\t\t\t\tarray_unshift($joints, array('', 0));\n\n\t\t\t\tfor ($i = count($joints) - 1, $pos = strlen($cond); $i >= 0; $i--)\n\t\t\t\t{\n\t\t\t\t\t$joints[$i][1] += strlen($joints[$i][0]); // offset\n\t\t\t\t\t$conditions[$i] = substr($cond, $joints[$i][1], $pos - $joints[$i][1]);\n\t\t\t\t\t$pos = $joints[$i][1] - strlen($joints[$i][0]);\n\t\t\t\t\t$joints[$i] = $joints[$i][0];\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$conditions = array($cond);\n\t\t\t\t$joints = array('');\n\t\t\t}\n\n\t\t\t$cond = ' ON ';\n\t\t\tfor ($i = 0, $c = count($conditions); $i < $c; $i++)\n\t\t\t{\n\t\t\t\t$operator = $this->_get_operator($conditions[$i]);\n\t\t\t\t$cond .= $joints[$i];\n\t\t\t\t$cond .= preg_match(\"/(\\(*)?([\\[\\]\\w\\.'-]+)\".preg_quote($operator).\"(.*)/i\", $conditions[$i], $match)\n\t\t\t\t\t? $match[1].$this->protect_identifiers($match[2]).$operator.$this->protect_identifiers($match[3])\n\t\t\t\t\t: $conditions[$i];\n\t\t\t}\n\t\t}\n\n\t\t// Do we want to escape the table name?\n\t\tif ($escape === TRUE)\n\t\t{\n\t\t\t$table = $this->protect_identifiers($table, TRUE, NULL, FALSE);\n\t\t}\n\n\t\t// Assemble the JOIN statement\n\t\t$this->qb_join[] = $join = $type.'JOIN '.$table.$cond;\n\n\t\tif ($this->qb_caching === TRUE)\n\t\t{\n\t\t\t$this->qb_cache_join[] = $join;\n\t\t\t$this->qb_cache_exists[] = 'join';\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * WHERE\n\t *\n\t * Generates the WHERE portion of the query.\n\t * Separates multiple calls with 'AND'.\n\t *\n\t * @param\tmixed\n\t * @param\tmixed\n\t * @param\tbool\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function where($key, $value = NULL, $escape = NULL)\n\t{\n\t\treturn $this->_wh('qb_where', $key, $value, 'AND ', $escape);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * OR WHERE\n\t *\n\t * Generates the WHERE portion of the query.\n\t * Separates multiple calls with 'OR'.\n\t *\n\t * @param\tmixed\n\t * @param\tmixed\n\t * @param\tbool\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function or_where($key, $value = NULL, $escape = NULL)\n\t{\n\t\treturn $this->_wh('qb_where', $key, $value, 'OR ', $escape);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * WHERE, HAVING\n\t *\n\t * @used-by\twhere()\n\t * @used-by\tor_where()\n\t * @used-by\thaving()\n\t * @used-by\tor_having()\n\t *\n\t * @param\tstring\t$qb_key\t'qb_where' or 'qb_having'\n\t * @param\tmixed\t$key\n\t * @param\tmixed\t$value\n\t * @param\tstring\t$type\n\t * @param\tbool\t$escape\n\t * @return\tCI_DB_query_builder\n\t */\n\tprotected function _wh($qb_key, $key, $value = NULL, $type = 'AND ', $escape = NULL)\n\t{\n\t\t$qb_cache_key = ($qb_key === 'qb_having') ? 'qb_cache_having' : 'qb_cache_where';\n\n\t\tif ( ! is_array($key))\n\t\t{\n\t\t\t$key = array($key => $value);\n\t\t}\n\n\t\t// If the escape value was not set will base it on the global setting\n\t\tis_bool($escape) OR $escape = $this->_protect_identifiers;\n\n\t\tforeach ($key as $k => $v)\n\t\t{\n\t\t\t$prefix = (count($this->$qb_key) === 0 && count($this->$qb_cache_key) === 0)\n\t\t\t\t? $this->_group_get_type('')\n\t\t\t\t: $this->_group_get_type($type);\n\n\t\t\tif ($v !== NULL)\n\t\t\t{\n\t\t\t\tif ($escape === TRUE)\n\t\t\t\t{\n\t\t\t\t\t$v = ' '.$this->escape($v);\n\t\t\t\t}\n\n\t\t\t\tif ( ! $this->_has_operator($k))\n\t\t\t\t{\n\t\t\t\t\t$k .= ' = ';\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ( ! $this->_has_operator($k))\n\t\t\t{\n\t\t\t\t// value appears not to have been set, assign the test to IS NULL\n\t\t\t\t$k .= ' IS NULL';\n\t\t\t}\n\t\t\telseif (preg_match('/\\s*(!?=|<>|IS(?:\\s+NOT)?)\\s*$/i', $k, $match, PREG_OFFSET_CAPTURE))\n\t\t\t{\n\t\t\t\t$k = substr($k, 0, $match[0][1]).($match[1][0] === '=' ? ' IS NULL' : ' IS NOT NULL');\n\t\t\t}\n\n\t\t\t$this->{$qb_key}[] = array('condition' => $prefix.$k.$v, 'escape' => $escape);\n\t\t\tif ($this->qb_caching === TRUE)\n\t\t\t{\n\t\t\t\t$this->{$qb_cache_key}[] = array('condition' => $prefix.$k.$v, 'escape' => $escape);\n\t\t\t\t$this->qb_cache_exists[] = substr($qb_key, 3);\n\t\t\t}\n\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * WHERE IN\n\t *\n\t * Generates a WHERE field IN('item', 'item') SQL query,\n\t * joined with 'AND' if appropriate.\n\t *\n\t * @param\tstring\t$key\tThe field to search\n\t * @param\tarray\t$values\tThe values searched on\n\t * @param\tbool\t$escape\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function where_in($key = NULL, $values = NULL, $escape = NULL)\n\t{\n\t\treturn $this->_where_in($key, $values, FALSE, 'AND ', $escape);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * OR WHERE IN\n\t *\n\t * Generates a WHERE field IN('item', 'item') SQL query,\n\t * joined with 'OR' if appropriate.\n\t *\n\t * @param\tstring\t$key\tThe field to search\n\t * @param\tarray\t$values\tThe values searched on\n\t * @param\tbool\t$escape\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function or_where_in($key = NULL, $values = NULL, $escape = NULL)\n\t{\n\t\treturn $this->_where_in($key, $values, FALSE, 'OR ', $escape);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * WHERE NOT IN\n\t *\n\t * Generates a WHERE field NOT IN('item', 'item') SQL query,\n\t * joined with 'AND' if appropriate.\n\t *\n\t * @param\tstring\t$key\tThe field to search\n\t * @param\tarray\t$values\tThe values searched on\n\t * @param\tbool\t$escape\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function where_not_in($key = NULL, $values = NULL, $escape = NULL)\n\t{\n\t\treturn $this->_where_in($key, $values, TRUE, 'AND ', $escape);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * OR WHERE NOT IN\n\t *\n\t * Generates a WHERE field NOT IN('item', 'item') SQL query,\n\t * joined with 'OR' if appropriate.\n\t *\n\t * @param\tstring\t$key\tThe field to search\n\t * @param\tarray\t$values\tThe values searched on\n\t * @param\tbool\t$escape\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function or_where_not_in($key = NULL, $values = NULL, $escape = NULL)\n\t{\n\t\treturn $this->_where_in($key, $values, TRUE, 'OR ', $escape);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Internal WHERE IN\n\t *\n\t * @used-by\twhere_in()\n\t * @used-by\tor_where_in()\n\t * @used-by\twhere_not_in()\n\t * @used-by\tor_where_not_in()\n\t *\n\t * @param\tstring\t$key\tThe field to search\n\t * @param\tarray\t$values\tThe values searched on\n\t * @param\tbool\t$not\tIf the statement would be IN or NOT IN\n\t * @param\tstring\t$type\n\t * @param\tbool\t$escape\n\t * @return\tCI_DB_query_builder\n\t */\n\tprotected function _where_in($key = NULL, $values = NULL, $not = FALSE, $type = 'AND ', $escape = NULL)\n\t{\n\t\tif ($key === NULL OR $values === NULL)\n\t\t{\n\t\t\treturn $this;\n\t\t}\n\n\t\tif ( ! is_array($values))\n\t\t{\n\t\t\t$values = array($values);\n\t\t}\n\n\t\tis_bool($escape) OR $escape = $this->_protect_identifiers;\n\n\t\t$not = ($not) ? ' NOT' : '';\n\n\t\tif ($escape === TRUE)\n\t\t{\n\t\t\t$where_in = array();\n\t\t\tforeach ($values as $value)\n\t\t\t{\n\t\t\t\t$where_in[] = $this->escape($value);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$where_in = array_values($values);\n\t\t}\n\n\t\t$prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0)\n\t\t\t? $this->_group_get_type('')\n\t\t\t: $this->_group_get_type($type);\n\n\t\t$where_in = array(\n\t\t\t'condition' => $prefix.$key.$not.' IN('.implode(', ', $where_in).')',\n\t\t\t'escape' => $escape\n\t\t);\n\n\t\t$this->qb_where[] = $where_in;\n\t\tif ($this->qb_caching === TRUE)\n\t\t{\n\t\t\t$this->qb_cache_where[] = $where_in;\n\t\t\t$this->qb_cache_exists[] = 'where';\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * LIKE\n\t *\n\t * Generates a %LIKE% portion of the query.\n\t * Separates multiple calls with 'AND'.\n\t *\n\t * @param\tmixed\t$field\n\t * @param\tstring\t$match\n\t * @param\tstring\t$side\n\t * @param\tbool\t$escape\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function like($field, $match = '', $side = 'both', $escape = NULL)\n\t{\n\t\treturn $this->_like($field, $match, 'AND ', $side, '', $escape);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * NOT LIKE\n\t *\n\t * Generates a NOT LIKE portion of the query.\n\t * Separates multiple calls with 'AND'.\n\t *\n\t * @param\tmixed\t$field\n\t * @param\tstring\t$match\n\t * @param\tstring\t$side\n\t * @param\tbool\t$escape\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function not_like($field, $match = '', $side = 'both', $escape = NULL)\n\t{\n\t\treturn $this->_like($field, $match, 'AND ', $side, 'NOT', $escape);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * OR LIKE\n\t *\n\t * Generates a %LIKE% portion of the query.\n\t * Separates multiple calls with 'OR'.\n\t *\n\t * @param\tmixed\t$field\n\t * @param\tstring\t$match\n\t * @param\tstring\t$side\n\t * @param\tbool\t$escape\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function or_like($field, $match = '', $side = 'both', $escape = NULL)\n\t{\n\t\treturn $this->_like($field, $match, 'OR ', $side, '', $escape);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * OR NOT LIKE\n\t *\n\t * Generates a NOT LIKE portion of the query.\n\t * Separates multiple calls with 'OR'.\n\t *\n\t * @param\tmixed\t$field\n\t * @param\tstring\t$match\n\t * @param\tstring\t$side\n\t * @param\tbool\t$escape\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function or_not_like($field, $match = '', $side = 'both', $escape = NULL)\n\t{\n\t\treturn $this->_like($field, $match, 'OR ', $side, 'NOT', $escape);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Internal LIKE\n\t *\n\t * @used-by\tlike()\n\t * @used-by\tor_like()\n\t * @used-by\tnot_like()\n\t * @used-by\tor_not_like()\n\t *\n\t * @param\tmixed\t$field\n\t * @param\tstring\t$match\n\t * @param\tstring\t$type\n\t * @param\tstring\t$side\n\t * @param\tstring\t$not\n\t * @param\tbool\t$escape\n\t * @return\tCI_DB_query_builder\n\t */\n\tprotected function _like($field, $match = '', $type = 'AND ', $side = 'both', $not = '', $escape = NULL)\n\t{\n\t\tif ( ! is_array($field))\n\t\t{\n\t\t\t$field = array($field => $match);\n\t\t}\n\n\t\tis_bool($escape) OR $escape = $this->_protect_identifiers;\n\t\t// lowercase $side in case somebody writes e.g. 'BEFORE' instead of 'before' (doh)\n\t\t$side = strtolower($side);\n\n\t\tforeach ($field as $k => $v)\n\t\t{\n\t\t\t$prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0)\n\t\t\t\t? $this->_group_get_type('') : $this->_group_get_type($type);\n\n\t\t\tif ($escape === TRUE)\n\t\t\t{\n\t\t\t\t$v = $this->escape_like_str($v);\n\t\t\t}\n\n\t\t\tif ($side === 'none')\n\t\t\t{\n\t\t\t\t$like_statement = \"{$prefix} {$k} {$not} LIKE '{$v}'\";\n\t\t\t}\n\t\t\telseif ($side === 'before')\n\t\t\t{\n\t\t\t\t$like_statement = \"{$prefix} {$k} {$not} LIKE '%{$v}'\";\n\t\t\t}\n\t\t\telseif ($side === 'after')\n\t\t\t{\n\t\t\t\t$like_statement = \"{$prefix} {$k} {$not} LIKE '{$v}%'\";\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$like_statement = \"{$prefix} {$k} {$not} LIKE '%{$v}%'\";\n\t\t\t}\n\n\t\t\t// some platforms require an escape sequence definition for LIKE wildcards\n\t\t\tif ($escape === TRUE && $this->_like_escape_str !== '')\n\t\t\t{\n\t\t\t\t$like_statement .= sprintf($this->_like_escape_str, $this->_like_escape_chr);\n\t\t\t}\n\n\t\t\t$this->qb_where[] = array('condition' => $like_statement, 'escape' => $escape);\n\t\t\tif ($this->qb_caching === TRUE)\n\t\t\t{\n\t\t\t\t$this->qb_cache_where[] = array('condition' => $like_statement, 'escape' => $escape);\n\t\t\t\t$this->qb_cache_exists[] = 'where';\n\t\t\t}\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Starts a query group.\n\t *\n\t * @param\tstring\t$not\t(Internal use only)\n\t * @param\tstring\t$type\t(Internal use only)\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function group_start($not = '', $type = 'AND ')\n\t{\n\t\t$type = $this->_group_get_type($type);\n\n\t\t$this->qb_where_group_started = TRUE;\n\t\t$prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) ? '' : $type;\n\t\t$where = array(\n\t\t\t'condition' => $prefix.$not.str_repeat(' ', ++$this->qb_where_group_count).' (',\n\t\t\t'escape' => FALSE\n\t\t);\n\n\t\t$this->qb_where[] = $where;\n\t\tif ($this->qb_caching)\n\t\t{\n\t\t\t$this->qb_cache_where[] = $where;\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Starts a query group, but ORs the group\n\t *\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function or_group_start()\n\t{\n\t\treturn $this->group_start('', 'OR ');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Starts a query group, but NOTs the group\n\t *\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function not_group_start()\n\t{\n\t\treturn $this->group_start('NOT ', 'AND ');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Starts a query group, but OR NOTs the group\n\t *\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function or_not_group_start()\n\t{\n\t\treturn $this->group_start('NOT ', 'OR ');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Ends a query group\n\t *\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function group_end()\n\t{\n\t\t$this->qb_where_group_started = FALSE;\n\t\t$where = array(\n\t\t\t'condition' => str_repeat(' ', $this->qb_where_group_count--).')',\n\t\t\t'escape' => FALSE\n\t\t);\n\n\t\t$this->qb_where[] = $where;\n\t\tif ($this->qb_caching)\n\t\t{\n\t\t\t$this->qb_cache_where[] = $where;\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Group_get_type\n\t *\n\t * @used-by\tgroup_start()\n\t * @used-by\t_like()\n\t * @used-by\t_wh()\n\t * @used-by\t_where_in()\n\t *\n\t * @param\tstring\t$type\n\t * @return\tstring\n\t */\n\tprotected function _group_get_type($type)\n\t{\n\t\tif ($this->qb_where_group_started)\n\t\t{\n\t\t\t$type = '';\n\t\t\t$this->qb_where_group_started = FALSE;\n\t\t}\n\n\t\treturn $type;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * GROUP BY\n\t *\n\t * @param\tstring\t$by\n\t * @param\tbool\t$escape\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function group_by($by, $escape = NULL)\n\t{\n\t\tis_bool($escape) OR $escape = $this->_protect_identifiers;\n\n\t\tif (is_string($by))\n\t\t{\n\t\t\t$by = ($escape === TRUE)\n\t\t\t\t? explode(',', $by)\n\t\t\t\t: array($by);\n\t\t}\n\n\t\tforeach ($by as $val)\n\t\t{\n\t\t\t$val = trim($val);\n\n\t\t\tif ($val !== '')\n\t\t\t{\n\t\t\t\t$val = array('field' => $val, 'escape' => $escape);\n\n\t\t\t\t$this->qb_groupby[] = $val;\n\t\t\t\tif ($this->qb_caching === TRUE)\n\t\t\t\t{\n\t\t\t\t\t$this->qb_cache_groupby[] = $val;\n\t\t\t\t\t$this->qb_cache_exists[] = 'groupby';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * HAVING\n\t *\n\t * Separates multiple calls with 'AND'.\n\t *\n\t * @param\tstring\t$key\n\t * @param\tstring\t$value\n\t * @param\tbool\t$escape\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function having($key, $value = NULL, $escape = NULL)\n\t{\n\t\treturn $this->_wh('qb_having', $key, $value, 'AND ', $escape);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * OR HAVING\n\t *\n\t * Separates multiple calls with 'OR'.\n\t *\n\t * @param\tstring\t$key\n\t * @param\tstring\t$value\n\t * @param\tbool\t$escape\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function or_having($key, $value = NULL, $escape = NULL)\n\t{\n\t\treturn $this->_wh('qb_having', $key, $value, 'OR ', $escape);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ORDER BY\n\t *\n\t * @param\tstring\t$orderby\n\t * @param\tstring\t$direction\tASC, DESC or RANDOM\n\t * @param\tbool\t$escape\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function order_by($orderby, $direction = '', $escape = NULL)\n\t{\n\t\t$direction = strtoupper(trim($direction));\n\n\t\tif ($direction === 'RANDOM')\n\t\t{\n\t\t\t$direction = '';\n\n\t\t\t// Do we have a seed value?\n\t\t\t$orderby = ctype_digit((string) $orderby)\n\t\t\t\t? sprintf($this->_random_keyword[1], $orderby)\n\t\t\t\t: $this->_random_keyword[0];\n\t\t}\n\t\telseif (empty($orderby))\n\t\t{\n\t\t\treturn $this;\n\t\t}\n\t\telseif ($direction !== '')\n\t\t{\n\t\t\t$direction = in_array($direction, array('ASC', 'DESC'), TRUE) ? ' '.$direction : '';\n\t\t}\n\n\t\tis_bool($escape) OR $escape = $this->_protect_identifiers;\n\n\t\tif ($escape === FALSE)\n\t\t{\n\t\t\t$qb_orderby[] = array('field' => $orderby, 'direction' => $direction, 'escape' => FALSE);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$qb_orderby = array();\n\t\t\tforeach (explode(',', $orderby) as $field)\n\t\t\t{\n\t\t\t\t$qb_orderby[] = ($direction === '' && preg_match('/\\s+(ASC|DESC)$/i', rtrim($field), $match, PREG_OFFSET_CAPTURE))\n\t\t\t\t\t? array('field' => ltrim(substr($field, 0, $match[0][1])), 'direction' => ' '.$match[1][0], 'escape' => TRUE)\n\t\t\t\t\t: array('field' => trim($field), 'direction' => $direction, 'escape' => TRUE);\n\t\t\t}\n\t\t}\n\n\t\t$this->qb_orderby = array_merge($this->qb_orderby, $qb_orderby);\n\t\tif ($this->qb_caching === TRUE)\n\t\t{\n\t\t\t$this->qb_cache_orderby = array_merge($this->qb_cache_orderby, $qb_orderby);\n\t\t\t$this->qb_cache_exists[] = 'orderby';\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * LIMIT\n\t *\n\t * @param\tint\t$value\tLIMIT value\n\t * @param\tint\t$offset\tOFFSET value\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function limit($value, $offset = 0)\n\t{\n\t\tis_null($value) OR $this->qb_limit = (int) $value;\n\t\tempty($offset) OR $this->qb_offset = (int) $offset;\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Sets the OFFSET value\n\t *\n\t * @param\tint\t$offset\tOFFSET value\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function offset($offset)\n\t{\n\t\tempty($offset) OR $this->qb_offset = (int) $offset;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * LIMIT string\n\t *\n\t * Generates a platform-specific LIMIT clause.\n\t *\n\t * @param\tstring\t$sql\tSQL Query\n\t * @return\tstring\n\t */\n\tprotected function _limit($sql)\n\t{\n\t\treturn $sql.' LIMIT '.($this->qb_offset ? $this->qb_offset.', ' : '').$this->qb_limit;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * The \"set\" function.\n\t *\n\t * Allows key/value pairs to be set for inserting or updating\n\t *\n\t * @param\tmixed\n\t * @param\tstring\n\t * @param\tbool\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function set($key, $value = '', $escape = NULL)\n\t{\n\t\t$key = $this->_object_to_array($key);\n\n\t\tif ( ! is_array($key))\n\t\t{\n\t\t\t$key = array($key => $value);\n\t\t}\n\n\t\tis_bool($escape) OR $escape = $this->_protect_identifiers;\n\n\t\tforeach ($key as $k => $v)\n\t\t{\n\t\t\t$this->qb_set[$this->protect_identifiers($k, FALSE, $escape)] = ($escape)\n\t\t\t\t? $this->escape($v) : $v;\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get SELECT query string\n\t *\n\t * Compiles a SELECT query string and returns the sql.\n\t *\n\t * @param\tstring\tthe table name to select from (optional)\n\t * @param\tbool\tTRUE: resets QB values; FALSE: leave QB values alone\n\t * @return\tstring\n\t */\n\tpublic function get_compiled_select($table = '', $reset = TRUE)\n\t{\n\t\tif ($table !== '')\n\t\t{\n\t\t\t$this->_track_aliases($table);\n\t\t\t$this->from($table);\n\t\t}\n\n\t\t$select = $this->_compile_select();\n\n\t\tif ($reset === TRUE)\n\t\t{\n\t\t\t$this->_reset_select();\n\t\t}\n\n\t\treturn $select;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get\n\t *\n\t * Compiles the select statement based on the other functions called\n\t * and runs the query\n\t *\n\t * @param\tstring\tthe table\n\t * @param\tstring\tthe limit clause\n\t * @param\tstring\tthe offset clause\n\t * @return\tCI_DB_result\n\t */\n\tpublic function get($table = '', $limit = NULL, $offset = NULL)\n\t{\n\t\tif ($table !== '')\n\t\t{\n\t\t\t$this->_track_aliases($table);\n\t\t\t$this->from($table);\n\t\t}\n\n\t\tif ( ! empty($limit))\n\t\t{\n\t\t\t$this->limit($limit, $offset);\n\t\t}\n\n\t\t$result = $this->query($this->_compile_select());\n\t\t$this->_reset_select();\n\t\treturn $result;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * \"Count All Results\" query\n\t *\n\t * Generates a platform-specific query string that counts all records\n\t * returned by an Query Builder query.\n\t *\n\t * @param\tstring\n\t * @param\tbool\tthe reset clause\n\t * @return\tint\n\t */\n\tpublic function count_all_results($table = '', $reset = TRUE)\n\t{\n\t\tif ($table !== '')\n\t\t{\n\t\t\t$this->_track_aliases($table);\n\t\t\t$this->from($table);\n\t\t}\n\n\t\t// ORDER BY usage is often problematic here (most notably\n\t\t// on Microsoft SQL Server) and ultimately unnecessary\n\t\t// for selecting COUNT(*) ...\n\t\tif ( ! empty($this->qb_orderby))\n\t\t{\n\t\t\t$orderby = $this->qb_orderby;\n\t\t\t$this->qb_orderby = NULL;\n\t\t}\n\n\t\t$result = ($this->qb_distinct === TRUE OR ! empty($this->qb_groupby))\n\t\t\t? $this->query($this->_count_string.$this->protect_identifiers('numrows').\"\\nFROM (\\n\".$this->_compile_select().\"\\n) CI_count_all_results\")\n\t\t\t: $this->query($this->_compile_select($this->_count_string.$this->protect_identifiers('numrows')));\n\n\t\tif ($reset === TRUE)\n\t\t{\n\t\t\t$this->_reset_select();\n\t\t}\n\t\t// If we've previously reset the qb_orderby values, get them back\n\t\telseif ( ! isset($this->qb_orderby))\n\t\t{\n\t\t\t$this->qb_orderby = $orderby;\n\t\t}\n\n\t\tif ($result->num_rows() === 0)\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\n\t\t$row = $result->row();\n\t\treturn (int) $row->numrows;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get_Where\n\t *\n\t * Allows the where clause, limit and offset to be added directly\n\t *\n\t * @param\tstring\t$table\n\t * @param\tstring\t$where\n\t * @param\tint\t$limit\n\t * @param\tint\t$offset\n\t * @return\tCI_DB_result\n\t */\n\tpublic function get_where($table = '', $where = NULL, $limit = NULL, $offset = NULL)\n\t{\n\t\tif ($table !== '')\n\t\t{\n\t\t\t$this->from($table);\n\t\t}\n\n\t\tif ($where !== NULL)\n\t\t{\n\t\t\t$this->where($where);\n\t\t}\n\n\t\tif ( ! empty($limit))\n\t\t{\n\t\t\t$this->limit($limit, $offset);\n\t\t}\n\n\t\t$result = $this->query($this->_compile_select());\n\t\t$this->_reset_select();\n\t\treturn $result;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert_Batch\n\t *\n\t * Compiles batch insert strings and runs the queries\n\t *\n\t * @param\tstring\t$table\tTable to insert into\n\t * @param\tarray\t$set \tAn associative array of insert values\n\t * @param\tbool\t$escape\tWhether to escape values and identifiers\n\t * @return\tint\tNumber of rows inserted or FALSE on failure\n\t */\n\tpublic function insert_batch($table, $set = NULL, $escape = NULL, $batch_size = 100)\n\t{\n\t\tif ($set === NULL)\n\t\t{\n\t\t\tif (empty($this->qb_set))\n\t\t\t{\n\t\t\t\treturn ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (empty($set))\n\t\t\t{\n\t\t\t\treturn ($this->db_debug) ? $this->display_error('insert_batch() called with no data') : FALSE;\n\t\t\t}\n\n\t\t\t$this->set_insert_batch($set, '', $escape);\n\t\t}\n\n\t\tif (strlen($table) === 0)\n\t\t{\n\t\t\tif ( ! isset($this->qb_from[0]))\n\t\t\t{\n\t\t\t\treturn ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;\n\t\t\t}\n\n\t\t\t$table = $this->qb_from[0];\n\t\t}\n\n\t\t// Batch this baby\n\t\t$affected_rows = 0;\n\t\tfor ($i = 0, $total = count($this->qb_set); $i < $total; $i += $batch_size)\n\t\t{\n\t\t\tif ($this->query($this->_insert_batch($this->protect_identifiers($table, TRUE, $escape, FALSE), $this->qb_keys, array_slice($this->qb_set, $i, $batch_size))))\n\t\t\t{\n\t\t\t\t$affected_rows += $this->affected_rows();\n\t\t\t}\n\t\t}\n\n\t\t$this->_reset_write();\n\t\treturn $affected_rows;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert batch statement\n\t *\n\t * Generates a platform-specific insert string from the supplied data.\n\t *\n\t * @param\tstring\t$table\tTable name\n\t * @param\tarray\t$keys\tINSERT keys\n\t * @param\tarray\t$values\tINSERT values\n\t * @return\tstring\n\t */\n\tprotected function _insert_batch($table, $keys, $values)\n\t{\n\t\treturn 'INSERT INTO '.$table.' ('.implode(', ', $keys).') VALUES '.implode(', ', $values);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * The \"set_insert_batch\" function.  Allows key/value pairs to be set for batch inserts\n\t *\n\t * @param\tmixed\n\t * @param\tstring\n\t * @param\tbool\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function set_insert_batch($key, $value = '', $escape = NULL)\n\t{\n\t\t$key = $this->_object_to_array_batch($key);\n\n\t\tif ( ! is_array($key))\n\t\t{\n\t\t\t$key = array($key => $value);\n\t\t}\n\n\t\tis_bool($escape) OR $escape = $this->_protect_identifiers;\n\n\t\t$keys = array_keys($this->_object_to_array(current($key)));\n\t\tsort($keys);\n\n\t\tforeach ($key as $row)\n\t\t{\n\t\t\t$row = $this->_object_to_array($row);\n\t\t\tif (count(array_diff($keys, array_keys($row))) > 0 OR count(array_diff(array_keys($row), $keys)) > 0)\n\t\t\t{\n\t\t\t\t// batch function above returns an error on an empty array\n\t\t\t\t$this->qb_set[] = array();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tksort($row); // puts $row in the same order as our keys\n\n\t\t\tif ($escape !== FALSE)\n\t\t\t{\n\t\t\t\t$clean = array();\n\t\t\t\tforeach ($row as $value)\n\t\t\t\t{\n\t\t\t\t\t$clean[] = $this->escape($value);\n\t\t\t\t}\n\n\t\t\t\t$row = $clean;\n\t\t\t}\n\n\t\t\t$this->qb_set[] = '('.implode(',', $row).')';\n\t\t}\n\n\t\tforeach ($keys as $k)\n\t\t{\n\t\t\t$this->qb_keys[] = $this->protect_identifiers($k, FALSE, $escape);\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get INSERT query string\n\t *\n\t * Compiles an insert query and returns the sql\n\t *\n\t * @param\tstring\tthe table to insert into\n\t * @param\tbool\tTRUE: reset QB values; FALSE: leave QB values alone\n\t * @return\tstring\n\t */\n\tpublic function get_compiled_insert($table = '', $reset = TRUE)\n\t{\n\t\tif ($this->_validate_insert($table) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$sql = $this->_insert(\n\t\t\t$this->protect_identifiers(\n\t\t\t\t$this->qb_from[0], TRUE, NULL, FALSE\n\t\t\t),\n\t\t\tarray_keys($this->qb_set),\n\t\t\tarray_values($this->qb_set)\n\t\t);\n\n\t\tif ($reset === TRUE)\n\t\t{\n\t\t\t$this->_reset_write();\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert\n\t *\n\t * Compiles an insert string and runs the query\n\t *\n\t * @param\tstring\tthe table to insert data into\n\t * @param\tarray\tan associative array of insert values\n\t * @param\tbool\t$escape\tWhether to escape values and identifiers\n\t * @return\tbool\tTRUE on success, FALSE on failure\n\t */\n\tpublic function insert($table = '', $set = NULL, $escape = NULL)\n\t{\n\t\tif ($set !== NULL)\n\t\t{\n\t\t\t$this->set($set, '', $escape);\n\t\t}\n\n\t\tif ($this->_validate_insert($table) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$sql = $this->_insert(\n\t\t\t$this->protect_identifiers(\n\t\t\t\t$this->qb_from[0], TRUE, $escape, FALSE\n\t\t\t),\n\t\t\tarray_keys($this->qb_set),\n\t\t\tarray_values($this->qb_set)\n\t\t);\n\n\t\t$this->_reset_write();\n\t\treturn $this->query($sql);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Validate Insert\n\t *\n\t * This method is used by both insert() and get_compiled_insert() to\n\t * validate that the there data is actually being set and that table\n\t * has been chosen to be inserted into.\n\t *\n\t * @param\tstring\tthe table to insert data into\n\t * @return\tstring\n\t */\n\tprotected function _validate_insert($table = '')\n\t{\n\t\tif (count($this->qb_set) === 0)\n\t\t{\n\t\t\treturn ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE;\n\t\t}\n\n\t\tif ($table !== '')\n\t\t{\n\t\t\t$this->qb_from[0] = $table;\n\t\t}\n\t\telseif ( ! isset($this->qb_from[0]))\n\t\t{\n\t\t\treturn ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Replace\n\t *\n\t * Compiles an replace into string and runs the query\n\t *\n\t * @param\tstring\tthe table to replace data into\n\t * @param\tarray\tan associative array of insert values\n\t * @return\tbool\tTRUE on success, FALSE on failure\n\t */\n\tpublic function replace($table = '', $set = NULL)\n\t{\n\t\tif ($set !== NULL)\n\t\t{\n\t\t\t$this->set($set);\n\t\t}\n\n\t\tif (count($this->qb_set) === 0)\n\t\t{\n\t\t\treturn ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE;\n\t\t}\n\n\t\tif ($table === '')\n\t\t{\n\t\t\tif ( ! isset($this->qb_from[0]))\n\t\t\t{\n\t\t\t\treturn ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;\n\t\t\t}\n\n\t\t\t$table = $this->qb_from[0];\n\t\t}\n\n\t\t$sql = $this->_replace($this->protect_identifiers($table, TRUE, NULL, FALSE), array_keys($this->qb_set), array_values($this->qb_set));\n\n\t\t$this->_reset_write();\n\t\treturn $this->query($sql);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Replace statement\n\t *\n\t * Generates a platform-specific replace string from the supplied data\n\t *\n\t * @param\tstring\tthe table name\n\t * @param\tarray\tthe insert keys\n\t * @param\tarray\tthe insert values\n\t * @return\tstring\n\t */\n\tprotected function _replace($table, $keys, $values)\n\t{\n\t\treturn 'REPLACE INTO '.$table.' ('.implode(', ', $keys).') VALUES ('.implode(', ', $values).')';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * FROM tables\n\t *\n\t * Groups tables in FROM clauses if needed, so there is no confusion\n\t * about operator precedence.\n\t *\n\t * Note: This is only used (and overridden) by MySQL and CUBRID.\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _from_tables()\n\t{\n\t\treturn implode(', ', $this->qb_from);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get UPDATE query string\n\t *\n\t * Compiles an update query and returns the sql\n\t *\n\t * @param\tstring\tthe table to update\n\t * @param\tbool\tTRUE: reset QB values; FALSE: leave QB values alone\n\t * @return\tstring\n\t */\n\tpublic function get_compiled_update($table = '', $reset = TRUE)\n\t{\n\t\t// Combine any cached components with the current statements\n\t\t$this->_merge_cache();\n\n\t\tif ($this->_validate_update($table) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$sql = $this->_update($this->qb_from[0], $this->qb_set);\n\n\t\tif ($reset === TRUE)\n\t\t{\n\t\t\t$this->_reset_write();\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * UPDATE\n\t *\n\t * Compiles an update string and runs the query.\n\t *\n\t * @param\tstring\t$table\n\t * @param\tarray\t$set\tAn associative array of update values\n\t * @param\tmixed\t$where\n\t * @param\tint\t$limit\n\t * @return\tbool\tTRUE on success, FALSE on failure\n\t */\n\tpublic function update($table = '', $set = NULL, $where = NULL, $limit = NULL)\n\t{\n\t\t// Combine any cached components with the current statements\n\t\t$this->_merge_cache();\n\n\t\tif ($set !== NULL)\n\t\t{\n\t\t\t$this->set($set);\n\t\t}\n\n\t\tif ($this->_validate_update($table) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ($where !== NULL)\n\t\t{\n\t\t\t$this->where($where);\n\t\t}\n\n\t\tif ( ! empty($limit))\n\t\t{\n\t\t\t$this->limit($limit);\n\t\t}\n\n\t\t$sql = $this->_update($this->qb_from[0], $this->qb_set);\n\t\t$this->_reset_write();\n\t\treturn $this->query($sql);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Validate Update\n\t *\n\t * This method is used by both update() and get_compiled_update() to\n\t * validate that data is actually being set and that a table has been\n\t * chosen to be update.\n\t *\n\t * @param\tstring\tthe table to update data on\n\t * @return\tbool\n\t */\n\tprotected function _validate_update($table)\n\t{\n\t\tif (count($this->qb_set) === 0)\n\t\t{\n\t\t\treturn ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE;\n\t\t}\n\n\t\tif ($table !== '')\n\t\t{\n\t\t\t$this->qb_from = array($this->protect_identifiers($table, TRUE, NULL, FALSE));\n\t\t}\n\t\telseif ( ! isset($this->qb_from[0]))\n\t\t{\n\t\t\treturn ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update_Batch\n\t *\n\t * Compiles an update string and runs the query\n\t *\n\t * @param\tstring\tthe table to retrieve the results from\n\t * @param\tarray\tan associative array of update values\n\t * @param\tstring\tthe where key\n\t * @return\tint\tnumber of rows affected or FALSE on failure\n\t */\n\tpublic function update_batch($table, $set = NULL, $index = NULL, $batch_size = 100)\n\t{\n\t\t// Combine any cached components with the current statements\n\t\t$this->_merge_cache();\n\n\t\tif ($index === NULL)\n\t\t{\n\t\t\treturn ($this->db_debug) ? $this->display_error('db_must_use_index') : FALSE;\n\t\t}\n\n\t\tif ($set === NULL)\n\t\t{\n\t\t\tif (empty($this->qb_set))\n\t\t\t{\n\t\t\t\treturn ($this->db_debug) ? $this->display_error('db_must_use_set') : FALSE;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (empty($set))\n\t\t\t{\n\t\t\t\treturn ($this->db_debug) ? $this->display_error('update_batch() called with no data') : FALSE;\n\t\t\t}\n\n\t\t\t$this->set_update_batch($set, $index);\n\t\t}\n\n\t\tif (strlen($table) === 0)\n\t\t{\n\t\t\tif ( ! isset($this->qb_from[0]))\n\t\t\t{\n\t\t\t\treturn ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;\n\t\t\t}\n\n\t\t\t$table = $this->qb_from[0];\n\t\t}\n\n\t\t// Batch this baby\n\t\t$affected_rows = 0;\n\t\tfor ($i = 0, $total = count($this->qb_set); $i < $total; $i += $batch_size)\n\t\t{\n\t\t\tif ($this->query($this->_update_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->qb_set, $i, $batch_size), $this->protect_identifiers($index))))\n\t\t\t{\n\t\t\t\t$affected_rows += $this->affected_rows();\n\t\t\t}\n\n\t\t\t$this->qb_where = array();\n\t\t}\n\n\t\t$this->_reset_write();\n\t\treturn $affected_rows;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update_Batch statement\n\t *\n\t * Generates a platform-specific batch update string from the supplied data\n\t *\n\t * @param\tstring\t$table\tTable name\n\t * @param\tarray\t$values\tUpdate data\n\t * @param\tstring\t$index\tWHERE key\n\t * @return\tstring\n\t */\n\tprotected function _update_batch($table, $values, $index)\n\t{\n\t\t$ids = array();\n\t\tforeach ($values as $key => $val)\n\t\t{\n\t\t\t$ids[] = $val[$index];\n\n\t\t\tforeach (array_keys($val) as $field)\n\t\t\t{\n\t\t\t\tif ($field !== $index)\n\t\t\t\t{\n\t\t\t\t\t$final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$cases = '';\n\t\tforeach ($final as $k => $v)\n\t\t{\n\t\t\t$cases .= $k.\" = CASE \\n\"\n\t\t\t\t.implode(\"\\n\", $v).\"\\n\"\n\t\t\t\t.'ELSE '.$k.' END, ';\n\t\t}\n\n\t\t$this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);\n\n\t\treturn 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * The \"set_update_batch\" function.  Allows key/value pairs to be set for batch updating\n\t *\n\t * @param\tarray\n\t * @param\tstring\n\t * @param\tbool\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function set_update_batch($key, $index = '', $escape = NULL)\n\t{\n\t\t$key = $this->_object_to_array_batch($key);\n\n\t\tif ( ! is_array($key))\n\t\t{\n\t\t\t// @todo error\n\t\t}\n\n\t\tis_bool($escape) OR $escape = $this->_protect_identifiers;\n\n\t\tforeach ($key as $k => $v)\n\t\t{\n\t\t\t$index_set = FALSE;\n\t\t\t$clean = array();\n\t\t\tforeach ($v as $k2 => $v2)\n\t\t\t{\n\t\t\t\tif ($k2 === $index)\n\t\t\t\t{\n\t\t\t\t\t$index_set = TRUE;\n\t\t\t\t}\n\n\t\t\t\t$clean[$this->protect_identifiers($k2, FALSE, $escape)] = ($escape === FALSE) ? $v2 : $this->escape($v2);\n\t\t\t}\n\n\t\t\tif ($index_set === FALSE)\n\t\t\t{\n\t\t\t\treturn $this->display_error('db_batch_missing_index');\n\t\t\t}\n\n\t\t\t$this->qb_set[] = $clean;\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Empty Table\n\t *\n\t * Compiles a delete string and runs \"DELETE FROM table\"\n\t *\n\t * @param\tstring\tthe table to empty\n\t * @return\tbool\tTRUE on success, FALSE on failure\n\t */\n\tpublic function empty_table($table = '')\n\t{\n\t\tif ($table === '')\n\t\t{\n\t\t\tif ( ! isset($this->qb_from[0]))\n\t\t\t{\n\t\t\t\treturn ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;\n\t\t\t}\n\n\t\t\t$table = $this->qb_from[0];\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$table = $this->protect_identifiers($table, TRUE, NULL, FALSE);\n\t\t}\n\n\t\t$sql = $this->_delete($table);\n\t\t$this->_reset_write();\n\t\treturn $this->query($sql);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Truncate\n\t *\n\t * Compiles a truncate string and runs the query\n\t * If the database does not support the truncate() command\n\t * This function maps to \"DELETE FROM table\"\n\t *\n\t * @param\tstring\tthe table to truncate\n\t * @return\tbool\tTRUE on success, FALSE on failure\n\t */\n\tpublic function truncate($table = '')\n\t{\n\t\tif ($table === '')\n\t\t{\n\t\t\tif ( ! isset($this->qb_from[0]))\n\t\t\t{\n\t\t\t\treturn ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;\n\t\t\t}\n\n\t\t\t$table = $this->qb_from[0];\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$table = $this->protect_identifiers($table, TRUE, NULL, FALSE);\n\t\t}\n\n\t\t$sql = $this->_truncate($table);\n\t\t$this->_reset_write();\n\t\treturn $this->query($sql);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Truncate statement\n\t *\n\t * Generates a platform-specific truncate string from the supplied data\n\t *\n\t * If the database does not support the truncate() command,\n\t * then this method maps to 'DELETE FROM table'\n\t *\n\t * @param\tstring\tthe table name\n\t * @return\tstring\n\t */\n\tprotected function _truncate($table)\n\t{\n\t\treturn 'TRUNCATE '.$table;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get DELETE query string\n\t *\n\t * Compiles a delete query string and returns the sql\n\t *\n\t * @param\tstring\tthe table to delete from\n\t * @param\tbool\tTRUE: reset QB values; FALSE: leave QB values alone\n\t * @return\tstring\n\t */\n\tpublic function get_compiled_delete($table = '', $reset = TRUE)\n\t{\n\t\t$this->return_delete_sql = TRUE;\n\t\t$sql = $this->delete($table, '', NULL, $reset);\n\t\t$this->return_delete_sql = FALSE;\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Delete\n\t *\n\t * Compiles a delete string and runs the query\n\t *\n\t * @param\tmixed\tthe table(s) to delete from. String or array\n\t * @param\tmixed\tthe where clause\n\t * @param\tmixed\tthe limit clause\n\t * @param\tbool\n\t * @return\tmixed\n\t */\n\tpublic function delete($table = '', $where = '', $limit = NULL, $reset_data = TRUE)\n\t{\n\t\t// Combine any cached components with the current statements\n\t\t$this->_merge_cache();\n\n\t\tif ($table === '')\n\t\t{\n\t\t\tif ( ! isset($this->qb_from[0]))\n\t\t\t{\n\t\t\t\treturn ($this->db_debug) ? $this->display_error('db_must_set_table') : FALSE;\n\t\t\t}\n\n\t\t\t$table = $this->qb_from[0];\n\t\t}\n\t\telseif (is_array($table))\n\t\t{\n\t\t\tempty($where) && $reset_data = FALSE;\n\n\t\t\tforeach ($table as $single_table)\n\t\t\t{\n\t\t\t\t$this->delete($single_table, $where, $limit, $reset_data);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$table = $this->protect_identifiers($table, TRUE, NULL, FALSE);\n\t\t}\n\n\t\tif ($where !== '')\n\t\t{\n\t\t\t$this->where($where);\n\t\t}\n\n\t\tif ( ! empty($limit))\n\t\t{\n\t\t\t$this->limit($limit);\n\t\t}\n\n\t\tif (count($this->qb_where) === 0)\n\t\t{\n\t\t\treturn ($this->db_debug) ? $this->display_error('db_del_must_use_where') : FALSE;\n\t\t}\n\n\t\t$sql = $this->_delete($table);\n\t\tif ($reset_data)\n\t\t{\n\t\t\t$this->_reset_write();\n\t\t}\n\n\t\treturn ($this->return_delete_sql === TRUE) ? $sql : $this->query($sql);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Delete statement\n\t *\n\t * Generates a platform-specific delete string from the supplied data\n\t *\n\t * @param\tstring\tthe table name\n\t * @return\tstring\n\t */\n\tprotected function _delete($table)\n\t{\n\t\treturn 'DELETE FROM '.$table.$this->_compile_wh('qb_where')\n\t\t\t.($this->qb_limit ? ' LIMIT '.$this->qb_limit : '');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * DB Prefix\n\t *\n\t * Prepends a database prefix if one exists in configuration\n\t *\n\t * @param\tstring\tthe table\n\t * @return\tstring\n\t */\n\tpublic function dbprefix($table = '')\n\t{\n\t\tif ($table === '')\n\t\t{\n\t\t\t$this->display_error('db_table_name_required');\n\t\t}\n\n\t\treturn $this->dbprefix.$table;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set DB Prefix\n\t *\n\t * Set's the DB Prefix to something new without needing to reconnect\n\t *\n\t * @param\tstring\tthe prefix\n\t * @return\tstring\n\t */\n\tpublic function set_dbprefix($prefix = '')\n\t{\n\t\treturn $this->dbprefix = $prefix;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Track Aliases\n\t *\n\t * Used to track SQL statements written with aliased tables.\n\t *\n\t * @param\tstring\tThe table to inspect\n\t * @return\tstring\n\t */\n\tprotected function _track_aliases($table)\n\t{\n\t\tif (is_array($table))\n\t\t{\n\t\t\tforeach ($table as $t)\n\t\t\t{\n\t\t\t\t$this->_track_aliases($t);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Does the string contain a comma?  If so, we need to separate\n\t\t// the string into discreet statements\n\t\tif (strpos($table, ',') !== FALSE)\n\t\t{\n\t\t\treturn $this->_track_aliases(explode(',', $table));\n\t\t}\n\n\t\t// if a table alias is used we can recognize it by a space\n\t\tif (strpos($table, ' ') !== FALSE)\n\t\t{\n\t\t\t// if the alias is written with the AS keyword, remove it\n\t\t\t$table = preg_replace('/\\s+AS\\s+/i', ' ', $table);\n\n\t\t\t// Grab the alias\n\t\t\t$table = trim(strrchr($table, ' '));\n\n\t\t\t// Store the alias, if it doesn't already exist\n\t\t\tif ( ! in_array($table, $this->qb_aliased_tables))\n\t\t\t{\n\t\t\t\t$this->qb_aliased_tables[] = $table;\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile the SELECT statement\n\t *\n\t * Generates a query string based on which functions were used.\n\t * Should not be called directly.\n\t *\n\t * @param\tbool\t$select_override\n\t * @return\tstring\n\t */\n\tprotected function _compile_select($select_override = FALSE)\n\t{\n\t\t// Combine any cached components with the current statements\n\t\t$this->_merge_cache();\n\n\t\t// Write the \"select\" portion of the query\n\t\tif ($select_override !== FALSE)\n\t\t{\n\t\t\t$sql = $select_override;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$sql = ( ! $this->qb_distinct) ? 'SELECT ' : 'SELECT DISTINCT ';\n\n\t\t\tif (count($this->qb_select) === 0)\n\t\t\t{\n\t\t\t\t$sql .= '*';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Cycle through the \"select\" portion of the query and prep each column name.\n\t\t\t\t// The reason we protect identifiers here rather than in the select() function\n\t\t\t\t// is because until the user calls the from() function we don't know if there are aliases\n\t\t\t\tforeach ($this->qb_select as $key => $val)\n\t\t\t\t{\n\t\t\t\t\t$no_escape = isset($this->qb_no_escape[$key]) ? $this->qb_no_escape[$key] : NULL;\n\t\t\t\t\t$this->qb_select[$key] = $this->protect_identifiers($val, FALSE, $no_escape);\n\t\t\t\t}\n\n\t\t\t\t$sql .= implode(', ', $this->qb_select);\n\t\t\t}\n\t\t}\n\n\t\t// Write the \"FROM\" portion of the query\n\t\tif (count($this->qb_from) > 0)\n\t\t{\n\t\t\t$sql .= \"\\nFROM \".$this->_from_tables();\n\t\t}\n\n\t\t// Write the \"JOIN\" portion of the query\n\t\tif (count($this->qb_join) > 0)\n\t\t{\n\t\t\t$sql .= \"\\n\".implode(\"\\n\", $this->qb_join);\n\t\t}\n\n\t\t$sql .= $this->_compile_wh('qb_where')\n\t\t\t.$this->_compile_group_by()\n\t\t\t.$this->_compile_wh('qb_having')\n\t\t\t.$this->_compile_order_by(); // ORDER BY\n\n\t\t// LIMIT\n\t\tif ($this->qb_limit)\n\t\t{\n\t\t\treturn $this->_limit($sql.\"\\n\");\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile WHERE, HAVING statements\n\t *\n\t * Escapes identifiers in WHERE and HAVING statements at execution time.\n\t *\n\t * Required so that aliases are tracked properly, regardless of whether\n\t * where(), or_where(), having(), or_having are called prior to from(),\n\t * join() and dbprefix is added only if needed.\n\t *\n\t * @param\tstring\t$qb_key\t'qb_where' or 'qb_having'\n\t * @return\tstring\tSQL statement\n\t */\n\tprotected function _compile_wh($qb_key)\n\t{\n\t\tif (count($this->$qb_key) > 0)\n\t\t{\n\t\t\tfor ($i = 0, $c = count($this->$qb_key); $i < $c; $i++)\n\t\t\t{\n\t\t\t\t// Is this condition already compiled?\n\t\t\t\tif (is_string($this->{$qb_key}[$i]))\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telseif ($this->{$qb_key}[$i]['escape'] === FALSE)\n\t\t\t\t{\n\t\t\t\t\t$this->{$qb_key}[$i] = $this->{$qb_key}[$i]['condition'];\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Split multiple conditions\n\t\t\t\t$conditions = preg_split(\n\t\t\t\t\t'/((?:^|\\s+)AND\\s+|(?:^|\\s+)OR\\s+)/i',\n\t\t\t\t\t$this->{$qb_key}[$i]['condition'],\n\t\t\t\t\t-1,\n\t\t\t\t\tPREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY\n\t\t\t\t);\n\n\t\t\t\tfor ($ci = 0, $cc = count($conditions); $ci < $cc; $ci++)\n\t\t\t\t{\n\t\t\t\t\tif (($op = $this->_get_operator($conditions[$ci])) === FALSE\n\t\t\t\t\t\tOR ! preg_match('/^(\\(?)(.*)('.preg_quote($op, '/').')\\s*(.*(?<!\\)))?(\\)?)$/i', $conditions[$ci], $matches))\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t// $matches = array(\n\t\t\t\t\t//\t0 => '(test <= foo)',\t/* the whole thing */\n\t\t\t\t\t//\t1 => '(',\t\t/* optional */\n\t\t\t\t\t//\t2 => 'test',\t\t/* the field name */\n\t\t\t\t\t//\t3 => ' <= ',\t\t/* $op */\n\t\t\t\t\t//\t4 => 'foo',\t\t/* optional, if $op is e.g. 'IS NULL' */\n\t\t\t\t\t//\t5 => ')'\t\t/* optional */\n\t\t\t\t\t// );\n\n\t\t\t\t\tif ( ! empty($matches[4]))\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->_is_literal($matches[4]) OR $matches[4] = $this->protect_identifiers(trim($matches[4]));\n\t\t\t\t\t\t$matches[4] = ' '.$matches[4];\n\t\t\t\t\t}\n\n\t\t\t\t\t$conditions[$ci] = $matches[1].$this->protect_identifiers(trim($matches[2]))\n\t\t\t\t\t\t.' '.trim($matches[3]).$matches[4].$matches[5];\n\t\t\t\t}\n\n\t\t\t\t$this->{$qb_key}[$i] = implode('', $conditions);\n\t\t\t}\n\n\t\t\treturn ($qb_key === 'qb_having' ? \"\\nHAVING \" : \"\\nWHERE \")\n\t\t\t\t.implode(\"\\n\", $this->$qb_key);\n\t\t}\n\n\t\treturn '';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile GROUP BY\n\t *\n\t * Escapes identifiers in GROUP BY statements at execution time.\n\t *\n\t * Required so that aliases are tracked properly, regardless of wether\n\t * group_by() is called prior to from(), join() and dbprefix is added\n\t * only if needed.\n\t *\n\t * @return\tstring\tSQL statement\n\t */\n\tprotected function _compile_group_by()\n\t{\n\t\tif (count($this->qb_groupby) > 0)\n\t\t{\n\t\t\tfor ($i = 0, $c = count($this->qb_groupby); $i < $c; $i++)\n\t\t\t{\n\t\t\t\t// Is it already compiled?\n\t\t\t\tif (is_string($this->qb_groupby[$i]))\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t$this->qb_groupby[$i] = ($this->qb_groupby[$i]['escape'] === FALSE OR $this->_is_literal($this->qb_groupby[$i]['field']))\n\t\t\t\t\t? $this->qb_groupby[$i]['field']\n\t\t\t\t\t: $this->protect_identifiers($this->qb_groupby[$i]['field']);\n\t\t\t}\n\n\t\t\treturn \"\\nGROUP BY \".implode(', ', $this->qb_groupby);\n\t\t}\n\n\t\treturn '';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile ORDER BY\n\t *\n\t * Escapes identifiers in ORDER BY statements at execution time.\n\t *\n\t * Required so that aliases are tracked properly, regardless of wether\n\t * order_by() is called prior to from(), join() and dbprefix is added\n\t * only if needed.\n\t *\n\t * @return\tstring\tSQL statement\n\t */\n\tprotected function _compile_order_by()\n\t{\n\t\tif (is_array($this->qb_orderby) && count($this->qb_orderby) > 0)\n\t\t{\n\t\t\tfor ($i = 0, $c = count($this->qb_orderby); $i < $c; $i++)\n\t\t\t{\n\t\t\t\tif ($this->qb_orderby[$i]['escape'] !== FALSE && ! $this->_is_literal($this->qb_orderby[$i]['field']))\n\t\t\t\t{\n\t\t\t\t\t$this->qb_orderby[$i]['field'] = $this->protect_identifiers($this->qb_orderby[$i]['field']);\n\t\t\t\t}\n\n\t\t\t\t$this->qb_orderby[$i] = $this->qb_orderby[$i]['field'].$this->qb_orderby[$i]['direction'];\n\t\t\t}\n\n\t\t\treturn $this->qb_orderby = \"\\nORDER BY \".implode(', ', $this->qb_orderby);\n\t\t}\n\t\telseif (is_string($this->qb_orderby))\n\t\t{\n\t\t\treturn $this->qb_orderby;\n\t\t}\n\n\t\treturn '';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Object to Array\n\t *\n\t * Takes an object as input and converts the class variables to array key/vals\n\t *\n\t * @param\tobject\n\t * @return\tarray\n\t */\n\tprotected function _object_to_array($object)\n\t{\n\t\tif ( ! is_object($object))\n\t\t{\n\t\t\treturn $object;\n\t\t}\n\n\t\t$array = array();\n\t\tforeach (get_object_vars($object) as $key => $val)\n\t\t{\n\t\t\t// There are some built in keys we need to ignore for this conversion\n\t\t\tif ( ! is_object($val) && ! is_array($val) && $key !== '_parent_name')\n\t\t\t{\n\t\t\t\t$array[$key] = $val;\n\t\t\t}\n\t\t}\n\n\t\treturn $array;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Object to Array\n\t *\n\t * Takes an object as input and converts the class variables to array key/vals\n\t *\n\t * @param\tobject\n\t * @return\tarray\n\t */\n\tprotected function _object_to_array_batch($object)\n\t{\n\t\tif ( ! is_object($object))\n\t\t{\n\t\t\treturn $object;\n\t\t}\n\n\t\t$array = array();\n\t\t$out = get_object_vars($object);\n\t\t$fields = array_keys($out);\n\n\t\tforeach ($fields as $val)\n\t\t{\n\t\t\t// There are some built in keys we need to ignore for this conversion\n\t\t\tif ($val !== '_parent_name')\n\t\t\t{\n\t\t\t\t$i = 0;\n\t\t\t\tforeach ($out[$val] as $data)\n\t\t\t\t{\n\t\t\t\t\t$array[$i++][$val] = $data;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn $array;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Start Cache\n\t *\n\t * Starts QB caching\n\t *\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function start_cache()\n\t{\n\t\t$this->qb_caching = TRUE;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Stop Cache\n\t *\n\t * Stops QB caching\n\t *\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function stop_cache()\n\t{\n\t\t$this->qb_caching = FALSE;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Flush Cache\n\t *\n\t * Empties the QB cache\n\t *\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function flush_cache()\n\t{\n\t\t$this->_reset_run(array(\n\t\t\t'qb_cache_select'\t\t=> array(),\n\t\t\t'qb_cache_from'\t\t\t=> array(),\n\t\t\t'qb_cache_join'\t\t\t=> array(),\n\t\t\t'qb_cache_where'\t\t=> array(),\n\t\t\t'qb_cache_groupby'\t\t=> array(),\n\t\t\t'qb_cache_having'\t\t=> array(),\n\t\t\t'qb_cache_orderby'\t\t=> array(),\n\t\t\t'qb_cache_set'\t\t\t=> array(),\n\t\t\t'qb_cache_exists'\t\t=> array(),\n\t\t\t'qb_cache_no_escape'\t=> array()\n\t\t));\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Merge Cache\n\t *\n\t * When called, this function merges any cached QB arrays with\n\t * locally called ones.\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _merge_cache()\n\t{\n\t\tif (count($this->qb_cache_exists) === 0)\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\telseif (in_array('select', $this->qb_cache_exists, TRUE))\n\t\t{\n\t\t\t$qb_no_escape = $this->qb_cache_no_escape;\n\t\t}\n\n\t\tforeach (array_unique($this->qb_cache_exists) as $val) // select, from, etc.\n\t\t{\n\t\t\t$qb_variable\t= 'qb_'.$val;\n\t\t\t$qb_cache_var\t= 'qb_cache_'.$val;\n\t\t\t$qb_new \t= $this->$qb_cache_var;\n\n\t\t\tfor ($i = 0, $c = count($this->$qb_variable); $i < $c; $i++)\n\t\t\t{\n\t\t\t\tif ( ! in_array($this->{$qb_variable}[$i], $qb_new, TRUE))\n\t\t\t\t{\n\t\t\t\t\t$qb_new[] = $this->{$qb_variable}[$i];\n\t\t\t\t\tif ($val === 'select')\n\t\t\t\t\t{\n\t\t\t\t\t\t$qb_no_escape[] = $this->qb_no_escape[$i];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$this->$qb_variable = $qb_new;\n\t\t\tif ($val === 'select')\n\t\t\t{\n\t\t\t\t$this->qb_no_escape = $qb_no_escape;\n\t\t\t}\n\t\t}\n\n\t\t// If we are \"protecting identifiers\" we need to examine the \"from\"\n\t\t// portion of the query to determine if there are any aliases\n\t\tif ($this->_protect_identifiers === TRUE && count($this->qb_cache_from) > 0)\n\t\t{\n\t\t\t$this->_track_aliases($this->qb_from);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is literal\n\t *\n\t * Determines if a string represents a literal value or a field name\n\t *\n\t * @param\tstring\t$str\n\t * @return\tbool\n\t */\n\tprotected function _is_literal($str)\n\t{\n\t\t$str = trim($str);\n\n\t\tif (empty($str) OR ctype_digit($str) OR (string) (float) $str === $str OR in_array(strtoupper($str), array('TRUE', 'FALSE'), TRUE))\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\tstatic $_str;\n\n\t\tif (empty($_str))\n\t\t{\n\t\t\t$_str = ($this->_escape_char !== '\"')\n\t\t\t\t? array('\"', \"'\") : array(\"'\");\n\t\t}\n\n\t\treturn in_array($str[0], $_str, TRUE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Reset Query Builder values.\n\t *\n\t * Publicly-visible method to reset the QB values.\n\t *\n\t * @return\tCI_DB_query_builder\n\t */\n\tpublic function reset_query()\n\t{\n\t\t$this->_reset_select();\n\t\t$this->_reset_write();\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Resets the query builder values.  Called by the get() function\n\t *\n\t * @param\tarray\tAn array of fields to reset\n\t * @return\tvoid\n\t */\n\tprotected function _reset_run($qb_reset_items)\n\t{\n\t\tforeach ($qb_reset_items as $item => $default_value)\n\t\t{\n\t\t\t$this->$item = $default_value;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Resets the query builder values.  Called by the get() function\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _reset_select()\n\t{\n\t\t$this->_reset_run(array(\n\t\t\t'qb_select'\t\t=> array(),\n\t\t\t'qb_from'\t\t=> array(),\n\t\t\t'qb_join'\t\t=> array(),\n\t\t\t'qb_where'\t\t=> array(),\n\t\t\t'qb_groupby'\t\t=> array(),\n\t\t\t'qb_having'\t\t=> array(),\n\t\t\t'qb_orderby'\t\t=> array(),\n\t\t\t'qb_aliased_tables'\t=> array(),\n\t\t\t'qb_no_escape'\t\t=> array(),\n\t\t\t'qb_distinct'\t\t=> FALSE,\n\t\t\t'qb_limit'\t\t=> FALSE,\n\t\t\t'qb_offset'\t\t=> FALSE\n\t\t));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Resets the query builder \"write\" values.\n\t *\n\t * Called by the insert() update() insert_batch() update_batch() and delete() functions\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _reset_write()\n\t{\n\t\t$this->_reset_run(array(\n\t\t\t'qb_set'\t=> array(),\n\t\t\t'qb_from'\t=> array(),\n\t\t\t'qb_join'\t=> array(),\n\t\t\t'qb_where'\t=> array(),\n\t\t\t'qb_orderby'\t=> array(),\n\t\t\t'qb_keys'\t=> array(),\n\t\t\t'qb_limit'\t=> FALSE\n\t\t));\n\t}\n\n}\n"
  },
  {
    "path": "system/database/DB_result.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Database Result Class\n *\n * This is the platform-independent result class.\n * This class will not be called directly. Rather, the adapter\n * class for the specific database will extend and instantiate it.\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_result {\n\n\t/**\n\t * Connection ID\n\t *\n\t * @var\tresource|object\n\t */\n\tpublic $conn_id;\n\n\t/**\n\t * Result ID\n\t *\n\t * @var\tresource|object\n\t */\n\tpublic $result_id;\n\n\t/**\n\t * Result Array\n\t *\n\t * @var\tarray[]\n\t */\n\tpublic $result_array\t\t\t= array();\n\n\t/**\n\t * Result Object\n\t *\n\t * @var\tobject[]\n\t */\n\tpublic $result_object\t\t\t= array();\n\n\t/**\n\t * Custom Result Object\n\t *\n\t * @var\tobject[]\n\t */\n\tpublic $custom_result_object\t\t= array();\n\n\t/**\n\t * Current Row index\n\t *\n\t * @var\tint\n\t */\n\tpublic $current_row\t\t\t= 0;\n\n\t/**\n\t * Number of rows\n\t *\n\t * @var\tint\n\t */\n\tpublic $num_rows;\n\n\t/**\n\t * Row data\n\t *\n\t * @var\tarray\n\t */\n\tpublic $row_data;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @param\tobject\t$driver_object\n\t * @return\tvoid\n\t */\n\tpublic function __construct(&$driver_object)\n\t{\n\t\t$this->conn_id = $driver_object->conn_id;\n\t\t$this->result_id = $driver_object->result_id;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Number of rows in the result set\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_rows()\n\t{\n\t\tif (is_int($this->num_rows))\n\t\t{\n\t\t\treturn $this->num_rows;\n\t\t}\n\t\telseif (count($this->result_array) > 0)\n\t\t{\n\t\t\treturn $this->num_rows = count($this->result_array);\n\t\t}\n\t\telseif (count($this->result_object) > 0)\n\t\t{\n\t\t\treturn $this->num_rows = count($this->result_object);\n\t\t}\n\n\t\treturn $this->num_rows = count($this->result_array());\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Query result. Acts as a wrapper function for the following functions.\n\t *\n\t * @param\tstring\t$type\t'object', 'array' or a custom class name\n\t * @return\tarray\n\t */\n\tpublic function result($type = 'object')\n\t{\n\t\tif ($type === 'array')\n\t\t{\n\t\t\treturn $this->result_array();\n\t\t}\n\t\telseif ($type === 'object')\n\t\t{\n\t\t\treturn $this->result_object();\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn $this->custom_result_object($type);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Custom query result.\n\t *\n\t * @param\tstring\t$class_name\n\t * @return\tarray\n\t */\n\tpublic function custom_result_object($class_name)\n\t{\n\t\tif (isset($this->custom_result_object[$class_name]))\n\t\t{\n\t\t\treturn $this->custom_result_object[$class_name];\n\t\t}\n\t\telseif ( ! $this->result_id OR $this->num_rows === 0)\n\t\t{\n\t\t\treturn array();\n\t\t}\n\n\t\t// Don't fetch the result set again if we already have it\n\t\t$_data = NULL;\n\t\tif (($c = count($this->result_array)) > 0)\n\t\t{\n\t\t\t$_data = 'result_array';\n\t\t}\n\t\telseif (($c = count($this->result_object)) > 0)\n\t\t{\n\t\t\t$_data = 'result_object';\n\t\t}\n\n\t\tif ($_data !== NULL)\n\t\t{\n\t\t\tfor ($i = 0; $i < $c; $i++)\n\t\t\t{\n\t\t\t\t$this->custom_result_object[$class_name][$i] = new $class_name();\n\n\t\t\t\tforeach ($this->{$_data}[$i] as $key => $value)\n\t\t\t\t{\n\t\t\t\t\t$this->custom_result_object[$class_name][$i]->$key = $value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn $this->custom_result_object[$class_name];\n\t\t}\n\n\t\tis_null($this->row_data) OR $this->data_seek(0);\n\t\t$this->custom_result_object[$class_name] = array();\n\n\t\twhile ($row = $this->_fetch_object($class_name))\n\t\t{\n\t\t\t$this->custom_result_object[$class_name][] = $row;\n\t\t}\n\n\t\treturn $this->custom_result_object[$class_name];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Query result. \"object\" version.\n\t *\n\t * @return\tarray\n\t */\n\tpublic function result_object()\n\t{\n\t\tif (count($this->result_object) > 0)\n\t\t{\n\t\t\treturn $this->result_object;\n\t\t}\n\n\t\t// In the event that query caching is on, the result_id variable\n\t\t// will not be a valid resource so we'll simply return an empty\n\t\t// array.\n\t\tif ( ! $this->result_id OR $this->num_rows === 0)\n\t\t{\n\t\t\treturn array();\n\t\t}\n\n\t\tif (($c = count($this->result_array)) > 0)\n\t\t{\n\t\t\tfor ($i = 0; $i < $c; $i++)\n\t\t\t{\n\t\t\t\t$this->result_object[$i] = (object) $this->result_array[$i];\n\t\t\t}\n\n\t\t\treturn $this->result_object;\n\t\t}\n\n\t\tis_null($this->row_data) OR $this->data_seek(0);\n\t\twhile ($row = $this->_fetch_object())\n\t\t{\n\t\t\t$this->result_object[] = $row;\n\t\t}\n\n\t\treturn $this->result_object;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Query result. \"array\" version.\n\t *\n\t * @return\tarray\n\t */\n\tpublic function result_array()\n\t{\n\t\tif (count($this->result_array) > 0)\n\t\t{\n\t\t\treturn $this->result_array;\n\t\t}\n\n\t\t// In the event that query caching is on, the result_id variable\n\t\t// will not be a valid resource so we'll simply return an empty\n\t\t// array.\n\t\tif ( ! $this->result_id OR $this->num_rows === 0)\n\t\t{\n\t\t\treturn array();\n\t\t}\n\n\t\tif (($c = count($this->result_object)) > 0)\n\t\t{\n\t\t\tfor ($i = 0; $i < $c; $i++)\n\t\t\t{\n\t\t\t\t$this->result_array[$i] = (array) $this->result_object[$i];\n\t\t\t}\n\n\t\t\treturn $this->result_array;\n\t\t}\n\n\t\tis_null($this->row_data) OR $this->data_seek(0);\n\t\twhile ($row = $this->_fetch_assoc())\n\t\t{\n\t\t\t$this->result_array[] = $row;\n\t\t}\n\n\t\treturn $this->result_array;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Row\n\t *\n\t * A wrapper method.\n\t *\n\t * @param\tmixed\t$n\n\t * @param\tstring\t$type\t'object' or 'array'\n\t * @return\tmixed\n\t */\n\tpublic function row($n = 0, $type = 'object')\n\t{\n\t\tif ( ! is_numeric($n))\n\t\t{\n\t\t\t// We cache the row data for subsequent uses\n\t\t\tis_array($this->row_data) OR $this->row_data = $this->row_array(0);\n\n\t\t\t// array_key_exists() instead of isset() to allow for NULL values\n\t\t\tif (empty($this->row_data) OR ! array_key_exists($n, $this->row_data))\n\t\t\t{\n\t\t\t\treturn NULL;\n\t\t\t}\n\n\t\t\treturn $this->row_data[$n];\n\t\t}\n\n\t\tif ($type === 'object') return $this->row_object($n);\n\t\telseif ($type === 'array') return $this->row_array($n);\n\t\telse return $this->custom_row_object($n, $type);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Assigns an item into a particular column slot\n\t *\n\t * @param\tmixed\t$key\n\t * @param\tmixed\t$value\n\t * @return\tvoid\n\t */\n\tpublic function set_row($key, $value = NULL)\n\t{\n\t\t// We cache the row data for subsequent uses\n\t\tif ( ! is_array($this->row_data))\n\t\t{\n\t\t\t$this->row_data = $this->row_array(0);\n\t\t}\n\n\t\tif (is_array($key))\n\t\t{\n\t\t\tforeach ($key as $k => $v)\n\t\t\t{\n\t\t\t\t$this->row_data[$k] = $v;\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tif ($key !== '' && $value !== NULL)\n\t\t{\n\t\t\t$this->row_data[$key] = $value;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns a single result row - custom object version\n\t *\n\t * @param\tint\t$n\n\t * @param\tstring\t$type\n\t * @return\tobject\n\t */\n\tpublic function custom_row_object($n, $type)\n\t{\n\t\tisset($this->custom_result_object[$type]) OR $this->custom_result_object($type);\n\n\t\tif (count($this->custom_result_object[$type]) === 0)\n\t\t{\n\t\t\treturn NULL;\n\t\t}\n\n\t\tif ($n !== $this->current_row && isset($this->custom_result_object[$type][$n]))\n\t\t{\n\t\t\t$this->current_row = $n;\n\t\t}\n\n\t\treturn $this->custom_result_object[$type][$this->current_row];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns a single result row - object version\n\t *\n\t * @param\tint\t$n\n\t * @return\tobject\n\t */\n\tpublic function row_object($n = 0)\n\t{\n\t\t$result = $this->result_object();\n\t\tif (count($result) === 0)\n\t\t{\n\t\t\treturn NULL;\n\t\t}\n\n\t\tif ($n !== $this->current_row && isset($result[$n]))\n\t\t{\n\t\t\t$this->current_row = $n;\n\t\t}\n\n\t\treturn $result[$this->current_row];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns a single result row - array version\n\t *\n\t * @param\tint\t$n\n\t * @return\tarray\n\t */\n\tpublic function row_array($n = 0)\n\t{\n\t\t$result = $this->result_array();\n\t\tif (count($result) === 0)\n\t\t{\n\t\t\treturn NULL;\n\t\t}\n\n\t\tif ($n !== $this->current_row && isset($result[$n]))\n\t\t{\n\t\t\t$this->current_row = $n;\n\t\t}\n\n\t\treturn $result[$this->current_row];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns the \"first\" row\n\t *\n\t * @param\tstring\t$type\n\t * @return\tmixed\n\t */\n\tpublic function first_row($type = 'object')\n\t{\n\t\t$result = $this->result($type);\n\t\treturn (count($result) === 0) ? NULL : $result[0];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns the \"last\" row\n\t *\n\t * @param\tstring\t$type\n\t * @return\tmixed\n\t */\n\tpublic function last_row($type = 'object')\n\t{\n\t\t$result = $this->result($type);\n\t\treturn (count($result) === 0) ? NULL : $result[count($result) - 1];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns the \"next\" row\n\t *\n\t * @param\tstring\t$type\n\t * @return\tmixed\n\t */\n\tpublic function next_row($type = 'object')\n\t{\n\t\t$result = $this->result($type);\n\t\tif (count($result) === 0)\n\t\t{\n\t\t\treturn NULL;\n\t\t}\n\n\t\treturn isset($result[$this->current_row + 1])\n\t\t\t? $result[++$this->current_row]\n\t\t\t: NULL;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns the \"previous\" row\n\t *\n\t * @param\tstring\t$type\n\t * @return\tmixed\n\t */\n\tpublic function previous_row($type = 'object')\n\t{\n\t\t$result = $this->result($type);\n\t\tif (count($result) === 0)\n\t\t{\n\t\t\treturn NULL;\n\t\t}\n\n\t\tif (isset($result[$this->current_row - 1]))\n\t\t{\n\t\t\t--$this->current_row;\n\t\t}\n\t\treturn $result[$this->current_row];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an unbuffered row and move pointer to next row\n\t *\n\t * @param\tstring\t$type\t'array', 'object' or a custom class name\n\t * @return\tmixed\n\t */\n\tpublic function unbuffered_row($type = 'object')\n\t{\n\t\tif ($type === 'array')\n\t\t{\n\t\t\treturn $this->_fetch_assoc();\n\t\t}\n\t\telseif ($type === 'object')\n\t\t{\n\t\t\treturn $this->_fetch_object();\n\t\t}\n\n\t\treturn $this->_fetch_object($type);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * The following methods are normally overloaded by the identically named\n\t * methods in the platform-specific driver -- except when query caching\n\t * is used. When caching is enabled we do not load the other driver.\n\t * These functions are primarily here to prevent undefined function errors\n\t * when a cached result object is in use. They are not otherwise fully\n\t * operational due to the unavailability of the database resource IDs with\n\t * cached results.\n\t */\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Number of fields in the result set\n\t *\n\t * Overridden by driver result classes.\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_fields()\n\t{\n\t\treturn 0;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch Field Names\n\t *\n\t * Generates an array of column names.\n\t *\n\t * Overridden by driver result classes.\n\t *\n\t * @return\tarray\n\t */\n\tpublic function list_fields()\n\t{\n\t\treturn array();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field data\n\t *\n\t * Generates an array of objects containing field meta-data.\n\t *\n\t * Overridden by driver result classes.\n\t *\n\t * @return\tarray\n\t */\n\tpublic function field_data()\n\t{\n\t\treturn array();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Free the result\n\t *\n\t * Overridden by driver result classes.\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function free_result()\n\t{\n\t\t$this->result_id = FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Data Seek\n\t *\n\t * Moves the internal pointer to the desired offset. We call\n\t * this internally before fetching results to make sure the\n\t * result set starts at zero.\n\t *\n\t * Overridden by driver result classes.\n\t *\n\t * @param\tint\t$n\n\t * @return\tbool\n\t */\n\tpublic function data_seek($n = 0)\n\t{\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - associative array\n\t *\n\t * Returns the result set as an array.\n\t *\n\t * Overridden by driver result classes.\n\t *\n\t * @return\tarray\n\t */\n\tprotected function _fetch_assoc()\n\t{\n\t\treturn array();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - object\n\t *\n\t * Returns the result set as an object.\n\t *\n\t * Overridden by driver result classes.\n\t *\n\t * @param\tstring\t$class_name\n\t * @return\tobject\n\t */\n\tprotected function _fetch_object($class_name = 'stdClass')\n\t{\n\t\treturn array();\n\t}\n\n}\n"
  },
  {
    "path": "system/database/DB_utility.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Database Utility Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nabstract class CI_DB_utility {\n\n\t/**\n\t * Database object\n\t *\n\t * @var\tobject\n\t */\n\tprotected $db;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * List databases statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_list_databases\t\t= FALSE;\n\n\t/**\n\t * OPTIMIZE TABLE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_optimize_table\t= FALSE;\n\n\t/**\n\t * REPAIR TABLE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_repair_table\t= FALSE;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tobject\t&$db\tDatabase object\n\t * @return\tvoid\n\t */\n\tpublic function __construct(&$db)\n\t{\n\t\t$this->db =& $db;\n\t\tlog_message('info', 'Database Utility Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * List databases\n\t *\n\t * @return\tarray\n\t */\n\tpublic function list_databases()\n\t{\n\t\t// Is there a cached result?\n\t\tif (isset($this->db->data_cache['db_names']))\n\t\t{\n\t\t\treturn $this->db->data_cache['db_names'];\n\t\t}\n\t\telseif ($this->_list_databases === FALSE)\n\t\t{\n\t\t\treturn ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;\n\t\t}\n\n\t\t$this->db->data_cache['db_names'] = array();\n\n\t\t$query = $this->db->query($this->_list_databases);\n\t\tif ($query === FALSE)\n\t\t{\n\t\t\treturn $this->db->data_cache['db_names'];\n\t\t}\n\n\t\tfor ($i = 0, $query = $query->result_array(), $c = count($query); $i < $c; $i++)\n\t\t{\n\t\t\t$this->db->data_cache['db_names'][] = current($query[$i]);\n\t\t}\n\n\t\treturn $this->db->data_cache['db_names'];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Determine if a particular database exists\n\t *\n\t * @param\tstring\t$database_name\n\t * @return\tbool\n\t */\n\tpublic function database_exists($database_name)\n\t{\n\t\treturn in_array($database_name, $this->list_databases());\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Optimize Table\n\t *\n\t * @param\tstring\t$table_name\n\t * @return\tmixed\n\t */\n\tpublic function optimize_table($table_name)\n\t{\n\t\tif ($this->_optimize_table === FALSE)\n\t\t{\n\t\t\treturn ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;\n\t\t}\n\n\t\t$query = $this->db->query(sprintf($this->_optimize_table, $this->db->escape_identifiers($table_name)));\n\t\tif ($query !== FALSE)\n\t\t{\n\t\t\t$query = $query->result_array();\n\t\t\treturn current($query);\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Optimize Database\n\t *\n\t * @return\tmixed\n\t */\n\tpublic function optimize_database()\n\t{\n\t\tif ($this->_optimize_table === FALSE)\n\t\t{\n\t\t\treturn ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;\n\t\t}\n\n\t\t$result = array();\n\t\tforeach ($this->db->list_tables() as $table_name)\n\t\t{\n\t\t\t$res = $this->db->query(sprintf($this->_optimize_table, $this->db->escape_identifiers($table_name)));\n\t\t\tif (is_bool($res))\n\t\t\t{\n\t\t\t\treturn $res;\n\t\t\t}\n\n\t\t\t// Build the result array...\n\t\t\t$res = $res->result_array();\n\t\t\t$res = current($res);\n\t\t\t$key = str_replace($this->db->database.'.', '', current($res));\n\t\t\t$keys = array_keys($res);\n\t\t\tunset($res[$keys[0]]);\n\n\t\t\t$result[$key] = $res;\n\t\t}\n\n\t\treturn $result;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Repair Table\n\t *\n\t * @param\tstring\t$table_name\n\t * @return\tmixed\n\t */\n\tpublic function repair_table($table_name)\n\t{\n\t\tif ($this->_repair_table === FALSE)\n\t\t{\n\t\t\treturn ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;\n\t\t}\n\n\t\t$query = $this->db->query(sprintf($this->_repair_table, $this->db->escape_identifiers($table_name)));\n\t\tif (is_bool($query))\n\t\t{\n\t\t\treturn $query;\n\t\t}\n\n\t\t$query = $query->result_array();\n\t\treturn current($query);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Generate CSV from a query result object\n\t *\n\t * @param\tobject\t$query\t\tQuery result object\n\t * @param\tstring\t$delim\t\tDelimiter (default: ,)\n\t * @param\tstring\t$newline\tNewline character (default: \\n)\n\t * @param\tstring\t$enclosure\tEnclosure (default: \")\n\t * @return\tstring\n\t */\n\tpublic function csv_from_result($query, $delim = ',', $newline = \"\\n\", $enclosure = '\"')\n\t{\n\t\tif ( ! is_object($query) OR ! method_exists($query, 'list_fields'))\n\t\t{\n\t\t\tshow_error('You must submit a valid result object');\n\t\t}\n\n\t\t$out = '';\n\t\t// First generate the headings from the table column names\n\t\tforeach ($query->list_fields() as $name)\n\t\t{\n\t\t\t$out .= $enclosure.str_replace($enclosure, $enclosure.$enclosure, $name).$enclosure.$delim;\n\t\t}\n\n\t\t$out = substr($out, 0, -strlen($delim)).$newline;\n\n\t\t// Next blast through the result array and build out the rows\n\t\twhile ($row = $query->unbuffered_row('array'))\n\t\t{\n\t\t\t$line = array();\n\t\t\tforeach ($row as $item)\n\t\t\t{\n\t\t\t\t$line[] = $enclosure.str_replace($enclosure, $enclosure.$enclosure, $item).$enclosure;\n\t\t\t}\n\t\t\t$out .= implode($delim, $line).$newline;\n\t\t}\n\n\t\treturn $out;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Generate XML data from a query result object\n\t *\n\t * @param\tobject\t$query\tQuery result object\n\t * @param\tarray\t$params\tAny preferences\n\t * @return\tstring\n\t */\n\tpublic function xml_from_result($query, $params = array())\n\t{\n\t\tif ( ! is_object($query) OR ! method_exists($query, 'list_fields'))\n\t\t{\n\t\t\tshow_error('You must submit a valid result object');\n\t\t}\n\n\t\t// Set our default values\n\t\tforeach (array('root' => 'root', 'element' => 'element', 'newline' => \"\\n\", 'tab' => \"\\t\") as $key => $val)\n\t\t{\n\t\t\tif ( ! isset($params[$key]))\n\t\t\t{\n\t\t\t\t$params[$key] = $val;\n\t\t\t}\n\t\t}\n\n\t\t// Create variables for convenience\n\t\textract($params);\n\n\t\t// Load the xml helper\n\t\tget_instance()->load->helper('xml');\n\n\t\t// Generate the result\n\t\t$xml = '<'.$root.'>'.$newline;\n\t\twhile ($row = $query->unbuffered_row())\n\t\t{\n\t\t\t$xml .= $tab.'<'.$element.'>'.$newline;\n\t\t\tforeach ($row as $key => $val)\n\t\t\t{\n\t\t\t\t$xml .= $tab.$tab.'<'.$key.'>'.xml_convert($val).'</'.$key.'>'.$newline;\n\t\t\t}\n\t\t\t$xml .= $tab.'</'.$element.'>'.$newline;\n\t\t}\n\n\t\treturn $xml.'</'.$root.'>'.$newline;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Database Backup\n\t *\n\t * @param\tarray\t$params\n\t * @return\tstring\n\t */\n\tpublic function backup($params = array())\n\t{\n\t\t// If the parameters have not been submitted as an\n\t\t// array then we know that it is simply the table\n\t\t// name, which is a valid short cut.\n\t\tif (is_string($params))\n\t\t{\n\t\t\t$params = array('tables' => $params);\n\t\t}\n\n\t\t// Set up our default preferences\n\t\t$prefs = array(\n\t\t\t'tables'\t\t=> array(),\n\t\t\t'ignore'\t\t=> array(),\n\t\t\t'filename'\t\t=> '',\n\t\t\t'format'\t\t=> 'gzip', // gzip, zip, txt\n\t\t\t'add_drop'\t\t=> TRUE,\n\t\t\t'add_insert'\t\t=> TRUE,\n\t\t\t'newline'\t\t=> \"\\n\",\n\t\t\t'foreign_key_checks'\t=> TRUE\n\t\t);\n\n\t\t// Did the user submit any preferences? If so set them....\n\t\tif (count($params) > 0)\n\t\t{\n\t\t\tforeach ($prefs as $key => $val)\n\t\t\t{\n\t\t\t\tif (isset($params[$key]))\n\t\t\t\t{\n\t\t\t\t\t$prefs[$key] = $params[$key];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Are we backing up a complete database or individual tables?\n\t\t// If no table names were submitted we'll fetch the entire table list\n\t\tif (count($prefs['tables']) === 0)\n\t\t{\n\t\t\t$prefs['tables'] = $this->db->list_tables();\n\t\t}\n\n\t\t// Validate the format\n\t\tif ( ! in_array($prefs['format'], array('gzip', 'zip', 'txt'), TRUE))\n\t\t{\n\t\t\t$prefs['format'] = 'txt';\n\t\t}\n\n\t\t// Is the encoder supported? If not, we'll either issue an\n\t\t// error or use plain text depending on the debug settings\n\t\tif (($prefs['format'] === 'gzip' && ! function_exists('gzencode'))\n\t\t\tOR ($prefs['format'] === 'zip' && ! function_exists('gzcompress')))\n\t\t{\n\t\t\tif ($this->db->db_debug)\n\t\t\t{\n\t\t\t\treturn $this->db->display_error('db_unsupported_compression');\n\t\t\t}\n\n\t\t\t$prefs['format'] = 'txt';\n\t\t}\n\n\t\t// Was a Zip file requested?\n\t\tif ($prefs['format'] === 'zip')\n\t\t{\n\t\t\t// Set the filename if not provided (only needed with Zip files)\n\t\t\tif ($prefs['filename'] === '')\n\t\t\t{\n\t\t\t\t$prefs['filename'] = (count($prefs['tables']) === 1 ? $prefs['tables'] : $this->db->database)\n\t\t\t\t\t\t\t.date('Y-m-d_H-i', time()).'.sql';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// If they included the .zip file extension we'll remove it\n\t\t\t\tif (preg_match('|.+?\\.zip$|', $prefs['filename']))\n\t\t\t\t{\n\t\t\t\t\t$prefs['filename'] = str_replace('.zip', '', $prefs['filename']);\n\t\t\t\t}\n\n\t\t\t\t// Tack on the \".sql\" file extension if needed\n\t\t\t\tif ( ! preg_match('|.+?\\.sql$|', $prefs['filename']))\n\t\t\t\t{\n\t\t\t\t\t$prefs['filename'] .= '.sql';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Load the Zip class and output it\n\t\t\t$CI =& get_instance();\n\t\t\t$CI->load->library('zip');\n\t\t\t$CI->zip->add_data($prefs['filename'], $this->_backup($prefs));\n\t\t\treturn $CI->zip->get_zip();\n\t\t}\n\t\telseif ($prefs['format'] === 'txt') // Was a text file requested?\n\t\t{\n\t\t\treturn $this->_backup($prefs);\n\t\t}\n\t\telseif ($prefs['format'] === 'gzip') // Was a Gzip file requested?\n\t\t{\n\t\t\treturn gzencode($this->_backup($prefs));\n\t\t}\n\n\t\treturn;\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/cubrid/cubrid_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 2.1.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CUBRID Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEsen Sagynov\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_cubrid_driver extends CI_DB {\n\n\t/**\n\t * Database driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $dbdriver = 'cubrid';\n\n\t/**\n\t * Auto-commit flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $auto_commit = TRUE;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Identifier escape character\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_escape_char = '`';\n\n\t/**\n\t * ORDER BY random keyword\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_random_keyword = array('RANDOM()', 'RANDOM(%d)');\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif (preg_match('/^CUBRID:[^:]+(:[0-9][1-9]{0,4})?:[^:]+:[^:]*:[^:]*:(\\?.+)?$/', $this->dsn, $matches))\n\t\t{\n\t\t\tif (stripos($matches[2], 'autocommit=off') !== FALSE)\n\t\t\t{\n\t\t\t\t$this->auto_commit = FALSE;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// If no port is defined by the user, use the default value\n\t\t\tempty($this->port) OR $this->port = 33000;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Non-persistent database connection\n\t *\n\t * @param\tbool\t$persistent\n\t * @return\tresource\n\t */\n\tpublic function db_connect($persistent = FALSE)\n\t{\n\t\tif (preg_match('/^CUBRID:[^:]+(:[0-9][1-9]{0,4})?:[^:]+:([^:]*):([^:]*):(\\?.+)?$/', $this->dsn, $matches))\n\t\t{\n\t\t\t$func = ($persistent !== TRUE) ? 'cubrid_connect_with_url' : 'cubrid_pconnect_with_url';\n\t\t\treturn ($matches[2] === '' && $matches[3] === '' && $this->username !== '' && $this->password !== '')\n\t\t\t\t? $func($this->dsn, $this->username, $this->password)\n\t\t\t\t: $func($this->dsn);\n\t\t}\n\n\t\t$func = ($persistent !== TRUE) ? 'cubrid_connect' : 'cubrid_pconnect';\n\t\treturn ($this->username !== '')\n\t\t\t? $func($this->hostname, $this->port, $this->database, $this->username, $this->password)\n\t\t\t: $func($this->hostname, $this->port, $this->database);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Reconnect\n\t *\n\t * Keep / reestablish the db connection if no queries have been\n\t * sent for a length of time exceeding the server's idle timeout\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function reconnect()\n\t{\n\t\tif (cubrid_ping($this->conn_id) === FALSE)\n\t\t{\n\t\t\t$this->conn_id = FALSE;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Database version number\n\t *\n\t * @return\tstring\n\t */\n\tpublic function version()\n\t{\n\t\tif (isset($this->data_cache['version']))\n\t\t{\n\t\t\treturn $this->data_cache['version'];\n\t\t}\n\n\t\treturn ( ! $this->conn_id OR ($version = cubrid_get_server_info($this->conn_id)) === FALSE)\n\t\t\t? FALSE\n\t\t\t: $this->data_cache['version'] = $version;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Execute the query\n\t *\n\t * @param\tstring\t$sql\tan SQL query\n\t * @return\tresource\n\t */\n\tprotected function _execute($sql)\n\t{\n\t\treturn cubrid_query($sql, $this->conn_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Begin Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_begin()\n\t{\n\t\tif (($autocommit = cubrid_get_autocommit($this->conn_id)) === NULL)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\telseif ($autocommit === TRUE)\n\t\t{\n\t\t\treturn cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_FALSE);\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Commit Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_commit()\n\t{\n\t\tif ( ! cubrid_commit($this->conn_id))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ($this->auto_commit && ! cubrid_get_autocommit($this->conn_id))\n\t\t{\n\t\t\treturn cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_TRUE);\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Rollback Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_rollback()\n\t{\n\t\tif ( ! cubrid_rollback($this->conn_id))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ($this->auto_commit && ! cubrid_get_autocommit($this->conn_id))\n\t\t{\n\t\t\tcubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_TRUE);\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Platform-dependant string escape\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _escape_str($str)\n\t{\n\t\treturn cubrid_real_escape_string($str, $this->conn_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Affected Rows\n\t *\n\t * @return\tint\n\t */\n\tpublic function affected_rows()\n\t{\n\t\treturn cubrid_affected_rows();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert ID\n\t *\n\t * @return\tint\n\t */\n\tpublic function insert_id()\n\t{\n\t\treturn cubrid_insert_id($this->conn_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * List table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\t$prefix_limit\n\t * @return\tstring\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\t$sql = 'SHOW TABLES';\n\n\t\tif ($prefix_limit !== FALSE && $this->dbprefix !== '')\n\t\t{\n\t\t\treturn $sql.\" LIKE '\".$this->escape_like_str($this->dbprefix).\"%'\";\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show column query\n\t *\n\t * Generates a platform-specific query string so that the column names can be fetched\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _list_columns($table = '')\n\t{\n\t\treturn 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an object with field data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tarray\n\t */\n\tpublic function field_data($table)\n\t{\n\t\tif (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\t$query = $query->result_object();\n\n\t\t$retval = array();\n\t\tfor ($i = 0, $c = count($query); $i < $c; $i++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= $query[$i]->Field;\n\n\t\t\tsscanf($query[$i]->Type, '%[a-z](%d)',\n\t\t\t\t$retval[$i]->type,\n\t\t\t\t$retval[$i]->max_length\n\t\t\t);\n\n\t\t\t$retval[$i]->default\t\t= $query[$i]->Default;\n\t\t\t$retval[$i]->primary_key\t= (int) ($query[$i]->Key === 'PRI');\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Error\n\t *\n\t * Returns an array containing code and message of the last\n\t * database error that has occured.\n\t *\n\t * @return\tarray\n\t */\n\tpublic function error()\n\t{\n\t\treturn array('code' => cubrid_errno($this->conn_id), 'message' => cubrid_error($this->conn_id));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * FROM tables\n\t *\n\t * Groups tables in FROM clauses if needed, so there is no confusion\n\t * about operator precedence.\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _from_tables()\n\t{\n\t\tif ( ! empty($this->qb_join) && count($this->qb_from) > 1)\n\t\t{\n\t\t\treturn '('.implode(', ', $this->qb_from).')';\n\t\t}\n\n\t\treturn implode(', ', $this->qb_from);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Close DB Connection\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _close()\n\t{\n\t\tcubrid_close($this->conn_id);\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/cubrid/cubrid_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 2.1.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CUBRID Forge Class\n *\n * @category\tDatabase\n * @author\t\tEsen Sagynov\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_cubrid_forge extends CI_DB_forge {\n\n\t/**\n\t * CREATE DATABASE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_database\t= FALSE;\n\n\t/**\n\t * CREATE TABLE keys flag\n\t *\n\t * Whether table keys are created from within the\n\t * CREATE TABLE statement.\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_create_table_keys\t= TRUE;\n\n\t/**\n\t * DROP DATABASE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_drop_database\t= FALSE;\n\n\t/**\n\t * CREATE TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_table_if\t= FALSE;\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_unsigned\t\t= array(\n\t\t'SHORT'\t\t=> 'INTEGER',\n\t\t'SMALLINT'\t=> 'INTEGER',\n\t\t'INT'\t\t=> 'BIGINT',\n\t\t'INTEGER'\t=> 'BIGINT',\n\t\t'BIGINT'\t=> 'NUMERIC',\n\t\t'FLOAT'\t\t=> 'DOUBLE',\n\t\t'REAL'\t\t=> 'DOUBLE'\n\t);\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ALTER TABLE\n\t *\n\t * @param\tstring\t$alter_type\tALTER type\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tmixed\t$field\t\tColumn definition\n\t * @return\tstring|string[]\n\t */\n\tprotected function _alter_table($alter_type, $table, $field)\n\t{\n\t\tif (in_array($alter_type, array('DROP', 'ADD'), TRUE))\n\t\t{\n\t\t\treturn parent::_alter_table($alter_type, $table, $field);\n\t\t}\n\n\t\t$sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);\n\t\t$sqls = array();\n\t\tfor ($i = 0, $c = count($field); $i < $c; $i++)\n\t\t{\n\t\t\tif ($field[$i]['_literal'] !== FALSE)\n\t\t\t{\n\t\t\t\t$sqls[] = $sql.' CHANGE '.$field[$i]['_literal'];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$alter_type = empty($field[$i]['new_name']) ? ' MODIFY ' : ' CHANGE ';\n\t\t\t\t$sqls[] = $sql.$alter_type.$this->_process_column($field[$i]);\n\t\t\t}\n\t\t}\n\n\t\treturn $sqls;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Process column\n\t *\n\t * @param\tarray\t$field\n\t * @return\tstring\n\t */\n\tprotected function _process_column($field)\n\t{\n\t\t$extra_clause = isset($field['after'])\n\t\t\t? ' AFTER '.$this->db->escape_identifiers($field['after']) : '';\n\n\t\tif (empty($extra_clause) && isset($field['first']) && $field['first'] === TRUE)\n\t\t{\n\t\t\t$extra_clause = ' FIRST';\n\t\t}\n\n\t\treturn $this->db->escape_identifiers($field['name'])\n\t\t\t.(empty($field['new_name']) ? '' : ' '.$this->db->escape_identifiers($field['new_name']))\n\t\t\t.' '.$field['type'].$field['length']\n\t\t\t.$field['unsigned']\n\t\t\t.$field['null']\n\t\t\t.$field['default']\n\t\t\t.$field['auto_increment']\n\t\t\t.$field['unique']\n\t\t\t.$extra_clause;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute TYPE\n\t *\n\t * Performs a data type mapping between different databases.\n\t *\n\t * @param\tarray\t&$attributes\n\t * @return\tvoid\n\t */\n\tprotected function _attr_type(&$attributes)\n\t{\n\t\tswitch (strtoupper($attributes['TYPE']))\n\t\t{\n\t\t\tcase 'TINYINT':\n\t\t\t\t$attributes['TYPE'] = 'SMALLINT';\n\t\t\t\t$attributes['UNSIGNED'] = FALSE;\n\t\t\t\treturn;\n\t\t\tcase 'MEDIUMINT':\n\t\t\t\t$attributes['TYPE'] = 'INTEGER';\n\t\t\t\t$attributes['UNSIGNED'] = FALSE;\n\t\t\t\treturn;\n\t\t\tcase 'LONGTEXT':\n\t\t\t\t$attributes['TYPE'] = 'STRING';\n\t\t\t\treturn;\n\t\t\tdefault: return;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Process indexes\n\t *\n\t * @param\tstring\t$table\t(ignored)\n\t * @return\tstring\n\t */\n\tprotected function _process_indexes($table)\n\t{\n\t\t$sql = '';\n\n\t\tfor ($i = 0, $c = count($this->keys); $i < $c; $i++)\n\t\t{\n\t\t\tif (is_array($this->keys[$i]))\n\t\t\t{\n\t\t\t\tfor ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++)\n\t\t\t\t{\n\t\t\t\t\tif ( ! isset($this->fields[$this->keys[$i][$i2]]))\n\t\t\t\t\t{\n\t\t\t\t\t\tunset($this->keys[$i][$i2]);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ( ! isset($this->fields[$this->keys[$i]]))\n\t\t\t{\n\t\t\t\tunset($this->keys[$i]);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tis_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);\n\n\t\t\t$sql .= \",\\n\\tKEY \".$this->db->escape_identifiers(implode('_', $this->keys[$i]))\n\t\t\t\t.' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';\n\t\t}\n\n\t\t$this->keys = array();\n\n\t\treturn $sql;\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/cubrid/cubrid_result.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 2.1.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CUBRID Result Class\n *\n * This class extends the parent result class: CI_DB_result\n *\n * @category\tDatabase\n * @author\t\tEsen Sagynov\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_cubrid_result extends CI_DB_result {\n\n\t/**\n\t * Number of rows in the result set\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_rows()\n\t{\n\t\treturn is_int($this->num_rows)\n\t\t\t? $this->num_rows\n\t\t\t: $this->num_rows = cubrid_num_rows($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Number of fields in the result set\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_fields()\n\t{\n\t\treturn cubrid_num_fields($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch Field Names\n\t *\n\t * Generates an array of column names\n\t *\n\t * @return\tarray\n\t */\n\tpublic function list_fields()\n\t{\n\t\treturn cubrid_column_names($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field data\n\t *\n\t * Generates an array of objects containing field meta-data\n\t *\n\t * @return\tarray\n\t */\n\tpublic function field_data()\n\t{\n\t\t$retval = array();\n\n\t\tfor ($i = 0, $c = $this->num_fields(); $i < $c; $i++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= cubrid_field_name($this->result_id, $i);\n\t\t\t$retval[$i]->type\t\t= cubrid_field_type($this->result_id, $i);\n\t\t\t$retval[$i]->max_length\t\t= cubrid_field_len($this->result_id, $i);\n\t\t\t$retval[$i]->primary_key\t= (int) (strpos(cubrid_field_flags($this->result_id, $i), 'primary_key') !== FALSE);\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Free the result\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function free_result()\n\t{\n\t\tif (is_resource($this->result_id) OR\n\t\t\t(get_resource_type($this->result_id) === 'Unknown' && preg_match('/Resource id #/', strval($this->result_id))))\n\t\t{\n\t\t\tcubrid_close_request($this->result_id);\n\t\t\t$this->result_id = FALSE;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Data Seek\n\t *\n\t * Moves the internal pointer to the desired offset. We call\n\t * this internally before fetching results to make sure the\n\t * result set starts at zero.\n\t *\n\t * @param\tint\t$n\n\t * @return\tbool\n\t */\n\tpublic function data_seek($n = 0)\n\t{\n\t\treturn cubrid_data_seek($this->result_id, $n);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - associative array\n\t *\n\t * Returns the result set as an array\n\t *\n\t * @return\tarray\n\t */\n\tprotected function _fetch_assoc()\n\t{\n\t\treturn cubrid_fetch_assoc($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - object\n\t *\n\t * Returns the result set as an object\n\t *\n\t * @param\tstring\t$class_name\n\t * @return\tobject\n\t */\n\tprotected function _fetch_object($class_name = 'stdClass')\n\t{\n\t\treturn cubrid_fetch_object($this->result_id, $class_name);\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/cubrid/cubrid_utility.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 2.1.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CUBRID Utility Class\n *\n * @category\tDatabase\n * @author\t\tEsen Sagynov\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_cubrid_utility extends CI_DB_utility {\n\n\t/**\n\t * List databases\n\t *\n\t * @return\tarray\n\t */\n\tpublic function list_databases()\n\t{\n\t\tif (isset($this->db->data_cache['db_names']))\n\t\t{\n\t\t\treturn $this->db->data_cache['db_names'];\n\t\t}\n\n\t\treturn $this->db->data_cache['db_names'] = cubrid_list_dbs($this->db->conn_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * CUBRID Export\n\t *\n\t * @param\tarray\tPreferences\n\t * @return\tmixed\n\t */\n\tprotected function _backup($params = array())\n\t{\n\t\t// No SQL based support in CUBRID as of version 8.4.0. Database or\n\t\t// table backup can be performed using CUBRID Manager\n\t\t// database administration tool.\n\t\treturn $this->db->display_error('db_unsupported_feature');\n\t}\n}\n"
  },
  {
    "path": "system/database/drivers/cubrid/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/database/drivers/ibase/ibase_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Firebird/Interbase Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_ibase_driver extends CI_DB {\n\n\t/**\n\t * Database driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $dbdriver = 'ibase';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ORDER BY random keyword\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_random_keyword = array('RAND()', 'RAND()');\n\n\t/**\n\t * IBase Transaction status flag\n\t *\n\t * @var\tresource\n\t */\n\tprotected $_ibase_trans;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Non-persistent database connection\n\t *\n\t * @param\tbool\t$persistent\n\t * @return\tresource\n\t */\n\tpublic function db_connect($persistent = FALSE)\n\t{\n\t\treturn ($persistent === TRUE)\n\t\t\t? ibase_pconnect($this->hostname.':'.$this->database, $this->username, $this->password, $this->char_set)\n\t\t\t: ibase_connect($this->hostname.':'.$this->database, $this->username, $this->password, $this->char_set);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Database version number\n\t *\n\t * @return\tstring\n\t */\n\tpublic function version()\n\t{\n\t\tif (isset($this->data_cache['version']))\n\t\t{\n\t\t\treturn $this->data_cache['version'];\n\t\t}\n\n\t\tif (($service = ibase_service_attach($this->hostname, $this->username, $this->password)))\n\t\t{\n\t\t\t$this->data_cache['version'] = ibase_server_info($service, IBASE_SVC_SERVER_VERSION);\n\n\t\t\t// Don't keep the service open\n\t\t\tibase_service_detach($service);\n\t\t\treturn $this->data_cache['version'];\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Execute the query\n\t *\n\t * @param\tstring\t$sql\tan SQL query\n\t * @return\tresource\n\t */\n\tprotected function _execute($sql)\n\t{\n\t\treturn ibase_query(isset($this->_ibase_trans) ? $this->_ibase_trans : $this->conn_id, $sql);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Begin Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_begin()\n\t{\n\t\tif (($trans_handle = ibase_trans($this->conn_id)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->_ibase_trans = $trans_handle;\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Commit Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_commit()\n\t{\n\t\tif (ibase_commit($this->_ibase_trans))\n\t\t{\n\t\t\t$this->_ibase_trans = NULL;\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Rollback Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_rollback()\n\t{\n\t\tif (ibase_rollback($this->_ibase_trans))\n\t\t{\n\t\t\t$this->_ibase_trans = NULL;\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Affected Rows\n\t *\n\t * @return\tint\n\t */\n\tpublic function affected_rows()\n\t{\n\t\treturn ibase_affected_rows($this->conn_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert ID\n\t *\n\t * @param\tstring\t$generator_name\n\t * @param\tint\t$inc_by\n\t * @return\tint\n\t */\n\tpublic function insert_id($generator_name, $inc_by = 0)\n\t{\n\t\t//If a generator hasn't been used before it will return 0\n\t\treturn ibase_gen_id('\"'.$generator_name.'\"', $inc_by);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * List table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\t$prefix_limit\n\t * @return\tstring\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\t$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$%\\'';\n\n\t\tif ($prefix_limit !== FALSE && $this->dbprefix !== '')\n\t\t{\n\t\t\treturn $sql.' AND TRIM(\"RDB$RELATION_NAME\") AS TABLE_NAME LIKE \\''.$this->escape_like_str($this->dbprefix).\"%' \"\n\t\t\t\t.sprintf($this->_like_escape_str, $this->_like_escape_chr);\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show column query\n\t *\n\t * Generates a platform-specific query string so that the column names can be fetched\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _list_columns($table = '')\n\t{\n\t\treturn 'SELECT TRIM(\"RDB$FIELD_NAME\") AS COLUMN_NAME FROM \"RDB$RELATION_FIELDS\" WHERE \"RDB$RELATION_NAME\" = '.$this->escape($table);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an object with field data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tarray\n\t */\n\tpublic function field_data($table)\n\t{\n\t\t$sql = 'SELECT \"rfields\".\"RDB$FIELD_NAME\" AS \"name\",\n\t\t\t\tCASE \"fields\".\"RDB$FIELD_TYPE\"\n\t\t\t\t\tWHEN 7 THEN \\'SMALLINT\\'\n\t\t\t\t\tWHEN 8 THEN \\'INTEGER\\'\n\t\t\t\t\tWHEN 9 THEN \\'QUAD\\'\n\t\t\t\t\tWHEN 10 THEN \\'FLOAT\\'\n\t\t\t\t\tWHEN 11 THEN \\'DFLOAT\\'\n\t\t\t\t\tWHEN 12 THEN \\'DATE\\'\n\t\t\t\t\tWHEN 13 THEN \\'TIME\\'\n\t\t\t\t\tWHEN 14 THEN \\'CHAR\\'\n\t\t\t\t\tWHEN 16 THEN \\'INT64\\'\n\t\t\t\t\tWHEN 27 THEN \\'DOUBLE\\'\n\t\t\t\t\tWHEN 35 THEN \\'TIMESTAMP\\'\n\t\t\t\t\tWHEN 37 THEN \\'VARCHAR\\'\n\t\t\t\t\tWHEN 40 THEN \\'CSTRING\\'\n\t\t\t\t\tWHEN 261 THEN \\'BLOB\\'\n\t\t\t\t\tELSE NULL\n\t\t\t\tEND AS \"type\",\n\t\t\t\t\"fields\".\"RDB$FIELD_LENGTH\" AS \"max_length\",\n\t\t\t\t\"rfields\".\"RDB$DEFAULT_VALUE\" AS \"default\"\n\t\t\tFROM \"RDB$RELATION_FIELDS\" \"rfields\"\n\t\t\t\tJOIN \"RDB$FIELDS\" \"fields\" ON \"rfields\".\"RDB$FIELD_SOURCE\" = \"fields\".\"RDB$FIELD_NAME\"\n\t\t\tWHERE \"rfields\".\"RDB$RELATION_NAME\" = '.$this->escape($table).'\n\t\t\tORDER BY \"rfields\".\"RDB$FIELD_POSITION\"';\n\n\t\treturn (($query = $this->query($sql)) !== FALSE)\n\t\t\t? $query->result_object()\n\t\t\t: FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Error\n\t *\n\t * Returns an array containing code and message of the last\n\t * database error that has occured.\n\t *\n\t * @return\tarray\n\t */\n\tpublic function error()\n\t{\n\t\treturn array('code' => ibase_errcode(), 'message' => ibase_errmsg());\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update statement\n\t *\n\t * Generates a platform-specific update string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @param\tarray\t$values\n\t * @return\tstring\n\t */\n\tprotected function _update($table, $values)\n\t{\n\t\t$this->qb_limit = FALSE;\n\t\treturn parent::_update($table, $values);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Truncate statement\n\t *\n\t * Generates a platform-specific truncate string from the supplied data\n\t *\n\t * If the database does not support the TRUNCATE statement,\n\t * then this method maps to 'DELETE FROM table'\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _truncate($table)\n\t{\n\t\treturn 'DELETE FROM '.$table;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Delete statement\n\t *\n\t * Generates a platform-specific delete string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _delete($table)\n\t{\n\t\t$this->qb_limit = FALSE;\n\t\treturn parent::_delete($table);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * LIMIT\n\t *\n\t * Generates a platform-specific LIMIT clause\n\t *\n\t * @param\tstring\t$sql\tSQL Query\n\t * @return\tstring\n\t */\n\tprotected function _limit($sql)\n\t{\n\t\t// Limit clause depends on if Interbase or Firebird\n\t\tif (stripos($this->version(), 'firebird') !== FALSE)\n\t\t{\n\t\t\t$select = 'FIRST '.$this->qb_limit\n\t\t\t\t.($this->qb_offset ? ' SKIP '.$this->qb_offset : '');\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$select = 'ROWS '\n\t\t\t\t.($this->qb_offset ? $this->qb_offset.' TO '.($this->qb_limit + $this->qb_offset) : $this->qb_limit);\n\t\t}\n\n\t\treturn preg_replace('`SELECT`i', 'SELECT '.$select, $sql, 1);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Close DB Connection\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _close()\n\t{\n\t\tibase_close($this->conn_id);\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/ibase/ibase_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Interbase/Firebird Forge Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_ibase_forge extends CI_DB_forge {\n\n\t/**\n\t * CREATE TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_table_if\t= FALSE;\n\n\t/**\n\t * RENAME TABLE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_rename_table\t= FALSE;\n\n\t/**\n\t * DROP TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_drop_table_if\t= FALSE;\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_unsigned\t\t= array(\n\t\t'SMALLINT'\t=> 'INTEGER',\n\t\t'INTEGER'\t=> 'INT64',\n\t\t'FLOAT'\t\t=> 'DOUBLE PRECISION'\n\t);\n\n\t/**\n\t * NULL value representation in CREATE/ALTER TABLE statements\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_null\t\t= 'NULL';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Create database\n\t *\n\t * @param\tstring\t$db_name\n\t * @return\tstring\n\t */\n\tpublic function create_database($db_name)\n\t{\n\t\t// Firebird databases are flat files, so a path is required\n\n\t\t// Hostname is needed for remote access\n\t\tempty($this->db->hostname) OR $db_name = $this->hostname.':'.$db_name;\n\n\t\treturn parent::create_database('\"'.$db_name.'\"');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Drop database\n\t *\n\t * @param\tstring\t$db_name\t(ignored)\n\t * @return\tbool\n\t */\n\tpublic function drop_database($db_name = '')\n\t{\n\t\tif ( ! ibase_drop_db($this->conn_id))\n\t\t{\n\t\t\treturn ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE;\n\t\t}\n\t\telseif ( ! empty($this->db->data_cache['db_names']))\n\t\t{\n\t\t\t$key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE);\n\t\t\tif ($key !== FALSE)\n\t\t\t{\n\t\t\t\tunset($this->db->data_cache['db_names'][$key]);\n\t\t\t}\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ALTER TABLE\n\t *\n\t * @param\tstring\t$alter_type\tALTER type\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tmixed\t$field\t\tColumn definition\n\t * @return\tstring|string[]\n\t */\n\tprotected function _alter_table($alter_type, $table, $field)\n \t{\n\t\tif (in_array($alter_type, array('DROP', 'ADD'), TRUE))\n\t\t{\n\t\t\treturn parent::_alter_table($alter_type, $table, $field);\n\t\t}\n\n\t\t$sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);\n\t\t$sqls = array();\n\t\tfor ($i = 0, $c = count($field); $i < $c; $i++)\n\t\t{\n\t\t\tif ($field[$i]['_literal'] !== FALSE)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tif (isset($field[$i]['type']))\n\t\t\t{\n\t\t\t\t$sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identififers($field[$i]['name'])\n\t\t\t\t\t.' TYPE '.$field[$i]['type'].$field[$i]['length'];\n\t\t\t}\n\n\t\t\tif ( ! empty($field[$i]['default']))\n\t\t\t{\n\t\t\t\t$sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])\n\t\t\t\t\t.' SET DEFAULT '.$field[$i]['default'];\n\t\t\t}\n\n\t\t\tif (isset($field[$i]['null']))\n\t\t\t{\n\t\t\t\t$sqls[] = 'UPDATE \"RDB$RELATION_FIELDS\" SET \"RDB$NULL_FLAG\" = '\n\t\t\t\t\t.($field[$i]['null'] === TRUE ? 'NULL' : '1')\n\t\t\t\t\t.' WHERE \"RDB$FIELD_NAME\" = '.$this->db->escape($field[$i]['name'])\n\t\t\t\t\t.' AND \"RDB$RELATION_NAME\" = '.$this->db->escape($table);\n\t\t\t}\n\n\t\t\tif ( ! empty($field[$i]['new_name']))\n\t\t\t{\n\t\t\t\t$sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])\n\t\t\t\t\t.' TO '.$this->db->escape_identifiers($field[$i]['new_name']);\n\t\t\t}\n\t\t}\n\n\t\treturn $sqls;\n \t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Process column\n\t *\n\t * @param\tarray\t$field\n\t * @return\tstring\n\t */\n\tprotected function _process_column($field)\n\t{\n\t\treturn $this->db->escape_identifiers($field['name'])\n\t\t\t.' '.$field['type'].$field['length']\n\t\t\t.$field['null']\n\t\t\t.$field['unique']\n\t\t\t.$field['default'];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute TYPE\n\t *\n\t * Performs a data type mapping between different databases.\n\t *\n\t * @param\tarray\t&$attributes\n\t * @return\tvoid\n\t */\n\tprotected function _attr_type(&$attributes)\n\t{\n\t\tswitch (strtoupper($attributes['TYPE']))\n\t\t{\n\t\t\tcase 'TINYINT':\n\t\t\t\t$attributes['TYPE'] = 'SMALLINT';\n\t\t\t\t$attributes['UNSIGNED'] = FALSE;\n\t\t\t\treturn;\n\t\t\tcase 'MEDIUMINT':\n\t\t\t\t$attributes['TYPE'] = 'INTEGER';\n\t\t\t\t$attributes['UNSIGNED'] = FALSE;\n\t\t\t\treturn;\n\t\t\tcase 'INT':\n\t\t\t\t$attributes['TYPE'] = 'INTEGER';\n\t\t\t\treturn;\n\t\t\tcase 'BIGINT':\n\t\t\t\t$attributes['TYPE'] = 'INT64';\n\t\t\t\treturn;\n\t\t\tdefault: return;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute AUTO_INCREMENT\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_auto_increment(&$attributes, &$field)\n\t{\n\t\t// Not supported\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/ibase/ibase_result.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Interbase/Firebird Result Class\n *\n * This class extends the parent result class: CI_DB_result\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_ibase_result extends CI_DB_result {\n\n\t/**\n\t * Number of fields in the result set\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_fields()\n\t{\n\t\treturn ibase_num_fields($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch Field Names\n\t *\n\t * Generates an array of column names\n\t *\n\t * @return\tarray\n\t */\n\tpublic function list_fields()\n\t{\n\t\t$field_names = array();\n\t\tfor ($i = 0, $num_fields = $this->num_fields(); $i < $num_fields; $i++)\n\t\t{\n\t\t\t$info = ibase_field_info($this->result_id, $i);\n\t\t\t$field_names[] = $info['name'];\n\t\t}\n\n\t\treturn $field_names;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field data\n\t *\n\t * Generates an array of objects containing field meta-data\n\t *\n\t * @return\tarray\n\t */\n\tpublic function field_data()\n\t{\n\t\t$retval = array();\n\t\tfor ($i = 0, $c = $this->num_fields(); $i < $c; $i++)\n\t\t{\n\t\t\t$info = ibase_field_info($this->result_id, $i);\n\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= $info['name'];\n\t\t\t$retval[$i]->type\t\t= $info['type'];\n\t\t\t$retval[$i]->max_length\t\t= $info['length'];\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Free the result\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function free_result()\n\t{\n\t\tibase_free_result($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - associative array\n\t *\n\t * Returns the result set as an array\n\t *\n\t * @return\tarray\n\t */\n\tprotected function _fetch_assoc()\n\t{\n\t\treturn ibase_fetch_assoc($this->result_id, IBASE_FETCH_BLOBS);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - object\n\t *\n\t * Returns the result set as an object\n\t *\n\t * @param\tstring\t$class_name\n\t * @return\tobject\n\t */\n\tprotected function _fetch_object($class_name = 'stdClass')\n\t{\n\t\t$row = ibase_fetch_object($this->result_id, IBASE_FETCH_BLOBS);\n\n\t\tif ($class_name === 'stdClass' OR ! $row)\n\t\t{\n\t\t\treturn $row;\n\t\t}\n\n\t\t$class_name = new $class_name();\n\t\tforeach ($row as $key => $value)\n\t\t{\n\t\t\t$class_name->$key = $value;\n\t\t}\n\n\t\treturn $class_name;\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/ibase/ibase_utility.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Interbase/Firebird Utility Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_ibase_utility extends CI_DB_utility {\n\n\t/**\n\t * Export\n\t *\n\t * @param\tstring\t$filename\n\t * @return\tmixed\n\t */\n\tprotected function _backup($filename)\n\t{\n\t\tif ($service = ibase_service_attach($this->db->hostname, $this->db->username, $this->db->password))\n\t\t{\n\t\t\t$res = ibase_backup($service, $this->db->database, $filename.'.fbk');\n\n\t\t\t// Close the service connection\n\t\t\tibase_service_detach($service);\n\t\t\treturn $res;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/ibase/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/database/drivers/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/database/drivers/mssql/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/database/drivers/mssql/mssql_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.3.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * MS SQL Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_mssql_driver extends CI_DB {\n\n\t/**\n\t * Database driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $dbdriver = 'mssql';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ORDER BY random keyword\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_random_keyword = array('NEWID()', 'RAND(%d)');\n\n\t/**\n\t * Quoted identifier flag\n\t *\n\t * Whether to use SQL-92 standard quoted identifier\n\t * (double quotes) or brackets for identifier escaping.\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_quoted_identifier = TRUE;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Appends the port number to the hostname, if needed.\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif ( ! empty($this->port))\n\t\t{\n\t\t\t$this->hostname .= (DIRECTORY_SEPARATOR === '\\\\' ? ',' : ':').$this->port;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Non-persistent database connection\n\t *\n\t * @param\tbool\t$persistent\n\t * @return\tresource\n\t */\n\tpublic function db_connect($persistent = FALSE)\n\t{\n\t\t$this->conn_id = ($persistent)\n\t\t\t\t? mssql_pconnect($this->hostname, $this->username, $this->password)\n\t\t\t\t: mssql_connect($this->hostname, $this->username, $this->password);\n\n\t\tif ( ! $this->conn_id)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// ----------------------------------------------------------------\n\n\t\t// Select the DB... assuming a database name is specified in the config file\n\t\tif ($this->database !== '' && ! $this->db_select())\n\t\t{\n\t\t\tlog_message('error', 'Unable to select database: '.$this->database);\n\n\t\t\treturn ($this->db_debug === TRUE)\n\t\t\t\t? $this->display_error('db_unable_to_select', $this->database)\n\t\t\t\t: FALSE;\n\t\t}\n\n\t\t// Determine how identifiers are escaped\n\t\t$query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi');\n\t\t$query = $query->row_array();\n\t\t$this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi'];\n\t\t$this->_escape_char = ($this->_quoted_identifier) ? '\"' : array('[', ']');\n\n\t\treturn $this->conn_id;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Select the database\n\t *\n\t * @param\tstring\t$database\n\t * @return\tbool\n\t */\n\tpublic function db_select($database = '')\n\t{\n\t\tif ($database === '')\n\t\t{\n\t\t\t$database = $this->database;\n\t\t}\n\n\t\t// Note: Escaping is required in the event that the DB name\n\t\t// contains reserved characters.\n\t\tif (mssql_select_db('['.$database.']', $this->conn_id))\n\t\t{\n\t\t\t$this->database = $database;\n\t\t\t$this->data_cache = array();\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Execute the query\n\t *\n\t * @param\tstring\t$sql\tan SQL query\n\t * @return\tmixed\tresource if rows are returned, bool otherwise\n\t */\n\tprotected function _execute($sql)\n\t{\n\t\treturn mssql_query($sql, $this->conn_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Begin Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_begin()\n\t{\n\t\treturn $this->simple_query('BEGIN TRAN');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Commit Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_commit()\n\t{\n\t\treturn $this->simple_query('COMMIT TRAN');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Rollback Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_rollback()\n\t{\n\t\treturn $this->simple_query('ROLLBACK TRAN');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Affected Rows\n\t *\n\t * @return\tint\n\t */\n\tpublic function affected_rows()\n\t{\n\t\treturn mssql_rows_affected($this->conn_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert ID\n\t *\n\t * Returns the last id created in the Identity column.\n\t *\n\t * @return\tstring\n\t */\n\tpublic function insert_id()\n\t{\n\t\t$query = version_compare($this->version(), '8', '>=')\n\t\t\t? 'SELECT SCOPE_IDENTITY() AS last_id'\n\t\t\t: 'SELECT @@IDENTITY AS last_id';\n\n\t\t$query = $this->query($query);\n\t\t$query = $query->row();\n\t\treturn $query->last_id;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set client character set\n\t *\n\t * @param\tstring\t$charset\n\t * @return\tbool\n\t */\n\tprotected function _db_set_charset($charset)\n\t{\n\t\treturn (ini_set('mssql.charset', $charset) !== FALSE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Version number query string\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _version()\n\t{\n\t\treturn \"SELECT SERVERPROPERTY('ProductVersion') AS ver\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * List table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\t$prefix_limit\n\t * @return\tstring\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\t$sql = 'SELECT '.$this->escape_identifiers('name')\n\t\t\t.' FROM '.$this->escape_identifiers('sysobjects')\n\t\t\t.' WHERE '.$this->escape_identifiers('type').\" = 'U'\";\n\n\t\tif ($prefix_limit !== FALSE && $this->dbprefix !== '')\n\t\t{\n\t\t\t$sql .= ' AND '.$this->escape_identifiers('name').\" LIKE '\".$this->escape_like_str($this->dbprefix).\"%' \"\n\t\t\t\t.sprintf($this->_like_escape_str, $this->_like_escape_chr);\n\t\t}\n\n\t\treturn $sql.' ORDER BY '.$this->escape_identifiers('name');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * List column query\n\t *\n\t * Generates a platform-specific query string so that the column names can be fetched\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _list_columns($table = '')\n\t{\n\t\treturn 'SELECT COLUMN_NAME\n\t\t\tFROM INFORMATION_SCHEMA.Columns\n\t\t\tWHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an object with field data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tarray\n\t */\n\tpublic function field_data($table)\n\t{\n\t\t$sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, COLUMN_DEFAULT\n\t\t\tFROM INFORMATION_SCHEMA.Columns\n\t\t\tWHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));\n\n\t\tif (($query = $this->query($sql)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\t$query = $query->result_object();\n\n\t\t$retval = array();\n\t\tfor ($i = 0, $c = count($query); $i < $c; $i++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= $query[$i]->COLUMN_NAME;\n\t\t\t$retval[$i]->type\t\t= $query[$i]->DATA_TYPE;\n\t\t\t$retval[$i]->max_length\t\t= ($query[$i]->CHARACTER_MAXIMUM_LENGTH > 0) ? $query[$i]->CHARACTER_MAXIMUM_LENGTH : $query[$i]->NUMERIC_PRECISION;\n\t\t\t$retval[$i]->default\t\t= $query[$i]->COLUMN_DEFAULT;\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Error\n\t *\n\t * Returns an array containing code and message of the last\n\t * database error that has occured.\n\t *\n\t * @return\tarray\n\t */\n\tpublic function error()\n\t{\n\t\t// We need this because the error info is discarded by the\n\t\t// server the first time you request it, and query() already\n\t\t// calls error() once for logging purposes when a query fails.\n\t\tstatic $error = array('code' => 0, 'message' => NULL);\n\n\t\t$message = mssql_get_last_message();\n\t\tif ( ! empty($message))\n\t\t{\n\t\t\t$error['code']    = $this->query('SELECT @@ERROR AS code')->row()->code;\n\t\t\t$error['message'] = $message;\n\t\t}\n\n\t\treturn $error;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update statement\n\t *\n\t * Generates a platform-specific update string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @param\tarray\t$values\n\t * @return\tstring\n\t */\n\tprotected function _update($table, $values)\n\t{\n\t\t$this->qb_limit = FALSE;\n\t\t$this->qb_orderby = array();\n\t\treturn parent::_update($table, $values);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Truncate statement\n\t *\n\t * Generates a platform-specific truncate string from the supplied data\n\t *\n\t * If the database does not support the TRUNCATE statement,\n\t * then this method maps to 'DELETE FROM table'\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _truncate($table)\n\t{\n\t\treturn 'TRUNCATE TABLE '.$table;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Delete statement\n\t *\n\t * Generates a platform-specific delete string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _delete($table)\n\t{\n\t\tif ($this->qb_limit)\n\t\t{\n\t\t\treturn 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete';\n\t\t}\n\n\t\treturn parent::_delete($table);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * LIMIT\n\t *\n\t * Generates a platform-specific LIMIT clause\n\t *\n\t * @param\tstring\t$sql\tSQL Query\n\t * @return\tstring\n\t */\n\tprotected function _limit($sql)\n\t{\n\t\t$limit = $this->qb_offset + $this->qb_limit;\n\n\t\t// As of SQL Server 2005 (9.0.*) ROW_NUMBER() is supported,\n\t\t// however an ORDER BY clause is required for it to work\n\t\tif (version_compare($this->version(), '9', '>=') && $this->qb_offset && ! empty($this->qb_orderby))\n\t\t{\n\t\t\t$orderby = $this->_compile_order_by();\n\n\t\t\t// We have to strip the ORDER BY clause\n\t\t\t$sql = trim(substr($sql, 0, strrpos($sql, $orderby)));\n\n\t\t\t// Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results\n\t\t\tif (count($this->qb_select) === 0)\n\t\t\t{\n\t\t\t\t$select = '*'; // Inevitable\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Use only field names and their aliases, everything else is out of our scope.\n\t\t\t\t$select = array();\n\t\t\t\t$field_regexp = ($this->_quoted_identifier)\n\t\t\t\t\t? '(\"[^\\\"]+\")' : '(\\[[^\\]]+\\])';\n\t\t\t\tfor ($i = 0, $c = count($this->qb_select); $i < $c; $i++)\n\t\t\t\t{\n\t\t\t\t\t$select[] = preg_match('/(?:\\s|\\.)'.$field_regexp.'$/i', $this->qb_select[$i], $m)\n\t\t\t\t\t\t? $m[1] : $this->qb_select[$i];\n\t\t\t\t}\n\t\t\t\t$select = implode(', ', $select);\n\t\t\t}\n\n\t\t\treturn 'SELECT '.$select.\" FROM (\\n\\n\"\n\t\t\t\t.preg_replace('/^(SELECT( DISTINCT)?)/i', '\\\\1 ROW_NUMBER() OVER('.trim($orderby).') AS '.$this->escape_identifiers('CI_rownum').', ', $sql)\n\t\t\t\t.\"\\n\\n) \".$this->escape_identifiers('CI_subquery')\n\t\t\t\t.\"\\nWHERE \".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit;\n\t\t}\n\n\t\treturn preg_replace('/(^\\SELECT (DISTINCT)?)/i','\\\\1 TOP '.$limit.' ', $sql);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert batch statement\n\t *\n\t * Generates a platform-specific insert string from the supplied data.\n\t *\n\t * @param\tstring\t$table\tTable name\n\t * @param\tarray\t$keys\tINSERT keys\n\t * @param\tarray\t$values\tINSERT values\n\t * @return\tstring|bool\n\t */\n\tprotected function _insert_batch($table, $keys, $values)\n\t{\n\t\t// Multiple-value inserts are only supported as of SQL Server 2008\n\t\tif (version_compare($this->version(), '10', '>='))\n\t\t{\n\t\t\treturn parent::_insert_batch($table, $keys, $values);\n\t\t}\n\n\t\treturn ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Close DB Connection\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _close()\n\t{\n\t\tmssql_close($this->conn_id);\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/mssql/mssql_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.3.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * MS SQL Forge Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_mssql_forge extends CI_DB_forge {\n\n\t/**\n\t * CREATE TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_table_if\t= \"IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\\nCREATE TABLE\";\n\n\t/**\n\t * DROP TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_drop_table_if\t= \"IF EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\\nDROP TABLE\";\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_unsigned\t\t= array(\n\t\t'TINYINT'\t=> 'SMALLINT',\n\t\t'SMALLINT'\t=> 'INT',\n\t\t'INT'\t\t=> 'BIGINT',\n\t\t'REAL'\t\t=> 'FLOAT'\n\t);\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ALTER TABLE\n\t *\n\t * @param\tstring\t$alter_type\tALTER type\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tmixed\t$field\t\tColumn definition\n\t * @return\tstring|string[]\n\t */\n\tprotected function _alter_table($alter_type, $table, $field)\n\t{\n\t\tif (in_array($alter_type, array('ADD', 'DROP'), TRUE))\n\t\t{\n\t\t\treturn parent::_alter_table($alter_type, $table, $field);\n\t\t}\n\n\t\t$sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ALTER COLUMN ';\n\t\t$sqls = array();\n\t\tfor ($i = 0, $c = count($field); $i < $c; $i++)\n\t\t{\n\t\t\t$sqls[] = $sql.$this->_process_column($field[$i]);\n\t\t}\n\n\t\treturn $sqls;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute TYPE\n\t *\n\t * Performs a data type mapping between different databases.\n\t *\n\t * @param\tarray\t&$attributes\n\t * @return\tvoid\n\t */\n\tprotected function _attr_type(&$attributes)\n\t{\n\t\tif (isset($attributes['CONSTRAINT']) && strpos($attributes['TYPE'], 'INT') !== FALSE)\n\t\t{\n\t\t\tunset($attributes['CONSTRAINT']);\n\t\t}\n\n\t\tswitch (strtoupper($attributes['TYPE']))\n\t\t{\n\t\t\tcase 'MEDIUMINT':\n\t\t\t\t$attributes['TYPE'] = 'INTEGER';\n\t\t\t\t$attributes['UNSIGNED'] = FALSE;\n\t\t\t\treturn;\n\t\t\tcase 'INTEGER':\n\t\t\t\t$attributes['TYPE'] = 'INT';\n\t\t\t\treturn;\n\t\t\tdefault: return;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute AUTO_INCREMENT\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_auto_increment(&$attributes, &$field)\n\t{\n\t\tif ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)\n\t\t{\n\t\t\t$field['auto_increment'] = ' IDENTITY(1,1)';\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/mssql/mssql_result.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.3.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * MSSQL Result Class\n *\n * This class extends the parent result class: CI_DB_result\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_mssql_result extends CI_DB_result {\n\n\t/**\n\t * Number of rows in the result set\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_rows()\n\t{\n\t\treturn is_int($this->num_rows)\n\t\t\t? $this->num_rows\n\t\t\t: $this->num_rows = mssql_num_rows($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Number of fields in the result set\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_fields()\n\t{\n\t\treturn mssql_num_fields($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch Field Names\n\t *\n\t * Generates an array of column names\n\t *\n\t * @return\tarray\n\t */\n\tpublic function list_fields()\n\t{\n\t\t$field_names = array();\n\t\tmssql_field_seek($this->result_id, 0);\n\t\twhile ($field = mssql_fetch_field($this->result_id))\n\t\t{\n\t\t\t$field_names[] = $field->name;\n\t\t}\n\n\t\treturn $field_names;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field data\n\t *\n\t * Generates an array of objects containing field meta-data\n\t *\n\t * @return\tarray\n\t */\n\tpublic function field_data()\n\t{\n\t\t$retval = array();\n\t\tfor ($i = 0, $c = $this->num_fields(); $i < $c; $i++)\n\t\t{\n\t\t\t$field = mssql_fetch_field($this->result_id, $i);\n\n\t\t\t$retval[$i]\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t= $field->name;\n\t\t\t$retval[$i]->type\t= $field->type;\n\t\t\t$retval[$i]->max_length\t= $field->max_length;\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Free the result\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function free_result()\n\t{\n\t\tif (is_resource($this->result_id))\n\t\t{\n\t\t\tmssql_free_result($this->result_id);\n\t\t\t$this->result_id = FALSE;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Data Seek\n\t *\n\t * Moves the internal pointer to the desired offset. We call\n\t * this internally before fetching results to make sure the\n\t * result set starts at zero.\n\t *\n\t * @param\tint\t$n\n\t * @return\tbool\n\t */\n\tpublic function data_seek($n = 0)\n\t{\n\t\treturn mssql_data_seek($this->result_id, $n);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - associative array\n\t *\n\t * Returns the result set as an array\n\t *\n\t * @return\tarray\n\t */\n\tprotected function _fetch_assoc()\n\t{\n\t\treturn mssql_fetch_assoc($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - object\n\t *\n\t * Returns the result set as an object\n\t *\n\t * @param\tstring\t$class_name\n\t * @return\tobject\n\t */\n\tprotected function _fetch_object($class_name = 'stdClass')\n\t{\n\t\t$row = mssql_fetch_object($this->result_id);\n\n\t\tif ($class_name === 'stdClass' OR ! $row)\n\t\t{\n\t\t\treturn $row;\n\t\t}\n\n\t\t$class_name = new $class_name();\n\t\tforeach ($row as $key => $value)\n\t\t{\n\t\t\t$class_name->$key = $value;\n\t\t}\n\n\t\treturn $class_name;\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/mssql/mssql_utility.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.3.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * MS SQL Utility Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_mssql_utility extends CI_DB_utility {\n\n\t/**\n\t * List databases statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_list_databases\t= 'EXEC sp_helpdb'; // Can also be: EXEC sp_databases\n\n\t/**\n\t * OPTIMIZE TABLE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_optimize_table\t= 'ALTER INDEX all ON %s REORGANIZE';\n\n\t/**\n\t * Export\n\t *\n\t * @param\tarray\t$params\tPreferences\n\t * @return\tbool\n\t */\n\tprotected function _backup($params = array())\n\t{\n\t\t// Currently unsupported\n\t\treturn $this->db->display_error('db_unsupported_feature');\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/mysql/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/database/drivers/mysql/mysql_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * MySQL Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_mysql_driver extends CI_DB {\n\n\t/**\n\t * Database driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $dbdriver = 'mysql';\n\n\t/**\n\t * Compression flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $compress = FALSE;\n\n\t/**\n\t * DELETE hack flag\n\t *\n\t * Whether to use the MySQL \"delete hack\" which allows the number\n\t * of affected rows to be shown. Uses a preg_replace when enabled,\n\t * adding a bit more processing to all queries.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $delete_hack = TRUE;\n\n\t/**\n\t * Strict ON flag\n\t *\n\t * Whether we're running in strict SQL mode.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $stricton;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Identifier escape character\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_escape_char = '`';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif ( ! empty($this->port))\n\t\t{\n\t\t\t$this->hostname .= ':'.$this->port;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Non-persistent database connection\n\t *\n\t * @param\tbool\t$persistent\n\t * @return\tresource\n\t */\n\tpublic function db_connect($persistent = FALSE)\n\t{\n\t\t$client_flags = ($this->compress === FALSE) ? 0 : MYSQL_CLIENT_COMPRESS;\n\n\t\tif ($this->encrypt === TRUE)\n\t\t{\n\t\t\t$client_flags = $client_flags | MYSQL_CLIENT_SSL;\n\t\t}\n\n\t\t// Error suppression is necessary mostly due to PHP 5.5+ issuing E_DEPRECATED messages\n\t\t$this->conn_id = ($persistent === TRUE)\n\t\t\t? mysql_pconnect($this->hostname, $this->username, $this->password, $client_flags)\n\t\t\t: mysql_connect($this->hostname, $this->username, $this->password, TRUE, $client_flags);\n\n\t\t// ----------------------------------------------------------------\n\n\t\t// Select the DB... assuming a database name is specified in the config file\n\t\tif ($this->database !== '' && ! $this->db_select())\n\t\t{\n\t\t\tlog_message('error', 'Unable to select database: '.$this->database);\n\n\t\t\treturn ($this->db_debug === TRUE)\n\t\t\t\t? $this->display_error('db_unable_to_select', $this->database)\n\t\t\t\t: FALSE;\n\t\t}\n\n\t\tif (isset($this->stricton) && is_resource($this->conn_id))\n\t\t{\n\t\t\tif ($this->stricton)\n\t\t\t{\n\t\t\t\t$this->simple_query('SET SESSION sql_mode = CONCAT(@@sql_mode, \",\", \"STRICT_ALL_TABLES\")');\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->simple_query(\n\t\t\t\t\t'SET SESSION sql_mode =\n\t\t\t\t\tREPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(\n\t\t\t\t\t@@sql_mode,\n\t\t\t\t\t\"STRICT_ALL_TABLES,\", \"\"),\n\t\t\t\t\t\",STRICT_ALL_TABLES\", \"\"),\n\t\t\t\t\t\"STRICT_ALL_TABLES\", \"\"),\n\t\t\t\t\t\"STRICT_TRANS_TABLES,\", \"\"),\n\t\t\t\t\t\",STRICT_TRANS_TABLES\", \"\"),\n\t\t\t\t\t\"STRICT_TRANS_TABLES\", \"\")'\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn $this->conn_id;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Reconnect\n\t *\n\t * Keep / reestablish the db connection if no queries have been\n\t * sent for a length of time exceeding the server's idle timeout\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function reconnect()\n\t{\n\t\tif (mysql_ping($this->conn_id) === FALSE)\n\t\t{\n\t\t\t$this->conn_id = FALSE;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Select the database\n\t *\n\t * @param\tstring\t$database\n\t * @return\tbool\n\t */\n\tpublic function db_select($database = '')\n\t{\n\t\tif ($database === '')\n\t\t{\n\t\t\t$database = $this->database;\n\t\t}\n\n\t\tif (mysql_select_db($database, $this->conn_id))\n\t\t{\n\t\t\t$this->database = $database;\n\t\t\t$this->data_cache = array();\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set client character set\n\t *\n\t * @param\tstring\t$charset\n\t * @return\tbool\n\t */\n\tprotected function _db_set_charset($charset)\n\t{\n\t\treturn mysql_set_charset($charset, $this->conn_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Database version number\n\t *\n\t * @return\tstring\n\t */\n\tpublic function version()\n\t{\n\t\tif (isset($this->data_cache['version']))\n\t\t{\n\t\t\treturn $this->data_cache['version'];\n\t\t}\n\n\t\tif ( ! $this->conn_id OR ($version = mysql_get_server_info($this->conn_id)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn $this->data_cache['version'] = $version;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Execute the query\n\t *\n\t * @param\tstring\t$sql\tan SQL query\n\t * @return\tmixed\n\t */\n\tprotected function _execute($sql)\n\t{\n\t\treturn mysql_query($this->_prep_query($sql), $this->conn_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prep the query\n\t *\n\t * If needed, each database adapter can prep the query string\n\t *\n\t * @param\tstring\t$sql\tan SQL query\n\t * @return\tstring\n\t */\n\tprotected function _prep_query($sql)\n\t{\n\t\t// mysql_affected_rows() returns 0 for \"DELETE FROM TABLE\" queries. This hack\n\t\t// modifies the query so that it a proper number of affected rows is returned.\n\t\tif ($this->delete_hack === TRUE && preg_match('/^\\s*DELETE\\s+FROM\\s+(\\S+)\\s*$/i', $sql))\n\t\t{\n\t\t\treturn trim($sql).' WHERE 1=1';\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Begin Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_begin()\n\t{\n\t\t$this->simple_query('SET AUTOCOMMIT=0');\n\t\treturn $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Commit Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_commit()\n\t{\n\t\tif ($this->simple_query('COMMIT'))\n\t\t{\n\t\t\t$this->simple_query('SET AUTOCOMMIT=1');\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Rollback Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_rollback()\n\t{\n\t\tif ($this->simple_query('ROLLBACK'))\n\t\t{\n\t\t\t$this->simple_query('SET AUTOCOMMIT=1');\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Platform-dependant string escape\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _escape_str($str)\n\t{\n\t\treturn mysql_real_escape_string($str, $this->conn_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Affected Rows\n\t *\n\t * @return\tint\n\t */\n\tpublic function affected_rows()\n\t{\n\t\treturn mysql_affected_rows($this->conn_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert ID\n\t *\n\t * @return\tint\n\t */\n\tpublic function insert_id()\n\t{\n\t\treturn mysql_insert_id($this->conn_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * List table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\t$prefix_limit\n\t * @return\tstring\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\t$sql = 'SHOW TABLES FROM '.$this->escape_identifiers($this->database);\n\n\t\tif ($prefix_limit !== FALSE && $this->dbprefix !== '')\n\t\t{\n\t\t\treturn $sql.\" LIKE '\".$this->escape_like_str($this->dbprefix).\"%'\";\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show column query\n\t *\n\t * Generates a platform-specific query string so that the column names can be fetched\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _list_columns($table = '')\n\t{\n\t\treturn 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an object with field data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tarray\n\t */\n\tpublic function field_data($table)\n\t{\n\t\tif (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\t$query = $query->result_object();\n\n\t\t$retval = array();\n\t\tfor ($i = 0, $c = count($query); $i < $c; $i++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= $query[$i]->Field;\n\n\t\t\tsscanf($query[$i]->Type, '%[a-z](%d)',\n\t\t\t\t$retval[$i]->type,\n\t\t\t\t$retval[$i]->max_length\n\t\t\t);\n\n\t\t\t$retval[$i]->default\t\t= $query[$i]->Default;\n\t\t\t$retval[$i]->primary_key\t= (int) ($query[$i]->Key === 'PRI');\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Error\n\t *\n\t * Returns an array containing code and message of the last\n\t * database error that has occured.\n\t *\n\t * @return\tarray\n\t */\n\tpublic function error()\n\t{\n\t\treturn array('code' => mysql_errno($this->conn_id), 'message' => mysql_error($this->conn_id));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * FROM tables\n\t *\n\t * Groups tables in FROM clauses if needed, so there is no confusion\n\t * about operator precedence.\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _from_tables()\n\t{\n\t\tif ( ! empty($this->qb_join) && count($this->qb_from) > 1)\n\t\t{\n\t\t\treturn '('.implode(', ', $this->qb_from).')';\n\t\t}\n\n\t\treturn implode(', ', $this->qb_from);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Close DB Connection\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _close()\n\t{\n\t\t// Error suppression to avoid annoying E_WARNINGs in cases\n\t\t// where the connection has already been closed for some reason.\n\t\t@mysql_close($this->conn_id);\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/mysql/mysql_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * MySQL Forge Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_mysql_forge extends CI_DB_forge {\n\n\t/**\n\t * CREATE DATABASE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_database\t= 'CREATE DATABASE %s CHARACTER SET %s COLLATE %s';\n\n\t/**\n\t * CREATE TABLE keys flag\n\t *\n\t * Whether table keys are created from within the\n\t * CREATE TABLE statement.\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_create_table_keys\t= TRUE;\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_unsigned\t\t= array(\n\t\t'TINYINT',\n\t\t'SMALLINT',\n\t\t'MEDIUMINT',\n\t\t'INT',\n\t\t'INTEGER',\n\t\t'BIGINT',\n\t\t'REAL',\n\t\t'DOUBLE',\n\t\t'DOUBLE PRECISION',\n\t\t'FLOAT',\n\t\t'DECIMAL',\n\t\t'NUMERIC'\n\t);\n\n\t/**\n\t * NULL value representation in CREATE/ALTER TABLE statements\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_null = 'NULL';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * CREATE TABLE attributes\n\t *\n\t * @param\tarray\t$attributes\tAssociative array of table attributes\n\t * @return\tstring\n\t */\n\tprotected function _create_table_attr($attributes)\n\t{\n\t\t$sql = '';\n\n\t\tforeach (array_keys($attributes) as $key)\n\t\t{\n\t\t\tif (is_string($key))\n\t\t\t{\n\t\t\t\t$sql .= ' '.strtoupper($key).' = '.$attributes[$key];\n\t\t\t}\n\t\t}\n\n\t\tif ( ! empty($this->db->char_set) && ! strpos($sql, 'CHARACTER SET') && ! strpos($sql, 'CHARSET'))\n\t\t{\n\t\t\t$sql .= ' DEFAULT CHARACTER SET = '.$this->db->char_set;\n\t\t}\n\n\t\tif ( ! empty($this->db->dbcollat) && ! strpos($sql, 'COLLATE'))\n\t\t{\n\t\t\t$sql .= ' COLLATE = '.$this->db->dbcollat;\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ALTER TABLE\n\t *\n\t * @param\tstring\t$alter_type\tALTER type\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tmixed\t$field\t\tColumn definition\n\t * @return\tstring|string[]\n\t */\n\tprotected function _alter_table($alter_type, $table, $field)\n\t{\n\t\tif ($alter_type === 'DROP')\n\t\t{\n\t\t\treturn parent::_alter_table($alter_type, $table, $field);\n\t\t}\n\n\t\t$sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);\n\t\tfor ($i = 0, $c = count($field); $i < $c; $i++)\n\t\t{\n\t\t\tif ($field[$i]['_literal'] !== FALSE)\n\t\t\t{\n\t\t\t\t$field[$i] = ($alter_type === 'ADD')\n\t\t\t\t\t\t? \"\\n\\tADD \".$field[$i]['_literal']\n\t\t\t\t\t\t: \"\\n\\tMODIFY \".$field[$i]['_literal'];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif ($alter_type === 'ADD')\n\t\t\t\t{\n\t\t\t\t\t$field[$i]['_literal'] = \"\\n\\tADD \";\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$field[$i]['_literal'] = empty($field[$i]['new_name']) ? \"\\n\\tMODIFY \" : \"\\n\\tCHANGE \";\n\t\t\t\t}\n\n\t\t\t\t$field[$i] = $field[$i]['_literal'].$this->_process_column($field[$i]);\n\t\t\t}\n\t\t}\n\n\t\treturn array($sql.implode(',', $field));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Process column\n\t *\n\t * @param\tarray\t$field\n\t * @return\tstring\n\t */\n\tprotected function _process_column($field)\n\t{\n\t\t$extra_clause = isset($field['after'])\n\t\t\t? ' AFTER '.$this->db->escape_identifiers($field['after']) : '';\n\n\t\tif (empty($extra_clause) && isset($field['first']) && $field['first'] === TRUE)\n\t\t{\n\t\t\t$extra_clause = ' FIRST';\n\t\t}\n\n\n\t\treturn $this->db->escape_identifiers($field['name'])\n\t\t\t.(empty($field['new_name']) ? '' : ' '.$this->db->escape_identifiers($field['new_name']))\n\t\t\t.' '.$field['type'].$field['length']\n\t\t\t.$field['unsigned']\n\t\t\t.$field['null']\n\t\t\t.$field['default']\n\t\t\t.$field['auto_increment']\n\t\t\t.$field['unique']\n\t\t\t.(empty($field['comment']) ? '' : ' COMMENT '.$field['comment'])\n\t\t\t.$extra_clause;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Process indexes\n\t *\n\t * @param\tstring\t$table\t(ignored)\n\t * @return\tstring\n\t */\n\tprotected function _process_indexes($table)\n\t{\n\t\t$sql = '';\n\n\t\tfor ($i = 0, $c = count($this->keys); $i < $c; $i++)\n\t\t{\n\t\t\tif (is_array($this->keys[$i]))\n\t\t\t{\n\t\t\t\tfor ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++)\n\t\t\t\t{\n\t\t\t\t\tif ( ! isset($this->fields[$this->keys[$i][$i2]]))\n\t\t\t\t\t{\n\t\t\t\t\t\tunset($this->keys[$i][$i2]);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ( ! isset($this->fields[$this->keys[$i]]))\n\t\t\t{\n\t\t\t\tunset($this->keys[$i]);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tis_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);\n\n\t\t\t$sql .= \",\\n\\tKEY \".$this->db->escape_identifiers(implode('_', $this->keys[$i]))\n\t\t\t\t.' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';\n\t\t}\n\n\t\t$this->keys = array();\n\n\t\treturn $sql;\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/mysql/mysql_result.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * MySQL Result Class\n *\n * This class extends the parent result class: CI_DB_result\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_mysql_result extends CI_DB_result {\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tobject\t&$driver_object\n\t * @return\tvoid\n\t */\n\tpublic function __construct(&$driver_object)\n\t{\n\t\tparent::__construct($driver_object);\n\n\t\t// Required, due to mysql_data_seek() causing nightmares\n\t\t// with empty result sets\n\t\t$this->num_rows = mysql_num_rows($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Number of rows in the result set\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_rows()\n\t{\n\t\treturn $this->num_rows;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Number of fields in the result set\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_fields()\n\t{\n\t\treturn mysql_num_fields($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch Field Names\n\t *\n\t * Generates an array of column names\n\t *\n\t * @return\tarray\n\t */\n\tpublic function list_fields()\n\t{\n\t\t$field_names = array();\n\t\tmysql_field_seek($this->result_id, 0);\n\t\twhile ($field = mysql_fetch_field($this->result_id))\n\t\t{\n\t\t\t$field_names[] = $field->name;\n\t\t}\n\n\t\treturn $field_names;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field data\n\t *\n\t * Generates an array of objects containing field meta-data\n\t *\n\t * @return\tarray\n\t */\n\tpublic function field_data()\n\t{\n\t\t$retval = array();\n\t\tfor ($i = 0, $c = $this->num_fields(); $i < $c; $i++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= mysql_field_name($this->result_id, $i);\n\t\t\t$retval[$i]->type\t\t= mysql_field_type($this->result_id, $i);\n\t\t\t$retval[$i]->max_length\t\t= mysql_field_len($this->result_id, $i);\n\t\t\t$retval[$i]->primary_key\t= (int) (strpos(mysql_field_flags($this->result_id, $i), 'primary_key') !== FALSE);\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Free the result\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function free_result()\n\t{\n\t\tif (is_resource($this->result_id))\n\t\t{\n\t\t\tmysql_free_result($this->result_id);\n\t\t\t$this->result_id = FALSE;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Data Seek\n\t *\n\t * Moves the internal pointer to the desired offset. We call\n\t * this internally before fetching results to make sure the\n\t * result set starts at zero.\n\t *\n\t * @param\tint\t$n\n\t * @return\tbool\n\t */\n\tpublic function data_seek($n = 0)\n\t{\n\t\treturn $this->num_rows\n\t\t\t? mysql_data_seek($this->result_id, $n)\n\t\t\t: FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - associative array\n\t *\n\t * Returns the result set as an array\n\t *\n\t * @return\tarray\n\t */\n\tprotected function _fetch_assoc()\n\t{\n\t\treturn mysql_fetch_assoc($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - object\n\t *\n\t * Returns the result set as an object\n\t *\n\t * @param\tstring\t$class_name\n\t * @return\tobject\n\t */\n\tprotected function _fetch_object($class_name = 'stdClass')\n\t{\n\t\treturn mysql_fetch_object($this->result_id, $class_name);\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/mysql/mysql_utility.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * MySQL Utility Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_mysql_utility extends CI_DB_utility {\n\n\t/**\n\t * List databases statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_list_databases\t= 'SHOW DATABASES';\n\n\t/**\n\t * OPTIMIZE TABLE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_optimize_table\t= 'OPTIMIZE TABLE %s';\n\n\t/**\n\t * REPAIR TABLE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_repair_table\t= 'REPAIR TABLE %s';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Export\n\t *\n\t * @param\tarray\t$params\tPreferences\n\t * @return\tmixed\n\t */\n\tprotected function _backup($params = array())\n\t{\n\t\tif (count($params) === 0)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Extract the prefs for simplicity\n\t\textract($params);\n\n\t\t// Build the output\n\t\t$output = '';\n\n\t\t// Do we need to include a statement to disable foreign key checks?\n\t\tif ($foreign_key_checks === FALSE)\n\t\t{\n\t\t\t$output .= 'SET foreign_key_checks = 0;'.$newline;\n\t\t}\n\n\t\tforeach ( (array) $tables as $table)\n\t\t{\n\t\t\t// Is the table in the \"ignore\" list?\n\t\t\tif (in_array($table, (array) $ignore, TRUE))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Get the table schema\n\t\t\t$query = $this->db->query('SHOW CREATE TABLE '.$this->db->escape_identifiers($this->db->database.'.'.$table));\n\n\t\t\t// No result means the table name was invalid\n\t\t\tif ($query === FALSE)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Write out the table schema\n\t\t\t$output .= '#'.$newline.'# TABLE STRUCTURE FOR: '.$table.$newline.'#'.$newline.$newline;\n\n\t\t\tif ($add_drop === TRUE)\n\t\t\t{\n\t\t\t\t$output .= 'DROP TABLE IF EXISTS '.$this->db->protect_identifiers($table).';'.$newline.$newline;\n\t\t\t}\n\n\t\t\t$i = 0;\n\t\t\t$result = $query->result_array();\n\t\t\tforeach ($result[0] as $val)\n\t\t\t{\n\t\t\t\tif ($i++ % 2)\n\t\t\t\t{\n\t\t\t\t\t$output .= $val.';'.$newline.$newline;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If inserts are not needed we're done...\n\t\t\tif ($add_insert === FALSE)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Grab all the data from the current table\n\t\t\t$query = $this->db->query('SELECT * FROM '.$this->db->protect_identifiers($table));\n\n\t\t\tif ($query->num_rows() === 0)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Fetch the field names and determine if the field is an\n\t\t\t// integer type. We use this info to decide whether to\n\t\t\t// surround the data with quotes or not\n\n\t\t\t$i = 0;\n\t\t\t$field_str = '';\n\t\t\t$is_int = array();\n\t\t\twhile ($field = mysql_fetch_field($query->result_id))\n\t\t\t{\n\t\t\t\t// Most versions of MySQL store timestamp as a string\n\t\t\t\t$is_int[$i] = in_array(strtolower(mysql_field_type($query->result_id, $i)),\n\t\t\t\t\t\t\tarray('tinyint', 'smallint', 'mediumint', 'int', 'bigint'), //, 'timestamp'),\n\t\t\t\t\t\t\tTRUE);\n\n\t\t\t\t// Create a string of field names\n\t\t\t\t$field_str .= $this->db->escape_identifiers($field->name).', ';\n\t\t\t\t$i++;\n\t\t\t}\n\n\t\t\t// Trim off the end comma\n\t\t\t$field_str = preg_replace('/, $/' , '', $field_str);\n\n\t\t\t// Build the insert string\n\t\t\tforeach ($query->result_array() as $row)\n\t\t\t{\n\t\t\t\t$val_str = '';\n\n\t\t\t\t$i = 0;\n\t\t\t\tforeach ($row as $v)\n\t\t\t\t{\n\t\t\t\t\t// Is the value NULL?\n\t\t\t\t\tif ($v === NULL)\n\t\t\t\t\t{\n\t\t\t\t\t\t$val_str .= 'NULL';\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// Escape the data if it's not an integer\n\t\t\t\t\t\t$val_str .= ($is_int[$i] === FALSE) ? $this->db->escape($v) : $v;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Append a comma\n\t\t\t\t\t$val_str .= ', ';\n\t\t\t\t\t$i++;\n\t\t\t\t}\n\n\t\t\t\t// Remove the comma at the end of the string\n\t\t\t\t$val_str = preg_replace('/, $/' , '', $val_str);\n\n\t\t\t\t// Build the INSERT string\n\t\t\t\t$output .= 'INSERT INTO '.$this->db->protect_identifiers($table).' ('.$field_str.') VALUES ('.$val_str.');'.$newline;\n\t\t\t}\n\n\t\t\t$output .= $newline.$newline;\n\t\t}\n\n\t\t// Do we need to include a statement to re-enable foreign key checks?\n\t\tif ($foreign_key_checks === FALSE)\n\t\t{\n\t\t\t$output .= 'SET foreign_key_checks = 1;'.$newline;\n\t\t}\n\n\t\treturn $output;\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/mysqli/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/database/drivers/mysqli/mysqli_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.3.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * MySQLi Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_mysqli_driver extends CI_DB {\n\n\t/**\n\t * Database driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $dbdriver = 'mysqli';\n\n\t/**\n\t * Compression flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $compress = FALSE;\n\n\t/**\n\t * DELETE hack flag\n\t *\n\t * Whether to use the MySQL \"delete hack\" which allows the number\n\t * of affected rows to be shown. Uses a preg_replace when enabled,\n\t * adding a bit more processing to all queries.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $delete_hack = TRUE;\n\n\t/**\n\t * Strict ON flag\n\t *\n\t * Whether we're running in strict SQL mode.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $stricton;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Identifier escape character\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_escape_char = '`';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * MySQLi object\n\t *\n\t * Has to be preserved without being assigned to $conn_id.\n\t *\n\t * @var\tMySQLi\n\t */\n\tprotected $_mysqli;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Database connection\n\t *\n\t * @param\tbool\t$persistent\n\t * @return\tobject\n\t */\n\tpublic function db_connect($persistent = FALSE)\n\t{\n\t\t// Do we have a socket path?\n\t\tif ($this->hostname[0] === '/')\n\t\t{\n\t\t\t$hostname = NULL;\n\t\t\t$port = NULL;\n\t\t\t$socket = $this->hostname;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Persistent connection support was added in PHP 5.3.0\n\t\t\t$hostname = ($persistent === TRUE && is_php('5.3'))\n\t\t\t\t? 'p:'.$this->hostname : $this->hostname;\n\t\t\t$port = empty($this->port) ? NULL : $this->port;\n\t\t\t$socket = NULL;\n\t\t}\n\n\t\t$client_flags = ($this->compress === TRUE) ? MYSQLI_CLIENT_COMPRESS : 0;\n\t\t$this->_mysqli = mysqli_init();\n\n\t\t$this->_mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 10);\n\n\t\tif (isset($this->stricton))\n\t\t{\n\t\t\tif ($this->stricton)\n\t\t\t{\n\t\t\t\t$this->_mysqli->options(MYSQLI_INIT_COMMAND, 'SET SESSION sql_mode = CONCAT(@@sql_mode, \",\", \"STRICT_ALL_TABLES\")');\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->_mysqli->options(MYSQLI_INIT_COMMAND,\n\t\t\t\t\t'SET SESSION sql_mode =\n\t\t\t\t\tREPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(\n\t\t\t\t\t@@sql_mode,\n\t\t\t\t\t\"STRICT_ALL_TABLES,\", \"\"),\n\t\t\t\t\t\",STRICT_ALL_TABLES\", \"\"),\n\t\t\t\t\t\"STRICT_ALL_TABLES\", \"\"),\n\t\t\t\t\t\"STRICT_TRANS_TABLES,\", \"\"),\n\t\t\t\t\t\",STRICT_TRANS_TABLES\", \"\"),\n\t\t\t\t\t\"STRICT_TRANS_TABLES\", \"\")'\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (is_array($this->encrypt))\n\t\t{\n\t\t\t$ssl = array();\n\t\t\tempty($this->encrypt['ssl_key'])    OR $ssl['key']    = $this->encrypt['ssl_key'];\n\t\t\tempty($this->encrypt['ssl_cert'])   OR $ssl['cert']   = $this->encrypt['ssl_cert'];\n\t\t\tempty($this->encrypt['ssl_ca'])     OR $ssl['ca']     = $this->encrypt['ssl_ca'];\n\t\t\tempty($this->encrypt['ssl_capath']) OR $ssl['capath'] = $this->encrypt['ssl_capath'];\n\t\t\tempty($this->encrypt['ssl_cipher']) OR $ssl['cipher'] = $this->encrypt['ssl_cipher'];\n\n\t\t\tif ( ! empty($ssl))\n\t\t\t{\n\t\t\t\tif (isset($this->encrypt['ssl_verify']))\n\t\t\t\t{\n\t\t\t\t\tif ($this->encrypt['ssl_verify'])\n\t\t\t\t\t{\n\t\t\t\t\t\tdefined('MYSQLI_OPT_SSL_VERIFY_SERVER_CERT') && $this->_mysqli->options(MYSQLI_OPT_SSL_VERIFY_SERVER_CERT, TRUE);\n\t\t\t\t\t}\n\t\t\t\t\t// Apparently (when it exists), setting MYSQLI_OPT_SSL_VERIFY_SERVER_CERT\n\t\t\t\t\t// to FALSE didn't do anything, so PHP 5.6.16 introduced yet another\n\t\t\t\t\t// constant ...\n\t\t\t\t\t//\n\t\t\t\t\t// https://secure.php.net/ChangeLog-5.php#5.6.16\n\t\t\t\t\t// https://bugs.php.net/bug.php?id=68344\n\t\t\t\t\telseif (defined('MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT'))\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->_mysqli->options(MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT, TRUE);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t$client_flags |= MYSQLI_CLIENT_SSL;\n\t\t\t\t$this->_mysqli->ssl_set(\n\t\t\t\t\tisset($ssl['key'])    ? $ssl['key']    : NULL,\n\t\t\t\t\tisset($ssl['cert'])   ? $ssl['cert']   : NULL,\n\t\t\t\t\tisset($ssl['ca'])     ? $ssl['ca']     : NULL,\n\t\t\t\t\tisset($ssl['capath']) ? $ssl['capath'] : NULL,\n\t\t\t\t\tisset($ssl['cipher']) ? $ssl['cipher'] : NULL\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif ($this->_mysqli->real_connect($hostname, $this->username, $this->password, $this->database, $port, $socket, $client_flags))\n\t\t{\n\t\t\t// Prior to version 5.7.3, MySQL silently downgrades to an unencrypted connection if SSL setup fails\n\t\t\tif (\n\t\t\t\t($client_flags & MYSQLI_CLIENT_SSL)\n\t\t\t\t&& version_compare($this->_mysqli->client_info, '5.7.3', '<=')\n\t\t\t\t&& empty($this->_mysqli->query(\"SHOW STATUS LIKE 'ssl_cipher'\")->fetch_object()->Value)\n\t\t\t)\n\t\t\t{\n\t\t\t\t$this->_mysqli->close();\n\t\t\t\t$message = 'MySQLi was configured for an SSL connection, but got an unencrypted connection instead!';\n\t\t\t\tlog_message('error', $message);\n\t\t\t\treturn ($this->db->db_debug) ? $this->db->display_error($message, '', TRUE) : FALSE;\n\t\t\t}\n\n\t\t\treturn $this->_mysqli;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Reconnect\n\t *\n\t * Keep / reestablish the db connection if no queries have been\n\t * sent for a length of time exceeding the server's idle timeout\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function reconnect()\n\t{\n\t\tif ($this->conn_id !== FALSE && $this->conn_id->ping() === FALSE)\n\t\t{\n\t\t\t$this->conn_id = FALSE;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Select the database\n\t *\n\t * @param\tstring\t$database\n\t * @return\tbool\n\t */\n\tpublic function db_select($database = '')\n\t{\n\t\tif ($database === '')\n\t\t{\n\t\t\t$database = $this->database;\n\t\t}\n\n\t\tif ($this->conn_id->select_db($database))\n\t\t{\n\t\t\t$this->database = $database;\n\t\t\t$this->data_cache = array();\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set client character set\n\t *\n\t * @param\tstring\t$charset\n\t * @return\tbool\n\t */\n\tprotected function _db_set_charset($charset)\n\t{\n\t\treturn $this->conn_id->set_charset($charset);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Database version number\n\t *\n\t * @return\tstring\n\t */\n\tpublic function version()\n\t{\n\t\tif (isset($this->data_cache['version']))\n\t\t{\n\t\t\treturn $this->data_cache['version'];\n\t\t}\n\n\t\treturn $this->data_cache['version'] = $this->conn_id->server_info;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Execute the query\n\t *\n\t * @param\tstring\t$sql\tan SQL query\n\t * @return\tmixed\n\t */\n\tprotected function _execute($sql)\n\t{\n\t\treturn $this->conn_id->query($this->_prep_query($sql));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prep the query\n\t *\n\t * If needed, each database adapter can prep the query string\n\t *\n\t * @param\tstring\t$sql\tan SQL query\n\t * @return\tstring\n\t */\n\tprotected function _prep_query($sql)\n\t{\n\t\t// mysqli_affected_rows() returns 0 for \"DELETE FROM TABLE\" queries. This hack\n\t\t// modifies the query so that it a proper number of affected rows is returned.\n\t\tif ($this->delete_hack === TRUE && preg_match('/^\\s*DELETE\\s+FROM\\s+(\\S+)\\s*$/i', $sql))\n\t\t{\n\t\t\treturn trim($sql).' WHERE 1=1';\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Begin Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_begin()\n\t{\n\t\t$this->conn_id->autocommit(FALSE);\n\t\treturn is_php('5.5')\n\t\t\t? $this->conn_id->begin_transaction()\n\t\t\t: $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Commit Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_commit()\n\t{\n\t\tif ($this->conn_id->commit())\n\t\t{\n\t\t\t$this->conn_id->autocommit(TRUE);\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Rollback Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_rollback()\n\t{\n\t\tif ($this->conn_id->rollback())\n\t\t{\n\t\t\t$this->conn_id->autocommit(TRUE);\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Platform-dependant string escape\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _escape_str($str)\n\t{\n\t\treturn $this->conn_id->real_escape_string($str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Affected Rows\n\t *\n\t * @return\tint\n\t */\n\tpublic function affected_rows()\n\t{\n\t\treturn $this->conn_id->affected_rows;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert ID\n\t *\n\t * @return\tint\n\t */\n\tpublic function insert_id()\n\t{\n\t\treturn $this->conn_id->insert_id;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * List table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\t$prefix_limit\n\t * @return\tstring\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\t$sql = 'SHOW TABLES FROM '.$this->escape_identifiers($this->database);\n\n\t\tif ($prefix_limit !== FALSE && $this->dbprefix !== '')\n\t\t{\n\t\t\treturn $sql.\" LIKE '\".$this->escape_like_str($this->dbprefix).\"%'\";\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show column query\n\t *\n\t * Generates a platform-specific query string so that the column names can be fetched\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _list_columns($table = '')\n\t{\n\t\treturn 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an object with field data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tarray\n\t */\n\tpublic function field_data($table)\n\t{\n\t\tif (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\t$query = $query->result_object();\n\n\t\t$retval = array();\n\t\tfor ($i = 0, $c = count($query); $i < $c; $i++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= $query[$i]->Field;\n\n\t\t\tsscanf($query[$i]->Type, '%[a-z](%d)',\n\t\t\t\t$retval[$i]->type,\n\t\t\t\t$retval[$i]->max_length\n\t\t\t);\n\n\t\t\t$retval[$i]->default\t\t= $query[$i]->Default;\n\t\t\t$retval[$i]->primary_key\t= (int) ($query[$i]->Key === 'PRI');\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Error\n\t *\n\t * Returns an array containing code and message of the last\n\t * database error that has occurred.\n\t *\n\t * @return\tarray\n\t */\n\tpublic function error()\n\t{\n\t\tif ( ! empty($this->_mysqli->connect_errno))\n\t\t{\n\t\t\treturn array(\n\t\t\t\t'code' => $this->_mysqli->connect_errno,\n\t\t\t\t'message' => is_php('5.2.9') ? $this->_mysqli->connect_error : mysqli_connect_error()\n\t\t\t);\n\t\t}\n\n\t\treturn array('code' => $this->conn_id->errno, 'message' => $this->conn_id->error);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * FROM tables\n\t *\n\t * Groups tables in FROM clauses if needed, so there is no confusion\n\t * about operator precedence.\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _from_tables()\n\t{\n\t\tif ( ! empty($this->qb_join) && count($this->qb_from) > 1)\n\t\t{\n\t\t\treturn '('.implode(', ', $this->qb_from).')';\n\t\t}\n\n\t\treturn implode(', ', $this->qb_from);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Close DB Connection\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _close()\n\t{\n\t\t$this->conn_id->close();\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/mysqli/mysqli_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.3.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * MySQLi Forge Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_mysqli_forge extends CI_DB_forge {\n\n\t/**\n\t * CREATE DATABASE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_database\t= 'CREATE DATABASE %s CHARACTER SET %s COLLATE %s';\n\n\t/**\n\t * CREATE TABLE keys flag\n\t *\n\t * Whether table keys are created from within the\n\t * CREATE TABLE statement.\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_create_table_keys\t= TRUE;\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_unsigned\t\t= array(\n\t\t'TINYINT',\n\t\t'SMALLINT',\n\t\t'MEDIUMINT',\n\t\t'INT',\n\t\t'INTEGER',\n\t\t'BIGINT',\n\t\t'REAL',\n\t\t'DOUBLE',\n\t\t'DOUBLE PRECISION',\n\t\t'FLOAT',\n\t\t'DECIMAL',\n\t\t'NUMERIC'\n\t);\n\n\t/**\n\t * NULL value representation in CREATE/ALTER TABLE statements\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_null = 'NULL';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * CREATE TABLE attributes\n\t *\n\t * @param\tarray\t$attributes\tAssociative array of table attributes\n\t * @return\tstring\n\t */\n\tprotected function _create_table_attr($attributes)\n\t{\n\t\t$sql = '';\n\n\t\tforeach (array_keys($attributes) as $key)\n\t\t{\n\t\t\tif (is_string($key))\n\t\t\t{\n\t\t\t\t$sql .= ' '.strtoupper($key).' = '.$attributes[$key];\n\t\t\t}\n\t\t}\n\n\t\tif ( ! empty($this->db->char_set) && ! strpos($sql, 'CHARACTER SET') && ! strpos($sql, 'CHARSET'))\n\t\t{\n\t\t\t$sql .= ' DEFAULT CHARACTER SET = '.$this->db->char_set;\n\t\t}\n\n\t\tif ( ! empty($this->db->dbcollat) && ! strpos($sql, 'COLLATE'))\n\t\t{\n\t\t\t$sql .= ' COLLATE = '.$this->db->dbcollat;\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ALTER TABLE\n\t *\n\t * @param\tstring\t$alter_type\tALTER type\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tmixed\t$field\t\tColumn definition\n\t * @return\tstring|string[]\n\t */\n\tprotected function _alter_table($alter_type, $table, $field)\n\t{\n\t\tif ($alter_type === 'DROP')\n\t\t{\n\t\t\treturn parent::_alter_table($alter_type, $table, $field);\n\t\t}\n\n\t\t$sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);\n\t\tfor ($i = 0, $c = count($field); $i < $c; $i++)\n\t\t{\n\t\t\tif ($field[$i]['_literal'] !== FALSE)\n\t\t\t{\n\t\t\t\t$field[$i] = ($alter_type === 'ADD')\n\t\t\t\t\t\t? \"\\n\\tADD \".$field[$i]['_literal']\n\t\t\t\t\t\t: \"\\n\\tMODIFY \".$field[$i]['_literal'];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif ($alter_type === 'ADD')\n\t\t\t\t{\n\t\t\t\t\t$field[$i]['_literal'] = \"\\n\\tADD \";\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$field[$i]['_literal'] = empty($field[$i]['new_name']) ? \"\\n\\tMODIFY \" : \"\\n\\tCHANGE \";\n\t\t\t\t}\n\n\t\t\t\t$field[$i] = $field[$i]['_literal'].$this->_process_column($field[$i]);\n\t\t\t}\n\t\t}\n\n\t\treturn array($sql.implode(',', $field));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Process column\n\t *\n\t * @param\tarray\t$field\n\t * @return\tstring\n\t */\n\tprotected function _process_column($field)\n\t{\n\t\t$extra_clause = isset($field['after'])\n\t\t\t? ' AFTER '.$this->db->escape_identifiers($field['after']) : '';\n\n\t\tif (empty($extra_clause) && isset($field['first']) && $field['first'] === TRUE)\n\t\t{\n\t\t\t$extra_clause = ' FIRST';\n\t\t}\n\n\t\treturn $this->db->escape_identifiers($field['name'])\n\t\t\t.(empty($field['new_name']) ? '' : ' '.$this->db->escape_identifiers($field['new_name']))\n\t\t\t.' '.$field['type'].$field['length']\n\t\t\t.$field['unsigned']\n\t\t\t.$field['null']\n\t\t\t.$field['default']\n\t\t\t.$field['auto_increment']\n\t\t\t.$field['unique']\n\t\t\t.(empty($field['comment']) ? '' : ' COMMENT '.$field['comment'])\n\t\t\t.$extra_clause;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Process indexes\n\t *\n\t * @param\tstring\t$table\t(ignored)\n\t * @return\tstring\n\t */\n\tprotected function _process_indexes($table)\n\t{\n\t\t$sql = '';\n\n\t\tfor ($i = 0, $c = count($this->keys); $i < $c; $i++)\n\t\t{\n\t\t\tif (is_array($this->keys[$i]))\n\t\t\t{\n\t\t\t\tfor ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++)\n\t\t\t\t{\n\t\t\t\t\tif ( ! isset($this->fields[$this->keys[$i][$i2]]))\n\t\t\t\t\t{\n\t\t\t\t\t\tunset($this->keys[$i][$i2]);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ( ! isset($this->fields[$this->keys[$i]]))\n\t\t\t{\n\t\t\t\tunset($this->keys[$i]);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tis_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);\n\n\t\t\t$sql .= \",\\n\\tKEY \".$this->db->escape_identifiers(implode('_', $this->keys[$i]))\n\t\t\t\t.' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';\n\t\t}\n\n\t\t$this->keys = array();\n\n\t\treturn $sql;\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/mysqli/mysqli_result.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.3.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * MySQLi Result Class\n *\n * This class extends the parent result class: CI_DB_result\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_mysqli_result extends CI_DB_result {\n\n\t/**\n\t * Number of rows in the result set\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_rows()\n\t{\n\t\treturn is_int($this->num_rows)\n\t\t\t? $this->num_rows\n\t\t\t: $this->num_rows = $this->result_id->num_rows;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Number of fields in the result set\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_fields()\n\t{\n\t\treturn $this->result_id->field_count;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch Field Names\n\t *\n\t * Generates an array of column names\n\t *\n\t * @return\tarray\n\t */\n\tpublic function list_fields()\n\t{\n\t\t$field_names = array();\n\t\t$this->result_id->field_seek(0);\n\t\twhile ($field = $this->result_id->fetch_field())\n\t\t{\n\t\t\t$field_names[] = $field->name;\n\t\t}\n\n\t\treturn $field_names;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field data\n\t *\n\t * Generates an array of objects containing field meta-data\n\t *\n\t * @return\tarray\n\t */\n\tpublic function field_data()\n\t{\n\t\t$retval = array();\n\t\t$field_data = $this->result_id->fetch_fields();\n\t\tfor ($i = 0, $c = count($field_data); $i < $c; $i++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= $field_data[$i]->name;\n\t\t\t$retval[$i]->type\t\t= $field_data[$i]->type;\n\t\t\t$retval[$i]->max_length\t\t= $field_data[$i]->max_length;\n\t\t\t$retval[$i]->primary_key\t= (int) ($field_data[$i]->flags & 2);\n\t\t\t$retval[$i]->default\t\t= $field_data[$i]->def;\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Free the result\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function free_result()\n\t{\n\t\tif (is_object($this->result_id))\n\t\t{\n\t\t\t$this->result_id->free();\n\t\t\t$this->result_id = FALSE;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Data Seek\n\t *\n\t * Moves the internal pointer to the desired offset. We call\n\t * this internally before fetching results to make sure the\n\t * result set starts at zero.\n\t *\n\t * @param\tint\t$n\n\t * @return\tbool\n\t */\n\tpublic function data_seek($n = 0)\n\t{\n\t\treturn $this->result_id->data_seek($n);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - associative array\n\t *\n\t * Returns the result set as an array\n\t *\n\t * @return\tarray\n\t */\n\tprotected function _fetch_assoc()\n\t{\n\t\treturn $this->result_id->fetch_assoc();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - object\n\t *\n\t * Returns the result set as an object\n\t *\n\t * @param\tstring\t$class_name\n\t * @return\tobject\n\t */\n\tprotected function _fetch_object($class_name = 'stdClass')\n\t{\n\t\treturn $this->result_id->fetch_object($class_name);\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/mysqli/mysqli_utility.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.3.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * MySQLi Utility Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_mysqli_utility extends CI_DB_utility {\n\n\t/**\n\t * List databases statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_list_databases\t= 'SHOW DATABASES';\n\n\t/**\n\t * OPTIMIZE TABLE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_optimize_table\t= 'OPTIMIZE TABLE %s';\n\n\t/**\n\t * REPAIR TABLE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_repair_table\t= 'REPAIR TABLE %s';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Export\n\t *\n\t * @param\tarray\t$params\tPreferences\n\t * @return\tmixed\n\t */\n\tprotected function _backup($params = array())\n\t{\n\t\tif (count($params) === 0)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Extract the prefs for simplicity\n\t\textract($params);\n\n\t\t// Build the output\n\t\t$output = '';\n\n\t\t// Do we need to include a statement to disable foreign key checks?\n\t\tif ($foreign_key_checks === FALSE)\n\t\t{\n\t\t\t$output .= 'SET foreign_key_checks = 0;'.$newline;\n\t\t}\n\n\t\tforeach ( (array) $tables as $table)\n\t\t{\n\t\t\t// Is the table in the \"ignore\" list?\n\t\t\tif (in_array($table, (array) $ignore, TRUE))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Get the table schema\n\t\t\t$query = $this->db->query('SHOW CREATE TABLE '.$this->db->escape_identifiers($this->db->database.'.'.$table));\n\n\t\t\t// No result means the table name was invalid\n\t\t\tif ($query === FALSE)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Write out the table schema\n\t\t\t$output .= '#'.$newline.'# TABLE STRUCTURE FOR: '.$table.$newline.'#'.$newline.$newline;\n\n\t\t\tif ($add_drop === TRUE)\n\t\t\t{\n\t\t\t\t$output .= 'DROP TABLE IF EXISTS '.$this->db->protect_identifiers($table).';'.$newline.$newline;\n\t\t\t}\n\n\t\t\t$i = 0;\n\t\t\t$result = $query->result_array();\n\t\t\tforeach ($result[0] as $val)\n\t\t\t{\n\t\t\t\tif ($i++ % 2)\n\t\t\t\t{\n\t\t\t\t\t$output .= $val.';'.$newline.$newline;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If inserts are not needed we're done...\n\t\t\tif ($add_insert === FALSE)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Grab all the data from the current table\n\t\t\t$query = $this->db->query('SELECT * FROM '.$this->db->protect_identifiers($table));\n\n\t\t\tif ($query->num_rows() === 0)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Fetch the field names and determine if the field is an\n\t\t\t// integer type. We use this info to decide whether to\n\t\t\t// surround the data with quotes or not\n\n\t\t\t$i = 0;\n\t\t\t$field_str = '';\n\t\t\t$is_int = array();\n\t\t\twhile ($field = $query->result_id->fetch_field())\n\t\t\t{\n\t\t\t\t// Most versions of MySQL store timestamp as a string\n\t\t\t\t$is_int[$i] = in_array(strtolower($field->type),\n\t\t\t\t\t\t\tarray('tinyint', 'smallint', 'mediumint', 'int', 'bigint'), //, 'timestamp'),\n\t\t\t\t\t\t\tTRUE);\n\n\t\t\t\t// Create a string of field names\n\t\t\t\t$field_str .= $this->db->escape_identifiers($field->name).', ';\n\t\t\t\t$i++;\n\t\t\t}\n\n\t\t\t// Trim off the end comma\n\t\t\t$field_str = preg_replace('/, $/' , '', $field_str);\n\n\t\t\t// Build the insert string\n\t\t\tforeach ($query->result_array() as $row)\n\t\t\t{\n\t\t\t\t$val_str = '';\n\n\t\t\t\t$i = 0;\n\t\t\t\tforeach ($row as $v)\n\t\t\t\t{\n\t\t\t\t\t// Is the value NULL?\n\t\t\t\t\tif ($v === NULL)\n\t\t\t\t\t{\n\t\t\t\t\t\t$val_str .= 'NULL';\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// Escape the data if it's not an integer\n\t\t\t\t\t\t$val_str .= ($is_int[$i] === FALSE) ? $this->db->escape($v) : $v;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Append a comma\n\t\t\t\t\t$val_str .= ', ';\n\t\t\t\t\t$i++;\n\t\t\t\t}\n\n\t\t\t\t// Remove the comma at the end of the string\n\t\t\t\t$val_str = preg_replace('/, $/' , '', $val_str);\n\n\t\t\t\t// Build the INSERT string\n\t\t\t\t$output .= 'INSERT INTO '.$this->db->protect_identifiers($table).' ('.$field_str.') VALUES ('.$val_str.');'.$newline;\n\t\t\t}\n\n\t\t\t$output .= $newline.$newline;\n\t\t}\n\n\t\t// Do we need to include a statement to re-enable foreign key checks?\n\t\tif ($foreign_key_checks === FALSE)\n\t\t{\n\t\t\t$output .= 'SET foreign_key_checks = 1;'.$newline;\n\t\t}\n\n\t\treturn $output;\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/oci8/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/database/drivers/oci8/oci8_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.4.1\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * oci8 Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage  Drivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\n\n/**\n * oci8 Database Adapter Class\n *\n * This is a modification of the DB_driver class to\n * permit access to oracle databases\n *\n * @author\t  Kelly McArdle\n */\nclass CI_DB_oci8_driver extends CI_DB {\n\n\t/**\n\t * Database driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $dbdriver = 'oci8';\n\n\t/**\n\t * Statement ID\n\t *\n\t * @var\tresource\n\t */\n\tpublic $stmt_id;\n\n\t/**\n\t * Cursor ID\n\t *\n\t * @var\tresource\n\t */\n\tpublic $curs_id;\n\n\t/**\n\t * Commit mode flag\n\t *\n\t * @var\tint\n\t */\n\tpublic $commit_mode = OCI_COMMIT_ON_SUCCESS;\n\n\t/**\n\t * Limit used flag\n\t *\n\t * If we use LIMIT, we'll add a field that will\n\t * throw off num_fields later.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $limit_used;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Reset $stmt_id flag\n\t *\n\t * Used by stored_procedure() to prevent _execute() from\n\t * re-setting the statement ID.\n\t */\n\tprotected $_reset_stmt_id = TRUE;\n\n\t/**\n\t * List of reserved identifiers\n\t *\n\t * Identifiers that must NOT be escaped.\n\t *\n\t * @var\tstring[]\n\t */\n\tprotected $_reserved_identifiers = array('*', 'rownum');\n\n\t/**\n\t * ORDER BY random keyword\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_random_keyword = array('ASC', 'ASC'); // not currently supported\n\n\t/**\n\t * COUNT string\n\t *\n\t * @used-by\tCI_DB_driver::count_all()\n\t * @used-by\tCI_DB_query_builder::count_all_results()\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_count_string = 'SELECT COUNT(1) AS ';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\tparent::__construct($params);\n\n\t\t$valid_dsns = array(\n\t\t\t'tns'\t=> '/^\\(DESCRIPTION=(\\(.+\\)){2,}\\)$/', // TNS\n\t\t\t// Easy Connect string (Oracle 10g+)\n\t\t\t'ec'\t=> '/^(\\/\\/)?[a-z0-9.:_-]+(:[1-9][0-9]{0,4})?(\\/[a-z0-9$_]+)?(:[^\\/])?(\\/[a-z0-9$_]+)?$/i',\n\t\t\t'in'\t=> '/^[a-z0-9$_]+$/i' // Instance name (defined in tnsnames.ora)\n\t\t);\n\n\t\t/* Space characters don't have any effect when actually\n\t\t * connecting, but can be a hassle while validating the DSN.\n\t\t */\n\t\t$this->dsn = str_replace(array(\"\\n\", \"\\r\", \"\\t\", ' '), '', $this->dsn);\n\n\t\tif ($this->dsn !== '')\n\t\t{\n\t\t\tforeach ($valid_dsns as $regexp)\n\t\t\t{\n\t\t\t\tif (preg_match($regexp, $this->dsn))\n\t\t\t\t{\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Legacy support for TNS in the hostname configuration field\n\t\t$this->hostname = str_replace(array(\"\\n\", \"\\r\", \"\\t\", ' '), '', $this->hostname);\n\t\tif (preg_match($valid_dsns['tns'], $this->hostname))\n\t\t{\n\t\t\t$this->dsn = $this->hostname;\n\t\t\treturn;\n\t\t}\n\t\telseif ($this->hostname !== '' && strpos($this->hostname, '/') === FALSE && strpos($this->hostname, ':') === FALSE\n\t\t\t&& (( ! empty($this->port) && ctype_digit($this->port)) OR $this->database !== ''))\n\t\t{\n\t\t\t/* If the hostname field isn't empty, doesn't contain\n\t\t\t * ':' and/or '/' and if port and/or database aren't\n\t\t\t * empty, then the hostname field is most likely indeed\n\t\t\t * just a hostname. Therefore we'll try and build an\n\t\t\t * Easy Connect string from these 3 settings, assuming\n\t\t\t * that the database field is a service name.\n\t\t\t */\n\t\t\t$this->dsn = $this->hostname\n\t\t\t\t.(( ! empty($this->port) && ctype_digit($this->port)) ? ':'.$this->port : '')\n\t\t\t\t.($this->database !== '' ? '/'.ltrim($this->database, '/') : '');\n\n\t\t\tif (preg_match($valid_dsns['ec'], $this->dsn))\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t/* At this point, we can only try and validate the hostname and\n\t\t * database fields separately as DSNs.\n\t\t */\n\t\tif (preg_match($valid_dsns['ec'], $this->hostname) OR preg_match($valid_dsns['in'], $this->hostname))\n\t\t{\n\t\t\t$this->dsn = $this->hostname;\n\t\t\treturn;\n\t\t}\n\n\t\t$this->database = str_replace(array(\"\\n\", \"\\r\", \"\\t\", ' '), '', $this->database);\n\t\tforeach ($valid_dsns as $regexp)\n\t\t{\n\t\t\tif (preg_match($regexp, $this->database))\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t/* Well - OK, an empty string should work as well.\n\t\t * PHP will try to use environment variables to\n\t\t * determine which Oracle instance to connect to.\n\t\t */\n\t\t$this->dsn = '';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Non-persistent database connection\n\t *\n\t * @param\tbool\t$persistent\n\t * @return\tresource\n\t */\n\tpublic function db_connect($persistent = FALSE)\n\t{\n\t\t$func = ($persistent === TRUE) ? 'oci_pconnect' : 'oci_connect';\n\t\treturn empty($this->char_set)\n\t\t\t? $func($this->username, $this->password, $this->dsn)\n\t\t\t: $func($this->username, $this->password, $this->dsn, $this->char_set);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Database version number\n\t *\n\t * @return\tstring\n\t */\n\tpublic function version()\n\t{\n\t\tif (isset($this->data_cache['version']))\n\t\t{\n\t\t\treturn $this->data_cache['version'];\n\t\t}\n\n\t\tif ( ! $this->conn_id OR ($version_string = oci_server_version($this->conn_id)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\telseif (preg_match('#Release\\s(\\d+(?:\\.\\d+)+)#', $version_string, $match))\n\t\t{\n\t\t\treturn $this->data_cache['version'] = $match[1];\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Execute the query\n\t *\n\t * @param\tstring\t$sql\tan SQL query\n\t * @return\tresource\n\t */\n\tprotected function _execute($sql)\n\t{\n\t\t/* Oracle must parse the query before it is run. All of the actions with\n\t\t * the query are based on the statement id returned by oci_parse().\n\t\t */\n\t\tif ($this->_reset_stmt_id === TRUE)\n\t\t{\n\t\t\t$this->stmt_id = oci_parse($this->conn_id, $sql);\n\t\t}\n\n\t\toci_set_prefetch($this->stmt_id, 1000);\n\t\treturn oci_execute($this->stmt_id, $this->commit_mode);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get cursor. Returns a cursor from the database\n\t *\n\t * @return\tresource\n\t */\n\tpublic function get_cursor()\n\t{\n\t\treturn $this->curs_id = oci_new_cursor($this->conn_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Stored Procedure.  Executes a stored procedure\n\t *\n\t * @param\tstring\tpackage name in which the stored procedure is in\n\t * @param\tstring\tstored procedure name to execute\n\t * @param\tarray\tparameters\n\t * @return\tmixed\n\t *\n\t * params array keys\n\t *\n\t * KEY      OPTIONAL  NOTES\n\t * name     no        the name of the parameter should be in :<param_name> format\n\t * value    no        the value of the parameter.  If this is an OUT or IN OUT parameter,\n\t *                    this should be a reference to a variable\n\t * type     yes       the type of the parameter\n\t * length   yes       the max size of the parameter\n\t */\n\tpublic function stored_procedure($package, $procedure, array $params)\n\t{\n\t\tif ($package === '' OR $procedure === '')\n\t\t{\n\t\t\tlog_message('error', 'Invalid query: '.$package.'.'.$procedure);\n\t\t\treturn ($this->db_debug) ? $this->display_error('db_invalid_query') : FALSE;\n\t\t}\n\n\t\t// Build the query string\n\t\t$sql = 'BEGIN '.$package.'.'.$procedure.'(';\n\n\t\t$have_cursor = FALSE;\n\t\tforeach ($params as $param)\n\t\t{\n\t\t\t$sql .= $param['name'].',';\n\n\t\t\tif (isset($param['type']) && $param['type'] === OCI_B_CURSOR)\n\t\t\t{\n\t\t\t\t$have_cursor = TRUE;\n\t\t\t}\n\t\t}\n\t\t$sql = trim($sql, ',').'); END;';\n\n\t\t$this->_reset_stmt_id = FALSE;\n\t\t$this->stmt_id = oci_parse($this->conn_id, $sql);\n\t\t$this->_bind_params($params);\n\t\t$result = $this->query($sql, FALSE, $have_cursor);\n\t\t$this->_reset_stmt_id = TRUE;\n\t\treturn $result;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Bind parameters\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tprotected function _bind_params($params)\n\t{\n\t\tif ( ! is_array($params) OR ! is_resource($this->stmt_id))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tforeach ($params as $param)\n\t\t{\n\t\t\tforeach (array('name', 'value', 'type', 'length') as $val)\n\t\t\t{\n\t\t\t\tif ( ! isset($param[$val]))\n\t\t\t\t{\n\t\t\t\t\t$param[$val] = '';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\toci_bind_by_name($this->stmt_id, $param['name'], $param['value'], $param['length'], $param['type']);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Begin Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_begin()\n\t{\n\t\t$this->commit_mode = is_php('5.3.2') ? OCI_NO_AUTO_COMMIT : OCI_DEFAULT;\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Commit Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_commit()\n\t{\n\t\t$this->commit_mode = OCI_COMMIT_ON_SUCCESS;\n\n\t\treturn oci_commit($this->conn_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Rollback Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_rollback()\n\t{\n\t\t$this->commit_mode = OCI_COMMIT_ON_SUCCESS;\n\t\treturn oci_rollback($this->conn_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Affected Rows\n\t *\n\t * @return\tint\n\t */\n\tpublic function affected_rows()\n\t{\n\t\treturn oci_num_rows($this->stmt_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert ID\n\t *\n\t * @return\tint\n\t */\n\tpublic function insert_id()\n\t{\n\t\t// not supported in oracle\n\t\treturn $this->display_error('db_unsupported_function');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\t$prefix_limit\n\t * @return\tstring\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\t$sql = 'SELECT \"TABLE_NAME\" FROM \"ALL_TABLES\"';\n\n\t\tif ($prefix_limit !== FALSE && $this->dbprefix !== '')\n\t\t{\n\t\t\treturn $sql.' WHERE \"TABLE_NAME\" LIKE \\''.$this->escape_like_str($this->dbprefix).\"%' \"\n\t\t\t\t.sprintf($this->_like_escape_str, $this->_like_escape_chr);\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show column query\n\t *\n\t * Generates a platform-specific query string so that the column names can be fetched\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _list_columns($table = '')\n\t{\n\t\tif (strpos($table, '.') !== FALSE)\n\t\t{\n\t\t\tsscanf($table, '%[^.].%s', $owner, $table);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$owner = $this->username;\n\t\t}\n\n\t\treturn 'SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS\n\t\t\tWHERE UPPER(OWNER) = '.$this->escape(strtoupper($owner)).'\n\t\t\t\tAND UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an object with field data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tarray\n\t */\n\tpublic function field_data($table)\n\t{\n\t\tif (strpos($table, '.') !== FALSE)\n\t\t{\n\t\t\tsscanf($table, '%[^.].%s', $owner, $table);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$owner = $this->username;\n\t\t}\n\n\t\t$sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHAR_LENGTH, DATA_PRECISION, DATA_LENGTH, DATA_DEFAULT, NULLABLE\n\t\t\tFROM ALL_TAB_COLUMNS\n\t\t\tWHERE UPPER(OWNER) = '.$this->escape(strtoupper($owner)).'\n\t\t\t\tAND UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));\n\n\t\tif (($query = $this->query($sql)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\t$query = $query->result_object();\n\n\t\t$retval = array();\n\t\tfor ($i = 0, $c = count($query); $i < $c; $i++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= $query[$i]->COLUMN_NAME;\n\t\t\t$retval[$i]->type\t\t= $query[$i]->DATA_TYPE;\n\n\t\t\t$length = ($query[$i]->CHAR_LENGTH > 0)\n\t\t\t\t? $query[$i]->CHAR_LENGTH : $query[$i]->DATA_PRECISION;\n\t\t\tif ($length === NULL)\n\t\t\t{\n\t\t\t\t$length = $query[$i]->DATA_LENGTH;\n\t\t\t}\n\t\t\t$retval[$i]->max_length\t\t= $length;\n\n\t\t\t$default = $query[$i]->DATA_DEFAULT;\n\t\t\tif ($default === NULL && $query[$i]->NULLABLE === 'N')\n\t\t\t{\n\t\t\t\t$default = '';\n\t\t\t}\n\t\t\t$retval[$i]->default = $default;\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Error\n\t *\n\t * Returns an array containing code and message of the last\n\t * database error that has occured.\n\t *\n\t * @return\tarray\n\t */\n\tpublic function error()\n\t{\n\t\t// oci_error() returns an array that already contains\n\t\t// 'code' and 'message' keys, but it can return false\n\t\t// if there was no error ....\n\t\tif (is_resource($this->curs_id))\n\t\t{\n\t\t\t$error = oci_error($this->curs_id);\n\t\t}\n\t\telseif (is_resource($this->stmt_id))\n\t\t{\n\t\t\t$error = oci_error($this->stmt_id);\n\t\t}\n\t\telseif (is_resource($this->conn_id))\n\t\t{\n\t\t\t$error = oci_error($this->conn_id);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$error = oci_error();\n\t\t}\n\n\t\treturn is_array($error)\n\t\t\t? $error\n\t\t\t: array('code' => '', 'message' => '');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert batch statement\n\t *\n\t * Generates a platform-specific insert string from the supplied data\n\t *\n\t * @param\tstring\t$table\tTable name\n\t * @param\tarray\t$keys\tINSERT keys\n\t * @param \tarray\t$values\tINSERT values\n\t * @return\tstring\n\t */\n\tprotected function _insert_batch($table, $keys, $values)\n\t{\n\t\t$keys = implode(', ', $keys);\n\t\t$sql = \"INSERT ALL\\n\";\n\n\t\tfor ($i = 0, $c = count($values); $i < $c; $i++)\n\t\t{\n\t\t\t$sql .= '\tINTO '.$table.' ('.$keys.') VALUES '.$values[$i].\"\\n\";\n\t\t}\n\n\t\treturn $sql.'SELECT * FROM dual';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Truncate statement\n\t *\n\t * Generates a platform-specific truncate string from the supplied data\n\t *\n\t * If the database does not support the TRUNCATE statement,\n\t * then this method maps to 'DELETE FROM table'\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _truncate($table)\n\t{\n\t\treturn 'TRUNCATE TABLE '.$table;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Delete statement\n\t *\n\t * Generates a platform-specific delete string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _delete($table)\n\t{\n\t\tif ($this->qb_limit)\n\t\t{\n\t\t\t$this->where('rownum <= ',$this->qb_limit, FALSE);\n\t\t\t$this->qb_limit = FALSE;\n\t\t}\n\n\t\treturn parent::_delete($table);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * LIMIT\n\t *\n\t * Generates a platform-specific LIMIT clause\n\t *\n\t * @param\tstring\t$sql\tSQL Query\n\t * @return\tstring\n\t */\n\tprotected function _limit($sql)\n\t{\n\t\tif (version_compare($this->version(), '12.1', '>='))\n\t\t{\n\t\t\t// OFFSET-FETCH can be used only with the ORDER BY clause\n\t\t\tempty($this->qb_orderby) && $sql .= ' ORDER BY 1';\n\n\t\t\treturn $sql.' OFFSET '.(int) $this->qb_offset.' ROWS FETCH NEXT '.$this->qb_limit.' ROWS ONLY';\n\t\t}\n\n\t\t$this->limit_used = TRUE;\n\t\treturn 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($this->qb_offset + $this->qb_limit + 1).')'\n\t\t\t.($this->qb_offset ? ' WHERE rnum >= '.($this->qb_offset + 1) : '');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Close DB Connection\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _close()\n\t{\n\t\toci_close($this->conn_id);\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/oci8/oci8_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.4.1\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Oracle Forge Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_oci8_forge extends CI_DB_forge {\n\n\t/**\n\t * CREATE DATABASE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_database\t= FALSE;\n\n\t/**\n\t * CREATE TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_table_if\t= FALSE;\n\n\t/**\n\t * DROP DATABASE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_drop_database\t= FALSE;\n\n\t/**\n\t * DROP TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_drop_table_if\t= FALSE;\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tbool|array\n\t */\n\tprotected $_unsigned\t\t= FALSE;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ALTER TABLE\n\t *\n\t * @param\tstring\t$alter_type\tALTER type\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tmixed\t$field\t\tColumn definition\n\t * @return\tstring|string[]\n\t */\n\tprotected function _alter_table($alter_type, $table, $field)\n\t{\n\t\tif ($alter_type === 'DROP')\n\t\t{\n\t\t\treturn parent::_alter_table($alter_type, $table, $field);\n\t\t}\n\t\telseif ($alter_type === 'CHANGE')\n\t\t{\n\t\t\t$alter_type = 'MODIFY';\n\t\t}\n\n\t\t$sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);\n\t\t$sqls = array();\n\t\tfor ($i = 0, $c = count($field); $i < $c; $i++)\n\t\t{\n\t\t\tif ($field[$i]['_literal'] !== FALSE)\n\t\t\t{\n\t\t\t\t$field[$i] = \"\\n\\t\".$field[$i]['_literal'];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$field[$i]['_literal'] = \"\\n\\t\".$this->_process_column($field[$i]);\n\n\t\t\t\tif ( ! empty($field[$i]['comment']))\n\t\t\t\t{\n\t\t\t\t\t$sqls[] = 'COMMENT ON COLUMN '\n\t\t\t\t\t\t.$this->db->escape_identifiers($table).'.'.$this->db->escape_identifiers($field[$i]['name'])\n\t\t\t\t\t\t.' IS '.$field[$i]['comment'];\n\t\t\t\t}\n\n\t\t\t\tif ($alter_type === 'MODIFY' && ! empty($field[$i]['new_name']))\n\t\t\t\t{\n\t\t\t\t\t$sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name'])\n\t\t\t\t\t\t.' '.$this->db->escape_identifiers($field[$i]['new_name']);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$sql .= ' '.$alter_type.' ';\n\t\t$sql .= (count($field) === 1)\n\t\t\t\t? $field[0]\n\t\t\t\t: '('.implode(',', $field).')';\n\n\t\t// RENAME COLUMN must be executed after MODIFY\n\t\tarray_unshift($sqls, $sql);\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute AUTO_INCREMENT\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_auto_increment(&$attributes, &$field)\n\t{\n\t\t// Not supported - sequences and triggers must be used instead\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute TYPE\n\t *\n\t * Performs a data type mapping between different databases.\n\t *\n\t * @param\tarray\t&$attributes\n\t * @return\tvoid\n\t */\n\tprotected function _attr_type(&$attributes)\n\t{\n\t\tswitch (strtoupper($attributes['TYPE']))\n\t\t{\n\t\t\tcase 'TINYINT':\n\t\t\t\t$attributes['TYPE'] = 'NUMBER';\n\t\t\t\treturn;\n\t\t\tcase 'MEDIUMINT':\n\t\t\t\t$attributes['TYPE'] = 'NUMBER';\n\t\t\t\treturn;\n\t\t\tcase 'INT':\n\t\t\t\t$attributes['TYPE'] = 'NUMBER';\n\t\t\t\treturn;\n\t\t\tcase 'BIGINT':\n\t\t\t\t$attributes['TYPE'] = 'NUMBER';\n\t\t\t\treturn;\n\t\t\tdefault: return;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "system/database/drivers/oci8/oci8_result.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.4.1\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * oci8 Result Class\n *\n * This class extends the parent result class: CI_DB_result\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_oci8_result extends CI_DB_result {\n\n\t/**\n\t * Statement ID\n\t *\n\t * @var\tresource\n\t */\n\tpublic $stmt_id;\n\n\t/**\n\t * Cursor ID\n\t *\n\t * @var\tresource\n\t */\n\tpublic $curs_id;\n\n\t/**\n\t * Limit used flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $limit_used;\n\n\t/**\n\t * Commit mode flag\n\t *\n\t * @var\tint\n\t */\n\tpublic $commit_mode;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tobject\t&$driver_object\n\t * @return\tvoid\n\t */\n\tpublic function __construct(&$driver_object)\n\t{\n\t\tparent::__construct($driver_object);\n\n\t\t$this->stmt_id = $driver_object->stmt_id;\n\t\t$this->curs_id = $driver_object->curs_id;\n\t\t$this->limit_used = $driver_object->limit_used;\n\t\t$this->commit_mode =& $driver_object->commit_mode;\n\t\t$driver_object->stmt_id = FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Number of fields in the result set\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_fields()\n\t{\n\t\t$count = oci_num_fields($this->stmt_id);\n\n\t\t// if we used a limit we subtract it\n\t\treturn ($this->limit_used) ? $count - 1 : $count;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch Field Names\n\t *\n\t * Generates an array of column names\n\t *\n\t * @return\tarray\n\t */\n\tpublic function list_fields()\n\t{\n\t\t$field_names = array();\n\t\tfor ($c = 1, $fieldCount = $this->num_fields(); $c <= $fieldCount; $c++)\n\t\t{\n\t\t\t$field_names[] = oci_field_name($this->stmt_id, $c);\n\t\t}\n\t\treturn $field_names;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field data\n\t *\n\t * Generates an array of objects containing field meta-data\n\t *\n\t * @return\tarray\n\t */\n\tpublic function field_data()\n\t{\n\t\t$retval = array();\n\t\tfor ($c = 1, $fieldCount = $this->num_fields(); $c <= $fieldCount; $c++)\n\t\t{\n\t\t\t$F\t\t= new stdClass();\n\t\t\t$F->name\t= oci_field_name($this->stmt_id, $c);\n\t\t\t$F->type\t= oci_field_type($this->stmt_id, $c);\n\t\t\t$F->max_length\t= oci_field_size($this->stmt_id, $c);\n\n\t\t\t$retval[] = $F;\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Free the result\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function free_result()\n\t{\n\t\tif (is_resource($this->result_id))\n\t\t{\n\t\t\toci_free_statement($this->result_id);\n\t\t\t$this->result_id = FALSE;\n\t\t}\n\n\t\tif (is_resource($this->stmt_id))\n\t\t{\n\t\t\toci_free_statement($this->stmt_id);\n\t\t}\n\n\t\tif (is_resource($this->curs_id))\n\t\t{\n\t\t\toci_cancel($this->curs_id);\n\t\t\t$this->curs_id = NULL;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - associative array\n\t *\n\t * Returns the result set as an array\n\t *\n\t * @return\tarray\n\t */\n\tprotected function _fetch_assoc()\n\t{\n\t\t$id = ($this->curs_id) ? $this->curs_id : $this->stmt_id;\n\t\treturn oci_fetch_assoc($id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - object\n\t *\n\t * Returns the result set as an object\n\t *\n\t * @param\tstring\t$class_name\n\t * @return\tobject\n\t */\n\tprotected function _fetch_object($class_name = 'stdClass')\n\t{\n\t\t$row = ($this->curs_id)\n\t\t\t? oci_fetch_object($this->curs_id)\n\t\t\t: oci_fetch_object($this->stmt_id);\n\n\t\tif ($class_name === 'stdClass' OR ! $row)\n\t\t{\n\t\t\treturn $row;\n\t\t}\n\n\t\t$class_name = new $class_name();\n\t\tforeach ($row as $key => $value)\n\t\t{\n\t\t\t$class_name->$key = $value;\n\t\t}\n\n\t\treturn $class_name;\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/oci8/oci8_utility.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.4.1\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Oracle Utility Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_oci8_utility extends CI_DB_utility {\n\n\t/**\n\t * List databases statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_list_databases\t= 'SELECT username FROM dba_users'; // Schemas are actual usernames\n\n\t/**\n\t * Export\n\t *\n\t * @param\tarray\t$params\tPreferences\n\t * @return\tmixed\n\t */\n\tprotected function _backup($params = array())\n\t{\n\t\t// Currently unsupported\n\t\treturn $this->db->display_error('db_unsupported_feature');\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/odbc/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/database/drivers/odbc/odbc_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.3.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * ODBC Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_odbc_driver extends CI_DB_driver {\n\n\t/**\n\t * Database driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $dbdriver = 'odbc';\n\n\t/**\n\t * Database schema\n\t *\n\t * @var\tstring\n\t */\n\tpublic $schema = 'public';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Identifier escape character\n\t *\n\t * Must be empty for ODBC.\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_escape_char = '';\n\n\t/**\n\t * ESCAPE statement string\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_like_escape_str = \" {escape '%s'} \";\n\n\t/**\n\t * ORDER BY random keyword\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_random_keyword = array('RND()', 'RND(%d)');\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ODBC result ID resource returned from odbc_prepare()\n\t *\n\t * @var\tresource\n\t */\n\tprivate $odbc_result;\n\n\t/**\n\t * Values to use with odbc_execute() for prepared statements\n\t *\n\t * @var\tarray\n\t */\n\tprivate $binds = array();\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\tparent::__construct($params);\n\n\t\t// Legacy support for DSN in the hostname field\n\t\tif (empty($this->dsn))\n\t\t{\n\t\t\t$this->dsn = $this->hostname;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Non-persistent database connection\n\t *\n\t * @param\tbool\t$persistent\n\t * @return\tresource\n\t */\n\tpublic function db_connect($persistent = FALSE)\n\t{\n\t\treturn ($persistent === TRUE)\n\t\t\t? odbc_pconnect($this->dsn, $this->username, $this->password)\n\t\t\t: odbc_connect($this->dsn, $this->username, $this->password);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile Bindings\n\t *\n\t * @param\tstring\t$sql\tSQL statement\n\t * @param\tarray\t$binds\tAn array of values to bind\n\t * @return\tstring\n\t */\n\tpublic function compile_binds($sql, $binds)\n\t{\n\t\tif (empty($binds) OR empty($this->bind_marker) OR strpos($sql, $this->bind_marker) === FALSE)\n\t\t{\n\t\t\treturn $sql;\n\t\t}\n\t\telseif ( ! is_array($binds))\n\t\t{\n\t\t\t$binds = array($binds);\n\t\t\t$bind_count = 1;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Make sure we're using numeric keys\n\t\t\t$binds = array_values($binds);\n\t\t\t$bind_count = count($binds);\n\t\t}\n\n\t\t// We'll need the marker length later\n\t\t$ml = strlen($this->bind_marker);\n\n\t\t// Make sure not to replace a chunk inside a string that happens to match the bind marker\n\t\tif ($c = preg_match_all(\"/'[^']*'/i\", $sql, $matches))\n\t\t{\n\t\t\t$c = preg_match_all('/'.preg_quote($this->bind_marker, '/').'/i',\n\t\t\t\tstr_replace($matches[0],\n\t\t\t\t\tstr_replace($this->bind_marker, str_repeat(' ', $ml), $matches[0]),\n\t\t\t\t\t$sql, $c),\n\t\t\t\t$matches, PREG_OFFSET_CAPTURE);\n\n\t\t\t// Bind values' count must match the count of markers in the query\n\t\t\tif ($bind_count !== $c)\n\t\t\t{\n\t\t\t\treturn $sql;\n\t\t\t}\n\t\t}\n\t\telseif (($c = preg_match_all('/'.preg_quote($this->bind_marker, '/').'/i', $sql, $matches, PREG_OFFSET_CAPTURE)) !== $bind_count)\n\t\t{\n\t\t\treturn $sql;\n\t\t}\n\n\t\tif ($this->bind_marker !== '?')\n\t\t{\n\t\t\tdo\n\t\t\t{\n\t\t\t\t$c--;\n\t\t\t\t$sql = substr_replace($sql, '?', $matches[0][$c][1], $ml);\n\t\t\t}\n\t\t\twhile ($c !== 0);\n\t\t}\n\n\t\tif (FALSE !== ($this->odbc_result = odbc_prepare($this->conn_id, $sql)))\n\t\t{\n\t\t\t$this->binds = array_values($binds);\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Execute the query\n\t *\n\t * @param\tstring\t$sql\tan SQL query\n\t * @return\tresource\n\t */\n\tprotected function _execute($sql)\n\t{\n\t\tif ( ! isset($this->odbc_result))\n\t\t{\n\t\t\treturn odbc_exec($this->conn_id, $sql);\n\t\t}\n\t\telseif ($this->odbc_result === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (TRUE === ($success = odbc_execute($this->odbc_result, $this->binds)))\n\t\t{\n\t\t\t// For queries that return result sets, return the result_id resource on success\n\t\t\t$this->is_write_type($sql) OR $success = $this->odbc_result;\n\t\t}\n\n\t\t$this->odbc_result = NULL;\n\t\t$this->binds       = array();\n\n\t\treturn $success;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Begin Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_begin()\n\t{\n\t\treturn odbc_autocommit($this->conn_id, FALSE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Commit Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_commit()\n\t{\n\t\tif (odbc_commit($this->conn_id))\n\t\t{\n\t\t\todbc_autocommit($this->conn_id, TRUE);\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Rollback Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_rollback()\n\t{\n\t\tif (odbc_rollback($this->conn_id))\n\t\t{\n\t\t\todbc_autocommit($this->conn_id, TRUE);\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Determines if a query is a \"write\" type.\n\t *\n\t * @param\tstring\tAn SQL query string\n\t * @return\tbool\n\t */\n\tpublic function is_write_type($sql)\n\t{\n\t\tif (preg_match('#^(INSERT|UPDATE).*RETURNING\\s.+(\\,\\s?.+)*$#i', $sql))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn parent::is_write_type($sql);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Platform-dependant string escape\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _escape_str($str)\n\t{\n\t\t$this->db->display_error('db_unsupported_feature');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Affected Rows\n\t *\n\t * @return\tint\n\t */\n\tpublic function affected_rows()\n\t{\n\t\treturn odbc_num_rows($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert ID\n\t *\n\t * @return\tbool\n\t */\n\tpublic function insert_id()\n\t{\n\t\treturn ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\t$prefix_limit\n\t * @return\tstring\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\t$sql = \"SELECT table_name FROM information_schema.tables WHERE table_schema = '\".$this->schema.\"'\";\n\n\t\tif ($prefix_limit !== FALSE && $this->dbprefix !== '')\n\t\t{\n\t\t\treturn $sql.\" AND table_name LIKE '\".$this->escape_like_str($this->dbprefix).\"%' \"\n\t\t\t\t.sprintf($this->_like_escape_str, $this->_like_escape_chr);\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show column query\n\t *\n\t * Generates a platform-specific query string so that the column names can be fetched\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _list_columns($table = '')\n\t{\n\t\treturn 'SHOW COLUMNS FROM '.$table;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field data query\n\t *\n\t * Generates a platform-specific query so that the column data can be retrieved\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _field_data($table)\n\t{\n\t\treturn 'SELECT TOP 1 FROM '.$table;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Error\n\t *\n\t * Returns an array containing code and message of the last\n\t * database error that has occured.\n\t *\n\t * @return\tarray\n\t */\n\tpublic function error()\n\t{\n\t\treturn array('code' => odbc_error($this->conn_id), 'message' => odbc_errormsg($this->conn_id));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Close DB Connection\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _close()\n\t{\n\t\todbc_close($this->conn_id);\n\t}\n}\n"
  },
  {
    "path": "system/database/drivers/odbc/odbc_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.3.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * ODBC Forge Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/database/\n */\nclass CI_DB_odbc_forge extends CI_DB_forge {\n\n\t/**\n\t * CREATE TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_table_if\t= FALSE;\n\n\t/**\n\t * DROP TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_drop_table_if\t= FALSE;\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tbool|array\n\t */\n\tprotected $_unsigned\t\t= FALSE;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute AUTO_INCREMENT\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_auto_increment(&$attributes, &$field)\n\t{\n\t\t// Not supported (in most databases at least)\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/odbc/odbc_result.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.3.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * ODBC Result Class\n *\n * This class extends the parent result class: CI_DB_result\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_odbc_result extends CI_DB_result {\n\n\t/**\n\t * Number of rows in the result set\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_rows()\n\t{\n\t\tif (is_int($this->num_rows))\n\t\t{\n\t\t\treturn $this->num_rows;\n\t\t}\n\t\telseif (($this->num_rows = odbc_num_rows($this->result_id)) !== -1)\n\t\t{\n\t\t\treturn $this->num_rows;\n\t\t}\n\n\t\t// Work-around for ODBC subdrivers that don't support num_rows()\n\t\tif (count($this->result_array) > 0)\n\t\t{\n\t\t\treturn $this->num_rows = count($this->result_array);\n\t\t}\n\t\telseif (count($this->result_object) > 0)\n\t\t{\n\t\t\treturn $this->num_rows = count($this->result_object);\n\t\t}\n\n\t\treturn $this->num_rows = count($this->result_array());\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Number of fields in the result set\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_fields()\n\t{\n\t\treturn odbc_num_fields($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch Field Names\n\t *\n\t * Generates an array of column names\n\t *\n\t * @return\tarray\n\t */\n\tpublic function list_fields()\n\t{\n\t\t$field_names = array();\n\t\t$num_fields = $this->num_fields();\n\n\t\tif ($num_fields > 0)\n\t\t{\n\t\t\tfor ($i = 1; $i <= $num_fields; $i++)\n\t\t\t{\n\t\t\t\t$field_names[] = odbc_field_name($this->result_id, $i);\n\t\t\t}\n\t\t}\n\n\t\treturn $field_names;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field data\n\t *\n\t * Generates an array of objects containing field meta-data\n\t *\n\t * @return\tarray\n\t */\n\tpublic function field_data()\n\t{\n\t\t$retval = array();\n\t\tfor ($i = 0, $odbc_index = 1, $c = $this->num_fields(); $i < $c; $i++, $odbc_index++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= odbc_field_name($this->result_id, $odbc_index);\n\t\t\t$retval[$i]->type\t\t= odbc_field_type($this->result_id, $odbc_index);\n\t\t\t$retval[$i]->max_length\t\t= odbc_field_len($this->result_id, $odbc_index);\n\t\t\t$retval[$i]->primary_key\t= 0;\n\t\t\t$retval[$i]->default\t\t= '';\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Free the result\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function free_result()\n\t{\n\t\tif (is_resource($this->result_id))\n\t\t{\n\t\t\todbc_free_result($this->result_id);\n\t\t\t$this->result_id = FALSE;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - associative array\n\t *\n\t * Returns the result set as an array\n\t *\n\t * @return\tarray\n\t */\n\tprotected function _fetch_assoc()\n\t{\n\t\treturn odbc_fetch_array($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - object\n\t *\n\t * Returns the result set as an object\n\t *\n\t * @param\tstring\t$class_name\n\t * @return\tobject\n\t */\n\tprotected function _fetch_object($class_name = 'stdClass')\n\t{\n\t\t$row = odbc_fetch_object($this->result_id);\n\n\t\tif ($class_name === 'stdClass' OR ! $row)\n\t\t{\n\t\t\treturn $row;\n\t\t}\n\n\t\t$class_name = new $class_name();\n\t\tforeach ($row as $key => $value)\n\t\t{\n\t\t\t$class_name->$key = $value;\n\t\t}\n\n\t\treturn $class_name;\n\t}\n\n}\n\n// --------------------------------------------------------------------\n\nif ( ! function_exists('odbc_fetch_array'))\n{\n\t/**\n\t * ODBC Fetch array\n\t *\n\t * Emulates the native odbc_fetch_array() function when\n\t * it is not available (odbc_fetch_array() requires unixODBC)\n\t *\n\t * @param\tresource\t&$result\n\t * @param\tint\t\t$rownumber\n\t * @return\tarray\n\t */\n\tfunction odbc_fetch_array(&$result, $rownumber = 1)\n\t{\n\t\t$rs = array();\n\t\tif ( ! odbc_fetch_into($result, $rs, $rownumber))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$rs_assoc = array();\n\t\tforeach ($rs as $k => $v)\n\t\t{\n\t\t\t$field_name = odbc_field_name($result, $k+1);\n\t\t\t$rs_assoc[$field_name] = $v;\n\t\t}\n\n\t\treturn $rs_assoc;\n\t}\n}\n\n// --------------------------------------------------------------------\n\nif ( ! function_exists('odbc_fetch_object'))\n{\n\t/**\n\t * ODBC Fetch object\n\t *\n\t * Emulates the native odbc_fetch_object() function when\n\t * it is not available.\n\t *\n\t * @param\tresource\t&$result\n\t * @param\tint\t\t$rownumber\n\t * @return\tobject\n\t */\n\tfunction odbc_fetch_object(&$result, $rownumber = 1)\n\t{\n\t\t$rs = array();\n\t\tif ( ! odbc_fetch_into($result, $rs, $rownumber))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$rs_object = new stdClass();\n\t\tforeach ($rs as $k => $v)\n\t\t{\n\t\t\t$field_name = odbc_field_name($result, $k+1);\n\t\t\t$rs_object->$field_name = $v;\n\t\t}\n\n\t\treturn $rs_object;\n\t}\n}\n"
  },
  {
    "path": "system/database/drivers/odbc/odbc_utility.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.3.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * ODBC Utility Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/database/\n */\nclass CI_DB_odbc_utility extends CI_DB_utility {\n\n\t/**\n\t * Export\n\t *\n\t * @param\tarray\t$params\tPreferences\n\t * @return\tmixed\n\t */\n\tprotected function _backup($params = array())\n\t{\n\t\t// Currently unsupported\n\t\treturn $this->db->display_error('db_unsupported_feature');\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/database/drivers/pdo/pdo_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 2.1.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_driver extends CI_DB {\n\n\t/**\n\t * Database driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $dbdriver = 'pdo';\n\n\t/**\n\t * PDO Options\n\t *\n\t * @var\tarray\n\t */\n\tpublic $options = array();\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Validates the DSN string and/or detects the subdriver.\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif (preg_match('/([^:]+):/', $this->dsn, $match) && count($match) === 2)\n\t\t{\n\t\t\t// If there is a minimum valid dsn string pattern found, we're done\n\t\t\t// This is for general PDO users, who tend to have a full DSN string.\n\t\t\t$this->subdriver = $match[1];\n\t\t\treturn;\n\t\t}\n\t\t// Legacy support for DSN specified in the hostname field\n\t\telseif (preg_match('/([^:]+):/', $this->hostname, $match) && count($match) === 2)\n\t\t{\n\t\t\t$this->dsn = $this->hostname;\n\t\t\t$this->hostname = NULL;\n\t\t\t$this->subdriver = $match[1];\n\t\t\treturn;\n\t\t}\n\t\telseif (in_array($this->subdriver, array('mssql', 'sybase'), TRUE))\n\t\t{\n\t\t\t$this->subdriver = 'dblib';\n\t\t}\n\t\telseif ($this->subdriver === '4D')\n\t\t{\n\t\t\t$this->subdriver = '4d';\n\t\t}\n\t\telseif ( ! in_array($this->subdriver, array('4d', 'cubrid', 'dblib', 'firebird', 'ibm', 'informix', 'mysql', 'oci', 'odbc', 'pgsql', 'sqlite', 'sqlsrv'), TRUE))\n\t\t{\n\t\t\tlog_message('error', 'PDO: Invalid or non-existent subdriver');\n\n\t\t\tif ($this->db_debug)\n\t\t\t{\n\t\t\t\tshow_error('Invalid or non-existent PDO subdriver');\n\t\t\t}\n\t\t}\n\n\t\t$this->dsn = NULL;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Database connection\n\t *\n\t * @param\tbool\t$persistent\n\t * @return\tobject\n\t */\n\tpublic function db_connect($persistent = FALSE)\n\t{\n\t\tif ($persistent === TRUE)\n\t\t{\n\t\t\t$this->options[PDO::ATTR_PERSISTENT] = TRUE;\n\t\t}\n\n\t\ttry\n\t\t{\n\t\t\treturn new PDO($this->dsn, $this->username, $this->password, $this->options);\n\t\t}\n\t\tcatch (PDOException $e)\n\t\t{\n\t\t\tif ($this->db_debug && empty($this->failover))\n\t\t\t{\n\t\t\t\t$this->display_error($e->getMessage(), '', TRUE);\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Database version number\n\t *\n\t * @return\tstring\n\t */\n\tpublic function version()\n\t{\n\t\tif (isset($this->data_cache['version']))\n\t\t{\n\t\t\treturn $this->data_cache['version'];\n\t\t}\n\n\t\t// Not all subdrivers support the getAttribute() method\n\t\ttry\n\t\t{\n\t\t\treturn $this->data_cache['version'] = $this->conn_id->getAttribute(PDO::ATTR_SERVER_VERSION);\n\t\t}\n\t\tcatch (PDOException $e)\n\t\t{\n\t\t\treturn parent::version();\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Execute the query\n\t *\n\t * @param\tstring\t$sql\tSQL query\n\t * @return\tmixed\n\t */\n\tprotected function _execute($sql)\n\t{\n\t\treturn $this->conn_id->query($sql);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Begin Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_begin()\n\t{\n\t\treturn $this->conn_id->beginTransaction();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Commit Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_commit()\n\t{\n\t\treturn $this->conn_id->commit();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Rollback Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_rollback()\n\t{\n\t\treturn $this->conn_id->rollBack();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Platform-dependant string escape\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _escape_str($str)\n\t{\n\t\t// Escape the string\n\t\t$str = $this->conn_id->quote($str);\n\n\t\t// If there are duplicated quotes, trim them away\n\t\treturn ($str[0] === \"'\")\n\t\t\t? substr($str, 1, -1)\n\t\t\t: $str;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Affected Rows\n\t *\n\t * @return\tint\n\t */\n\tpublic function affected_rows()\n\t{\n\t\treturn is_object($this->result_id) ? $this->result_id->rowCount() : 0;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert ID\n\t *\n\t * @param\tstring\t$name\n\t * @return\tint\n\t */\n\tpublic function insert_id($name = NULL)\n\t{\n\t\treturn $this->conn_id->lastInsertId($name);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field data query\n\t *\n\t * Generates a platform-specific query so that the column data can be retrieved\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _field_data($table)\n\t{\n\t\treturn 'SELECT TOP 1 * FROM '.$this->protect_identifiers($table);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Error\n\t *\n\t * Returns an array containing code and message of the last\n\t * database error that has occured.\n\t *\n\t * @return\tarray\n\t */\n\tpublic function error()\n\t{\n\t\t$error = array('code' => '00000', 'message' => '');\n\t\t$pdo_error = $this->conn_id->errorInfo();\n\n\t\tif (empty($pdo_error[0]))\n\t\t{\n\t\t\treturn $error;\n\t\t}\n\n\t\t$error['code'] = isset($pdo_error[1]) ? $pdo_error[0].'/'.$pdo_error[1] : $pdo_error[0];\n\t\tif (isset($pdo_error[2]))\n\t\t{\n\t\t\t $error['message'] = $pdo_error[2];\n\t\t}\n\n\t\treturn $error;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update_Batch statement\n\t *\n\t * Generates a platform-specific batch update string from the supplied data\n\t *\n\t * @param\tstring\t$table\tTable name\n\t * @param\tarray\t$values\tUpdate data\n\t * @param\tstring\t$index\tWHERE key\n\t * @return\tstring\n\t */\n\tprotected function _update_batch($table, $values, $index)\n\t{\n\t\t$ids = array();\n\t\tforeach ($values as $key => $val)\n\t\t{\n\t\t\t$ids[] = $val[$index];\n\n\t\t\tforeach (array_keys($val) as $field)\n\t\t\t{\n\t\t\t\tif ($field !== $index)\n\t\t\t\t{\n\t\t\t\t\t$final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$cases = '';\n\t\tforeach ($final as $k => $v)\n\t\t{\n\t\t\t$cases .= $k.' = CASE '.\"\\n\";\n\n\t\t\tforeach ($v as $row)\n\t\t\t{\n\t\t\t\t$cases .= $row.\"\\n\";\n\t\t\t}\n\n\t\t\t$cases .= 'ELSE '.$k.' END, ';\n\t\t}\n\n\t\t$this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);\n\n\t\treturn 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Truncate statement\n\t *\n\t * Generates a platform-specific truncate string from the supplied data\n\t *\n\t * If the database does not support the TRUNCATE statement,\n\t * then this method maps to 'DELETE FROM table'\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _truncate($table)\n\t{\n\t\treturn 'TRUNCATE TABLE '.$table;\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/pdo_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 2.1.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO Forge Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/database/\n */\nclass CI_DB_pdo_forge extends CI_DB_forge {\n\n\t/**\n\t * CREATE TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_table_if\t= FALSE;\n\n\t/**\n\t * DROP TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_drop_table_if\t= FALSE;\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/pdo_result.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 2.1.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO Result Class\n *\n * This class extends the parent result class: CI_DB_result\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_result extends CI_DB_result {\n\n\t/**\n\t * Number of rows in the result set\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_rows()\n\t{\n\t\tif (is_int($this->num_rows))\n\t\t{\n\t\t\treturn $this->num_rows;\n\t\t}\n\t\telseif (count($this->result_array) > 0)\n\t\t{\n\t\t\treturn $this->num_rows = count($this->result_array);\n\t\t}\n\t\telseif (count($this->result_object) > 0)\n\t\t{\n\t\t\treturn $this->num_rows = count($this->result_object);\n\t\t}\n\t\telseif (($num_rows = $this->result_id->rowCount()) > 0)\n\t\t{\n\t\t\treturn $this->num_rows = $num_rows;\n\t\t}\n\n\t\treturn $this->num_rows = count($this->result_array());\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Number of fields in the result set\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_fields()\n\t{\n\t\treturn $this->result_id->columnCount();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch Field Names\n\t *\n\t * Generates an array of column names\n\t *\n\t * @return\tbool\n\t */\n\tpublic function list_fields()\n\t{\n\t\t$field_names = array();\n\t\tfor ($i = 0, $c = $this->num_fields(); $i < $c; $i++)\n\t\t{\n\t\t\t// Might trigger an E_WARNING due to not all subdrivers\n\t\t\t// supporting getColumnMeta()\n\t\t\t$field_names[$i] = @$this->result_id->getColumnMeta($i);\n\t\t\t$field_names[$i] = $field_names[$i]['name'];\n\t\t}\n\n\t\treturn $field_names;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field data\n\t *\n\t * Generates an array of objects containing field meta-data\n\t *\n\t * @return\tarray\n\t */\n\tpublic function field_data()\n\t{\n\t\ttry\n\t\t{\n\t\t\t$retval = array();\n\n\t\t\tfor ($i = 0, $c = $this->num_fields(); $i < $c; $i++)\n\t\t\t{\n\t\t\t\t$field = $this->result_id->getColumnMeta($i);\n\n\t\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t\t$retval[$i]->name\t\t= $field['name'];\n\t\t\t\t$retval[$i]->type\t\t= $field['native_type'];\n\t\t\t\t$retval[$i]->max_length\t\t= ($field['len'] > 0) ? $field['len'] : NULL;\n\t\t\t\t$retval[$i]->primary_key\t= (int) ( ! empty($field['flags']) && in_array('primary_key', $field['flags'], TRUE));\n\t\t\t}\n\n\t\t\treturn $retval;\n\t\t}\n\t\tcatch (Exception $e)\n\t\t{\n\t\t\tif ($this->db->db_debug)\n\t\t\t{\n\t\t\t\treturn $this->db->display_error('db_unsupported_feature');\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Free the result\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function free_result()\n\t{\n\t\tif (is_object($this->result_id))\n\t\t{\n\t\t\t$this->result_id = FALSE;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - associative array\n\t *\n\t * Returns the result set as an array\n\t *\n\t * @return\tarray\n\t */\n\tprotected function _fetch_assoc()\n\t{\n\t\treturn $this->result_id->fetch(PDO::FETCH_ASSOC);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - object\n\t *\n\t * Returns the result set as an object\n\t *\n\t * @param\tstring\t$class_name\n\t * @return\tobject\n\t */\n\tprotected function _fetch_object($class_name = 'stdClass')\n\t{\n\t\treturn $this->result_id->fetchObject($class_name);\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/pdo_utility.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 2.1.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO Utility Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/database/\n */\nclass CI_DB_pdo_utility extends CI_DB_utility {\n\n\t/**\n\t * Export\n\t *\n\t * @param\tarray\t$params\tPreferences\n\t * @return\tmixed\n\t */\n\tprotected function _backup($params = array())\n\t{\n\t\t// Currently unsupported\n\t\treturn $this->db->display_error('db_unsupported_feature');\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_4d_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO 4D Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_4d_driver extends CI_DB_pdo_driver {\n\n\t/**\n\t * Sub-driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $subdriver = '4d';\n\n\t/**\n\t * Identifier escape character\n\t *\n\t * @var\tstring[]\n\t */\n\tprotected $_escape_char = array('[', ']');\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Builds the DSN if not already set.\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif (empty($this->dsn))\n\t\t{\n\t\t\t$this->dsn = '4D:host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);\n\n\t\t\tempty($this->port) OR $this->dsn .= ';port='.$this->port;\n\t\t\tempty($this->database) OR $this->dsn .= ';dbname='.$this->database;\n\t\t\tempty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;\n\t\t}\n\t\telseif ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 3) === FALSE)\n\t\t{\n\t\t\t$this->dsn .= ';charset='.$this->char_set;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\t$prefix_limit\n\t * @return\tstring\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\t$sql = 'SELECT '.$this->escape_identifiers('TABLE_NAME').' FROM '.$this->escape_identifiers('_USER_TABLES');\n\n\t\tif ($prefix_limit === TRUE && $this->dbprefix !== '')\n\t\t{\n\t\t\t$sql .= ' WHERE '.$this->escape_identifiers('TABLE_NAME').\" LIKE '\".$this->escape_like_str($this->dbprefix).\"%' \"\n\t\t\t\t.sprintf($this->_like_escape_str, $this->_like_escape_chr);\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show column query\n\t *\n\t * Generates a platform-specific query string so that the column names can be fetched\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _list_columns($table = '')\n\t{\n\t\treturn 'SELECT '.$this->escape_identifiers('COLUMN_NAME').' FROM '.$this->escape_identifiers('_USER_COLUMNS')\n\t\t\t.' WHERE '.$this->escape_identifiers('TABLE_NAME').' = '.$this->escape($table);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field data query\n\t *\n\t * Generates a platform-specific query so that the column data can be retrieved\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _field_data($table)\n\t{\n\t\treturn 'SELECT * FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE).' LIMIT 1';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update statement\n\t *\n\t * Generates a platform-specific update string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @param\tarray\t$values\n\t * @return\tstring\n\t */\n\tprotected function _update($table, $values)\n\t{\n\t\t$this->qb_limit = FALSE;\n\t\t$this->qb_orderby = array();\n\t\treturn parent::_update($table, $values);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Delete statement\n\t *\n\t * Generates a platform-specific delete string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _delete($table)\n\t{\n\t\t$this->qb_limit = FALSE;\n\t\treturn parent::_delete($table);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * LIMIT\n\t *\n\t * Generates a platform-specific LIMIT clause\n\t *\n\t * @param\tstring\t$sql\tSQL Query\n\t * @return\tstring\n\t */\n\tprotected function _limit($sql)\n\t{\n\t\treturn $sql.' LIMIT '.$this->qb_limit.($this->qb_offset ? ' OFFSET '.$this->qb_offset : '');\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_4d_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO 4D Forge Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_4d_forge extends CI_DB_pdo_forge {\n\n\t/**\n\t * CREATE DATABASE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_database\t= 'CREATE SCHEMA %s';\n\n\t/**\n\t * DROP DATABASE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_drop_database\t= 'DROP SCHEMA %s';\n\n\t/**\n\t * CREATE TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_table_if\t= 'CREATE TABLE IF NOT EXISTS';\n\n\t/**\n\t * RENAME TABLE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_rename_table\t= FALSE;\n\n\t/**\n\t * DROP TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_drop_table_if\t= 'DROP TABLE IF EXISTS';\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_unsigned\t\t= array(\n\t\t'INT16'\t\t=> 'INT',\n\t\t'SMALLINT'\t=> 'INT',\n\t\t'INT'\t\t=> 'INT64',\n\t\t'INT32'\t\t=> 'INT64'\n\t);\n\n\t/**\n\t * DEFAULT value representation in CREATE/ALTER TABLE statements\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_default\t\t= FALSE;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ALTER TABLE\n\t *\n\t * @param\tstring\t$alter_type\tALTER type\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tmixed\t$field\t\tColumn definition\n\t * @return\tstring|string[]\n\t */\n\tprotected function _alter_table($alter_type, $table, $field)\n\t{\n\t\tif (in_array($alter_type, array('ADD', 'DROP'), TRUE))\n\t\t{\n\t\t\treturn parent::_alter_table($alter_type, $table, $field);\n\t\t}\n\n\t\t// No method of modifying columns is supported\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Process column\n\t *\n\t * @param\tarray\t$field\n\t * @return\tstring\n\t */\n\tprotected function _process_column($field)\n\t{\n\t\treturn $this->db->escape_identifiers($field['name'])\n\t\t\t.' '.$field['type'].$field['length']\n\t\t\t.$field['null']\n\t\t\t.$field['unique']\n\t\t\t.$field['auto_increment'];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute TYPE\n\t *\n\t * Performs a data type mapping between different databases.\n\t *\n\t * @param\tarray\t&$attributes\n\t * @return\tvoid\n\t */\n\tprotected function _attr_type(&$attributes)\n\t{\n\t\tswitch (strtoupper($attributes['TYPE']))\n\t\t{\n\t\t\tcase 'TINYINT':\n\t\t\t\t$attributes['TYPE'] = 'SMALLINT';\n\t\t\t\t$attributes['UNSIGNED'] = FALSE;\n\t\t\t\treturn;\n\t\t\tcase 'MEDIUMINT':\n\t\t\t\t$attributes['TYPE'] = 'INTEGER';\n\t\t\t\t$attributes['UNSIGNED'] = FALSE;\n\t\t\t\treturn;\n\t\t\tcase 'INTEGER':\n\t\t\t\t$attributes['TYPE'] = 'INT';\n\t\t\t\treturn;\n\t\t\tcase 'BIGINT':\n\t\t\t\t$attributes['TYPE'] = 'INT64';\n\t\t\t\treturn;\n\t\t\tdefault: return;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute UNIQUE\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_unique(&$attributes, &$field)\n\t{\n\t\tif ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE)\n\t\t{\n\t\t\t$field['unique'] = ' UNIQUE';\n\n\t\t\t// UNIQUE must be used with NOT NULL\n\t\t\t$field['null'] = ' NOT NULL';\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute AUTO_INCREMENT\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_auto_increment(&$attributes, &$field)\n\t{\n\t\tif ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)\n\t\t{\n\t\t\tif (stripos($field['type'], 'int') !== FALSE)\n\t\t\t{\n\t\t\t\t$field['auto_increment'] = ' AUTO_INCREMENT';\n\t\t\t}\n\t\t\telseif (strcasecmp($field['type'], 'UUID') === 0)\n\t\t\t{\n\t\t\t\t$field['auto_increment'] = ' AUTO_GENERATE';\n\t\t\t}\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_cubrid_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO CUBRID Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_cubrid_driver extends CI_DB_pdo_driver {\n\n\t/**\n\t * Sub-driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $subdriver = 'cubrid';\n\n\t/**\n\t * Identifier escape character\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_escape_char = '`';\n\n\t/**\n\t * ORDER BY random keyword\n\t *\n\t * @var array\n\t */\n\tprotected $_random_keyword = array('RANDOM()', 'RANDOM(%d)');\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Builds the DSN if not already set.\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif (empty($this->dsn))\n\t\t{\n\t\t\t$this->dsn = 'cubrid:host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);\n\n\t\t\tempty($this->port) OR $this->dsn .= ';port='.$this->port;\n\t\t\tempty($this->database) OR $this->dsn .= ';dbname='.$this->database;\n\t\t\tempty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\t$prefix_limit\n\t * @return\tstring\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\t$sql = 'SHOW TABLES';\n\n\t\tif ($prefix_limit === TRUE && $this->dbprefix !== '')\n\t\t{\n\t\t\treturn $sql.\" LIKE '\".$this->escape_like_str($this->dbprefix).\"%'\";\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show column query\n\t *\n\t * Generates a platform-specific query string so that the column names can be fetched\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _list_columns($table = '')\n\t{\n\t\treturn 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an object with field data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tarray\n\t */\n\tpublic function field_data($table)\n\t{\n\t\tif (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\t$query = $query->result_object();\n\n\t\t$retval = array();\n\t\tfor ($i = 0, $c = count($query); $i < $c; $i++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= $query[$i]->Field;\n\n\t\t\tsscanf($query[$i]->Type, '%[a-z](%d)',\n\t\t\t\t$retval[$i]->type,\n\t\t\t\t$retval[$i]->max_length\n\t\t\t);\n\n\t\t\t$retval[$i]->default\t\t= $query[$i]->Default;\n\t\t\t$retval[$i]->primary_key\t= (int) ($query[$i]->Key === 'PRI');\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update_Batch statement\n\t *\n\t * Generates a platform-specific batch update string from the supplied data\n\t *\n\t * @param\tstring\t$table\tTable name\n\t * @param\tarray\t$values\tUpdate data\n\t * @param\tstring\t$index\tWHERE key\n\t * @return\tstring\n\t */\n\tprotected function _update_batch($table, $values, $index)\n\t{\n\t\t$ids = array();\n\t\tforeach ($values as $key => $val)\n\t\t{\n\t\t\t$ids[] = $val[$index];\n\n\t\t\tforeach (array_keys($val) as $field)\n\t\t\t{\n\t\t\t\tif ($field !== $index)\n\t\t\t\t{\n\t\t\t\t\t$final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$cases = '';\n\t\tforeach ($final as $k => $v)\n\t\t{\n\t\t\t$cases .= $k.\" = CASE \\n\"\n\t\t\t\t.implode(\"\\n\", $v).\"\\n\"\n\t\t\t\t.'ELSE '.$k.' END), ';\n\t\t}\n\n\t\t$this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);\n\n\t\treturn 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Truncate statement\n\t *\n\t * Generates a platform-specific truncate string from the supplied data\n\t *\n\t * If the database does not support the TRUNCATE statement,\n\t * then this method maps to 'DELETE FROM table'\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _truncate($table)\n\t{\n\t\treturn 'TRUNCATE '.$table;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * FROM tables\n\t *\n\t * Groups tables in FROM clauses if needed, so there is no confusion\n\t * about operator precedence.\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _from_tables()\n\t{\n\t\tif ( ! empty($this->qb_join) && count($this->qb_from) > 1)\n\t\t{\n\t\t\treturn '('.implode(', ', $this->qb_from).')';\n\t\t}\n\n\t\treturn implode(', ', $this->qb_from);\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_cubrid_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO CUBRID Forge Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_cubrid_forge extends CI_DB_pdo_forge {\n\n\t/**\n\t * CREATE DATABASE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_database\t= FALSE;\n\n\t/**\n\t * DROP DATABASE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_drop_database\t= FALSE;\n\n\t/**\n\t * CREATE TABLE keys flag\n\t *\n\t * Whether table keys are created from within the\n\t * CREATE TABLE statement.\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_create_table_keys\t= TRUE;\n\n\t/**\n\t * DROP TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_drop_table_if\t= 'DROP TABLE IF EXISTS';\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_unsigned\t\t= array(\n\t\t'SHORT'\t\t=> 'INTEGER',\n\t\t'SMALLINT'\t=> 'INTEGER',\n\t\t'INT'\t\t=> 'BIGINT',\n\t\t'INTEGER'\t=> 'BIGINT',\n\t\t'BIGINT'\t=> 'NUMERIC',\n\t\t'FLOAT'\t\t=> 'DOUBLE',\n\t\t'REAL'\t\t=> 'DOUBLE'\n\t);\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ALTER TABLE\n\t *\n\t * @param\tstring\t$alter_type\tALTER type\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tmixed\t$field\t\tColumn definition\n\t * @return\tstring|string[]\n\t */\n\tprotected function _alter_table($alter_type, $table, $field)\n\t{\n\t\tif (in_array($alter_type, array('DROP', 'ADD'), TRUE))\n\t\t{\n\t\t\treturn parent::_alter_table($alter_type, $table, $field);\n\t\t}\n\n\t\t$sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);\n\t\t$sqls = array();\n\t\tfor ($i = 0, $c = count($field); $i < $c; $i++)\n\t\t{\n\t\t\tif ($field[$i]['_literal'] !== FALSE)\n\t\t\t{\n\t\t\t\t$sqls[] = $sql.' CHANGE '.$field[$i]['_literal'];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$alter_type = empty($field[$i]['new_name']) ? ' MODIFY ' : ' CHANGE ';\n\t\t\t\t$sqls[] = $sql.$alter_type.$this->_process_column($field[$i]);\n\t\t\t}\n\t\t}\n\n\t\treturn $sqls;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Process column\n\t *\n\t * @param\tarray\t$field\n\t * @return\tstring\n\t */\n\tprotected function _process_column($field)\n\t{\n\t\t$extra_clause = isset($field['after'])\n\t\t\t? ' AFTER '.$this->db->escape_identifiers($field['after']) : '';\n\n\t\tif (empty($extra_clause) && isset($field['first']) && $field['first'] === TRUE)\n\t\t{\n\t\t\t$extra_clause = ' FIRST';\n\t\t}\n\n\t\treturn $this->db->escape_identifiers($field['name'])\n\t\t\t.(empty($field['new_name']) ? '' : ' '.$this->db->escape_identifiers($field['new_name']))\n\t\t\t.' '.$field['type'].$field['length']\n\t\t\t.$field['unsigned']\n\t\t\t.$field['null']\n\t\t\t.$field['default']\n\t\t\t.$field['auto_increment']\n\t\t\t.$field['unique']\n\t\t\t.$extra_clause;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute TYPE\n\t *\n\t * Performs a data type mapping between different databases.\n\t *\n\t * @param\tarray\t&$attributes\n\t * @return\tvoid\n\t */\n\tprotected function _attr_type(&$attributes)\n\t{\n\t\tswitch (strtoupper($attributes['TYPE']))\n\t\t{\n\t\t\tcase 'TINYINT':\n\t\t\t\t$attributes['TYPE'] = 'SMALLINT';\n\t\t\t\t$attributes['UNSIGNED'] = FALSE;\n\t\t\t\treturn;\n\t\t\tcase 'MEDIUMINT':\n\t\t\t\t$attributes['TYPE'] = 'INTEGER';\n\t\t\t\t$attributes['UNSIGNED'] = FALSE;\n\t\t\t\treturn;\n\t\t\tcase 'LONGTEXT':\n\t\t\t\t$attributes['TYPE'] = 'STRING';\n\t\t\t\treturn;\n\t\t\tdefault: return;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Process indexes\n\t *\n\t * @param\tstring\t$table\t(ignored)\n\t * @return\tstring\n\t */\n\tprotected function _process_indexes($table)\n\t{\n\t\t$sql = '';\n\n\t\tfor ($i = 0, $c = count($this->keys); $i < $c; $i++)\n\t\t{\n\t\t\tif (is_array($this->keys[$i]))\n\t\t\t{\n\t\t\t\tfor ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++)\n\t\t\t\t{\n\t\t\t\t\tif ( ! isset($this->fields[$this->keys[$i][$i2]]))\n\t\t\t\t\t{\n\t\t\t\t\t\tunset($this->keys[$i][$i2]);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ( ! isset($this->fields[$this->keys[$i]]))\n\t\t\t{\n\t\t\t\tunset($this->keys[$i]);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tis_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);\n\n\t\t\t$sql .= \",\\n\\tKEY \".$this->db->escape_identifiers(implode('_', $this->keys[$i]))\n\t\t\t\t.' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';\n\t\t}\n\n\t\t$this->keys = array();\n\n\t\treturn $sql;\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_dblib_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO DBLIB Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_dblib_driver extends CI_DB_pdo_driver {\n\n\t/**\n\t * Sub-driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $subdriver = 'dblib';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ORDER BY random keyword\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_random_keyword = array('NEWID()', 'RAND(%d)');\n\n\t/**\n\t * Quoted identifier flag\n\t *\n\t * Whether to use SQL-92 standard quoted identifier\n\t * (double quotes) or brackets for identifier escaping.\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_quoted_identifier;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Builds the DSN if not already set.\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif (empty($this->dsn))\n\t\t{\n\t\t\t$this->dsn = $params['subdriver'].':host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);\n\n\t\t\tif ( ! empty($this->port))\n\t\t\t{\n\t\t\t\t$this->dsn .= (DIRECTORY_SEPARATOR === '\\\\' ? ',' : ':').$this->port;\n\t\t\t}\n\n\t\t\tempty($this->database) OR $this->dsn .= ';dbname='.$this->database;\n\t\t\tempty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;\n\t\t\tempty($this->appname) OR $this->dsn .= ';appname='.$this->appname;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 6) === FALSE)\n\t\t\t{\n\t\t\t\t$this->dsn .= ';charset='.$this->char_set;\n\t\t\t}\n\n\t\t\t$this->subdriver = 'dblib';\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Database connection\n\t *\n\t * @param\tbool\t$persistent\n\t * @return\tobject\n\t */\n\tpublic function db_connect($persistent = FALSE)\n\t{\n\t\tif ($persistent === TRUE)\n\t\t{\n\t\t\tlog_message('debug', \"dblib driver doesn't support persistent connections\");\n\t\t}\n\n\t\t$this->conn_id = parent::db_connect(FALSE);\n\n\t\tif ( ! is_object($this->conn_id))\n\t\t{\n\t\t\treturn $this->conn_id;\n\t\t}\n\n\t\t// Determine how identifiers are escaped\n\t\t$query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi');\n\t\t$query = $query->row_array();\n\t\t$this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi'];\n\t\t$this->_escape_char = ($this->_quoted_identifier) ? '\"' : array('[', ']');\n\n\t\treturn $this->conn_id;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\t$prefix_limit\n\t * @return\tstring\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\t$sql = 'SELECT '.$this->escape_identifiers('name')\n\t\t\t.' FROM '.$this->escape_identifiers('sysobjects')\n\t\t\t.' WHERE '.$this->escape_identifiers('type').\" = 'U'\";\n\n\t\tif ($prefix_limit === TRUE && $this->dbprefix !== '')\n\t\t{\n\t\t\t$sql .= ' AND '.$this->escape_identifiers('name').\" LIKE '\".$this->escape_like_str($this->dbprefix).\"%' \"\n\t\t\t\t.sprintf($this->_like_escape_str, $this->_like_escape_chr);\n\t\t}\n\n\t\treturn $sql.' ORDER BY '.$this->escape_identifiers('name');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show column query\n\t *\n\t * Generates a platform-specific query string so that the column names can be fetched\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _list_columns($table = '')\n\t{\n\t\treturn 'SELECT COLUMN_NAME\n\t\t\tFROM INFORMATION_SCHEMA.Columns\n\t\t\tWHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an object with field data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tarray\n\t */\n\tpublic function field_data($table)\n\t{\n\t\t$sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, COLUMN_DEFAULT\n\t\t\tFROM INFORMATION_SCHEMA.Columns\n\t\t\tWHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));\n\n\t\tif (($query = $this->query($sql)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\t$query = $query->result_object();\n\n\t\t$retval = array();\n\t\tfor ($i = 0, $c = count($query); $i < $c; $i++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= $query[$i]->COLUMN_NAME;\n\t\t\t$retval[$i]->type\t\t= $query[$i]->DATA_TYPE;\n\t\t\t$retval[$i]->max_length\t\t= ($query[$i]->CHARACTER_MAXIMUM_LENGTH > 0) ? $query[$i]->CHARACTER_MAXIMUM_LENGTH : $query[$i]->NUMERIC_PRECISION;\n\t\t\t$retval[$i]->default\t\t= $query[$i]->COLUMN_DEFAULT;\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update statement\n\t *\n\t * Generates a platform-specific update string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @param\tarray\t$values\n\t * @return\tstring\n\t */\n\tprotected function _update($table, $values)\n\t{\n\t\t$this->qb_limit = FALSE;\n\t\t$this->qb_orderby = array();\n\t\treturn parent::_update($table, $values);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Delete statement\n\t *\n\t * Generates a platform-specific delete string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _delete($table)\n\t{\n\t\tif ($this->qb_limit)\n\t\t{\n\t\t\treturn 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete';\n\t\t}\n\n\t\treturn parent::_delete($table);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * LIMIT\n\t *\n\t * Generates a platform-specific LIMIT clause\n\t *\n\t * @param\tstring\t$sql\tSQL Query\n\t * @return\tstring\n\t */\n\tprotected function _limit($sql)\n\t{\n\t\t$limit = $this->qb_offset + $this->qb_limit;\n\n\t\t// As of SQL Server 2005 (9.0.*) ROW_NUMBER() is supported,\n\t\t// however an ORDER BY clause is required for it to work\n\t\tif (version_compare($this->version(), '9', '>=') && $this->qb_offset && ! empty($this->qb_orderby))\n\t\t{\n\t\t\t$orderby = $this->_compile_order_by();\n\n\t\t\t// We have to strip the ORDER BY clause\n\t\t\t$sql = trim(substr($sql, 0, strrpos($sql, $orderby)));\n\n\t\t\t// Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results\n\t\t\tif (count($this->qb_select) === 0)\n\t\t\t{\n\t\t\t\t$select = '*'; // Inevitable\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Use only field names and their aliases, everything else is out of our scope.\n\t\t\t\t$select = array();\n\t\t\t\t$field_regexp = ($this->_quoted_identifier)\n\t\t\t\t\t? '(\"[^\\\"]+\")' : '(\\[[^\\]]+\\])';\n\t\t\t\tfor ($i = 0, $c = count($this->qb_select); $i < $c; $i++)\n\t\t\t\t{\n\t\t\t\t\t$select[] = preg_match('/(?:\\s|\\.)'.$field_regexp.'$/i', $this->qb_select[$i], $m)\n\t\t\t\t\t\t? $m[1] : $this->qb_select[$i];\n\t\t\t\t}\n\t\t\t\t$select = implode(', ', $select);\n\t\t\t}\n\n\t\t\treturn 'SELECT '.$select.\" FROM (\\n\\n\"\n\t\t\t\t.preg_replace('/^(SELECT( DISTINCT)?)/i', '\\\\1 ROW_NUMBER() OVER('.trim($orderby).') AS '.$this->escape_identifiers('CI_rownum').', ', $sql)\n\t\t\t\t.\"\\n\\n) \".$this->escape_identifiers('CI_subquery')\n\t\t\t\t.\"\\nWHERE \".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit;\n\t\t}\n\n\t\treturn preg_replace('/(^\\SELECT (DISTINCT)?)/i','\\\\1 TOP '.$limit.' ', $sql);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert batch statement\n\t *\n\t * Generates a platform-specific insert string from the supplied data.\n\t *\n\t * @param\tstring\t$table\tTable name\n\t * @param\tarray\t$keys\tINSERT keys\n\t * @param\tarray\t$values\tINSERT values\n\t * @return\tstring|bool\n\t */\n\tprotected function _insert_batch($table, $keys, $values)\n\t{\n\t\t// Multiple-value inserts are only supported as of SQL Server 2008\n\t\tif (version_compare($this->version(), '10', '>='))\n\t\t{\n\t\t\treturn parent::_insert_batch($table, $keys, $values);\n\t\t}\n\n\t\treturn ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_dblib_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO DBLIB Forge Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_dblib_forge extends CI_DB_pdo_forge {\n\n\t/**\n\t * CREATE TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_table_if\t= \"IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\\nCREATE TABLE\";\n\n\t/**\n\t * DROP TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_drop_table_if\t= \"IF EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\\nDROP TABLE\";\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_unsigned\t\t= array(\n\t\t'TINYINT'\t=> 'SMALLINT',\n\t\t'SMALLINT'\t=> 'INT',\n\t\t'INT'\t\t=> 'BIGINT',\n\t\t'REAL'\t\t=> 'FLOAT'\n\t);\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ALTER TABLE\n\t *\n\t * @param\tstring\t$alter_type\tALTER type\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tmixed\t$field\t\tColumn definition\n\t * @return\tstring|string[]\n\t */\n\tprotected function _alter_table($alter_type, $table, $field)\n\t{\n\t\tif (in_array($alter_type, array('ADD', 'DROP'), TRUE))\n\t\t{\n\t\t\treturn parent::_alter_table($alter_type, $table, $field);\n\t\t}\n\n\t\t$sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ALTER COLUMN ';\n\t\t$sqls = array();\n\t\tfor ($i = 0, $c = count($field); $i < $c; $i++)\n\t\t{\n\t\t\t$sqls[] = $sql.$this->_process_column($field[$i]);\n\t\t}\n\n\t\treturn $sqls;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute TYPE\n\t *\n\t * Performs a data type mapping between different databases.\n\t *\n\t * @param\tarray\t&$attributes\n\t * @return\tvoid\n\t */\n\tprotected function _attr_type(&$attributes)\n\t{\n\t\tif (isset($attributes['CONSTRAINT']) && strpos($attributes['TYPE'], 'INT') !== FALSE)\n\t\t{\n\t\t\tunset($attributes['CONSTRAINT']);\n\t\t}\n\n\t\tswitch (strtoupper($attributes['TYPE']))\n\t\t{\n\t\t\tcase 'MEDIUMINT':\n\t\t\t\t$attributes['TYPE'] = 'INTEGER';\n\t\t\t\t$attributes['UNSIGNED'] = FALSE;\n\t\t\t\treturn;\n\t\t\tcase 'INTEGER':\n\t\t\t\t$attributes['TYPE'] = 'INT';\n\t\t\t\treturn;\n\t\t\tdefault: return;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute AUTO_INCREMENT\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_auto_increment(&$attributes, &$field)\n\t{\n\t\tif ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)\n\t\t{\n\t\t\t$field['auto_increment'] = ' IDENTITY(1,1)';\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_firebird_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO Firebird Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_firebird_driver extends CI_DB_pdo_driver {\n\n\t/**\n\t * Sub-driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $subdriver = 'firebird';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ORDER BY random keyword\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_random_keyword = array('RAND()', 'RAND()');\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Builds the DSN if not already set.\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif (empty($this->dsn))\n\t\t{\n\t\t\t$this->dsn = 'firebird:';\n\n\t\t\tif ( ! empty($this->database))\n\t\t\t{\n\t\t\t\t$this->dsn .= 'dbname='.$this->database;\n\t\t\t}\n\t\t\telseif ( ! empty($this->hostname))\n\t\t\t{\n\t\t\t\t$this->dsn .= 'dbname='.$this->hostname;\n\t\t\t}\n\n\t\t\tempty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;\n\t\t\tempty($this->role) OR $this->dsn .= ';role='.$this->role;\n\t\t}\n\t\telseif ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 9) === FALSE)\n\t\t{\n\t\t\t$this->dsn .= ';charset='.$this->char_set;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\t$prefix_limit\n\t * @return\tstring\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\t$sql = 'SELECT \"RDB$RELATION_NAME\" FROM \"RDB$RELATIONS\" WHERE \"RDB$RELATION_NAME\" NOT LIKE \\'RDB$%\\' AND \"RDB$RELATION_NAME\" NOT LIKE \\'MON$%\\'';\n\n\t\tif ($prefix_limit === TRUE && $this->dbprefix !== '')\n\t\t{\n\t\t\treturn $sql.' AND \"RDB$RELATION_NAME\" LIKE \\''.$this->escape_like_str($this->dbprefix).\"%' \"\n\t\t\t\t.sprintf($this->_like_escape_str, $this->_like_escape_chr);\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show column query\n\t *\n\t * Generates a platform-specific query string so that the column names can be fetched\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _list_columns($table = '')\n\t{\n\t\treturn 'SELECT \"RDB$FIELD_NAME\" FROM \"RDB$RELATION_FIELDS\" WHERE \"RDB$RELATION_NAME\" = '.$this->escape($table);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an object with field data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tarray\n\t */\n\tpublic function field_data($table)\n\t{\n\t\t$sql = 'SELECT \"rfields\".\"RDB$FIELD_NAME\" AS \"name\",\n\t\t\t\tCASE \"fields\".\"RDB$FIELD_TYPE\"\n\t\t\t\t\tWHEN 7 THEN \\'SMALLINT\\'\n\t\t\t\t\tWHEN 8 THEN \\'INTEGER\\'\n\t\t\t\t\tWHEN 9 THEN \\'QUAD\\'\n\t\t\t\t\tWHEN 10 THEN \\'FLOAT\\'\n\t\t\t\t\tWHEN 11 THEN \\'DFLOAT\\'\n\t\t\t\t\tWHEN 12 THEN \\'DATE\\'\n\t\t\t\t\tWHEN 13 THEN \\'TIME\\'\n\t\t\t\t\tWHEN 14 THEN \\'CHAR\\'\n\t\t\t\t\tWHEN 16 THEN \\'INT64\\'\n\t\t\t\t\tWHEN 27 THEN \\'DOUBLE\\'\n\t\t\t\t\tWHEN 35 THEN \\'TIMESTAMP\\'\n\t\t\t\t\tWHEN 37 THEN \\'VARCHAR\\'\n\t\t\t\t\tWHEN 40 THEN \\'CSTRING\\'\n\t\t\t\t\tWHEN 261 THEN \\'BLOB\\'\n\t\t\t\t\tELSE NULL\n\t\t\t\tEND AS \"type\",\n\t\t\t\t\"fields\".\"RDB$FIELD_LENGTH\" AS \"max_length\",\n\t\t\t\t\"rfields\".\"RDB$DEFAULT_VALUE\" AS \"default\"\n\t\t\tFROM \"RDB$RELATION_FIELDS\" \"rfields\"\n\t\t\t\tJOIN \"RDB$FIELDS\" \"fields\" ON \"rfields\".\"RDB$FIELD_SOURCE\" = \"fields\".\"RDB$FIELD_NAME\"\n\t\t\tWHERE \"rfields\".\"RDB$RELATION_NAME\" = '.$this->escape($table).'\n\t\t\tORDER BY \"rfields\".\"RDB$FIELD_POSITION\"';\n\n\t\treturn (($query = $this->query($sql)) !== FALSE)\n\t\t\t? $query->result_object()\n\t\t\t: FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update statement\n\t *\n\t * Generates a platform-specific update string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @param\tarray\t$values\n\t * @return\tstring\n\t */\n\tprotected function _update($table, $values)\n\t{\n\t\t$this->qb_limit = FALSE;\n\t\treturn parent::_update($table, $values);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Truncate statement\n\t *\n\t * Generates a platform-specific truncate string from the supplied data\n\t *\n\t * If the database does not support the TRUNCATE statement,\n\t * then this method maps to 'DELETE FROM table'\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _truncate($table)\n\t{\n\t\treturn 'DELETE FROM '.$table;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Delete statement\n\t *\n\t * Generates a platform-specific delete string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _delete($table)\n\t{\n\t\t$this->qb_limit = FALSE;\n\t\treturn parent::_delete($table);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * LIMIT\n\t *\n\t * Generates a platform-specific LIMIT clause\n\t *\n\t * @param\tstring\t$sql\tSQL Query\n\t * @return\tstring\n\t */\n\tprotected function _limit($sql)\n\t{\n\t\t// Limit clause depends on if Interbase or Firebird\n\t\tif (stripos($this->version(), 'firebird') !== FALSE)\n\t\t{\n\t\t\t$select = 'FIRST '.$this->qb_limit\n\t\t\t\t.($this->qb_offset > 0 ? ' SKIP '.$this->qb_offset : '');\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$select = 'ROWS '\n\t\t\t\t.($this->qb_offset > 0 ? $this->qb_offset.' TO '.($this->qb_limit + $this->qb_offset) : $this->qb_limit);\n\t\t}\n\n\t\treturn preg_replace('`SELECT`i', 'SELECT '.$select, $sql);\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_firebird_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO Firebird Forge Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_firebird_forge extends CI_DB_pdo_forge {\n\n\t/**\n\t * RENAME TABLE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_rename_table\t= FALSE;\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_unsigned\t\t= array(\n\t\t'SMALLINT'\t=> 'INTEGER',\n\t\t'INTEGER'\t=> 'INT64',\n\t\t'FLOAT'\t\t=> 'DOUBLE PRECISION'\n\t);\n\n\t/**\n\t * NULL value representation in CREATE/ALTER TABLE statements\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_null\t\t= 'NULL';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Create database\n\t *\n\t * @param\tstring\t$db_name\n\t * @return\tstring\n\t */\n\tpublic function create_database($db_name)\n\t{\n\t\t// Firebird databases are flat files, so a path is required\n\n\t\t// Hostname is needed for remote access\n\t\tempty($this->db->hostname) OR $db_name = $this->hostname.':'.$db_name;\n\n\t\treturn parent::create_database('\"'.$db_name.'\"');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Drop database\n\t *\n\t * @param\tstring\t$db_name\t(ignored)\n\t * @return\tbool\n\t */\n\tpublic function drop_database($db_name = '')\n\t{\n\t\tif ( ! ibase_drop_db($this->conn_id))\n\t\t{\n\t\t\treturn ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE;\n\t\t}\n\t\telseif ( ! empty($this->db->data_cache['db_names']))\n\t\t{\n\t\t\t$key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE);\n\t\t\tif ($key !== FALSE)\n\t\t\t{\n\t\t\t\tunset($this->db->data_cache['db_names'][$key]);\n\t\t\t}\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ALTER TABLE\n\t *\n\t * @param\tstring\t$alter_type\tALTER type\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tmixed\t$field\t\tColumn definition\n\t * @return\tstring|string[]\n\t */\n\tprotected function _alter_table($alter_type, $table, $field)\n \t{\n\t\tif (in_array($alter_type, array('DROP', 'ADD'), TRUE))\n\t\t{\n\t\t\treturn parent::_alter_table($alter_type, $table, $field);\n\t\t}\n\n\t\t$sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);\n\t\t$sqls = array();\n\t\tfor ($i = 0, $c = count($field); $i < $c; $i++)\n\t\t{\n\t\t\tif ($field[$i]['_literal'] !== FALSE)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tif (isset($field[$i]['type']))\n\t\t\t{\n\t\t\t\t$sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])\n\t\t\t\t\t.' TYPE '.$field[$i]['type'].$field[$i]['length'];\n\t\t\t}\n\n\t\t\tif ( ! empty($field[$i]['default']))\n\t\t\t{\n\t\t\t\t$sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])\n\t\t\t\t\t.' SET DEFAULT '.$field[$i]['default'];\n\t\t\t}\n\n\t\t\tif (isset($field[$i]['null']))\n\t\t\t{\n\t\t\t\t$sqls[] = 'UPDATE \"RDB$RELATION_FIELDS\" SET \"RDB$NULL_FLAG\" = '\n\t\t\t\t\t.($field[$i]['null'] === TRUE ? 'NULL' : '1')\n\t\t\t\t\t.' WHERE \"RDB$FIELD_NAME\" = '.$this->db->escape($field[$i]['name'])\n\t\t\t\t\t.' AND \"RDB$RELATION_NAME\" = '.$this->db->escape($table);\n\t\t\t}\n\n\t\t\tif ( ! empty($field[$i]['new_name']))\n\t\t\t{\n\t\t\t\t$sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])\n\t\t\t\t\t.' TO '.$this->db->escape_identifiers($field[$i]['new_name']);\n\t\t\t}\n\t\t}\n\n\t\treturn $sqls;\n \t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Process column\n\t *\n\t * @param\tarray\t$field\n\t * @return\tstring\n\t */\n\tprotected function _process_column($field)\n\t{\n\t\treturn $this->db->escape_identifiers($field['name'])\n\t\t\t.' '.$field['type'].$field['length']\n\t\t\t.$field['null']\n\t\t\t.$field['unique']\n\t\t\t.$field['default'];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute TYPE\n\t *\n\t * Performs a data type mapping between different databases.\n\t *\n\t * @param\tarray\t&$attributes\n\t * @return\tvoid\n\t */\n\tprotected function _attr_type(&$attributes)\n\t{\n\t\tswitch (strtoupper($attributes['TYPE']))\n\t\t{\n\t\t\tcase 'TINYINT':\n\t\t\t\t$attributes['TYPE'] = 'SMALLINT';\n\t\t\t\t$attributes['UNSIGNED'] = FALSE;\n\t\t\t\treturn;\n\t\t\tcase 'MEDIUMINT':\n\t\t\t\t$attributes['TYPE'] = 'INTEGER';\n\t\t\t\t$attributes['UNSIGNED'] = FALSE;\n\t\t\t\treturn;\n\t\t\tcase 'INT':\n\t\t\t\t$attributes['TYPE'] = 'INTEGER';\n\t\t\t\treturn;\n\t\t\tcase 'BIGINT':\n\t\t\t\t$attributes['TYPE'] = 'INT64';\n\t\t\t\treturn;\n\t\t\tdefault: return;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute AUTO_INCREMENT\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_auto_increment(&$attributes, &$field)\n\t{\n\t\t// Not supported\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_ibm_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO IBM DB2 Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_ibm_driver extends CI_DB_pdo_driver {\n\n\t/**\n\t * Sub-driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $subdriver = 'ibm';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Builds the DSN if not already set.\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif (empty($this->dsn))\n\t\t{\n\t\t\t$this->dsn = 'ibm:';\n\n\t\t\t// Pre-defined DSN\n\t\t\tif (empty($this->hostname) && empty($this->HOSTNAME) && empty($this->port) && empty($this->PORT))\n\t\t\t{\n\t\t\t\tif (isset($this->DSN))\n\t\t\t\t{\n\t\t\t\t\t$this->dsn .= 'DSN='.$this->DSN;\n\t\t\t\t}\n\t\t\t\telseif ( ! empty($this->database))\n\t\t\t\t{\n\t\t\t\t\t$this->dsn .= 'DSN='.$this->database;\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t$this->dsn .= 'DRIVER='.(isset($this->DRIVER) ? '{'.$this->DRIVER.'}' : '{IBM DB2 ODBC DRIVER}').';';\n\n\t\t\tif (isset($this->DATABASE))\n\t\t\t{\n\t\t\t\t$this->dsn .= 'DATABASE='.$this->DATABASE.';';\n\t\t\t}\n\t\t\telseif ( ! empty($this->database))\n\t\t\t{\n\t\t\t\t$this->dsn .= 'DATABASE='.$this->database.';';\n\t\t\t}\n\n\t\t\tif (isset($this->HOSTNAME))\n\t\t\t{\n\t\t\t\t$this->dsn .= 'HOSTNAME='.$this->HOSTNAME.';';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->dsn .= 'HOSTNAME='.(empty($this->hostname) ? '127.0.0.1;' : $this->hostname.';');\n\t\t\t}\n\n\t\t\tif (isset($this->PORT))\n\t\t\t{\n\t\t\t\t$this->dsn .= 'PORT='.$this->port.';';\n\t\t\t}\n\t\t\telseif ( ! empty($this->port))\n\t\t\t{\n\t\t\t\t$this->dsn .= ';PORT='.$this->port.';';\n\t\t\t}\n\n\t\t\t$this->dsn .= 'PROTOCOL='.(isset($this->PROTOCOL) ? $this->PROTOCOL.';' : 'TCPIP;');\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\t$prefix_limit\n\t * @return\tstring\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\t$sql = 'SELECT \"tabname\" FROM \"syscat\".\"tables\"\n\t\t\tWHERE \"type\" = \\'T\\' AND LOWER(\"tabschema\") = '.$this->escape(strtolower($this->database));\n\n\t\tif ($prefix_limit === TRUE && $this->dbprefix !== '')\n\t\t{\n\t\t\t$sql .= ' AND \"tabname\" LIKE \\''.$this->escape_like_str($this->dbprefix).\"%' \"\n\t\t\t\t.sprintf($this->_like_escape_str, $this->_like_escape_chr);\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show column query\n\t *\n\t * Generates a platform-specific query string so that the column names can be fetched\n\t *\n\t * @param\tstring\t$table\n\t * @return\tarray\n\t */\n\tprotected function _list_columns($table = '')\n\t{\n\t\treturn 'SELECT \"colname\" FROM \"syscat\".\"columns\"\n\t\t\tWHERE LOWER(\"tabschema\") = '.$this->escape(strtolower($this->database)).'\n\t\t\t\tAND LOWER(\"tabname\") = '.$this->escape(strtolower($table));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an object with field data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tarray\n\t */\n\tpublic function field_data($table)\n\t{\n\t\t$sql = 'SELECT \"colname\" AS \"name\", \"typename\" AS \"type\", \"default\" AS \"default\", \"length\" AS \"max_length\",\n\t\t\t\tCASE \"keyseq\" WHEN NULL THEN 0 ELSE 1 END AS \"primary_key\"\n\t\t\tFROM \"syscat\".\"columns\"\n\t\t\tWHERE LOWER(\"tabschema\") = '.$this->escape(strtolower($this->database)).'\n\t\t\t\tAND LOWER(\"tabname\") = '.$this->escape(strtolower($table)).'\n\t\t\tORDER BY \"colno\"';\n\n\t\treturn (($query = $this->query($sql)) !== FALSE)\n\t\t\t? $query->result_object()\n\t\t\t: FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update statement\n\t *\n\t * Generates a platform-specific update string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @param\tarray\t$values\n\t * @return\tstring\n\t */\n\tprotected function _update($table, $values)\n\t{\n\t\t$this->qb_limit = FALSE;\n\t\t$this->qb_orderby = array();\n\t\treturn parent::_update($table, $values);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Delete statement\n\t *\n\t * Generates a platform-specific delete string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _delete($table)\n\t{\n\t\t$this->qb_limit = FALSE;\n\t\treturn parent::_delete($table);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * LIMIT\n\t *\n\t * Generates a platform-specific LIMIT clause\n\t *\n\t * @param\tstring\t$sql\tSQL Query\n\t * @return\tstring\n\t */\n\tprotected function _limit($sql)\n\t{\n\t\t$sql .= ' FETCH FIRST '.($this->qb_limit + $this->qb_offset).' ROWS ONLY';\n\n\t\treturn ($this->qb_offset)\n\t\t\t? 'SELECT * FROM ('.$sql.') WHERE rownum > '.$this->qb_offset\n\t\t\t: $sql;\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_ibm_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO IBM DB2 Forge Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_ibm_forge extends CI_DB_pdo_forge {\n\n\t/**\n\t * RENAME TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_rename_table\t= 'RENAME TABLE %s TO %s';\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_unsigned\t\t= array(\n\t\t'SMALLINT'\t=> 'INTEGER',\n\t\t'INT'\t\t=> 'BIGINT',\n\t\t'INTEGER'\t=> 'BIGINT'\n\t);\n\n\t/**\n\t * DEFAULT value representation in CREATE/ALTER TABLE statements\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_default\t\t= FALSE;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ALTER TABLE\n\t *\n\t * @param\tstring\t$alter_type\tALTER type\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tmixed\t$field\t\tColumn definition\n\t * @return\tstring|string[]\n\t */\n\tprotected function _alter_table($alter_type, $table, $field)\n\t{\n\t\tif ($alter_type === 'CHANGE')\n\t\t{\n\t\t\t$alter_type = 'MODIFY';\n\t\t}\n\n\t\treturn parent::_alter_table($alter_type, $table, $field);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute TYPE\n\t *\n\t * Performs a data type mapping between different databases.\n\t *\n\t * @param\tarray\t&$attributes\n\t * @return\tvoid\n\t */\n\tprotected function _attr_type(&$attributes)\n\t{\n\t\tswitch (strtoupper($attributes['TYPE']))\n\t\t{\n\t\t\tcase 'TINYINT':\n\t\t\t\t$attributes['TYPE'] = 'SMALLINT';\n\t\t\t\t$attributes['UNSIGNED'] = FALSE;\n\t\t\t\treturn;\n\t\t\tcase 'MEDIUMINT':\n\t\t\t\t$attributes['TYPE'] = 'INTEGER';\n\t\t\t\t$attributes['UNSIGNED'] = FALSE;\n\t\t\t\treturn;\n\t\t\tdefault: return;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute UNIQUE\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_unique(&$attributes, &$field)\n\t{\n\t\tif ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE)\n\t\t{\n\t\t\t$field['unique'] = ' UNIQUE';\n\n\t\t\t// UNIQUE must be used with NOT NULL\n\t\t\t$field['null'] = ' NOT NULL';\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute AUTO_INCREMENT\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_auto_increment(&$attributes, &$field)\n\t{\n\t\t// Not supported\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_informix_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO Informix Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_informix_driver extends CI_DB_pdo_driver {\n\n\t/**\n\t * Sub-driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $subdriver = 'informix';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ORDER BY random keyword\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_random_keyword = array('ASC', 'ASC'); // Currently not supported\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Builds the DSN if not already set.\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif (empty($this->dsn))\n\t\t{\n\t\t\t$this->dsn = 'informix:';\n\n\t\t\t// Pre-defined DSN\n\t\t\tif (empty($this->hostname) && empty($this->host) && empty($this->port) && empty($this->service))\n\t\t\t{\n\t\t\t\tif (isset($this->DSN))\n\t\t\t\t{\n\t\t\t\t\t$this->dsn .= 'DSN='.$this->DSN;\n\t\t\t\t}\n\t\t\t\telseif ( ! empty($this->database))\n\t\t\t\t{\n\t\t\t\t\t$this->dsn .= 'DSN='.$this->database;\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (isset($this->host))\n\t\t\t{\n\t\t\t\t$this->dsn .= 'host='.$this->host;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->dsn .= 'host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);\n\t\t\t}\n\n\t\t\tif (isset($this->service))\n\t\t\t{\n\t\t\t\t$this->dsn .= '; service='.$this->service;\n\t\t\t}\n\t\t\telseif ( ! empty($this->port))\n\t\t\t{\n\t\t\t\t$this->dsn .= '; service='.$this->port;\n\t\t\t}\n\n\t\t\tempty($this->database) OR $this->dsn .= '; database='.$this->database;\n\t\t\tempty($this->server) OR $this->dsn .= '; server='.$this->server;\n\n\t\t\t$this->dsn .= '; protocol='.(isset($this->protocol) ? $this->protocol : 'onsoctcp')\n\t\t\t\t.'; EnableScrollableCursors=1';\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\t$prefix_limit\n\t * @return\tstring\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\t$sql = 'SELECT \"tabname\" FROM \"systables\"\n\t\t\tWHERE \"tabid\" > 99 AND \"tabtype\" = \\'T\\' AND LOWER(\"owner\") = '.$this->escape(strtolower($this->username));\n\n\t\tif ($prefix_limit === TRUE && $this->dbprefix !== '')\n\t\t{\n\t\t\t$sql .= ' AND \"tabname\" LIKE \\''.$this->escape_like_str($this->dbprefix).\"%' \"\n\t\t\t\t.sprintf($this->_like_escape_str, $this->_like_escape_chr);\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show column query\n\t *\n\t * Generates a platform-specific query string so that the column names can be fetched\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _list_columns($table = '')\n\t{\n\t\tif (strpos($table, '.') !== FALSE)\n\t\t{\n\t\t\tsscanf($table, '%[^.].%s', $owner, $table);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$owner = $this->username;\n\t\t}\n\n\t\treturn 'SELECT \"colname\" FROM \"systables\", \"syscolumns\"\n\t\t\tWHERE \"systables\".\"tabid\" = \"syscolumns\".\"tabid\"\n\t\t\t\tAND \"systables\".\"tabtype\" = \\'T\\'\n\t\t\t\tAND LOWER(\"systables\".\"owner\") = '.$this->escape(strtolower($owner)).'\n\t\t\t\tAND LOWER(\"systables\".\"tabname\") = '.$this->escape(strtolower($table));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an object with field data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tarray\n\t */\n\tpublic function field_data($table)\n\t{\n\t\t$sql = 'SELECT \"syscolumns\".\"colname\" AS \"name\",\n\t\t\t\tCASE \"syscolumns\".\"coltype\"\n\t\t\t\t\tWHEN 0 THEN \\'CHAR\\'\n\t\t\t\t\tWHEN 1 THEN \\'SMALLINT\\'\n\t\t\t\t\tWHEN 2 THEN \\'INTEGER\\'\n\t\t\t\t\tWHEN 3 THEN \\'FLOAT\\'\n\t\t\t\t\tWHEN 4 THEN \\'SMALLFLOAT\\'\n\t\t\t\t\tWHEN 5 THEN \\'DECIMAL\\'\n\t\t\t\t\tWHEN 6 THEN \\'SERIAL\\'\n\t\t\t\t\tWHEN 7 THEN \\'DATE\\'\n\t\t\t\t\tWHEN 8 THEN \\'MONEY\\'\n\t\t\t\t\tWHEN 9 THEN \\'NULL\\'\n\t\t\t\t\tWHEN 10 THEN \\'DATETIME\\'\n\t\t\t\t\tWHEN 11 THEN \\'BYTE\\'\n\t\t\t\t\tWHEN 12 THEN \\'TEXT\\'\n\t\t\t\t\tWHEN 13 THEN \\'VARCHAR\\'\n\t\t\t\t\tWHEN 14 THEN \\'INTERVAL\\'\n\t\t\t\t\tWHEN 15 THEN \\'NCHAR\\'\n\t\t\t\t\tWHEN 16 THEN \\'NVARCHAR\\'\n\t\t\t\t\tWHEN 17 THEN \\'INT8\\'\n\t\t\t\t\tWHEN 18 THEN \\'SERIAL8\\'\n\t\t\t\t\tWHEN 19 THEN \\'SET\\'\n\t\t\t\t\tWHEN 20 THEN \\'MULTISET\\'\n\t\t\t\t\tWHEN 21 THEN \\'LIST\\'\n\t\t\t\t\tWHEN 22 THEN \\'Unnamed ROW\\'\n\t\t\t\t\tWHEN 40 THEN \\'LVARCHAR\\'\n\t\t\t\t\tWHEN 41 THEN \\'BLOB/CLOB/BOOLEAN\\'\n\t\t\t\t\tWHEN 4118 THEN \\'Named ROW\\'\n\t\t\t\t\tELSE \"syscolumns\".\"coltype\"\n\t\t\t\tEND AS \"type\",\n\t\t\t\t\"syscolumns\".\"collength\" as \"max_length\",\n\t\t\t\tCASE \"sysdefaults\".\"type\"\n\t\t\t\t\tWHEN \\'L\\' THEN \"sysdefaults\".\"default\"\n\t\t\t\t\tELSE NULL\n\t\t\t\tEND AS \"default\"\n\t\t\tFROM \"syscolumns\", \"systables\", \"sysdefaults\"\n\t\t\tWHERE \"syscolumns\".\"tabid\" = \"systables\".\"tabid\"\n\t\t\t\tAND \"systables\".\"tabid\" = \"sysdefaults\".\"tabid\"\n\t\t\t\tAND \"syscolumns\".\"colno\" = \"sysdefaults\".\"colno\"\n\t\t\t\tAND \"systables\".\"tabtype\" = \\'T\\'\n\t\t\t\tAND LOWER(\"systables\".\"owner\") = '.$this->escape(strtolower($this->username)).'\n\t\t\t\tAND LOWER(\"systables\".\"tabname\") = '.$this->escape(strtolower($table)).'\n\t\t\tORDER BY \"syscolumns\".\"colno\"';\n\n\t\treturn (($query = $this->query($sql)) !== FALSE)\n\t\t\t? $query->result_object()\n\t\t\t: FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update statement\n\t *\n\t * Generates a platform-specific update string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @param\tarray\t$values\n\t * @return\tstring\n\t */\n\tprotected function _update($table, $values)\n\t{\n\t\t$this->qb_limit = FALSE;\n\t\t$this->qb_orderby = array();\n\t\treturn parent::_update($table, $values);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Truncate statement\n\t *\n\t * Generates a platform-specific truncate string from the supplied data\n\t *\n\t * If the database does not support the TRUNCATE statement,\n\t * then this method maps to 'DELETE FROM table'\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _truncate($table)\n\t{\n\t\treturn 'TRUNCATE TABLE ONLY '.$table;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Delete statement\n\t *\n\t * Generates a platform-specific delete string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _delete($table)\n\t{\n\t\t$this->qb_limit = FALSE;\n\t\treturn parent::_delete($table);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * LIMIT\n\t *\n\t * Generates a platform-specific LIMIT clause\n\t *\n\t * @param\tstring\t$sql\t$SQL Query\n\t * @return\tstring\n\t */\n\tprotected function _limit($sql)\n\t{\n\t\t$select = 'SELECT '.($this->qb_offset ? 'SKIP '.$this->qb_offset : '').'FIRST '.$this->qb_limit.' ';\n\t\treturn preg_replace('/^(SELECT\\s)/i', $select, $sql, 1);\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_informix_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO Informix Forge Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_informix_forge extends CI_DB_pdo_forge {\n\n\t/**\n\t * RENAME TABLE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_rename_table\t= 'RENAME TABLE %s TO %s';\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_unsigned\t\t= array(\n\t\t'SMALLINT'\t=> 'INTEGER',\n\t\t'INT'\t\t=> 'BIGINT',\n\t\t'INTEGER'\t=> 'BIGINT',\n\t\t'REAL'\t\t=> 'DOUBLE PRECISION',\n\t\t'SMALLFLOAT'\t=> 'DOUBLE PRECISION'\n\t);\n\n\t/**\n\t * DEFAULT value representation in CREATE/ALTER TABLE statements\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_default\t\t= ', ';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ALTER TABLE\n\t *\n\t * @param\tstring\t$alter_type\tALTER type\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tmixed\t$field\t\tColumn definition\n\t * @return\tstring|string[]\n\t */\n\tprotected function _alter_table($alter_type, $table, $field)\n\t{\n\t\tif ($alter_type === 'CHANGE')\n\t\t{\n\t\t\t$alter_type = 'MODIFY';\n\t\t}\n\n\t\treturn parent::_alter_table($alter_type, $table, $field);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute TYPE\n\t *\n\t * Performs a data type mapping between different databases.\n\t *\n\t * @param\tarray\t&$attributes\n\t * @return\tvoid\n\t */\n\tprotected function _attr_type(&$attributes)\n\t{\n\t\tswitch (strtoupper($attributes['TYPE']))\n\t\t{\n\t\t\tcase 'TINYINT':\n\t\t\t\t$attributes['TYPE'] = 'SMALLINT';\n\t\t\t\t$attributes['UNSIGNED'] = FALSE;\n\t\t\t\treturn;\n\t\t\tcase 'MEDIUMINT':\n\t\t\t\t$attributes['TYPE'] = 'INTEGER';\n\t\t\t\t$attributes['UNSIGNED'] = FALSE;\n\t\t\t\treturn;\n\t\t\tcase 'BYTE':\n\t\t\tcase 'TEXT':\n\t\t\tcase 'BLOB':\n\t\t\tcase 'CLOB':\n\t\t\t\t$attributes['UNIQUE'] = FALSE;\n\t\t\t\tif (isset($attributes['DEFAULT']))\n\t\t\t\t{\n\t\t\t\t\tunset($attributes['DEFAULT']);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\tdefault: return;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute UNIQUE\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_unique(&$attributes, &$field)\n\t{\n\t\tif ( ! empty($attributes['UNIQUE']) && $attributes['UNIQUE'] === TRUE)\n\t\t{\n\t\t\t$field['unique'] = ' UNIQUE CONSTRAINT '.$this->db->escape_identifiers($field['name']);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute AUTO_INCREMENT\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_auto_increment(&$attributes, &$field)\n\t{\n\t\t// Not supported\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO MySQL Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver {\n\n\t/**\n\t * Sub-driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $subdriver = 'mysql';\n\n\t/**\n\t * Compression flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $compress = FALSE;\n\n\t/**\n\t * Strict ON flag\n\t *\n\t * Whether we're running in strict SQL mode.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $stricton;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Identifier escape character\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_escape_char = '`';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Builds the DSN if not already set.\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif (empty($this->dsn))\n\t\t{\n\t\t\t$this->dsn = 'mysql:host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);\n\n\t\t\tempty($this->port) OR $this->dsn .= ';port='.$this->port;\n\t\t\tempty($this->database) OR $this->dsn .= ';dbname='.$this->database;\n\t\t\tempty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;\n\t\t}\n\t\telseif ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 6) === FALSE && is_php('5.3.6'))\n\t\t{\n\t\t\t$this->dsn .= ';charset='.$this->char_set;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Database connection\n\t *\n\t * @param\tbool\t$persistent\n\t * @return\tobject\n\t */\n\tpublic function db_connect($persistent = FALSE)\n\t{\n\t\t/* Prior to PHP 5.3.6, even if the charset was supplied in the DSN\n\t\t * on connect - it was ignored. This is a work-around for the issue.\n\t\t *\n\t\t * Reference: http://www.php.net/manual/en/ref.pdo-mysql.connection.php\n\t\t */\n\t\tif ( ! is_php('5.3.6') && ! empty($this->char_set))\n\t\t{\n\t\t\t$this->options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES '.$this->char_set\n\t\t\t\t.(empty($this->dbcollat) ? '' : ' COLLATE '.$this->dbcollat);\n\t\t}\n\n\t\tif (isset($this->stricton))\n\t\t{\n\t\t\tif ($this->stricton)\n\t\t\t{\n\t\t\t\t$sql = 'CONCAT(@@sql_mode, \",\", \"STRICT_ALL_TABLES\")';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$sql = 'REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(\n                                        @@sql_mode,\n                                        \"STRICT_ALL_TABLES,\", \"\"),\n                                        \",STRICT_ALL_TABLES\", \"\"),\n                                        \"STRICT_ALL_TABLES\", \"\"),\n                                        \"STRICT_TRANS_TABLES,\", \"\"),\n                                        \",STRICT_TRANS_TABLES\", \"\"),\n                                        \"STRICT_TRANS_TABLES\", \"\")';\n\t\t\t}\n\n\t\t\tif ( ! empty($sql))\n\t\t\t{\n\t\t\t\tif (empty($this->options[PDO::MYSQL_ATTR_INIT_COMMAND]))\n\t\t\t\t{\n\t\t\t\t\t$this->options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET SESSION sql_mode = '.$sql;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$this->options[PDO::MYSQL_ATTR_INIT_COMMAND] .= ', @@session.sql_mode = '.$sql;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ($this->compress === TRUE)\n\t\t{\n\t\t\t$this->options[PDO::MYSQL_ATTR_COMPRESS] = TRUE;\n\t\t}\n\n\t\t// SSL support was added to PDO_MYSQL in PHP 5.3.7\n\t\tif (is_array($this->encrypt) && is_php('5.3.7'))\n\t\t{\n\t\t\t$ssl = array();\n\t\t\tempty($this->encrypt['ssl_key'])    OR $ssl[PDO::MYSQL_ATTR_SSL_KEY]    = $this->encrypt['ssl_key'];\n\t\t\tempty($this->encrypt['ssl_cert'])   OR $ssl[PDO::MYSQL_ATTR_SSL_CERT]   = $this->encrypt['ssl_cert'];\n\t\t\tempty($this->encrypt['ssl_ca'])     OR $ssl[PDO::MYSQL_ATTR_SSL_CA]     = $this->encrypt['ssl_ca'];\n\t\t\tempty($this->encrypt['ssl_capath']) OR $ssl[PDO::MYSQL_ATTR_SSL_CAPATH] = $this->encrypt['ssl_capath'];\n\t\t\tempty($this->encrypt['ssl_cipher']) OR $ssl[PDO::MYSQL_ATTR_SSL_CIPHER] = $this->encrypt['ssl_cipher'];\n\n\t\t\t// DO NOT use array_merge() here!\n\t\t\t// It re-indexes numeric keys and the PDO_MYSQL_ATTR_SSL_* constants are integers.\n\t\t\tempty($ssl) OR $this->options += $ssl;\n\t\t}\n\n\t\t// Prior to version 5.7.3, MySQL silently downgrades to an unencrypted connection if SSL setup fails\n\t\tif (\n\t\t\t($pdo = parent::db_connect($persistent)) !== FALSE\n\t\t\t&& ! empty($ssl)\n\t\t\t&& version_compare($pdo->getAttribute(PDO::ATTR_CLIENT_VERSION), '5.7.3', '<=')\n\t\t\t&& empty($pdo->query(\"SHOW STATUS LIKE 'ssl_cipher'\")->fetchObject()->Value)\n\t\t)\n\t\t{\n\t\t\t$message = 'PDO_MYSQL was configured for an SSL connection, but got an unencrypted connection instead!';\n\t\t\tlog_message('error', $message);\n\t\t\treturn ($this->db->db_debug) ? $this->db->display_error($message, '', TRUE) : FALSE;\n\t\t}\n\n\t\treturn $pdo;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Select the database\n\t *\n\t * @param\tstring\t$database\n\t * @return\tbool\n\t */\n\tpublic function db_select($database = '')\n\t{\n\t\tif ($database === '')\n\t\t{\n\t\t\t$database = $this->database;\n\t\t}\n\n\t\tif (FALSE !== $this->simple_query('USE '.$this->escape_identifiers($database)))\n\t\t{\n\t\t\t$this->database = $database;\n\t\t\t$this->data_cache = array();\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\t$prefix_limit\n\t * @return\tstring\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\t$sql = 'SHOW TABLES';\n\n\t\tif ($prefix_limit === TRUE && $this->dbprefix !== '')\n\t\t{\n\t\t\treturn $sql.\" LIKE '\".$this->escape_like_str($this->dbprefix).\"%'\";\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show column query\n\t *\n\t * Generates a platform-specific query string so that the column names can be fetched\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _list_columns($table = '')\n\t{\n\t\treturn 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an object with field data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tarray\n\t */\n\tpublic function field_data($table)\n\t{\n\t\tif (($query = $this->query('SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE))) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\t$query = $query->result_object();\n\n\t\t$retval = array();\n\t\tfor ($i = 0, $c = count($query); $i < $c; $i++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= $query[$i]->Field;\n\n\t\t\tsscanf($query[$i]->Type, '%[a-z](%d)',\n\t\t\t\t$retval[$i]->type,\n\t\t\t\t$retval[$i]->max_length\n\t\t\t);\n\n\t\t\t$retval[$i]->default\t\t= $query[$i]->Default;\n\t\t\t$retval[$i]->primary_key\t= (int) ($query[$i]->Key === 'PRI');\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Truncate statement\n\t *\n\t * Generates a platform-specific truncate string from the supplied data\n\t *\n\t * If the database does not support the TRUNCATE statement,\n\t * then this method maps to 'DELETE FROM table'\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _truncate($table)\n\t{\n\t\treturn 'TRUNCATE '.$table;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * FROM tables\n\t *\n\t * Groups tables in FROM clauses if needed, so there is no confusion\n\t * about operator precedence.\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _from_tables()\n\t{\n\t\tif ( ! empty($this->qb_join) && count($this->qb_from) > 1)\n\t\t{\n\t\t\treturn '('.implode(', ', $this->qb_from).')';\n\t\t}\n\n\t\treturn implode(', ', $this->qb_from);\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_mysql_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO MySQL Forge Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_mysql_forge extends CI_DB_pdo_forge {\n\n\t/**\n\t * CREATE DATABASE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_database\t= 'CREATE DATABASE %s CHARACTER SET %s COLLATE %s';\n\n\t/**\n\t * CREATE TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_table_if\t= 'CREATE TABLE IF NOT EXISTS';\n\n\t/**\n\t * CREATE TABLE keys flag\n\t *\n\t * Whether table keys are created from within the\n\t * CREATE TABLE statement.\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_create_table_keys\t= TRUE;\n\n\t/**\n\t * DROP TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_drop_table_if\t= 'DROP TABLE IF EXISTS';\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_unsigned\t\t= array(\n\t\t'TINYINT',\n\t\t'SMALLINT',\n\t\t'MEDIUMINT',\n\t\t'INT',\n\t\t'INTEGER',\n\t\t'BIGINT',\n\t\t'REAL',\n\t\t'DOUBLE',\n\t\t'DOUBLE PRECISION',\n\t\t'FLOAT',\n\t\t'DECIMAL',\n\t\t'NUMERIC'\n\t);\n\n\t/**\n\t * NULL value representation in CREATE/ALTER TABLE statements\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_null = 'NULL';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * CREATE TABLE attributes\n\t *\n\t * @param\tarray\t$attributes\tAssociative array of table attributes\n\t * @return\tstring\n\t */\n\tprotected function _create_table_attr($attributes)\n\t{\n\t\t$sql = '';\n\n\t\tforeach (array_keys($attributes) as $key)\n\t\t{\n\t\t\tif (is_string($key))\n\t\t\t{\n\t\t\t\t$sql .= ' '.strtoupper($key).' = '.$attributes[$key];\n\t\t\t}\n\t\t}\n\n\t\tif ( ! empty($this->db->char_set) && ! strpos($sql, 'CHARACTER SET') && ! strpos($sql, 'CHARSET'))\n\t\t{\n\t\t\t$sql .= ' DEFAULT CHARACTER SET = '.$this->db->char_set;\n\t\t}\n\n\t\tif ( ! empty($this->db->dbcollat) && ! strpos($sql, 'COLLATE'))\n\t\t{\n\t\t\t$sql .= ' COLLATE = '.$this->db->dbcollat;\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ALTER TABLE\n\t *\n\t * @param\tstring\t$alter_type\tALTER type\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tmixed\t$field\t\tColumn definition\n\t * @return\tstring|string[]\n\t */\n\tprotected function _alter_table($alter_type, $table, $field)\n\t{\n\t\tif ($alter_type === 'DROP')\n\t\t{\n\t\t\treturn parent::_alter_table($alter_type, $table, $field);\n\t\t}\n\n\t\t$sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);\n\t\tfor ($i = 0, $c = count($field); $i < $c; $i++)\n\t\t{\n\t\t\tif ($field[$i]['_literal'] !== FALSE)\n\t\t\t{\n\t\t\t\t$field[$i] = ($alter_type === 'ADD')\n\t\t\t\t\t\t? \"\\n\\tADD \".$field[$i]['_literal']\n\t\t\t\t\t\t: \"\\n\\tMODIFY \".$field[$i]['_literal'];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif ($alter_type === 'ADD')\n\t\t\t\t{\n\t\t\t\t\t$field[$i]['_literal'] = \"\\n\\tADD \";\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$field[$i]['_literal'] = empty($field[$i]['new_name']) ? \"\\n\\tMODIFY \" : \"\\n\\tCHANGE \";\n\t\t\t\t}\n\n\t\t\t\t$field[$i] = $field[$i]['_literal'].$this->_process_column($field[$i]);\n\t\t\t}\n\t\t}\n\n\t\treturn array($sql.implode(',', $field));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Process column\n\t *\n\t * @param\tarray\t$field\n\t * @return\tstring\n\t */\n\tprotected function _process_column($field)\n\t{\n\t\t$extra_clause = isset($field['after'])\n\t\t\t? ' AFTER '.$this->db->escape_identifiers($field['after']) : '';\n\n\t\tif (empty($extra_clause) && isset($field['first']) && $field['first'] === TRUE)\n\t\t{\n\t\t\t$extra_clause = ' FIRST';\n\t\t}\n\n\t\treturn $this->db->escape_identifiers($field['name'])\n\t\t\t.(empty($field['new_name']) ? '' : ' '.$this->db->escape_identifiers($field['new_name']))\n\t\t\t.' '.$field['type'].$field['length']\n\t\t\t.$field['unsigned']\n\t\t\t.$field['null']\n\t\t\t.$field['default']\n\t\t\t.$field['auto_increment']\n\t\t\t.$field['unique']\n\t\t\t.(empty($field['comment']) ? '' : ' COMMENT '.$field['comment'])\n\t\t\t.$extra_clause;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Process indexes\n\t *\n\t * @param\tstring\t$table\t(ignored)\n\t * @return\tstring\n\t */\n\tprotected function _process_indexes($table)\n\t{\n\t\t$sql = '';\n\n\t\tfor ($i = 0, $c = count($this->keys); $i < $c; $i++)\n\t\t{\n\t\t\tif (is_array($this->keys[$i]))\n\t\t\t{\n\t\t\t\tfor ($i2 = 0, $c2 = count($this->keys[$i]); $i2 < $c2; $i2++)\n\t\t\t\t{\n\t\t\t\t\tif ( ! isset($this->fields[$this->keys[$i][$i2]]))\n\t\t\t\t\t{\n\t\t\t\t\t\tunset($this->keys[$i][$i2]);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ( ! isset($this->fields[$this->keys[$i]]))\n\t\t\t{\n\t\t\t\tunset($this->keys[$i]);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tis_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);\n\n\t\t\t$sql .= \",\\n\\tKEY \".$this->db->escape_identifiers(implode('_', $this->keys[$i]))\n\t\t\t\t.' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).')';\n\t\t}\n\n\t\t$this->keys = array();\n\n\t\treturn $sql;\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_oci_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO Oracle Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_oci_driver extends CI_DB_pdo_driver {\n\n\t/**\n\t * Sub-driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $subdriver = 'oci';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * List of reserved identifiers\n\t *\n\t * Identifiers that must NOT be escaped.\n\t *\n\t * @var\tstring[]\n\t */\n\tprotected $_reserved_identifiers = array('*', 'rownum');\n\n\t/**\n\t * ORDER BY random keyword\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_random_keyword = array('ASC', 'ASC'); // Currently not supported\n\n\t/**\n\t * COUNT string\n\t *\n\t * @used-by\tCI_DB_driver::count_all()\n\t * @used-by\tCI_DB_query_builder::count_all_results()\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_count_string = 'SELECT COUNT(1) AS ';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Builds the DSN if not already set.\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif (empty($this->dsn))\n\t\t{\n\t\t\t$this->dsn = 'oci:dbname=';\n\n\t\t\t// Oracle has a slightly different PDO DSN format (Easy Connect),\n\t\t\t// which also supports pre-defined DSNs.\n\t\t\tif (empty($this->hostname) && empty($this->port))\n\t\t\t{\n\t\t\t\t$this->dsn .= $this->database;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->dsn .= '//'.(empty($this->hostname) ? '127.0.0.1' : $this->hostname)\n\t\t\t\t\t.(empty($this->port) ? '' : ':'.$this->port).'/';\n\n\t\t\t\tempty($this->database) OR $this->dsn .= $this->database;\n\t\t\t}\n\n\t\t\tempty($this->char_set) OR $this->dsn .= ';charset='.$this->char_set;\n\t\t}\n\t\telseif ( ! empty($this->char_set) && strpos($this->dsn, 'charset=', 4) === FALSE)\n\t\t{\n\t\t\t$this->dsn .= ';charset='.$this->char_set;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Database version number\n\t *\n\t * @return\tstring\n\t */\n\tpublic function version()\n\t{\n\t\tif (isset($this->data_cache['version']))\n\t\t{\n\t\t\treturn $this->data_cache['version'];\n\t\t}\n\n\t\t$version_string = parent::version();\n\t\tif (preg_match('#Release\\s(?<version>\\d+(?:\\.\\d+)+)#', $version_string, $match))\n\t\t{\n\t\t\treturn $this->data_cache['version'] = $match[1];\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\t$prefix_limit\n\t * @return\tstring\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\t$sql = 'SELECT \"TABLE_NAME\" FROM \"ALL_TABLES\"';\n\n\t\tif ($prefix_limit === TRUE && $this->dbprefix !== '')\n\t\t{\n\t\t\treturn $sql.' WHERE \"TABLE_NAME\" LIKE \\''.$this->escape_like_str($this->dbprefix).\"%' \"\n\t\t\t\t.sprintf($this->_like_escape_str, $this->_like_escape_chr);\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show column query\n\t *\n\t * Generates a platform-specific query string so that the column names can be fetched\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _list_columns($table = '')\n\t{\n\t\tif (strpos($table, '.') !== FALSE)\n\t\t{\n\t\t\tsscanf($table, '%[^.].%s', $owner, $table);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$owner = $this->username;\n\t\t}\n\n\t\treturn 'SELECT COLUMN_NAME FROM ALL_TAB_COLUMNS\n\t\t\tWHERE UPPER(OWNER) = '.$this->escape(strtoupper($owner)).'\n\t\t\t\tAND UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an object with field data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tarray\n\t */\n\tpublic function field_data($table)\n\t{\n\t\tif (strpos($table, '.') !== FALSE)\n\t\t{\n\t\t\tsscanf($table, '%[^.].%s', $owner, $table);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$owner = $this->username;\n\t\t}\n\n\t\t$sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHAR_LENGTH, DATA_PRECISION, DATA_LENGTH, DATA_DEFAULT, NULLABLE\n\t\t\tFROM ALL_TAB_COLUMNS\n\t\t\tWHERE UPPER(OWNER) = '.$this->escape(strtoupper($owner)).'\n\t\t\t\tAND UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));\n\n\t\tif (($query = $this->query($sql)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\t$query = $query->result_object();\n\n\t\t$retval = array();\n\t\tfor ($i = 0, $c = count($query); $i < $c; $i++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= $query[$i]->COLUMN_NAME;\n\t\t\t$retval[$i]->type\t\t= $query[$i]->DATA_TYPE;\n\n\t\t\t$length = ($query[$i]->CHAR_LENGTH > 0)\n\t\t\t\t? $query[$i]->CHAR_LENGTH : $query[$i]->DATA_PRECISION;\n\t\t\tif ($length === NULL)\n\t\t\t{\n\t\t\t\t$length = $query[$i]->DATA_LENGTH;\n\t\t\t}\n\t\t\t$retval[$i]->max_length\t\t= $length;\n\n\t\t\t$default = $query[$i]->DATA_DEFAULT;\n\t\t\tif ($default === NULL && $query[$i]->NULLABLE === 'N')\n\t\t\t{\n\t\t\t\t$default = '';\n\t\t\t}\n\t\t\t$retval[$i]->default\t\t= $query[$i]->COLUMN_DEFAULT;\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert batch statement\n\t *\n\t * @param\tstring\t$table\tTable name\n\t * @param\tarray\t$keys\tINSERT keys\n\t * @param\tarray\t$values\tINSERT values\n\t * @return \tstring\n\t */\n\tprotected function _insert_batch($table, $keys, $values)\n\t{\n\t\t$keys = implode(', ', $keys);\n\t\t$sql = \"INSERT ALL\\n\";\n\n\t\tfor ($i = 0, $c = count($values); $i < $c; $i++)\n\t\t{\n\t\t\t$sql .= '\tINTO '.$table.' ('.$keys.') VALUES '.$values[$i].\"\\n\";\n\t\t}\n\n\t\treturn $sql.'SELECT * FROM dual';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Delete statement\n\t *\n\t * Generates a platform-specific delete string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _delete($table)\n\t{\n\t\tif ($this->qb_limit)\n\t\t{\n\t\t\t$this->where('rownum <= ',$this->qb_limit, FALSE);\n\t\t\t$this->qb_limit = FALSE;\n\t\t}\n\n\t\treturn parent::_delete($table);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * LIMIT\n\t *\n\t * Generates a platform-specific LIMIT clause\n\t *\n\t * @param\tstring\t$sql\tSQL Query\n\t * @return\tstring\n\t */\n\tprotected function _limit($sql)\n\t{\n\t\tif (version_compare($this->version(), '12.1', '>='))\n\t\t{\n\t\t\t// OFFSET-FETCH can be used only with the ORDER BY clause\n\t\t\tempty($this->qb_orderby) && $sql .= ' ORDER BY 1';\n\n\t\t\treturn $sql.' OFFSET '.(int) $this->qb_offset.' ROWS FETCH NEXT '.$this->qb_limit.' ROWS ONLY';\n\t\t}\n\n\t\treturn 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($this->qb_offset + $this->qb_limit + 1).')'\n\t\t\t.($this->qb_offset ? ' WHERE rnum >= '.($this->qb_offset + 1): '');\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_oci_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO Oracle Forge Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_oci_forge extends CI_DB_pdo_forge {\n\n\t/**\n\t * CREATE DATABASE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_database\t= FALSE;\n\n\t/**\n\t * CREATE TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_table_if\t= FALSE;\n\n\t/**\n\t * DROP DATABASE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_drop_database\t= FALSE;\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tbool|array\n\t */\n\tprotected $_unsigned\t\t= FALSE;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ALTER TABLE\n\t *\n\t * @param\tstring\t$alter_type\tALTER type\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tmixed\t$field\t\tColumn definition\n\t * @return\tstring|string[]\n\t */\n\tprotected function _alter_table($alter_type, $table, $field)\n\t{\n\t\tif ($alter_type === 'DROP')\n\t\t{\n\t\t\treturn parent::_alter_table($alter_type, $table, $field);\n\t\t}\n\t\telseif ($alter_type === 'CHANGE')\n\t\t{\n\t\t\t$alter_type = 'MODIFY';\n\t\t}\n\n\t\t$sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);\n\t\t$sqls = array();\n\t\tfor ($i = 0, $c = count($field); $i < $c; $i++)\n\t\t{\n\t\t\tif ($field[$i]['_literal'] !== FALSE)\n\t\t\t{\n\t\t\t\t$field[$i] = \"\\n\\t\".$field[$i]['_literal'];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$field[$i]['_literal'] = \"\\n\\t\".$this->_process_column($field[$i]);\n\n\t\t\t\tif ( ! empty($field[$i]['comment']))\n\t\t\t\t{\n\t\t\t\t\t$sqls[] = 'COMMENT ON COLUMN '\n\t\t\t\t\t\t.$this->db->escape_identifiers($table).'.'.$this->db->escape_identifiers($field[$i]['name'])\n\t\t\t\t\t\t.' IS '.$field[$i]['comment'];\n\t\t\t\t}\n\n\t\t\t\tif ($alter_type === 'MODIFY' && ! empty($field[$i]['new_name']))\n\t\t\t\t{\n\t\t\t\t\t$sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name'])\n\t\t\t\t\t\t.' '.$this->db->escape_identifiers($field[$i]['new_name']);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$sql .= ' '.$alter_type.' ';\n\t\t$sql .= (count($field) === 1)\n\t\t\t\t? $field[0]\n\t\t\t\t: '('.implode(',', $field).')';\n\n\t\t// RENAME COLUMN must be executed after MODIFY\n\t\tarray_unshift($sqls, $sql);\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute AUTO_INCREMENT\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_auto_increment(&$attributes, &$field)\n\t{\n\t\t// Not supported - sequences and triggers must be used instead\n\t}\n\n\t/**\n\t * Field attribute TYPE\n\t *\n\t * Performs a data type mapping between different databases.\n\t *\n\t * @param\tarray\t&$attributes\n\t * @return\tvoid\n\t */\n\tprotected function _attr_type(&$attributes)\n\t{\n\t\tswitch (strtoupper($attributes['TYPE']))\n\t\t{\n\t\t\tcase 'TINYINT':\n\t\t\t\t$attributes['TYPE'] = 'NUMBER';\n\t\t\t\treturn;\n\t\t\tcase 'MEDIUMINT':\n\t\t\t\t$attributes['TYPE'] = 'NUMBER';\n\t\t\t\treturn;\n\t\t\tcase 'INT':\n\t\t\t\t$attributes['TYPE'] = 'NUMBER';\n\t\t\t\treturn;\n\t\t\tcase 'BIGINT':\n\t\t\t\t$attributes['TYPE'] = 'NUMBER';\n\t\t\t\treturn;\n\t\t\tdefault: return;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_odbc_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO ODBC Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_odbc_driver extends CI_DB_pdo_driver {\n\n\t/**\n\t * Sub-driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $subdriver = 'odbc';\n\n\t/**\n\t * Database schema\n\t *\n\t * @var\tstring\n\t */\n\tpublic $schema = 'public';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Identifier escape character\n\t *\n\t * Must be empty for ODBC.\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_escape_char = '';\n\n\t/**\n\t * ESCAPE statement string\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_like_escape_str = \" {escape '%s'} \";\n\n\t/**\n\t * ORDER BY random keyword\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_random_keyword = array('RND()', 'RND(%d)');\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Builds the DSN if not already set.\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif (empty($this->dsn))\n\t\t{\n\t\t\t$this->dsn = 'odbc:';\n\n\t\t\t// Pre-defined DSN\n\t\t\tif (empty($this->hostname) && empty($this->HOSTNAME) && empty($this->port) && empty($this->PORT))\n\t\t\t{\n\t\t\t\tif (isset($this->DSN))\n\t\t\t\t{\n\t\t\t\t\t$this->dsn .= 'DSN='.$this->DSN;\n\t\t\t\t}\n\t\t\t\telseif ( ! empty($this->database))\n\t\t\t\t{\n\t\t\t\t\t$this->dsn .= 'DSN='.$this->database;\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If the DSN is not pre-configured - try to build an IBM DB2 connection string\n\t\t\t$this->dsn .= 'DRIVER='.(isset($this->DRIVER) ? '{'.$this->DRIVER.'}' : '{IBM DB2 ODBC DRIVER}').';';\n\n\t\t\tif (isset($this->DATABASE))\n\t\t\t{\n\t\t\t\t$this->dsn .= 'DATABASE='.$this->DATABASE.';';\n\t\t\t}\n\t\t\telseif ( ! empty($this->database))\n\t\t\t{\n\t\t\t\t$this->dsn .= 'DATABASE='.$this->database.';';\n\t\t\t}\n\n\t\t\tif (isset($this->HOSTNAME))\n\t\t\t{\n\t\t\t\t$this->dsn .= 'HOSTNAME='.$this->HOSTNAME.';';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->dsn .= 'HOSTNAME='.(empty($this->hostname) ? '127.0.0.1;' : $this->hostname.';');\n\t\t\t}\n\n\t\t\tif (isset($this->PORT))\n\t\t\t{\n\t\t\t\t$this->dsn .= 'PORT='.$this->port.';';\n\t\t\t}\n\t\t\telseif ( ! empty($this->port))\n\t\t\t{\n\t\t\t\t$this->dsn .= ';PORT='.$this->port.';';\n\t\t\t}\n\n\t\t\t$this->dsn .= 'PROTOCOL='.(isset($this->PROTOCOL) ? $this->PROTOCOL.';' : 'TCPIP;');\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Platform-dependant string escape\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _escape_str($str)\n\t{\n\t\t$this->db->display_error('db_unsupported_feature');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Determines if a query is a \"write\" type.\n\t *\n\t * @param\tstring\tAn SQL query string\n\t * @return\tbool\n\t */\n\tpublic function is_write_type($sql)\n\t{\n\t\tif (preg_match('#^(INSERT|UPDATE).*RETURNING\\s.+(\\,\\s?.+)*$#i', $sql))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn parent::is_write_type($sql);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\t$prefix_limit\n\t * @return\tstring\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\t$sql = \"SELECT table_name FROM information_schema.tables WHERE table_schema = '\".$this->schema.\"'\";\n\n\t\tif ($prefix_limit !== FALSE && $this->dbprefix !== '')\n\t\t{\n\t\t\treturn $sql.\" AND table_name LIKE '\".$this->escape_like_str($this->dbprefix).\"%' \"\n\t\t\t\t.sprintf($this->_like_escape_str, $this->_like_escape_chr);\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show column query\n\t *\n\t * Generates a platform-specific query string so that the column names can be fetched\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _list_columns($table = '')\n\t{\n\t\treturn 'SELECT column_name FROM information_schema.columns WHERE table_name = '.$this->escape($table);\n\t}\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_odbc_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO ODBC Forge Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/database/\n */\nclass CI_DB_pdo_odbc_forge extends CI_DB_pdo_forge {\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tbool|array\n\t */\n\tprotected $_unsigned\t\t= FALSE;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute AUTO_INCREMENT\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_auto_increment(&$attributes, &$field)\n\t{\n\t\t// Not supported (in most databases at least)\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO PostgreSQL Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver {\n\n\t/**\n\t * Sub-driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $subdriver = 'pgsql';\n\n\t/**\n\t * Database schema\n\t *\n\t * @var\tstring\n\t */\n\tpublic $schema = 'public';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ORDER BY random keyword\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_random_keyword = array('RANDOM()', 'RANDOM()');\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Builds the DSN if not already set.\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif (empty($this->dsn))\n\t\t{\n\t\t\t$this->dsn = 'pgsql:host='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);\n\n\t\t\tempty($this->port) OR $this->dsn .= ';port='.$this->port;\n\t\t\tempty($this->database) OR $this->dsn .= ';dbname='.$this->database;\n\n\t\t\tif ( ! empty($this->username))\n\t\t\t{\n\t\t\t\t$this->dsn .= ';username='.$this->username;\n\t\t\t\tempty($this->password) OR $this->dsn .= ';password='.$this->password;\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Database connection\n\t *\n\t * @param\tbool\t$persistent\n\t * @return\tobject\n\t */\n\tpublic function db_connect($persistent = FALSE)\n\t{\n\t\t$this->conn_id = parent::db_connect($persistent);\n\n\t\tif (is_object($this->conn_id) && ! empty($this->schema))\n\t\t{\n\t\t\t$this->simple_query('SET search_path TO '.$this->schema.',public');\n\t\t}\n\n\t\treturn $this->conn_id;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert ID\n\t *\n\t * @param\tstring\t$name\n\t * @return\tint\n\t */\n\tpublic function insert_id($name = NULL)\n\t{\n\t\tif ($name === NULL && version_compare($this->version(), '8.1', '>='))\n\t\t{\n\t\t\t$query = $this->query('SELECT LASTVAL() AS ins_id');\n\t\t\t$query = $query->row();\n\t\t\treturn $query->ins_id;\n\t\t}\n\n\t\treturn $this->conn_id->lastInsertId($name);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Determines if a query is a \"write\" type.\n\t *\n\t * @param\tstring\tAn SQL query string\n\t * @return\tbool\n\t */\n\tpublic function is_write_type($sql)\n\t{\n\t\tif (preg_match('#^(INSERT|UPDATE).*RETURNING\\s.+(\\,\\s?.+)*$#i', $sql))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn parent::is_write_type($sql);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * \"Smart\" Escape String\n\t *\n\t * Escapes data based on type\n\t *\n\t * @param\tstring\t$str\n\t * @return\tmixed\n\t */\n\tpublic function escape($str)\n\t{\n\t\tif (is_bool($str))\n\t\t{\n\t\t\treturn ($str) ? 'TRUE' : 'FALSE';\n\t\t}\n\n\t\treturn parent::escape($str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ORDER BY\n\t *\n\t * @param\tstring\t$orderby\n\t * @param\tstring\t$direction\tASC, DESC or RANDOM\n\t * @param\tbool\t$escape\n\t * @return\tobject\n\t */\n\tpublic function order_by($orderby, $direction = '', $escape = NULL)\n\t{\n\t\t$direction = strtoupper(trim($direction));\n\t\tif ($direction === 'RANDOM')\n\t\t{\n\t\t\tif ( ! is_float($orderby) && ctype_digit((string) $orderby))\n\t\t\t{\n\t\t\t\t$orderby = ($orderby > 1)\n\t\t\t\t\t? (float) '0.'.$orderby\n\t\t\t\t\t: (float) $orderby;\n\t\t\t}\n\n\t\t\tif (is_float($orderby))\n\t\t\t{\n\t\t\t\t$this->simple_query('SET SEED '.$orderby);\n\t\t\t}\n\n\t\t\t$orderby = $this->_random_keyword[0];\n\t\t\t$direction = '';\n\t\t\t$escape = FALSE;\n\t\t}\n\n\t\treturn parent::order_by($orderby, $direction, $escape);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\t$prefix_limit\n\t * @return\tstring\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\t$sql = 'SELECT \"table_name\" FROM \"information_schema\".\"tables\" WHERE \"table_schema\" = \\''.$this->schema.\"'\";\n\n\t\tif ($prefix_limit === TRUE && $this->dbprefix !== '')\n\t\t{\n\t\t\treturn $sql.' AND \"table_name\" LIKE \\''\n\t\t\t\t.$this->escape_like_str($this->dbprefix).\"%' \"\n\t\t\t\t.sprintf($this->_like_escape_str, $this->_like_escape_chr);\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * List column query\n\t *\n\t * Generates a platform-specific query string so that the column names can be fetched\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _list_columns($table = '')\n\t{\n\t\treturn 'SELECT \"column_name\"\n\t\t\tFROM \"information_schema\".\"columns\"\n\t\t\tWHERE LOWER(\"table_name\") = '.$this->escape(strtolower($table));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an object with field data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tarray\n\t */\n\tpublic function field_data($table)\n\t{\n\t\t$sql = 'SELECT \"column_name\", \"data_type\", \"character_maximum_length\", \"numeric_precision\", \"column_default\"\n\t\t\tFROM \"information_schema\".\"columns\"\n\t\t\tWHERE LOWER(\"table_name\") = '.$this->escape(strtolower($table));\n\n\t\tif (($query = $this->query($sql)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\t$query = $query->result_object();\n\n\t\t$retval = array();\n\t\tfor ($i = 0, $c = count($query); $i < $c; $i++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= $query[$i]->column_name;\n\t\t\t$retval[$i]->type\t\t= $query[$i]->data_type;\n\t\t\t$retval[$i]->max_length\t\t= ($query[$i]->character_maximum_length > 0) ? $query[$i]->character_maximum_length : $query[$i]->numeric_precision;\n\t\t\t$retval[$i]->default\t\t= $query[$i]->column_default;\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update statement\n\t *\n\t * Generates a platform-specific update string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @param\tarray\t$values\n\t * @return\tstring\n\t */\n\tprotected function _update($table, $values)\n\t{\n\t\t$this->qb_limit = FALSE;\n\t\t$this->qb_orderby = array();\n\t\treturn parent::_update($table, $values);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update_Batch statement\n\t *\n\t * Generates a platform-specific batch update string from the supplied data\n\t *\n\t * @param\tstring\t$table\tTable name\n\t * @param\tarray\t$values\tUpdate data\n\t * @param\tstring\t$index\tWHERE key\n\t * @return\tstring\n\t */\n\tprotected function _update_batch($table, $values, $index)\n\t{\n\t\t$ids = array();\n\t\tforeach ($values as $key => $val)\n\t\t{\n\t\t\t$ids[] = $val[$index];\n\n\t\t\tforeach (array_keys($val) as $field)\n\t\t\t{\n\t\t\t\tif ($field !== $index)\n\t\t\t\t{\n\t\t\t\t\t$final[$field][] = 'WHEN '.$val[$index].' THEN '.$val[$field];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$cases = '';\n\t\tforeach ($final as $k => $v)\n\t\t{\n\t\t\t$cases .= $k.' = (CASE '.$index.\"\\n\"\n\t\t\t\t.implode(\"\\n\", $v).\"\\n\"\n\t\t\t\t.'ELSE '.$k.' END), ';\n\t\t}\n\n\t\t$this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);\n\n\t\treturn 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Delete statement\n\t *\n\t * Generates a platform-specific delete string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _delete($table)\n\t{\n\t\t$this->qb_limit = FALSE;\n\t\treturn parent::_delete($table);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * LIMIT\n\t *\n\t * Generates a platform-specific LIMIT clause\n\t *\n\t * @param\tstring\t$sql\tSQL Query\n\t * @return\tstring\n\t */\n\tprotected function _limit($sql)\n\t{\n\t\treturn $sql.' LIMIT '.$this->qb_limit.($this->qb_offset ? ' OFFSET '.$this->qb_offset : '');\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_pgsql_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO PostgreSQL Forge Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_pgsql_forge extends CI_DB_pdo_forge {\n\n\t/**\n\t * DROP TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_drop_table_if\t= 'DROP TABLE IF EXISTS';\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_unsigned\t\t= array(\n\t\t'INT2'\t\t=> 'INTEGER',\n\t\t'SMALLINT'\t=> 'INTEGER',\n\t\t'INT'\t\t=> 'BIGINT',\n\t\t'INT4'\t\t=> 'BIGINT',\n\t\t'INTEGER'\t=> 'BIGINT',\n\t\t'INT8'\t\t=> 'NUMERIC',\n\t\t'BIGINT'\t=> 'NUMERIC',\n\t\t'REAL'\t\t=> 'DOUBLE PRECISION',\n\t\t'FLOAT'\t\t=> 'DOUBLE PRECISION'\n\t);\n\n\t/**\n\t * NULL value representation in CREATE/ALTER TABLE statements\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_null = 'NULL';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tobject\t&$db\tDatabase object\n\t * @return\tvoid\n\t */\n\tpublic function __construct(&$db)\n\t{\n\t\tparent::__construct($db);\n\n\t\tif (version_compare($this->db->version(), '9.0', '>'))\n\t\t{\n\t\t\t$this->create_table_if = 'CREATE TABLE IF NOT EXISTS';\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ALTER TABLE\n\t *\n\t * @param\tstring\t$alter_type\tALTER type\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tmixed\t$field\t\tColumn definition\n\t * @return\tstring|string[]\n\t */\n\tprotected function _alter_table($alter_type, $table, $field)\n \t{\n\t\tif (in_array($alter_type, array('DROP', 'ADD'), TRUE))\n\t\t{\n\t\t\treturn parent::_alter_table($alter_type, $table, $field);\n\t\t}\n\n\t\t$sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);\n\t\t$sqls = array();\n\t\tfor ($i = 0, $c = count($field); $i < $c; $i++)\n\t\t{\n\t\t\tif ($field[$i]['_literal'] !== FALSE)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tif (version_compare($this->db->version(), '8', '>=') && isset($field[$i]['type']))\n\t\t\t{\n\t\t\t\t$sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])\n\t\t\t\t\t.' TYPE '.$field[$i]['type'].$field[$i]['length'];\n\t\t\t}\n\n\t\t\tif ( ! empty($field[$i]['default']))\n\t\t\t{\n\t\t\t\t$sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])\n\t\t\t\t\t.' SET DEFAULT '.$field[$i]['default'];\n\t\t\t}\n\n\t\t\tif (isset($field[$i]['null']))\n\t\t\t{\n\t\t\t\t$sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])\n\t\t\t\t\t.($field[$i]['null'] === TRUE ? ' DROP NOT NULL' : ' SET NOT NULL');\n\t\t\t}\n\n\t\t\tif ( ! empty($field[$i]['new_name']))\n\t\t\t{\n\t\t\t\t$sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name'])\n\t\t\t\t\t.' TO '.$this->db->escape_identifiers($field[$i]['new_name']);\n\t\t\t}\n\n\t\t\tif ( ! empty($field[$i]['comment']))\n\t\t\t{\n\t\t\t\t$sqls[] = 'COMMENT ON COLUMN '\n\t\t\t\t\t.$this->db->escape_identifiers($table).'.'.$this->db->escape_identifiers($field[$i]['name'])\n\t\t\t\t\t.' IS '.$field[$i]['comment'];\n\t\t\t}\n\t\t}\n\n\t\treturn $sqls;\n \t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute TYPE\n\t *\n\t * Performs a data type mapping between different databases.\n\t *\n\t * @param\tarray\t&$attributes\n\t * @return\tvoid\n\t */\n\tprotected function _attr_type(&$attributes)\n\t{\n\t\t// Reset field lenghts for data types that don't support it\n\t\tif (isset($attributes['CONSTRAINT']) && stripos($attributes['TYPE'], 'int') !== FALSE)\n\t\t{\n\t\t\t$attributes['CONSTRAINT'] = NULL;\n\t\t}\n\n\t\tswitch (strtoupper($attributes['TYPE']))\n\t\t{\n\t\t\tcase 'TINYINT':\n\t\t\t\t$attributes['TYPE'] = 'SMALLINT';\n\t\t\t\t$attributes['UNSIGNED'] = FALSE;\n\t\t\t\treturn;\n\t\t\tcase 'MEDIUMINT':\n\t\t\t\t$attributes['TYPE'] = 'INTEGER';\n\t\t\t\t$attributes['UNSIGNED'] = FALSE;\n\t\t\t\treturn;\n\t\t\tdefault: return;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute AUTO_INCREMENT\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_auto_increment(&$attributes, &$field)\n\t{\n\t\tif ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)\n\t\t{\n\t\t\t$field['type'] = ($field['type'] === 'NUMERIC')\n\t\t\t\t? 'BIGSERIAL'\n\t\t\t\t: 'SERIAL';\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_sqlite_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO SQLite Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_sqlite_driver extends CI_DB_pdo_driver {\n\n\t/**\n\t * Sub-driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $subdriver = 'sqlite';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ORDER BY random keyword\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_random_keyword = ' RANDOM()';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Builds the DSN if not already set.\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif (empty($this->dsn))\n\t\t{\n\t\t\t$this->dsn = 'sqlite:';\n\n\t\t\tif (empty($this->database) && empty($this->hostname))\n\t\t\t{\n\t\t\t\t$this->database = ':memory:';\n\t\t\t}\n\n\t\t\t$this->database = empty($this->database) ? $this->hostname : $this->database;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\t$prefix_limit\n\t * @return\tstring\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\t$sql = 'SELECT \"NAME\" FROM \"SQLITE_MASTER\" WHERE \"TYPE\" = \\'table\\'';\n\n\t\tif ($prefix_limit === TRUE && $this->dbprefix !== '')\n\t\t{\n\t\t\treturn $sql.' AND \"NAME\" LIKE \\''.$this->escape_like_str($this->dbprefix).\"%' \"\n\t\t\t\t.sprintf($this->_like_escape_str, $this->_like_escape_chr);\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch Field Names\n\t *\n\t * @param\tstring\t$table\tTable name\n\t * @return\tarray\n\t */\n\tpublic function list_fields($table)\n\t{\n\t\t// Is there a cached result?\n\t\tif (isset($this->data_cache['field_names'][$table]))\n\t\t{\n\t\t\treturn $this->data_cache['field_names'][$table];\n\t\t}\n\n\t\tif (($result = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->data_cache['field_names'][$table] = array();\n\t\tforeach ($result->result_array() as $row)\n\t\t{\n\t\t\t$this->data_cache['field_names'][$table][] = $row['name'];\n\t\t}\n\n\t\treturn $this->data_cache['field_names'][$table];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an object with field data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tarray\n\t */\n\tpublic function field_data($table)\n\t{\n\t\tif (($query = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$query = $query->result_array();\n\t\tif (empty($query))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$retval = array();\n\t\tfor ($i = 0, $c = count($query); $i < $c; $i++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= $query[$i]['name'];\n\t\t\t$retval[$i]->type\t\t= $query[$i]['type'];\n\t\t\t$retval[$i]->max_length\t\t= NULL;\n\t\t\t$retval[$i]->default\t\t= $query[$i]['dflt_value'];\n\t\t\t$retval[$i]->primary_key\t= isset($query[$i]['pk']) ? (int) $query[$i]['pk'] : 0;\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Replace statement\n\t *\n\t * @param\tstring\t$table\tTable name\n\t * @param\tarray\t$keys\tINSERT keys\n\t * @param\tarray\t$values\tINSERT values\n\t * @return \tstring\n\t */\n\tprotected function _replace($table, $keys, $values)\n\t{\n\t\treturn 'INSERT OR '.parent::_replace($table, $keys, $values);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Truncate statement\n\t *\n\t * Generates a platform-specific truncate string from the supplied data\n\t *\n\t * If the database does not support the TRUNCATE statement,\n\t * then this method maps to 'DELETE FROM table'\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _truncate($table)\n\t{\n\t\treturn 'DELETE FROM '.$table;\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_sqlite_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO SQLite Forge Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_sqlite_forge extends CI_DB_pdo_forge {\n\n\t/**\n\t * CREATE TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_table_if\t= 'CREATE TABLE IF NOT EXISTS';\n\n\t/**\n\t * DROP TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_drop_table_if\t= 'DROP TABLE IF EXISTS';\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tbool|array\n\t */\n\tprotected $_unsigned\t\t= FALSE;\n\n\t/**\n\t * NULL value representation in CREATE/ALTER TABLE statements\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_null\t\t= 'NULL';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tobject\t&$db\tDatabase object\n\t * @return\tvoid\n\t */\n\tpublic function __construct(&$db)\n\t{\n\t\tparent::__construct($db);\n\n\t\tif (version_compare($this->db->version(), '3.3', '<'))\n\t\t{\n\t\t\t$this->_create_table_if = FALSE;\n\t\t\t$this->_drop_table_if   = FALSE;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Create database\n\t *\n\t * @param\tstring\t$db_name\t(ignored)\n\t * @return\tbool\n\t */\n\tpublic function create_database($db_name = '')\n\t{\n\t\t// In SQLite, a database is created when you connect to the database.\n\t\t// We'll return TRUE so that an error isn't generated\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Drop database\n\t *\n\t * @param\tstring\t$db_name\t(ignored)\n\t * @return\tbool\n\t */\n\tpublic function drop_database($db_name = '')\n\t{\n\t\t// In SQLite, a database is dropped when we delete a file\n\t\tif (file_exists($this->db->database))\n\t\t{\n\t\t\t// We need to close the pseudo-connection first\n\t\t\t$this->db->close();\n\t\t\tif ( ! @unlink($this->db->database))\n\t\t\t{\n\t\t\t\treturn $this->db->db_debug ? $this->db->display_error('db_unable_to_drop') : FALSE;\n\t\t\t}\n\t\t\telseif ( ! empty($this->db->data_cache['db_names']))\n\t\t\t{\n\t\t\t\t$key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE);\n\t\t\t\tif ($key !== FALSE)\n\t\t\t\t{\n\t\t\t\t\tunset($this->db->data_cache['db_names'][$key]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn $this->db->db_debug ? $this->db->display_error('db_unable_to_drop') : FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ALTER TABLE\n\t *\n\t * @param\tstring\t$alter_type\tALTER type\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tmixed\t$field\t\tColumn definition\n\t * @return\tstring|string[]\n\t */\n\tprotected function _alter_table($alter_type, $table, $field)\n\t{\n\t\tif ($alter_type === 'DROP' OR $alter_type === 'CHANGE')\n\t\t{\n\t\t\t// drop_column():\n\t\t\t//\tBEGIN TRANSACTION;\n\t\t\t//\tCREATE TEMPORARY TABLE t1_backup(a,b);\n\t\t\t//\tINSERT INTO t1_backup SELECT a,b FROM t1;\n\t\t\t//\tDROP TABLE t1;\n\t\t\t//\tCREATE TABLE t1(a,b);\n\t\t\t//\tINSERT INTO t1 SELECT a,b FROM t1_backup;\n\t\t\t//\tDROP TABLE t1_backup;\n\t\t\t//\tCOMMIT;\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn parent::_alter_table($alter_type, $table, $field);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Process column\n\t *\n\t * @param\tarray\t$field\n\t * @return\tstring\n\t */\n\tprotected function _process_column($field)\n\t{\n\t\treturn $this->db->escape_identifiers($field['name'])\n\t\t\t.' '.$field['type']\n\t\t\t.$field['auto_increment']\n\t\t\t.$field['null']\n\t\t\t.$field['unique']\n\t\t\t.$field['default'];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute TYPE\n\t *\n\t * Performs a data type mapping between different databases.\n\t *\n\t * @param\tarray\t&$attributes\n\t * @return\tvoid\n\t */\n\tprotected function _attr_type(&$attributes)\n\t{\n\t\tswitch (strtoupper($attributes['TYPE']))\n\t\t{\n\t\t\tcase 'ENUM':\n\t\t\tcase 'SET':\n\t\t\t\t$attributes['TYPE'] = 'TEXT';\n\t\t\t\treturn;\n\t\t\tdefault: return;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute AUTO_INCREMENT\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_auto_increment(&$attributes, &$field)\n\t{\n\t\tif ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)\n\t\t{\n\t\t\t$field['type'] = 'INTEGER PRIMARY KEY';\n\t\t\t$field['default'] = '';\n\t\t\t$field['null'] = '';\n\t\t\t$field['unique'] = '';\n\t\t\t$field['auto_increment'] = ' AUTOINCREMENT';\n\n\t\t\t$this->primary_keys = array();\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_sqlsrv_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO SQLSRV Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_sqlsrv_driver extends CI_DB_pdo_driver {\n\n\t/**\n\t * Sub-driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $subdriver = 'sqlsrv';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ORDER BY random keyword\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_random_keyword = array('NEWID()', 'RAND(%d)');\n\n\t/**\n\t * Quoted identifier flag\n\t *\n\t * Whether to use SQL-92 standard quoted identifier\n\t * (double quotes) or brackets for identifier escaping.\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_quoted_identifier;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Builds the DSN if not already set.\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif (empty($this->dsn))\n\t\t{\n\t\t\t$this->dsn = 'sqlsrv:Server='.(empty($this->hostname) ? '127.0.0.1' : $this->hostname);\n\n\t\t\tempty($this->port) OR $this->dsn .= ','.$this->port;\n\t\t\tempty($this->database) OR $this->dsn .= ';Database='.$this->database;\n\n\t\t\t// Some custom options\n\n\t\t\tif (isset($this->QuotedId))\n\t\t\t{\n\t\t\t\t$this->dsn .= ';QuotedId='.$this->QuotedId;\n\t\t\t\t$this->_quoted_identifier = (bool) $this->QuotedId;\n\t\t\t}\n\n\t\t\tif (isset($this->ConnectionPooling))\n\t\t\t{\n\t\t\t\t$this->dsn .= ';ConnectionPooling='.$this->ConnectionPooling;\n\t\t\t}\n\n\t\t\tif ($this->encrypt === TRUE)\n\t\t\t{\n\t\t\t\t$this->dsn .= ';Encrypt=1';\n\t\t\t}\n\n\t\t\tif (isset($this->TraceOn))\n\t\t\t{\n\t\t\t\t$this->dsn .= ';TraceOn='.$this->TraceOn;\n\t\t\t}\n\n\t\t\tif (isset($this->TrustServerCertificate))\n\t\t\t{\n\t\t\t\t$this->dsn .= ';TrustServerCertificate='.$this->TrustServerCertificate;\n\t\t\t}\n\n\t\t\tempty($this->APP) OR $this->dsn .= ';APP='.$this->APP;\n\t\t\tempty($this->Failover_Partner) OR $this->dsn .= ';Failover_Partner='.$this->Failover_Partner;\n\t\t\tempty($this->LoginTimeout) OR $this->dsn .= ';LoginTimeout='.$this->LoginTimeout;\n\t\t\tempty($this->MultipleActiveResultSets) OR $this->dsn .= ';MultipleActiveResultSets='.$this->MultipleActiveResultSets;\n\t\t\tempty($this->TraceFile) OR $this->dsn .= ';TraceFile='.$this->TraceFile;\n\t\t\tempty($this->WSID) OR $this->dsn .= ';WSID='.$this->WSID;\n\t\t}\n\t\telseif (preg_match('/QuotedId=(0|1)/', $this->dsn, $match))\n\t\t{\n\t\t\t$this->_quoted_identifier = (bool) $match[1];\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Database connection\n\t *\n\t * @param\tbool\t$persistent\n\t * @return\tobject\n\t */\n\tpublic function db_connect($persistent = FALSE)\n\t{\n\t\tif ( ! empty($this->char_set) && preg_match('/utf[^8]*8/i', $this->char_set))\n\t\t{\n\t\t\t$this->options[PDO::SQLSRV_ENCODING_UTF8] = 1;\n\t\t}\n\n\t\t$this->conn_id = parent::db_connect($persistent);\n\n\t\tif ( ! is_object($this->conn_id) OR is_bool($this->_quoted_identifier))\n\t\t{\n\t\t\treturn $this->conn_id;\n\t\t}\n\n\t\t// Determine how identifiers are escaped\n\t\t$query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi');\n\t\t$query = $query->row_array();\n\t\t$this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi'];\n\t\t$this->_escape_char = ($this->_quoted_identifier) ? '\"' : array('[', ']');\n\n\t\treturn $this->conn_id;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\t$prefix_limit\n\t * @return\tstring\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\t$sql = 'SELECT '.$this->escape_identifiers('name')\n\t\t\t.' FROM '.$this->escape_identifiers('sysobjects')\n\t\t\t.' WHERE '.$this->escape_identifiers('type').\" = 'U'\";\n\n\t\tif ($prefix_limit === TRUE && $this->dbprefix !== '')\n\t\t{\n\t\t\t$sql .= ' AND '.$this->escape_identifiers('name').\" LIKE '\".$this->escape_like_str($this->dbprefix).\"%' \"\n\t\t\t\t.sprintf($this->_like_escape_str, $this->_like_escape_chr);\n\t\t}\n\n\t\treturn $sql.' ORDER BY '.$this->escape_identifiers('name');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show column query\n\t *\n\t * Generates a platform-specific query string so that the column names can be fetched\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _list_columns($table = '')\n\t{\n\t\treturn 'SELECT COLUMN_NAME\n\t\t\tFROM INFORMATION_SCHEMA.Columns\n\t\t\tWHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an object with field data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tarray\n\t */\n\tpublic function field_data($table)\n\t{\n\t\t$sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, COLUMN_DEFAULT\n\t\t\tFROM INFORMATION_SCHEMA.Columns\n\t\t\tWHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));\n\n\t\tif (($query = $this->query($sql)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\t$query = $query->result_object();\n\n\t\t$retval = array();\n\t\tfor ($i = 0, $c = count($query); $i < $c; $i++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= $query[$i]->COLUMN_NAME;\n\t\t\t$retval[$i]->type\t\t= $query[$i]->DATA_TYPE;\n\t\t\t$retval[$i]->max_length\t\t= ($query[$i]->CHARACTER_MAXIMUM_LENGTH > 0) ? $query[$i]->CHARACTER_MAXIMUM_LENGTH : $query[$i]->NUMERIC_PRECISION;\n\t\t\t$retval[$i]->default\t\t= $query[$i]->COLUMN_DEFAULT;\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update statement\n\t *\n\t * Generates a platform-specific update string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @param\tarray\t$values\n\t * @return\tstring\n\t */\n\tprotected function _update($table, $values)\n\t{\n\t\t$this->qb_limit = FALSE;\n\t\t$this->qb_orderby = array();\n\t\treturn parent::_update($table, $values);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Delete statement\n\t *\n\t * Generates a platform-specific delete string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _delete($table)\n\t{\n\t\tif ($this->qb_limit)\n\t\t{\n\t\t\treturn 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete';\n\t\t}\n\n\t\treturn parent::_delete($table);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * LIMIT\n\t *\n\t * Generates a platform-specific LIMIT clause\n\t *\n\t * @param\tstring\t$sql\tSQL Query\n\t * @return\tstring\n\t */\n\tprotected function _limit($sql)\n\t{\n\t\t// As of SQL Server 2012 (11.0.*) OFFSET is supported\n\t\tif (version_compare($this->version(), '11', '>='))\n\t\t{\n\t\t\t// SQL Server OFFSET-FETCH can be used only with the ORDER BY clause\n\t\t\tempty($this->qb_orderby) && $sql .= ' ORDER BY 1';\n\n\t\t\treturn $sql.' OFFSET '.(int) $this->qb_offset.' ROWS FETCH NEXT '.$this->qb_limit.' ROWS ONLY';\n\t\t}\n\n\t\t$limit = $this->qb_offset + $this->qb_limit;\n\n\t\t// An ORDER BY clause is required for ROW_NUMBER() to work\n\t\tif ($this->qb_offset && ! empty($this->qb_orderby))\n\t\t{\n\t\t\t$orderby = $this->_compile_order_by();\n\n\t\t\t// We have to strip the ORDER BY clause\n\t\t\t$sql = trim(substr($sql, 0, strrpos($sql, $orderby)));\n\n\t\t\t// Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results\n\t\t\tif (count($this->qb_select) === 0)\n\t\t\t{\n\t\t\t\t$select = '*'; // Inevitable\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Use only field names and their aliases, everything else is out of our scope.\n\t\t\t\t$select = array();\n\t\t\t\t$field_regexp = ($this->_quoted_identifier)\n\t\t\t\t\t? '(\"[^\\\"]+\")' : '(\\[[^\\]]+\\])';\n\t\t\t\tfor ($i = 0, $c = count($this->qb_select); $i < $c; $i++)\n\t\t\t\t{\n\t\t\t\t\t$select[] = preg_match('/(?:\\s|\\.)'.$field_regexp.'$/i', $this->qb_select[$i], $m)\n\t\t\t\t\t\t? $m[1] : $this->qb_select[$i];\n\t\t\t\t}\n\t\t\t\t$select = implode(', ', $select);\n\t\t\t}\n\n\t\t\treturn 'SELECT '.$select.\" FROM (\\n\\n\"\n\t\t\t\t.preg_replace('/^(SELECT( DISTINCT)?)/i', '\\\\1 ROW_NUMBER() OVER('.trim($orderby).') AS '.$this->escape_identifiers('CI_rownum').', ', $sql)\n\t\t\t\t.\"\\n\\n) \".$this->escape_identifiers('CI_subquery')\n\t\t\t\t.\"\\nWHERE \".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit;\n\t\t}\n\n\t\treturn preg_replace('/(^\\SELECT (DISTINCT)?)/i','\\\\1 TOP '.$limit.' ', $sql);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert batch statement\n\t *\n\t * Generates a platform-specific insert string from the supplied data.\n\t *\n\t * @param\tstring\t$table\tTable name\n\t * @param\tarray\t$keys\tINSERT keys\n\t * @param\tarray\t$values\tINSERT values\n\t * @return\tstring|bool\n\t */\n\tprotected function _insert_batch($table, $keys, $values)\n\t{\n\t\t// Multiple-value inserts are only supported as of SQL Server 2008\n\t\tif (version_compare($this->version(), '10', '>='))\n\t\t{\n\t\t\treturn parent::_insert_batch($table, $keys, $values);\n\t\t}\n\n\t\treturn ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/pdo/subdrivers/pdo_sqlsrv_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * PDO SQLSRV Forge Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_pdo_sqlsrv_forge extends CI_DB_pdo_forge {\n\n\t/**\n\t * CREATE TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_table_if\t= \"IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\\nCREATE TABLE\";\n\n\t/**\n\t * DROP TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_drop_table_if\t= \"IF EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\\nDROP TABLE\";\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_unsigned\t\t= array(\n\t\t'TINYINT'\t=> 'SMALLINT',\n\t\t'SMALLINT'\t=> 'INT',\n\t\t'INT'\t\t=> 'BIGINT',\n\t\t'REAL'\t\t=> 'FLOAT'\n\t);\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ALTER TABLE\n\t *\n\t * @param\tstring\t$alter_type\tALTER type\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tmixed\t$field\t\tColumn definition\n\t * @return\tstring|string[]\n\t */\n\tprotected function _alter_table($alter_type, $table, $field)\n\t{\n\t\tif (in_array($alter_type, array('ADD', 'DROP'), TRUE))\n\t\t{\n\t\t\treturn parent::_alter_table($alter_type, $table, $field);\n\t\t}\n\n\t\t$sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ALTER COLUMN ';\n\t\t$sqls = array();\n\t\tfor ($i = 0, $c = count($field); $i < $c; $i++)\n\t\t{\n\t\t\t$sqls[] = $sql.$this->_process_column($field[$i]);\n\t\t}\n\n\t\treturn $sqls;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute TYPE\n\t *\n\t * Performs a data type mapping between different databases.\n\t *\n\t * @param\tarray\t&$attributes\n\t * @return\tvoid\n\t */\n\tprotected function _attr_type(&$attributes)\n\t{\n\t\tif (isset($attributes['CONSTRAINT']) && strpos($attributes['TYPE'], 'INT') !== FALSE)\n\t\t{\n\t\t\tunset($attributes['CONSTRAINT']);\n\t\t}\n\n\t\tswitch (strtoupper($attributes['TYPE']))\n\t\t{\n\t\t\tcase 'MEDIUMINT':\n\t\t\t\t$attributes['TYPE'] = 'INTEGER';\n\t\t\t\t$attributes['UNSIGNED'] = FALSE;\n\t\t\t\treturn;\n\t\t\tcase 'INTEGER':\n\t\t\t\t$attributes['TYPE'] = 'INT';\n\t\t\t\treturn;\n\t\t\tdefault: return;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute AUTO_INCREMENT\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_auto_increment(&$attributes, &$field)\n\t{\n\t\tif ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)\n\t\t{\n\t\t\t$field['auto_increment'] = ' IDENTITY(1,1)';\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/postgre/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/database/drivers/postgre/postgre_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.3.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Postgre Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_postgre_driver extends CI_DB {\n\n\t/**\n\t * Database driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $dbdriver = 'postgre';\n\n\t/**\n\t * Database schema\n\t *\n\t * @var\tstring\n\t */\n\tpublic $schema = 'public';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ORDER BY random keyword\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_random_keyword = array('RANDOM()', 'RANDOM()');\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Creates a DSN string to be used for db_connect() and db_pconnect()\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif ( ! empty($this->dsn))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\t$this->dsn === '' OR $this->dsn = '';\n\n\t\tif (strpos($this->hostname, '/') !== FALSE)\n\t\t{\n\t\t\t// If UNIX sockets are used, we shouldn't set a port\n\t\t\t$this->port = '';\n\t\t}\n\n\t\t$this->hostname === '' OR $this->dsn = 'host='.$this->hostname.' ';\n\n\t\tif ( ! empty($this->port) && ctype_digit($this->port))\n\t\t{\n\t\t\t$this->dsn .= 'port='.$this->port.' ';\n\t\t}\n\n\t\tif ($this->username !== '')\n\t\t{\n\t\t\t$this->dsn .= 'user='.$this->username.' ';\n\n\t\t\t/* An empty password is valid!\n\t\t\t *\n\t\t\t * $db['password'] = NULL must be done in order to ignore it.\n\t\t\t */\n\t\t\t$this->password === NULL OR $this->dsn .= \"password='\".$this->password.\"' \";\n\t\t}\n\n\t\t$this->database === '' OR $this->dsn .= 'dbname='.$this->database.' ';\n\n\t\t/* We don't have these options as elements in our standard configuration\n\t\t * array, but they might be set by parse_url() if the configuration was\n\t\t * provided via string. Example:\n\t\t *\n\t\t * postgre://username:password@localhost:5432/database?connect_timeout=5&sslmode=1\n\t\t */\n\t\tforeach (array('connect_timeout', 'options', 'sslmode', 'service') as $key)\n\t\t{\n\t\t\tif (isset($this->$key) && is_string($this->key) && $this->key !== '')\n\t\t\t{\n\t\t\t\t$this->dsn .= $key.\"='\".$this->key.\"' \";\n\t\t\t}\n\t\t}\n\n\t\t$this->dsn = rtrim($this->dsn);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Database connection\n\t *\n\t * @param\tbool\t$persistent\n\t * @return\tresource\n\t */\n\tpublic function db_connect($persistent = FALSE)\n\t{\n\t\t$this->conn_id = ($persistent === TRUE)\n\t\t\t? pg_pconnect($this->dsn)\n\t\t\t: pg_connect($this->dsn);\n\n\t\tif ($this->conn_id !== FALSE)\n\t\t{\n\t\t\tif ($persistent === TRUE\n\t\t\t\t&& pg_connection_status($this->conn_id) === PGSQL_CONNECTION_BAD\n\t\t\t\t&& pg_ping($this->conn_id) === FALSE\n\t\t\t)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tempty($this->schema) OR $this->simple_query('SET search_path TO '.$this->schema.',public');\n\t\t}\n\n\t\treturn $this->conn_id;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Reconnect\n\t *\n\t * Keep / reestablish the db connection if no queries have been\n\t * sent for a length of time exceeding the server's idle timeout\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function reconnect()\n\t{\n\t\tif (pg_ping($this->conn_id) === FALSE)\n\t\t{\n\t\t\t$this->conn_id = FALSE;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set client character set\n\t *\n\t * @param\tstring\t$charset\n\t * @return\tbool\n\t */\n\tprotected function _db_set_charset($charset)\n\t{\n\t\treturn (pg_set_client_encoding($this->conn_id, $charset) === 0);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Database version number\n\t *\n\t * @return\tstring\n\t */\n\tpublic function version()\n\t{\n\t\tif (isset($this->data_cache['version']))\n\t\t{\n\t\t\treturn $this->data_cache['version'];\n\t\t}\n\n\t\tif ( ! $this->conn_id OR ($pg_version = pg_version($this->conn_id)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t/* If PHP was compiled with PostgreSQL lib versions earlier\n\t\t * than 7.4, pg_version() won't return the server version\n\t\t * and so we'll have to fall back to running a query in\n\t\t * order to get it.\n\t\t */\n\t\treturn isset($pg_version['server'])\n\t\t\t? $this->data_cache['version'] = $pg_version['server']\n\t\t\t: parent::version();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Execute the query\n\t *\n\t * @param\tstring\t$sql\tan SQL query\n\t * @return\tresource\n\t */\n\tprotected function _execute($sql)\n\t{\n\t\treturn pg_query($this->conn_id, $sql);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Begin Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_begin()\n\t{\n\t\treturn (bool) pg_query($this->conn_id, 'BEGIN');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Commit Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_commit()\n\t{\n\t\treturn (bool) pg_query($this->conn_id, 'COMMIT');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Rollback Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_rollback()\n\t{\n\t\treturn (bool) pg_query($this->conn_id, 'ROLLBACK');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Determines if a query is a \"write\" type.\n\t *\n\t * @param\tstring\tAn SQL query string\n\t * @return\tbool\n\t */\n\tpublic function is_write_type($sql)\n\t{\n\t\tif (preg_match('#^(INSERT|UPDATE).*RETURNING\\s.+(\\,\\s?.+)*$#i', $sql))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn parent::is_write_type($sql);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Platform-dependant string escape\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _escape_str($str)\n\t{\n\t\treturn pg_escape_string($this->conn_id, $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * \"Smart\" Escape String\n\t *\n\t * Escapes data based on type\n\t *\n\t * @param\tstring\t$str\n\t * @return\tmixed\n\t */\n\tpublic function escape($str)\n\t{\n\t\tif (is_php('5.4.4') && (is_string($str) OR (is_object($str) && method_exists($str, '__toString'))))\n\t\t{\n\t\t\treturn pg_escape_literal($this->conn_id, $str);\n\t\t}\n\t\telseif (is_bool($str))\n\t\t{\n\t\t\treturn ($str) ? 'TRUE' : 'FALSE';\n\t\t}\n\n\t\treturn parent::escape($str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Affected Rows\n\t *\n\t * @return\tint\n\t */\n\tpublic function affected_rows()\n\t{\n\t\treturn pg_affected_rows($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert ID\n\t *\n\t * @return\tstring\n\t */\n\tpublic function insert_id()\n\t{\n\t\t$v = pg_version($this->conn_id);\n\t\t$v = isset($v['server']) ? $v['server'] : 0; // 'server' key is only available since PosgreSQL 7.4\n\n\t\t$table\t= (func_num_args() > 0) ? func_get_arg(0) : NULL;\n\t\t$column\t= (func_num_args() > 1) ? func_get_arg(1) : NULL;\n\n\t\tif ($table === NULL && $v >= '8.1')\n\t\t{\n\t\t\t$sql = 'SELECT LASTVAL() AS ins_id';\n\t\t}\n\t\telseif ($table !== NULL)\n\t\t{\n\t\t\tif ($column !== NULL && $v >= '8.0')\n\t\t\t{\n\t\t\t\t$sql = 'SELECT pg_get_serial_sequence(\\''.$table.\"', '\".$column.\"') AS seq\";\n\t\t\t\t$query = $this->query($sql);\n\t\t\t\t$query = $query->row();\n\t\t\t\t$seq = $query->seq;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// seq_name passed in table parameter\n\t\t\t\t$seq = $table;\n\t\t\t}\n\n\t\t\t$sql = 'SELECT CURRVAL(\\''.$seq.\"') AS ins_id\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn pg_last_oid($this->result_id);\n\t\t}\n\n\t\t$query = $this->query($sql);\n\t\t$query = $query->row();\n\t\treturn (int) $query->ins_id;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\t$prefix_limit\n\t * @return\tstring\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\t$sql = 'SELECT \"table_name\" FROM \"information_schema\".\"tables\" WHERE \"table_schema\" = \\''.$this->schema.\"'\";\n\n\t\tif ($prefix_limit !== FALSE && $this->dbprefix !== '')\n\t\t{\n\t\t\treturn $sql.' AND \"table_name\" LIKE \\''\n\t\t\t\t.$this->escape_like_str($this->dbprefix).\"%' \"\n\t\t\t\t.sprintf($this->_like_escape_str, $this->_like_escape_chr);\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * List column query\n\t *\n\t * Generates a platform-specific query string so that the column names can be fetched\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _list_columns($table = '')\n\t{\n\t\treturn 'SELECT \"column_name\"\n\t\t\tFROM \"information_schema\".\"columns\"\n\t\t\tWHERE LOWER(\"table_name\") = '.$this->escape(strtolower($table));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an object with field data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tarray\n\t */\n\tpublic function field_data($table)\n\t{\n\t\t$sql = 'SELECT \"column_name\", \"data_type\", \"character_maximum_length\", \"numeric_precision\", \"column_default\"\n\t\t\tFROM \"information_schema\".\"columns\"\n\t\t\tWHERE LOWER(\"table_name\") = '.$this->escape(strtolower($table));\n\n\t\tif (($query = $this->query($sql)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\t$query = $query->result_object();\n\n\t\t$retval = array();\n\t\tfor ($i = 0, $c = count($query); $i < $c; $i++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= $query[$i]->column_name;\n\t\t\t$retval[$i]->type\t\t= $query[$i]->data_type;\n\t\t\t$retval[$i]->max_length\t\t= ($query[$i]->character_maximum_length > 0) ? $query[$i]->character_maximum_length : $query[$i]->numeric_precision;\n\t\t\t$retval[$i]->default\t\t= $query[$i]->column_default;\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Error\n\t *\n\t * Returns an array containing code and message of the last\n\t * database error that has occured.\n\t *\n\t * @return\tarray\n\t */\n\tpublic function error()\n\t{\n\t\treturn array('code' => '', 'message' => pg_last_error($this->conn_id));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ORDER BY\n\t *\n\t * @param\tstring\t$orderby\n\t * @param\tstring\t$direction\tASC, DESC or RANDOM\n\t * @param\tbool\t$escape\n\t * @return\tobject\n\t */\n\tpublic function order_by($orderby, $direction = '', $escape = NULL)\n\t{\n\t\t$direction = strtoupper(trim($direction));\n\t\tif ($direction === 'RANDOM')\n\t\t{\n\t\t\tif ( ! is_float($orderby) && ctype_digit((string) $orderby))\n\t\t\t{\n\t\t\t\t$orderby = ($orderby > 1)\n\t\t\t\t\t? (float) '0.'.$orderby\n\t\t\t\t\t: (float) $orderby;\n\t\t\t}\n\n\t\t\tif (is_float($orderby))\n\t\t\t{\n\t\t\t\t$this->simple_query('SET SEED '.$orderby);\n\t\t\t}\n\n\t\t\t$orderby = $this->_random_keyword[0];\n\t\t\t$direction = '';\n\t\t\t$escape = FALSE;\n\t\t}\n\n\t\treturn parent::order_by($orderby, $direction, $escape);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update statement\n\t *\n\t * Generates a platform-specific update string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @param\tarray\t$values\n\t * @return\tstring\n\t */\n\tprotected function _update($table, $values)\n\t{\n\t\t$this->qb_limit = FALSE;\n\t\t$this->qb_orderby = array();\n\t\treturn parent::_update($table, $values);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update_Batch statement\n\t *\n\t * Generates a platform-specific batch update string from the supplied data\n\t *\n\t * @param\tstring\t$table\tTable name\n\t * @param\tarray\t$values\tUpdate data\n\t * @param\tstring\t$index\tWHERE key\n\t * @return\tstring\n\t */\n\tprotected function _update_batch($table, $values, $index)\n\t{\n\t\t$ids = array();\n\t\tforeach ($values as $key => $val)\n\t\t{\n\t\t\t$ids[] = $val[$index];\n\n\t\t\tforeach (array_keys($val) as $field)\n\t\t\t{\n\t\t\t\tif ($field !== $index)\n\t\t\t\t{\n\t\t\t\t\t$final[$field][] = 'WHEN '.$val[$index].' THEN '.$val[$field];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$cases = '';\n\t\tforeach ($final as $k => $v)\n\t\t{\n\t\t\t$cases .= $k.' = (CASE '.$index.\"\\n\"\n\t\t\t\t.implode(\"\\n\", $v).\"\\n\"\n\t\t\t\t.'ELSE '.$k.' END), ';\n\t\t}\n\n\t\t$this->where($index.' IN('.implode(',', $ids).')', NULL, FALSE);\n\n\t\treturn 'UPDATE '.$table.' SET '.substr($cases, 0, -2).$this->_compile_wh('qb_where');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Delete statement\n\t *\n\t * Generates a platform-specific delete string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _delete($table)\n\t{\n\t\t$this->qb_limit = FALSE;\n\t\treturn parent::_delete($table);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * LIMIT\n\t *\n\t * Generates a platform-specific LIMIT clause\n\t *\n\t * @param\tstring\t$sql\tSQL Query\n\t * @return\tstring\n\t */\n\tprotected function _limit($sql)\n\t{\n\t\treturn $sql.' LIMIT '.$this->qb_limit.($this->qb_offset ? ' OFFSET '.$this->qb_offset : '');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Close DB Connection\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _close()\n\t{\n\t\tpg_close($this->conn_id);\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/postgre/postgre_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.3.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Postgre Forge Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_postgre_forge extends CI_DB_forge {\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_unsigned\t\t= array(\n\t\t'INT2'\t\t=> 'INTEGER',\n\t\t'SMALLINT'\t=> 'INTEGER',\n\t\t'INT'\t\t=> 'BIGINT',\n\t\t'INT4'\t\t=> 'BIGINT',\n\t\t'INTEGER'\t=> 'BIGINT',\n\t\t'INT8'\t\t=> 'NUMERIC',\n\t\t'BIGINT'\t=> 'NUMERIC',\n\t\t'REAL'\t\t=> 'DOUBLE PRECISION',\n\t\t'FLOAT'\t\t=> 'DOUBLE PRECISION'\n\t);\n\n\t/**\n\t * NULL value representation in CREATE/ALTER TABLE statements\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_null = 'NULL';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tobject\t&$db\tDatabase object\n\t * @return\tvoid\n\t */\n\tpublic function __construct(&$db)\n\t{\n\t\tparent::__construct($db);\n\n\t\tif (version_compare($this->db->version(), '9.0', '>'))\n\t\t{\n\t\t\t$this->create_table_if = 'CREATE TABLE IF NOT EXISTS';\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ALTER TABLE\n\t *\n\t * @param\tstring\t$alter_type\tALTER type\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tmixed\t$field\t\tColumn definition\n\t * @return\tstring|string[]\n\t */\n\tprotected function _alter_table($alter_type, $table, $field)\n \t{\n\t\tif (in_array($alter_type, array('DROP', 'ADD'), TRUE))\n\t\t{\n\t\t\treturn parent::_alter_table($alter_type, $table, $field);\n\t\t}\n\n\t\t$sql = 'ALTER TABLE '.$this->db->escape_identifiers($table);\n\t\t$sqls = array();\n\t\tfor ($i = 0, $c = count($field); $i < $c; $i++)\n\t\t{\n\t\t\tif ($field[$i]['_literal'] !== FALSE)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tif (version_compare($this->db->version(), '8', '>=') && isset($field[$i]['type']))\n\t\t\t{\n\t\t\t\t$sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])\n\t\t\t\t\t.' TYPE '.$field[$i]['type'].$field[$i]['length'];\n\t\t\t}\n\n\t\t\tif ( ! empty($field[$i]['default']))\n\t\t\t{\n\t\t\t\t$sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])\n\t\t\t\t\t.' SET DEFAULT '.$field[$i]['default'];\n\t\t\t}\n\n\t\t\tif (isset($field[$i]['null']))\n\t\t\t{\n\t\t\t\t$sqls[] = $sql.' ALTER COLUMN '.$this->db->escape_identifiers($field[$i]['name'])\n\t\t\t\t\t.($field[$i]['null'] === TRUE ? ' DROP NOT NULL' : ' SET NOT NULL');\n\t\t\t}\n\n\t\t\tif ( ! empty($field[$i]['new_name']))\n\t\t\t{\n\t\t\t\t$sqls[] = $sql.' RENAME COLUMN '.$this->db->escape_identifiers($field[$i]['name'])\n\t\t\t\t\t.' TO '.$this->db->escape_identifiers($field[$i]['new_name']);\n\t\t\t}\n\n\t\t\tif ( ! empty($field[$i]['comment']))\n\t\t\t{\n\t\t\t\t$sqls[] = 'COMMENT ON COLUMN '\n\t\t\t\t\t.$this->db->escape_identifiers($table).'.'.$this->db->escape_identifiers($field[$i]['name'])\n\t\t\t\t\t.' IS '.$field[$i]['comment'];\n\t\t\t}\n\t\t}\n\n\t\treturn $sqls;\n \t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute TYPE\n\t *\n\t * Performs a data type mapping between different databases.\n\t *\n\t * @param\tarray\t&$attributes\n\t * @return\tvoid\n\t */\n\tprotected function _attr_type(&$attributes)\n\t{\n\t\t// Reset field lenghts for data types that don't support it\n\t\tif (isset($attributes['CONSTRAINT']) && stripos($attributes['TYPE'], 'int') !== FALSE)\n\t\t{\n\t\t\t$attributes['CONSTRAINT'] = NULL;\n\t\t}\n\n\t\tswitch (strtoupper($attributes['TYPE']))\n\t\t{\n\t\t\tcase 'TINYINT':\n\t\t\t\t$attributes['TYPE'] = 'SMALLINT';\n\t\t\t\t$attributes['UNSIGNED'] = FALSE;\n\t\t\t\treturn;\n\t\t\tcase 'MEDIUMINT':\n\t\t\t\t$attributes['TYPE'] = 'INTEGER';\n\t\t\t\t$attributes['UNSIGNED'] = FALSE;\n\t\t\t\treturn;\n\t\t\tdefault: return;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute AUTO_INCREMENT\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_auto_increment(&$attributes, &$field)\n\t{\n\t\tif ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE)\n\t\t{\n\t\t\t$field['type'] = ($field['type'] === 'NUMERIC')\n\t\t\t\t? 'BIGSERIAL'\n\t\t\t\t: 'SERIAL';\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/postgre/postgre_result.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.3.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Postgres Result Class\n *\n * This class extends the parent result class: CI_DB_result\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_postgre_result extends CI_DB_result {\n\n\t/**\n\t * Number of rows in the result set\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_rows()\n\t{\n\t\treturn is_int($this->num_rows)\n\t\t\t? $this->num_rows\n\t\t\t: $this->num_rows = pg_num_rows($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Number of fields in the result set\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_fields()\n\t{\n\t\treturn pg_num_fields($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch Field Names\n\t *\n\t * Generates an array of column names\n\t *\n\t * @return\tarray\n\t */\n\tpublic function list_fields()\n\t{\n\t\t$field_names = array();\n\t\tfor ($i = 0, $c = $this->num_fields(); $i < $c; $i++)\n\t\t{\n\t\t\t$field_names[] = pg_field_name($this->result_id, $i);\n\t\t}\n\n\t\treturn $field_names;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field data\n\t *\n\t * Generates an array of objects containing field meta-data\n\t *\n\t * @return\tarray\n\t */\n\tpublic function field_data()\n\t{\n\t\t$retval = array();\n\t\tfor ($i = 0, $c = $this->num_fields(); $i < $c; $i++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= pg_field_name($this->result_id, $i);\n\t\t\t$retval[$i]->type\t\t= pg_field_type($this->result_id, $i);\n\t\t\t$retval[$i]->max_length\t\t= pg_field_size($this->result_id, $i);\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Free the result\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function free_result()\n\t{\n\t\tif (is_resource($this->result_id))\n\t\t{\n\t\t\tpg_free_result($this->result_id);\n\t\t\t$this->result_id = FALSE;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Data Seek\n\t *\n\t * Moves the internal pointer to the desired offset. We call\n\t * this internally before fetching results to make sure the\n\t * result set starts at zero.\n\t *\n\t * @param\tint\t$n\n\t * @return\tbool\n\t */\n\tpublic function data_seek($n = 0)\n\t{\n\t\treturn pg_result_seek($this->result_id, $n);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - associative array\n\t *\n\t * Returns the result set as an array\n\t *\n\t * @return\tarray\n\t */\n\tprotected function _fetch_assoc()\n\t{\n\t\treturn pg_fetch_assoc($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - object\n\t *\n\t * Returns the result set as an object\n\t *\n\t * @param\tstring\t$class_name\n\t * @return\tobject\n\t */\n\tprotected function _fetch_object($class_name = 'stdClass')\n\t{\n\t\treturn pg_fetch_object($this->result_id, NULL, $class_name);\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/postgre/postgre_utility.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.3.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Postgre Utility Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_postgre_utility extends CI_DB_utility {\n\n\t/**\n\t * List databases statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_list_databases\t= 'SELECT datname FROM pg_database';\n\n\t/**\n\t * OPTIMIZE TABLE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_optimize_table\t= 'REINDEX TABLE %s';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Export\n\t *\n\t * @param\tarray\t$params\tPreferences\n\t * @return\tmixed\n\t */\n\tprotected function _backup($params = array())\n\t{\n\t\t// Currently unsupported\n\t\treturn $this->db->display_error('db_unsupported_feature');\n\t}\n}\n"
  },
  {
    "path": "system/database/drivers/sqlite/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/database/drivers/sqlite/sqlite_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.3.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * SQLite Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_sqlite_driver extends CI_DB {\n\n\t/**\n\t * Database driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $dbdriver = 'sqlite';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ORDER BY random keyword\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_random_keyword = array('RANDOM()', 'RANDOM()');\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Non-persistent database connection\n\t *\n\t * @param\tbool\t$persistent\n\t * @return\tresource\n\t */\n\tpublic function db_connect($persistent = FALSE)\n\t{\n\t\t$error = NULL;\n\t\t$conn_id = ($persistent === TRUE)\n\t\t\t? sqlite_popen($this->database, 0666, $error)\n\t\t\t: sqlite_open($this->database, 0666, $error);\n\n\t\tisset($error) && log_message('error', $error);\n\n\t\treturn $conn_id;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Database version number\n\t *\n\t * @return\tstring\n\t */\n\tpublic function version()\n\t{\n\t\treturn isset($this->data_cache['version'])\n\t\t\t? $this->data_cache['version']\n\t\t\t: $this->data_cache['version'] = sqlite_libversion();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Execute the query\n\t *\n\t * @param\tstring\t$sql\tan SQL query\n\t * @return\tresource\n\t */\n\tprotected function _execute($sql)\n\t{\n\t\treturn $this->is_write_type($sql)\n\t\t\t? sqlite_exec($this->conn_id, $sql)\n\t\t\t: sqlite_query($this->conn_id, $sql);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Begin Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_begin()\n\t{\n\t\treturn $this->simple_query('BEGIN TRANSACTION');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Commit Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_commit()\n\t{\n\t\treturn $this->simple_query('COMMIT');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Rollback Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_rollback()\n\t{\n\t\treturn $this->simple_query('ROLLBACK');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Platform-dependant string escape\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _escape_str($str)\n\t{\n\t\treturn sqlite_escape_string($str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Affected Rows\n\t *\n\t * @return\tint\n\t */\n\tpublic function affected_rows()\n\t{\n\t\treturn sqlite_changes($this->conn_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert ID\n\t *\n\t * @return\tint\n\t */\n\tpublic function insert_id()\n\t{\n\t\treturn sqlite_last_insert_rowid($this->conn_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * List table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\t$prefix_limit\n\t * @return\tstring\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\t$sql = \"SELECT name FROM sqlite_master WHERE type='table'\";\n\n\t\tif ($prefix_limit !== FALSE && $this->dbprefix != '')\n\t\t{\n\t\t\treturn $sql.\" AND 'name' LIKE '\".$this->escape_like_str($this->dbprefix).\"%' \".sprintf($this->_like_escape_str, $this->_like_escape_chr);\n\t\t}\n\n\t\treturn $sql;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show column query\n\t *\n\t * Generates a platform-specific query string so that the column names can be fetched\n\t *\n\t * @param\tstring\t$table\n\t * @return\tbool\n\t */\n\tprotected function _list_columns($table = '')\n\t{\n\t\t// Not supported\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an object with field data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tarray\n\t */\n\tpublic function field_data($table)\n\t{\n\t\tif (($query = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$query = $query->result_array();\n\t\tif (empty($query))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$retval = array();\n\t\tfor ($i = 0, $c = count($query); $i < $c; $i++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= $query[$i]['name'];\n\t\t\t$retval[$i]->type\t\t= $query[$i]['type'];\n\t\t\t$retval[$i]->max_length\t\t= NULL;\n\t\t\t$retval[$i]->default\t\t= $query[$i]['dflt_value'];\n\t\t\t$retval[$i]->primary_key\t= isset($query[$i]['pk']) ? (int) $query[$i]['pk'] : 0;\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Error\n\t *\n\t * Returns an array containing code and message of the last\n\t * database error that has occured.\n\t *\n\t * @return\tarray\n\t */\n\tpublic function error()\n\t{\n\t\t$error = array('code' => sqlite_last_error($this->conn_id));\n\t\t$error['message'] = sqlite_error_string($error['code']);\n\t\treturn $error;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Replace statement\n\t *\n\t * Generates a platform-specific replace string from the supplied data\n\t *\n\t * @param\tstring\t$table\tTable name\n\t * @param\tarray\t$keys\tINSERT keys\n\t * @param\tarray\t$values\tINSERT values\n\t * @return\tstring\n\t */\n\tprotected function _replace($table, $keys, $values)\n\t{\n\t\treturn 'INSERT OR '.parent::_replace($table, $keys, $values);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Truncate statement\n\t *\n\t * Generates a platform-specific truncate string from the supplied data\n\t *\n\t * If the database does not support the TRUNCATE statement,\n\t * then this function maps to 'DELETE FROM table'\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _truncate($table)\n\t{\n\t\treturn 'DELETE FROM '.$table;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Close DB Connection\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _close()\n\t{\n\t\tsqlite_close($this->conn_id);\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/sqlite/sqlite_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.3.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * SQLite Forge Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_sqlite_forge extends CI_DB_forge {\n\n\t/**\n\t * CREATE TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_table_if\t= FALSE;\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tbool|array\n\t */\n\tprotected $_unsigned\t\t= FALSE;\n\n\t/**\n\t * NULL value representation in CREATE/ALTER TABLE statements\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_null\t\t= 'NULL';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Create database\n\t *\n\t * @param\tstring\t$db_name\t(ignored)\n\t * @return\tbool\n\t */\n\tpublic function create_database($db_name = '')\n\t{\n\t\t// In SQLite, a database is created when you connect to the database.\n\t\t// We'll return TRUE so that an error isn't generated\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Drop database\n\t *\n\t * @param\tstring\t$db_name\t(ignored)\n\t * @return\tbool\n\t */\n\tpublic function drop_database($db_name = '')\n\t{\n\t\tif ( ! file_exists($this->db->database) OR ! @unlink($this->db->database))\n\t\t{\n\t\t\treturn ($this->db->db_debug) ? $this->db->display_error('db_unable_to_drop') : FALSE;\n\t\t}\n\t\telseif ( ! empty($this->db->data_cache['db_names']))\n\t\t{\n\t\t\t$key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE);\n\t\t\tif ($key !== FALSE)\n\t\t\t{\n\t\t\t\tunset($this->db->data_cache['db_names'][$key]);\n\t\t\t}\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ALTER TABLE\n\t *\n\t * @todo\timplement drop_column(), modify_column()\n\t * @param\tstring\t$alter_type\tALTER type\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tmixed\t$field\t\tColumn definition\n\t * @return\tstring|string[]\n\t */\n\tprotected function _alter_table($alter_type, $table, $field)\n\t{\n\t\tif ($alter_type === 'DROP' OR $alter_type === 'CHANGE')\n\t\t{\n\t\t\t// drop_column():\n\t\t\t//\tBEGIN TRANSACTION;\n\t\t\t//\tCREATE TEMPORARY TABLE t1_backup(a,b);\n\t\t\t//\tINSERT INTO t1_backup SELECT a,b FROM t1;\n\t\t\t//\tDROP TABLE t1;\n\t\t\t//\tCREATE TABLE t1(a,b);\n\t\t\t//\tINSERT INTO t1 SELECT a,b FROM t1_backup;\n\t\t\t//\tDROP TABLE t1_backup;\n\t\t\t//\tCOMMIT;\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn parent::_alter_table($alter_type, $table, $field);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Process column\n\t *\n\t * @param\tarray\t$field\n\t * @return\tstring\n\t */\n\tprotected function _process_column($field)\n\t{\n\t\treturn $this->db->escape_identifiers($field['name'])\n\t\t\t.' '.$field['type']\n\t\t\t.$field['auto_increment']\n\t\t\t.$field['null']\n\t\t\t.$field['unique']\n\t\t\t.$field['default'];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute TYPE\n\t *\n\t * Performs a data type mapping between different databases.\n\t *\n\t * @param\tarray\t&$attributes\n\t * @return\tvoid\n\t */\n\tprotected function _attr_type(&$attributes)\n\t{\n\t\tswitch (strtoupper($attributes['TYPE']))\n\t\t{\n\t\t\tcase 'ENUM':\n\t\t\tcase 'SET':\n\t\t\t\t$attributes['TYPE'] = 'TEXT';\n\t\t\t\treturn;\n\t\t\tdefault: return;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute AUTO_INCREMENT\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_auto_increment(&$attributes, &$field)\n\t{\n\t\tif ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)\n\t\t{\n\t\t\t$field['type'] = 'INTEGER PRIMARY KEY';\n\t\t\t$field['default'] = '';\n\t\t\t$field['null'] = '';\n\t\t\t$field['unique'] = '';\n\t\t\t$field['auto_increment'] = ' AUTOINCREMENT';\n\n\t\t\t$this->primary_keys = array();\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/sqlite/sqlite_result.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.3.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * SQLite Result Class\n *\n * This class extends the parent result class: CI_DB_result\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_sqlite_result extends CI_DB_result {\n\n\t/**\n\t * Number of rows in the result set\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_rows()\n\t{\n\t\treturn is_int($this->num_rows)\n\t\t\t? $this->num_rows\n\t\t\t: $this->num_rows = @sqlite_num_rows($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Number of fields in the result set\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_fields()\n\t{\n\t\treturn @sqlite_num_fields($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch Field Names\n\t *\n\t * Generates an array of column names\n\t *\n\t * @return\tarray\n\t */\n\tpublic function list_fields()\n\t{\n\t\t$field_names = array();\n\t\tfor ($i = 0, $c = $this->num_fields(); $i < $c; $i++)\n\t\t{\n\t\t\t$field_names[$i] = sqlite_field_name($this->result_id, $i);\n\t\t}\n\n\t\treturn $field_names;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field data\n\t *\n\t * Generates an array of objects containing field meta-data\n\t *\n\t * @return\tarray\n\t */\n\tpublic function field_data()\n\t{\n\t\t$retval = array();\n\t\tfor ($i = 0, $c = $this->num_fields(); $i < $c; $i++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= sqlite_field_name($this->result_id, $i);\n\t\t\t$retval[$i]->type\t\t= NULL;\n\t\t\t$retval[$i]->max_length\t\t= NULL;\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Data Seek\n\t *\n\t * Moves the internal pointer to the desired offset. We call\n\t * this internally before fetching results to make sure the\n\t * result set starts at zero.\n\t *\n\t * @param\tint\t$n\n\t * @return\tbool\n\t */\n\tpublic function data_seek($n = 0)\n\t{\n\t\treturn sqlite_seek($this->result_id, $n);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - associative array\n\t *\n\t * Returns the result set as an array\n\t *\n\t * @return\tarray\n\t */\n\tprotected function _fetch_assoc()\n\t{\n\t\treturn sqlite_fetch_array($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - object\n\t *\n\t * Returns the result set as an object\n\t *\n\t * @param\tstring\t$class_name\n\t * @return\tobject\n\t */\n\tprotected function _fetch_object($class_name = 'stdClass')\n\t{\n\t\treturn sqlite_fetch_object($this->result_id, $class_name);\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/sqlite/sqlite_utility.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.3.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * SQLite Utility Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_sqlite_utility extends CI_DB_utility {\n\n\t/**\n\t * Export\n\t *\n\t * @param\tarray\t$params\tPreferences\n\t * @return\tmixed\n\t */\n\tprotected function _backup($params = array())\n\t{\n\t\t// Currently unsupported\n\t\treturn $this->db->display_error('db_unsupported_feature');\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/sqlite3/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/database/drivers/sqlite3/sqlite3_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * SQLite3 Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tAndrey Andreev\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_sqlite3_driver extends CI_DB {\n\n\t/**\n\t * Database driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $dbdriver = 'sqlite3';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ORDER BY random keyword\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_random_keyword = array('RANDOM()', 'RANDOM()');\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Non-persistent database connection\n\t *\n\t * @param\tbool\t$persistent\n\t * @return\tSQLite3\n\t */\n\tpublic function db_connect($persistent = FALSE)\n\t{\n\t\tif ($persistent)\n\t\t{\n\t\t\tlog_message('debug', 'SQLite3 doesn\\'t support persistent connections');\n\t\t}\n\n\t\ttry\n\t\t{\n\t\t\treturn ( ! $this->password)\n\t\t\t\t? new SQLite3($this->database)\n\t\t\t\t: new SQLite3($this->database, SQLITE3_OPEN_READWRITE | SQLITE3_OPEN_CREATE, $this->password);\n\t\t}\n\t\tcatch (Exception $e)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Database version number\n\t *\n\t * @return\tstring\n\t */\n\tpublic function version()\n\t{\n\t\tif (isset($this->data_cache['version']))\n\t\t{\n\t\t\treturn $this->data_cache['version'];\n\t\t}\n\n\t\t$version = SQLite3::version();\n\t\treturn $this->data_cache['version'] = $version['versionString'];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Execute the query\n\t *\n\t * @todo\tImplement use of SQLite3::querySingle(), if needed\n\t * @param\tstring\t$sql\n\t * @return\tmixed\tSQLite3Result object or bool\n\t */\n\tprotected function _execute($sql)\n\t{\n\t\treturn $this->is_write_type($sql)\n\t\t\t? $this->conn_id->exec($sql)\n\t\t\t: $this->conn_id->query($sql);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Begin Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_begin()\n\t{\n\t\treturn $this->conn_id->exec('BEGIN TRANSACTION');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Commit Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_commit()\n\t{\n\t\treturn $this->conn_id->exec('END TRANSACTION');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Rollback Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_rollback()\n\t{\n\t\treturn $this->conn_id->exec('ROLLBACK');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Platform-dependant string escape\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _escape_str($str)\n\t{\n\t\treturn $this->conn_id->escapeString($str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Affected Rows\n\t *\n\t * @return\tint\n\t */\n\tpublic function affected_rows()\n\t{\n\t\treturn $this->conn_id->changes();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert ID\n\t *\n\t * @return\tint\n\t */\n\tpublic function insert_id()\n\t{\n\t\treturn $this->conn_id->lastInsertRowID();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\t$prefix_limit\n\t * @return\tstring\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\treturn 'SELECT \"NAME\" FROM \"SQLITE_MASTER\" WHERE \"TYPE\" = \\'table\\''\n\t\t\t.(($prefix_limit !== FALSE && $this->dbprefix != '')\n\t\t\t\t? ' AND \"NAME\" LIKE \\''.$this->escape_like_str($this->dbprefix).'%\\' '.sprintf($this->_like_escape_str, $this->_like_escape_chr)\n\t\t\t\t: '');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch Field Names\n\t *\n\t * @param\tstring\t$table\tTable name\n\t * @return\tarray\n\t */\n\tpublic function list_fields($table)\n\t{\n\t\t// Is there a cached result?\n\t\tif (isset($this->data_cache['field_names'][$table]))\n\t\t{\n\t\t\treturn $this->data_cache['field_names'][$table];\n\t\t}\n\n\t\tif (($result = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->data_cache['field_names'][$table] = array();\n\t\tforeach ($result->result_array() as $row)\n\t\t{\n\t\t\t$this->data_cache['field_names'][$table][] = $row['name'];\n\t\t}\n\n\t\treturn $this->data_cache['field_names'][$table];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an object with field data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tarray\n\t */\n\tpublic function field_data($table)\n\t{\n\t\tif (($query = $this->query('PRAGMA TABLE_INFO('.$this->protect_identifiers($table, TRUE, NULL, FALSE).')')) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$query = $query->result_array();\n\t\tif (empty($query))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$retval = array();\n\t\tfor ($i = 0, $c = count($query); $i < $c; $i++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= $query[$i]['name'];\n\t\t\t$retval[$i]->type\t\t= $query[$i]['type'];\n\t\t\t$retval[$i]->max_length\t\t= NULL;\n\t\t\t$retval[$i]->default\t\t= $query[$i]['dflt_value'];\n\t\t\t$retval[$i]->primary_key\t= isset($query[$i]['pk']) ? (int) $query[$i]['pk'] : 0;\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Error\n\t *\n\t * Returns an array containing code and message of the last\n\t * database error that has occured.\n\t *\n\t * @return\tarray\n\t */\n\tpublic function error()\n\t{\n\t\treturn array('code' => $this->conn_id->lastErrorCode(), 'message' => $this->conn_id->lastErrorMsg());\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Replace statement\n\t *\n\t * Generates a platform-specific replace string from the supplied data\n\t *\n\t * @param\tstring\t$table\tTable name\n\t * @param\tarray\t$keys\tINSERT keys\n\t * @param\tarray\t$values\tINSERT values\n\t * @return\tstring\n\t */\n\tprotected function _replace($table, $keys, $values)\n\t{\n\t\treturn 'INSERT OR '.parent::_replace($table, $keys, $values);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Truncate statement\n\t *\n\t * Generates a platform-specific truncate string from the supplied data\n\t *\n\t * If the database does not support the TRUNCATE statement,\n\t * then this method maps to 'DELETE FROM table'\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _truncate($table)\n\t{\n\t\treturn 'DELETE FROM '.$table;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Close DB Connection\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _close()\n\t{\n\t\t$this->conn_id->close();\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/sqlite3/sqlite3_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * SQLite3 Forge Class\n *\n * @category\tDatabase\n * @author\tAndrey Andreev\n * @link\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_sqlite3_forge extends CI_DB_forge {\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tbool|array\n\t */\n\tprotected $_unsigned\t\t= FALSE;\n\n\t/**\n\t * NULL value representation in CREATE/ALTER TABLE statements\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_null\t\t= 'NULL';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tobject\t&$db\tDatabase object\n\t * @return\tvoid\n\t */\n\tpublic function __construct(&$db)\n\t{\n\t\tparent::__construct($db);\n\n\t\tif (version_compare($this->db->version(), '3.3', '<'))\n\t\t{\n\t\t\t$this->_create_table_if = FALSE;\n\t\t\t$this->_drop_table_if   = FALSE;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Create database\n\t *\n\t * @param\tstring\t$db_name\n\t * @return\tbool\n\t */\n\tpublic function create_database($db_name = '')\n\t{\n\t\t// In SQLite, a database is created when you connect to the database.\n\t\t// We'll return TRUE so that an error isn't generated\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Drop database\n\t *\n\t * @param\tstring\t$db_name\t(ignored)\n\t * @return\tbool\n\t */\n\tpublic function drop_database($db_name = '')\n\t{\n\t\t// In SQLite, a database is dropped when we delete a file\n\t\tif (file_exists($this->db->database))\n\t\t{\n\t\t\t// We need to close the pseudo-connection first\n\t\t\t$this->db->close();\n\t\t\tif ( ! @unlink($this->db->database))\n\t\t\t{\n\t\t\t\treturn $this->db->db_debug ? $this->db->display_error('db_unable_to_drop') : FALSE;\n\t\t\t}\n\t\t\telseif ( ! empty($this->db->data_cache['db_names']))\n\t\t\t{\n\t\t\t\t$key = array_search(strtolower($this->db->database), array_map('strtolower', $this->db->data_cache['db_names']), TRUE);\n\t\t\t\tif ($key !== FALSE)\n\t\t\t\t{\n\t\t\t\t\tunset($this->db->data_cache['db_names'][$key]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn $this->db->db_debug ? $this->db->display_error('db_unable_to_drop') : FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ALTER TABLE\n\t *\n\t * @todo\timplement drop_column(), modify_column()\n\t * @param\tstring\t$alter_type\tALTER type\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tmixed\t$field\t\tColumn definition\n\t * @return\tstring|string[]\n\t */\n\tprotected function _alter_table($alter_type, $table, $field)\n\t{\n\t\tif ($alter_type === 'DROP' OR $alter_type === 'CHANGE')\n\t\t{\n\t\t\t// drop_column():\n\t\t\t//\tBEGIN TRANSACTION;\n\t\t\t//\tCREATE TEMPORARY TABLE t1_backup(a,b);\n\t\t\t//\tINSERT INTO t1_backup SELECT a,b FROM t1;\n\t\t\t//\tDROP TABLE t1;\n\t\t\t//\tCREATE TABLE t1(a,b);\n\t\t\t//\tINSERT INTO t1 SELECT a,b FROM t1_backup;\n\t\t\t//\tDROP TABLE t1_backup;\n\t\t\t//\tCOMMIT;\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn parent::_alter_table($alter_type, $table, $field);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Process column\n\t *\n\t * @param\tarray\t$field\n\t * @return\tstring\n\t */\n\tprotected function _process_column($field)\n\t{\n\t\treturn $this->db->escape_identifiers($field['name'])\n\t\t\t.' '.$field['type']\n\t\t\t.$field['auto_increment']\n\t\t\t.$field['null']\n\t\t\t.$field['unique']\n\t\t\t.$field['default'];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute TYPE\n\t *\n\t * Performs a data type mapping between different databases.\n\t *\n\t * @param\tarray\t&$attributes\n\t * @return\tvoid\n\t */\n\tprotected function _attr_type(&$attributes)\n\t{\n\t\tswitch (strtoupper($attributes['TYPE']))\n\t\t{\n\t\t\tcase 'ENUM':\n\t\t\tcase 'SET':\n\t\t\t\t$attributes['TYPE'] = 'TEXT';\n\t\t\t\treturn;\n\t\t\tdefault: return;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute AUTO_INCREMENT\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_auto_increment(&$attributes, &$field)\n\t{\n\t\tif ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)\n\t\t{\n\t\t\t$field['type'] = 'INTEGER PRIMARY KEY';\n\t\t\t$field['default'] = '';\n\t\t\t$field['null'] = '';\n\t\t\t$field['unique'] = '';\n\t\t\t$field['auto_increment'] = ' AUTOINCREMENT';\n\n\t\t\t$this->primary_keys = array();\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/sqlite3/sqlite3_result.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * SQLite3 Result Class\n *\n * This class extends the parent result class: CI_DB_result\n *\n * @category\tDatabase\n * @author\t\tAndrey Andreev\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_sqlite3_result extends CI_DB_result {\n\n\t/**\n\t * Number of fields in the result set\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_fields()\n\t{\n\t\treturn $this->result_id->numColumns();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch Field Names\n\t *\n\t * Generates an array of column names\n\t *\n\t * @return\tarray\n\t */\n\tpublic function list_fields()\n\t{\n\t\t$field_names = array();\n\t\tfor ($i = 0, $c = $this->num_fields(); $i < $c; $i++)\n\t\t{\n\t\t\t$field_names[] = $this->result_id->columnName($i);\n\t\t}\n\n\t\treturn $field_names;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field data\n\t *\n\t * Generates an array of objects containing field meta-data\n\t *\n\t * @return\tarray\n\t */\n\tpublic function field_data()\n\t{\n\t\tstatic $data_types = array(\n\t\t\tSQLITE3_INTEGER\t=> 'integer',\n\t\t\tSQLITE3_FLOAT\t=> 'float',\n\t\t\tSQLITE3_TEXT\t=> 'text',\n\t\t\tSQLITE3_BLOB\t=> 'blob',\n\t\t\tSQLITE3_NULL\t=> 'null'\n\t\t);\n\n\t\t$retval = array();\n\t\tfor ($i = 0, $c = $this->num_fields(); $i < $c; $i++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= $this->result_id->columnName($i);\n\n\t\t\t$type = $this->result_id->columnType($i);\n\t\t\t$retval[$i]->type\t\t= isset($data_types[$type]) ? $data_types[$type] : $type;\n\n\t\t\t$retval[$i]->max_length\t\t= NULL;\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Free the result\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function free_result()\n\t{\n\t\tif (is_object($this->result_id))\n\t\t{\n\t\t\t$this->result_id->finalize();\n\t\t\t$this->result_id = NULL;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - associative array\n\t *\n\t * Returns the result set as an array\n\t *\n\t * @return\tarray\n\t */\n\tprotected function _fetch_assoc()\n\t{\n\t\treturn $this->result_id->fetchArray(SQLITE3_ASSOC);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - object\n\t *\n\t * Returns the result set as an object\n\t *\n\t * @param\tstring\t$class_name\n\t * @return\tobject\n\t */\n\tprotected function _fetch_object($class_name = 'stdClass')\n\t{\n\t\t// No native support for fetching rows as objects\n\t\tif (($row = $this->result_id->fetchArray(SQLITE3_ASSOC)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\telseif ($class_name === 'stdClass')\n\t\t{\n\t\t\treturn (object) $row;\n\t\t}\n\n\t\t$class_name = new $class_name();\n\t\tforeach (array_keys($row) as $key)\n\t\t{\n\t\t\t$class_name->$key = $row[$key];\n\t\t}\n\n\t\treturn $class_name;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Data Seek\n\t *\n\t * Moves the internal pointer to the desired offset. We call\n\t * this internally before fetching results to make sure the\n\t * result set starts at zero.\n\t *\n\t * @param\tint\t$n\t(ignored)\n\t * @return\tarray\n\t */\n\tpublic function data_seek($n = 0)\n\t{\n\t\t// Only resetting to the start of the result set is supported\n\t\treturn ($n > 0) ? FALSE : $this->result_id->reset();\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/sqlite3/sqlite3_utility.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * SQLite3 Utility Class\n *\n * @category\tDatabase\n * @author\tAndrey Andreev\n * @link\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_sqlite3_utility extends CI_DB_utility {\n\n\t/**\n\t * Export\n\t *\n\t * @param\tarray\t$params\tPreferences\n\t * @return\tmixed\n\t */\n\tprotected function _backup($params = array())\n\t{\n\t\t// Not supported\n\t\treturn $this->db->display_error('db_unsupported_feature');\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/sqlsrv/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/database/drivers/sqlsrv/sqlsrv_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 2.0.3\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * SQLSRV Database Adapter Class\n *\n * Note: _DB is an extender class that the app controller\n * creates dynamically based on whether the query builder\n * class is being used or not.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tDrivers\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_sqlsrv_driver extends CI_DB {\n\n\t/**\n\t * Database driver\n\t *\n\t * @var\tstring\n\t */\n\tpublic $dbdriver = 'sqlsrv';\n\n\t/**\n\t * Scrollable flag\n\t *\n\t * Determines what cursor type to use when executing queries.\n\t *\n\t * FALSE or SQLSRV_CURSOR_FORWARD would increase performance,\n\t * but would disable num_rows() (and possibly insert_id())\n\t *\n\t * @var\tmixed\n\t */\n\tpublic $scrollable;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ORDER BY random keyword\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_random_keyword = array('NEWID()', 'RAND(%d)');\n\n\t/**\n\t * Quoted identifier flag\n\t *\n\t * Whether to use SQL-92 standard quoted identifier\n\t * (double quotes) or brackets for identifier escaping.\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_quoted_identifier = TRUE;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\tparent::__construct($params);\n\n\t\t// This is only supported as of SQLSRV 3.0\n\t\tif ($this->scrollable === NULL)\n\t\t{\n\t\t\t$this->scrollable = defined('SQLSRV_CURSOR_CLIENT_BUFFERED')\n\t\t\t\t? SQLSRV_CURSOR_CLIENT_BUFFERED\n\t\t\t\t: FALSE;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Database connection\n\t *\n\t * @param\tbool\t$pooling\n\t * @return\tresource\n\t */\n\tpublic function db_connect($pooling = FALSE)\n\t{\n\t\t$charset = in_array(strtolower($this->char_set), array('utf-8', 'utf8'), TRUE)\n\t\t\t? 'UTF-8' : SQLSRV_ENC_CHAR;\n\n\t\t$connection = array(\n\t\t\t'UID'\t\t\t=> empty($this->username) ? '' : $this->username,\n\t\t\t'PWD'\t\t\t=> empty($this->password) ? '' : $this->password,\n\t\t\t'Database'\t\t=> $this->database,\n\t\t\t'ConnectionPooling'\t=> ($pooling === TRUE) ? 1 : 0,\n\t\t\t'CharacterSet'\t\t=> $charset,\n\t\t\t'Encrypt'\t\t=> ($this->encrypt === TRUE) ? 1 : 0,\n\t\t\t'ReturnDatesAsStrings'\t=> 1\n\t\t);\n\n\t\t// If the username and password are both empty, assume this is a\n\t\t// 'Windows Authentication Mode' connection.\n\t\tif (empty($connection['UID']) && empty($connection['PWD']))\n\t\t{\n\t\t\tunset($connection['UID'], $connection['PWD']);\n\t\t}\n\n\t\tif (FALSE !== ($this->conn_id = sqlsrv_connect($this->hostname, $connection)))\n\t\t{\n\t\t\t// Determine how identifiers are escaped\n\t\t\t$query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi');\n\t\t\t$query = $query->row_array();\n\t\t\t$this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi'];\n\t\t\t$this->_escape_char = ($this->_quoted_identifier) ? '\"' : array('[', ']');\n\t\t}\n\n\t\treturn $this->conn_id;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Select the database\n\t *\n\t * @param\tstring\t$database\n\t * @return\tbool\n\t */\n\tpublic function db_select($database = '')\n\t{\n\t\tif ($database === '')\n\t\t{\n\t\t\t$database = $this->database;\n\t\t}\n\n\t\tif ($this->_execute('USE '.$this->escape_identifiers($database)))\n\t\t{\n\t\t\t$this->database = $database;\n\t\t\t$this->data_cache = array();\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Execute the query\n\t *\n\t * @param\tstring\t$sql\tan SQL query\n\t * @return\tresource\n\t */\n\tprotected function _execute($sql)\n\t{\n\t\treturn ($this->scrollable === FALSE OR $this->is_write_type($sql))\n\t\t\t? sqlsrv_query($this->conn_id, $sql)\n\t\t\t: sqlsrv_query($this->conn_id, $sql, NULL, array('Scrollable' => $this->scrollable));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Begin Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_begin()\n\t{\n\t\treturn sqlsrv_begin_transaction($this->conn_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Commit Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_commit()\n\t{\n\t\treturn sqlsrv_commit($this->conn_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Rollback Transaction\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _trans_rollback()\n\t{\n\t\treturn sqlsrv_rollback($this->conn_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Affected Rows\n\t *\n\t * @return\tint\n\t */\n\tpublic function affected_rows()\n\t{\n\t\treturn sqlsrv_rows_affected($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert ID\n\t *\n\t * Returns the last id created in the Identity column.\n\t *\n\t * @return\tstring\n\t */\n\tpublic function insert_id()\n\t{\n\t\treturn $this->query('SELECT SCOPE_IDENTITY() AS insert_id')->row()->insert_id;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Database version number\n\t *\n\t * @return\tstring\n\t */\n\tpublic function version()\n\t{\n\t\tif (isset($this->data_cache['version']))\n\t\t{\n\t\t\treturn $this->data_cache['version'];\n\t\t}\n\n\t\tif ( ! $this->conn_id OR ($info = sqlsrv_server_info($this->conn_id)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn $this->data_cache['version'] = $info['SQLServerVersion'];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * List table query\n\t *\n\t * Generates a platform-specific query string so that the table names can be fetched\n\t *\n\t * @param\tbool\n\t * @return\tstring\t$prefix_limit\n\t */\n\tprotected function _list_tables($prefix_limit = FALSE)\n\t{\n\t\t$sql = 'SELECT '.$this->escape_identifiers('name')\n\t\t\t.' FROM '.$this->escape_identifiers('sysobjects')\n\t\t\t.' WHERE '.$this->escape_identifiers('type').\" = 'U'\";\n\n\t\tif ($prefix_limit === TRUE && $this->dbprefix !== '')\n\t\t{\n\t\t\t$sql .= ' AND '.$this->escape_identifiers('name').\" LIKE '\".$this->escape_like_str($this->dbprefix).\"%' \"\n\t\t\t\t.sprintf($this->_escape_like_str, $this->_escape_like_chr);\n\t\t}\n\n\t\treturn $sql.' ORDER BY '.$this->escape_identifiers('name');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * List column query\n\t *\n\t * Generates a platform-specific query string so that the column names can be fetched\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _list_columns($table = '')\n\t{\n\t\treturn 'SELECT COLUMN_NAME\n\t\t\tFROM INFORMATION_SCHEMA.Columns\n\t\t\tWHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns an object with field data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tarray\n\t */\n\tpublic function field_data($table)\n\t{\n\t\t$sql = 'SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, COLUMN_DEFAULT\n\t\t\tFROM INFORMATION_SCHEMA.Columns\n\t\t\tWHERE UPPER(TABLE_NAME) = '.$this->escape(strtoupper($table));\n\n\t\tif (($query = $this->query($sql)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\t$query = $query->result_object();\n\n\t\t$retval = array();\n\t\tfor ($i = 0, $c = count($query); $i < $c; $i++)\n\t\t{\n\t\t\t$retval[$i]\t\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t\t= $query[$i]->COLUMN_NAME;\n\t\t\t$retval[$i]->type\t\t= $query[$i]->DATA_TYPE;\n\t\t\t$retval[$i]->max_length\t\t= ($query[$i]->CHARACTER_MAXIMUM_LENGTH > 0) ? $query[$i]->CHARACTER_MAXIMUM_LENGTH : $query[$i]->NUMERIC_PRECISION;\n\t\t\t$retval[$i]->default\t\t= $query[$i]->COLUMN_DEFAULT;\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Error\n\t *\n\t * Returns an array containing code and message of the last\n\t * database error that has occured.\n\t *\n\t * @return\tarray\n\t */\n\tpublic function error()\n\t{\n\t\t$error = array('code' => '00000', 'message' => '');\n\t\t$sqlsrv_errors = sqlsrv_errors(SQLSRV_ERR_ERRORS);\n\n\t\tif ( ! is_array($sqlsrv_errors))\n\t\t{\n\t\t\treturn $error;\n\t\t}\n\n\t\t$sqlsrv_error = array_shift($sqlsrv_errors);\n\t\tif (isset($sqlsrv_error['SQLSTATE']))\n\t\t{\n\t\t\t$error['code'] = isset($sqlsrv_error['code']) ? $sqlsrv_error['SQLSTATE'].'/'.$sqlsrv_error['code'] : $sqlsrv_error['SQLSTATE'];\n\t\t}\n\t\telseif (isset($sqlsrv_error['code']))\n\t\t{\n\t\t\t$error['code'] = $sqlsrv_error['code'];\n\t\t}\n\n\t\tif (isset($sqlsrv_error['message']))\n\t\t{\n\t\t\t$error['message'] = $sqlsrv_error['message'];\n\t\t}\n\n\t\treturn $error;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update statement\n\t *\n\t * Generates a platform-specific update string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @param\tarray\t$values\n\t * @return\tstring\n\t */\n\tprotected function _update($table, $values)\n\t{\n\t\t$this->qb_limit = FALSE;\n\t\t$this->qb_orderby = array();\n\t\treturn parent::_update($table, $values);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Truncate statement\n\t *\n\t * Generates a platform-specific truncate string from the supplied data\n\t *\n\t * If the database does not support the TRUNCATE statement,\n\t * then this method maps to 'DELETE FROM table'\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _truncate($table)\n\t{\n\t\treturn 'TRUNCATE TABLE '.$table;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Delete statement\n\t *\n\t * Generates a platform-specific delete string from the supplied data\n\t *\n\t * @param\tstring\t$table\n\t * @return\tstring\n\t */\n\tprotected function _delete($table)\n\t{\n\t\tif ($this->qb_limit)\n\t\t{\n\t\t\treturn 'WITH ci_delete AS (SELECT TOP '.$this->qb_limit.' * FROM '.$table.$this->_compile_wh('qb_where').') DELETE FROM ci_delete';\n\t\t}\n\n\t\treturn parent::_delete($table);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * LIMIT\n\t *\n\t * Generates a platform-specific LIMIT clause\n\t *\n\t * @param\tstring\t$sql\tSQL Query\n\t * @return\tstring\n\t */\n\tprotected function _limit($sql)\n\t{\n\t\t// As of SQL Server 2012 (11.0.*) OFFSET is supported\n\t\tif (version_compare($this->version(), '11', '>='))\n\t\t{\n\t\t\t// SQL Server OFFSET-FETCH can be used only with the ORDER BY clause\n\t\t\tempty($this->qb_orderby) && $sql .= ' ORDER BY 1';\n\n\t\t\treturn $sql.' OFFSET '.(int) $this->qb_offset.' ROWS FETCH NEXT '.$this->qb_limit.' ROWS ONLY';\n\t\t}\n\n\t\t$limit = $this->qb_offset + $this->qb_limit;\n\n\t\t// An ORDER BY clause is required for ROW_NUMBER() to work\n\t\tif ($this->qb_offset && ! empty($this->qb_orderby))\n\t\t{\n\t\t\t$orderby = $this->_compile_order_by();\n\n\t\t\t// We have to strip the ORDER BY clause\n\t\t\t$sql = trim(substr($sql, 0, strrpos($sql, $orderby)));\n\n\t\t\t// Get the fields to select from our subquery, so that we can avoid CI_rownum appearing in the actual results\n\t\t\tif (count($this->qb_select) === 0)\n\t\t\t{\n\t\t\t\t$select = '*'; // Inevitable\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Use only field names and their aliases, everything else is out of our scope.\n\t\t\t\t$select = array();\n\t\t\t\t$field_regexp = ($this->_quoted_identifier)\n\t\t\t\t\t? '(\"[^\\\"]+\")' : '(\\[[^\\]]+\\])';\n\t\t\t\tfor ($i = 0, $c = count($this->qb_select); $i < $c; $i++)\n\t\t\t\t{\n\t\t\t\t\t$select[] = preg_match('/(?:\\s|\\.)'.$field_regexp.'$/i', $this->qb_select[$i], $m)\n\t\t\t\t\t\t? $m[1] : $this->qb_select[$i];\n\t\t\t\t}\n\t\t\t\t$select = implode(', ', $select);\n\t\t\t}\n\n\t\t\treturn 'SELECT '.$select.\" FROM (\\n\\n\"\n\t\t\t\t.preg_replace('/^(SELECT( DISTINCT)?)/i', '\\\\1 ROW_NUMBER() OVER('.trim($orderby).') AS '.$this->escape_identifiers('CI_rownum').', ', $sql)\n\t\t\t\t.\"\\n\\n) \".$this->escape_identifiers('CI_subquery')\n\t\t\t\t.\"\\nWHERE \".$this->escape_identifiers('CI_rownum').' BETWEEN '.($this->qb_offset + 1).' AND '.$limit;\n\t\t}\n\n\t\treturn preg_replace('/(^\\SELECT (DISTINCT)?)/i','\\\\1 TOP '.$limit.' ', $sql);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert batch statement\n\t *\n\t * Generates a platform-specific insert string from the supplied data.\n\t *\n\t * @param\tstring\t$table\tTable name\n\t * @param\tarray\t$keys\tINSERT keys\n\t * @param\tarray\t$values\tINSERT values\n\t * @return\tstring|bool\n\t */\n\tprotected function _insert_batch($table, $keys, $values)\n\t{\n\t\t// Multiple-value inserts are only supported as of SQL Server 2008\n\t\tif (version_compare($this->version(), '10', '>='))\n\t\t{\n\t\t\treturn parent::_insert_batch($table, $keys, $values);\n\t\t}\n\n\t\treturn ($this->db->db_debug) ? $this->db->display_error('db_unsupported_feature') : FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Close DB Connection\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _close()\n\t{\n\t\tsqlsrv_close($this->conn_id);\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/sqlsrv/sqlsrv_forge.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 2.0.3\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * SQLSRV Forge Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_sqlsrv_forge extends CI_DB_forge {\n\n\t/**\n\t * CREATE TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_create_table_if\t= \"IF NOT EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\\nCREATE TABLE\";\n\n\t/**\n\t * DROP TABLE IF statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_drop_table_if\t= \"IF EXISTS (SELECT * FROM sysobjects WHERE ID = object_id(N'%s') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)\\nDROP TABLE\";\n\n\t/**\n\t * UNSIGNED support\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_unsigned\t\t= array(\n\t\t'TINYINT'\t=> 'SMALLINT',\n\t\t'SMALLINT'\t=> 'INT',\n\t\t'INT'\t\t=> 'BIGINT',\n\t\t'REAL'\t\t=> 'FLOAT'\n\t);\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ALTER TABLE\n\t *\n\t * @param\tstring\t$alter_type\tALTER type\n\t * @param\tstring\t$table\t\tTable name\n\t * @param\tmixed\t$field\t\tColumn definition\n\t * @return\tstring|string[]\n\t */\n\tprotected function _alter_table($alter_type, $table, $field)\n\t{\n\t\tif (in_array($alter_type, array('ADD', 'DROP'), TRUE))\n\t\t{\n\t\t\treturn parent::_alter_table($alter_type, $table, $field);\n\t\t}\n\n\t\t$sql = 'ALTER TABLE '.$this->db->escape_identifiers($table).' ALTER COLUMN ';\n\t\t$sqls = array();\n\t\tfor ($i = 0, $c = count($field); $i < $c; $i++)\n\t\t{\n\t\t\t$sqls[] = $sql.$this->_process_column($field[$i]);\n\t\t}\n\n\t\treturn $sqls;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute TYPE\n\t *\n\t * Performs a data type mapping between different databases.\n\t *\n\t * @param\tarray\t&$attributes\n\t * @return\tvoid\n\t */\n\tprotected function _attr_type(&$attributes)\n\t{\n\t\tif (isset($attributes['CONSTRAINT']) && strpos($attributes['TYPE'], 'INT') !== FALSE)\n\t\t{\n\t\t\tunset($attributes['CONSTRAINT']);\n\t\t}\n\n\t\tswitch (strtoupper($attributes['TYPE']))\n\t\t{\n\t\t\tcase 'MEDIUMINT':\n\t\t\t\t$attributes['TYPE'] = 'INTEGER';\n\t\t\t\t$attributes['UNSIGNED'] = FALSE;\n\t\t\t\treturn;\n\t\t\tcase 'INTEGER':\n\t\t\t\t$attributes['TYPE'] = 'INT';\n\t\t\t\treturn;\n\t\t\tdefault: return;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field attribute AUTO_INCREMENT\n\t *\n\t * @param\tarray\t&$attributes\n\t * @param\tarray\t&$field\n\t * @return\tvoid\n\t */\n\tprotected function _attr_auto_increment(&$attributes, &$field)\n\t{\n\t\tif ( ! empty($attributes['AUTO_INCREMENT']) && $attributes['AUTO_INCREMENT'] === TRUE && stripos($field['type'], 'int') !== FALSE)\n\t\t{\n\t\t\t$field['auto_increment'] = ' IDENTITY(1,1)';\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/sqlsrv/sqlsrv_result.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 2.0.3\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * SQLSRV Result Class\n *\n * This class extends the parent result class: CI_DB_result\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_sqlsrv_result extends CI_DB_result {\n\n\t/**\n\t * Scrollable flag\n\t *\n\t * @var\tmixed\n\t */\n\tpublic $scrollable;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @param\tobject\t$driver_object\n\t * @return\tvoid\n\t */\n\tpublic function __construct(&$driver_object)\n\t{\n\t\tparent::__construct($driver_object);\n\n\t\t$this->scrollable = $driver_object->scrollable;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Number of rows in the result set\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_rows()\n\t{\n\t\t// sqlsrv_num_rows() doesn't work with the FORWARD and DYNAMIC cursors (FALSE is the same as FORWARD)\n\t\tif ( ! in_array($this->scrollable, array(FALSE, SQLSRV_CURSOR_FORWARD, SQLSRV_CURSOR_DYNAMIC), TRUE))\n\t\t{\n\t\t\treturn parent::num_rows();\n\t\t}\n\n\t\treturn is_int($this->num_rows)\n\t\t\t? $this->num_rows\n\t\t\t: $this->num_rows = sqlsrv_num_rows($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Number of fields in the result set\n\t *\n\t * @return\tint\n\t */\n\tpublic function num_fields()\n\t{\n\t\treturn @sqlsrv_num_fields($this->result_id);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch Field Names\n\t *\n\t * Generates an array of column names\n\t *\n\t * @return\tarray\n\t */\n\tpublic function list_fields()\n\t{\n\t\t$field_names = array();\n\t\tforeach (sqlsrv_field_metadata($this->result_id) as $offset => $field)\n\t\t{\n\t\t\t$field_names[] = $field['Name'];\n\t\t}\n\n\t\treturn $field_names;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Field data\n\t *\n\t * Generates an array of objects containing field meta-data\n\t *\n\t * @return\tarray\n\t */\n\tpublic function field_data()\n\t{\n\t\t$retval = array();\n\t\tforeach (sqlsrv_field_metadata($this->result_id) as $i => $field)\n\t\t{\n\t\t\t$retval[$i]\t\t= new stdClass();\n\t\t\t$retval[$i]->name\t= $field['Name'];\n\t\t\t$retval[$i]->type\t= $field['Type'];\n\t\t\t$retval[$i]->max_length\t= $field['Size'];\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Free the result\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function free_result()\n\t{\n\t\tif (is_resource($this->result_id))\n\t\t{\n\t\t\tsqlsrv_free_stmt($this->result_id);\n\t\t\t$this->result_id = FALSE;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - associative array\n\t *\n\t * Returns the result set as an array\n\t *\n\t * @return\tarray\n\t */\n\tprotected function _fetch_assoc()\n\t{\n\t\treturn sqlsrv_fetch_array($this->result_id, SQLSRV_FETCH_ASSOC);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result - object\n\t *\n\t * Returns the result set as an object\n\t *\n\t * @param\tstring\t$class_name\n\t * @return\tobject\n\t */\n\tprotected function _fetch_object($class_name = 'stdClass')\n\t{\n\t\treturn sqlsrv_fetch_object($this->result_id, $class_name);\n\t}\n\n}\n"
  },
  {
    "path": "system/database/drivers/sqlsrv/sqlsrv_utility.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 2.0.3\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * SQLSRV Utility Class\n *\n * @category\tDatabase\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/database/\n */\nclass CI_DB_sqlsrv_utility extends CI_DB_utility {\n\n\t/**\n\t * List databases statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_list_databases\t= 'EXEC sp_helpdb'; // Can also be: EXEC sp_databases\n\n\t/**\n\t * OPTIMIZE TABLE statement\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_optimize_table\t= 'ALTER INDEX all ON %s REORGANIZE';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Export\n\t *\n\t * @param\tarray\t$params\tPreferences\n\t * @return\tbool\n\t */\n\tprotected function _backup($params = array())\n\t{\n\t\t// Currently unsupported\n\t\treturn $this->db->display_error('db_unsupported_feature');\n\t}\n\n}\n"
  },
  {
    "path": "system/database/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/fonts/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/helpers/array_helper.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Array Helpers\n *\n * @package\t\tCodeIgniter\n * @subpackage\tHelpers\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/helpers/array_helper.html\n */\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('element'))\n{\n\t/**\n\t * Element\n\t *\n\t * Lets you determine whether an array index is set and whether it has a value.\n\t * If the element is empty it returns NULL (or whatever you specify as the default value.)\n\t *\n\t * @param\tstring\n\t * @param\tarray\n\t * @param\tmixed\n\t * @return\tmixed\tdepends on what the array contains\n\t */\n\tfunction element($item, array $array, $default = NULL)\n\t{\n\t\treturn array_key_exists($item, $array) ? $array[$item] : $default;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('random_element'))\n{\n\t/**\n\t * Random Element - Takes an array as input and returns a random element\n\t *\n\t * @param\tarray\n\t * @return\tmixed\tdepends on what the array contains\n\t */\n\tfunction random_element($array)\n\t{\n\t\treturn is_array($array) ? $array[array_rand($array)] : $array;\n\t}\n}\n\n// --------------------------------------------------------------------\n\nif ( ! function_exists('elements'))\n{\n\t/**\n\t * Elements\n\t *\n\t * Returns only the array items specified. Will return a default value if\n\t * it is not set.\n\t *\n\t * @param\tarray\n\t * @param\tarray\n\t * @param\tmixed\n\t * @return\tmixed\tdepends on what the array contains\n\t */\n\tfunction elements($items, array $array, $default = NULL)\n\t{\n\t\t$return = array();\n\n\t\tis_array($items) OR $items = array($items);\n\n\t\tforeach ($items as $item)\n\t\t{\n\t\t\t$return[$item] = array_key_exists($item, $array) ? $array[$item] : $default;\n\t\t}\n\n\t\treturn $return;\n\t}\n}\n"
  },
  {
    "path": "system/helpers/captcha_helper.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter CAPTCHA Helper\n *\n * @package\t\tCodeIgniter\n * @subpackage\tHelpers\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/helpers/captcha_helper.html\n */\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('create_captcha'))\n{\n\t/**\n\t * Create CAPTCHA\n\t *\n\t * @param\tarray\t$data\t\tdata for the CAPTCHA\n\t * @param\tstring\t$img_path\tpath to create the image in\n\t * @param\tstring\t$img_url\tURL to the CAPTCHA image folder\n\t * @param\tstring\t$font_path\tserver path to font\n\t * @return\tstring\n\t */\n\tfunction create_captcha($data = '', $img_path = '', $img_url = '', $font_path = '')\n\t{\n\t\t$defaults = array(\n\t\t\t'word'\t\t=> '',\n\t\t\t'img_path'\t=> '',\n\t\t\t'img_url'\t=> '',\n\t\t\t'img_width'\t=> '150',\n\t\t\t'img_height'\t=> '30',\n\t\t\t'font_path'\t=> '',\n\t\t\t'expiration'\t=> 7200,\n\t\t\t'word_length'\t=> 8,\n\t\t\t'font_size'\t=> 16,\n\t\t\t'img_id'\t=> '',\n\t\t\t'pool'\t\t=> '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',\n\t\t\t'colors'\t=> array(\n\t\t\t\t'background'\t=> array(255,255,255),\n\t\t\t\t'border'\t=> array(153,102,102),\n\t\t\t\t'text'\t\t=> array(204,153,153),\n\t\t\t\t'grid'\t\t=> array(255,182,182)\n\t\t\t)\n\t\t);\n\n\t\tforeach ($defaults as $key => $val)\n\t\t{\n\t\t\tif ( ! is_array($data) && empty($$key))\n\t\t\t{\n\t\t\t\t$$key = $val;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$$key = isset($data[$key]) ? $data[$key] : $val;\n\t\t\t}\n\t\t}\n\n\t\tif ($img_path === '' OR $img_url === ''\n\t\t\tOR ! is_dir($img_path) OR ! is_really_writable($img_path)\n\t\t\tOR ! extension_loaded('gd'))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// -----------------------------------\n\t\t// Remove old images\n\t\t// -----------------------------------\n\n\t\t$now = microtime(TRUE);\n\n\t\t$current_dir = @opendir($img_path);\n\t\twhile ($filename = @readdir($current_dir))\n\t\t{\n\t\t\tif (substr($filename, -4) === '.jpg' && (str_replace('.jpg', '', $filename) + $expiration) < $now)\n\t\t\t{\n\t\t\t\t@unlink($img_path.$filename);\n\t\t\t}\n\t\t}\n\n\t\t@closedir($current_dir);\n\n\t\t// -----------------------------------\n\t\t// Do we have a \"word\" yet?\n\t\t// -----------------------------------\n\n\t\tif (empty($word))\n\t\t{\n\t\t\t$word = '';\n\t\t\t$pool_length = strlen($pool);\n\t\t\t$rand_max = $pool_length - 1;\n\n\t\t\t// PHP7 or a suitable polyfill\n\t\t\tif (function_exists('random_int'))\n\t\t\t{\n\t\t\t\ttry\n\t\t\t\t{\n\t\t\t\t\tfor ($i = 0; $i < $word_length; $i++)\n\t\t\t\t\t{\n\t\t\t\t\t\t$word .= $pool[random_int(0, $rand_max)];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcatch (Exception $e)\n\t\t\t\t{\n\t\t\t\t\t// This means fallback to the next possible\n\t\t\t\t\t// alternative to random_int()\n\t\t\t\t\t$word = '';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (empty($word))\n\t\t{\n\t\t\t// Nobody will have a larger character pool than\n\t\t\t// 256 characters, but let's handle it just in case ...\n\t\t\t//\n\t\t\t// No, I do not care that the fallback to mt_rand() can\n\t\t\t// handle it; if you trigger this, you're very obviously\n\t\t\t// trying to break it. -- Narf\n\t\t\tif ($pool_length > 256)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t// We'll try using the operating system's PRNG first,\n\t\t\t// which we can access through CI_Security::get_random_bytes()\n\t\t\t$security = get_instance()->security;\n\n\t\t\t// To avoid numerous get_random_bytes() calls, we'll\n\t\t\t// just try fetching as much bytes as we need at once.\n\t\t\tif (($bytes = $security->get_random_bytes($pool_length)) !== FALSE)\n\t\t\t{\n\t\t\t\t$byte_index = $word_index = 0;\n\t\t\t\twhile ($word_index < $word_length)\n\t\t\t\t{\n\t\t\t\t\t// Do we have more random data to use?\n\t\t\t\t\t// It could be exhausted by previous iterations\n\t\t\t\t\t// ignoring bytes higher than $rand_max.\n\t\t\t\t\tif ($byte_index === $pool_length)\n\t\t\t\t\t{\n\t\t\t\t\t\t// No failures should be possible if the\n\t\t\t\t\t\t// first get_random_bytes() call didn't\n\t\t\t\t\t\t// return FALSE, but still ...\n\t\t\t\t\t\tfor ($i = 0; $i < 5; $i++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (($bytes = $security->get_random_bytes($pool_length)) === FALSE)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t$byte_index = 0;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif ($bytes === FALSE)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// Sadly, this means fallback to mt_rand()\n\t\t\t\t\t\t\t$word = '';\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tlist(, $rand_index) = unpack('C', $bytes[$byte_index++]);\n\t\t\t\t\tif ($rand_index > $rand_max)\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t$word .= $pool[$rand_index];\n\t\t\t\t\t$word_index++;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (empty($word))\n\t\t{\n\t\t\tfor ($i = 0; $i < $word_length; $i++)\n\t\t\t{\n\t\t\t\t$word .= $pool[mt_rand(0, $rand_max)];\n\t\t\t}\n\t\t}\n\t\telseif ( ! is_string($word))\n\t\t{\n\t\t\t$word = (string) $word;\n\t\t}\n\n\t\t// -----------------------------------\n\t\t// Determine angle and position\n\t\t// -----------------------------------\n\t\t$length\t= strlen($word);\n\t\t$angle\t= ($length >= 6) ? mt_rand(-($length-6), ($length-6)) : 0;\n\t\t$x_axis\t= mt_rand(6, (360/$length)-16);\n\t\t$y_axis = ($angle >= 0) ? mt_rand($img_height, $img_width) : mt_rand(6, $img_height);\n\n\t\t// Create image\n\t\t// PHP.net recommends imagecreatetruecolor(), but it isn't always available\n\t\t$im = function_exists('imagecreatetruecolor')\n\t\t\t? imagecreatetruecolor($img_width, $img_height)\n\t\t\t: imagecreate($img_width, $img_height);\n\n\t\t// -----------------------------------\n\t\t//  Assign colors\n\t\t// ----------------------------------\n\n\t\tis_array($colors) OR $colors = $defaults['colors'];\n\n\t\tforeach (array_keys($defaults['colors']) as $key)\n\t\t{\n\t\t\t// Check for a possible missing value\n\t\t\tis_array($colors[$key]) OR $colors[$key] = $defaults['colors'][$key];\n\t\t\t$colors[$key] = imagecolorallocate($im, $colors[$key][0], $colors[$key][1], $colors[$key][2]);\n\t\t}\n\n\t\t// Create the rectangle\n\t\tImageFilledRectangle($im, 0, 0, $img_width, $img_height, $colors['background']);\n\n\t\t// -----------------------------------\n\t\t//  Create the spiral pattern\n\t\t// -----------------------------------\n\t\t$theta\t\t= 1;\n\t\t$thetac\t\t= 7;\n\t\t$radius\t\t= 16;\n\t\t$circles\t= 20;\n\t\t$points\t\t= 32;\n\n\t\tfor ($i = 0, $cp = ($circles * $points) - 1; $i < $cp; $i++)\n\t\t{\n\t\t\t$theta += $thetac;\n\t\t\t$rad = $radius * ($i / $points);\n\t\t\t$x = ($rad * cos($theta)) + $x_axis;\n\t\t\t$y = ($rad * sin($theta)) + $y_axis;\n\t\t\t$theta += $thetac;\n\t\t\t$rad1 = $radius * (($i + 1) / $points);\n\t\t\t$x1 = ($rad1 * cos($theta)) + $x_axis;\n\t\t\t$y1 = ($rad1 * sin($theta)) + $y_axis;\n\t\t\timageline($im, $x, $y, $x1, $y1, $colors['grid']);\n\t\t\t$theta -= $thetac;\n\t\t}\n\n\t\t// -----------------------------------\n\t\t//  Write the text\n\t\t// -----------------------------------\n\n\t\t$use_font = ($font_path !== '' && file_exists($font_path) && function_exists('imagettftext'));\n\t\tif ($use_font === FALSE)\n\t\t{\n\t\t\t($font_size > 5) && $font_size = 5;\n\t\t\t$x = mt_rand(0, $img_width / ($length / 3));\n\t\t\t$y = 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t($font_size > 30) && $font_size = 30;\n\t\t\t$x = mt_rand(0, $img_width / ($length / 1.5));\n\t\t\t$y = $font_size + 2;\n\t\t}\n\n\t\tfor ($i = 0; $i < $length; $i++)\n\t\t{\n\t\t\tif ($use_font === FALSE)\n\t\t\t{\n\t\t\t\t$y = mt_rand(0 , $img_height / 2);\n\t\t\t\timagestring($im, $font_size, $x, $y, $word[$i], $colors['text']);\n\t\t\t\t$x += ($font_size * 2);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$y = mt_rand($img_height / 2, $img_height - 3);\n\t\t\t\timagettftext($im, $font_size, $angle, $x, $y, $colors['text'], $font_path, $word[$i]);\n\t\t\t\t$x += $font_size;\n\t\t\t}\n\t\t}\n\n\t\t// Create the border\n\t\timagerectangle($im, 0, 0, $img_width - 1, $img_height - 1, $colors['border']);\n\n\t\t// -----------------------------------\n\t\t//  Generate the image\n\t\t// -----------------------------------\n\t\t$img_url = rtrim($img_url, '/').'/';\n\n\t\tif (function_exists('imagejpeg'))\n\t\t{\n\t\t\t$img_filename = $now.'.jpg';\n\t\t\timagejpeg($im, $img_path.$img_filename);\n\t\t}\n\t\telseif (function_exists('imagepng'))\n\t\t{\n\t\t\t$img_filename = $now.'.png';\n\t\t\timagepng($im, $img_path.$img_filename);\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$img = '<img '.($img_id === '' ? '' : 'id=\"'.$img_id.'\"').' src=\"'.$img_url.$img_filename.'\" style=\"width: '.$img_width.'; height: '.$img_height .'; border: 0;\" alt=\" \" />';\n\t\tImageDestroy($im);\n\n\t\treturn array('word' => $word, 'time' => $now, 'image' => $img, 'filename' => $img_filename);\n\t}\n}\n"
  },
  {
    "path": "system/helpers/cookie_helper.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Cookie Helpers\n *\n * @package\t\tCodeIgniter\n * @subpackage\tHelpers\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/helpers/cookie_helper.html\n */\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('set_cookie'))\n{\n\t/**\n\t * Set cookie\n\t *\n\t * Accepts seven parameters, or you can submit an associative\n\t * array in the first parameter containing all the values.\n\t *\n\t * @param\tmixed\n\t * @param\tstring\tthe value of the cookie\n\t * @param\tstring\tthe number of seconds until expiration\n\t * @param\tstring\tthe cookie domain.  Usually:  .yourdomain.com\n\t * @param\tstring\tthe cookie path\n\t * @param\tstring\tthe cookie prefix\n\t * @param\tbool\ttrue makes the cookie secure\n\t * @param\tbool\ttrue makes the cookie accessible via http(s) only (no javascript)\n\t * @return\tvoid\n\t */\n\tfunction set_cookie($name, $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = FALSE, $httponly = FALSE)\n\t{\n\t\t// Set the config file options\n\t\tget_instance()->input->set_cookie($name, $value, $expire, $domain, $path, $prefix, $secure, $httponly);\n\t}\n}\n\n// --------------------------------------------------------------------\n\nif ( ! function_exists('get_cookie'))\n{\n\t/**\n\t * Fetch an item from the COOKIE array\n\t *\n\t * @param\tstring\n\t * @param\tbool\n\t * @return\tmixed\n\t */\n\tfunction get_cookie($index, $xss_clean = NULL)\n\t{\n\t\tis_bool($xss_clean) OR $xss_clean = (config_item('global_xss_filtering') === TRUE);\n\t\t$prefix = isset($_COOKIE[$index]) ? '' : config_item('cookie_prefix');\n\t\treturn get_instance()->input->cookie($prefix.$index, $xss_clean);\n\t}\n}\n\n// --------------------------------------------------------------------\n\nif ( ! function_exists('delete_cookie'))\n{\n\t/**\n\t * Delete a COOKIE\n\t *\n\t * @param\tmixed\n\t * @param\tstring\tthe cookie domain. Usually: .yourdomain.com\n\t * @param\tstring\tthe cookie path\n\t * @param\tstring\tthe cookie prefix\n\t * @return\tvoid\n\t */\n\tfunction delete_cookie($name, $domain = '', $path = '/', $prefix = '')\n\t{\n\t\tset_cookie($name, '', '', $domain, $path, $prefix);\n\t}\n}\n"
  },
  {
    "path": "system/helpers/date_helper.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Date Helpers\n *\n * @package\t\tCodeIgniter\n * @subpackage\tHelpers\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/helpers/date_helper.html\n */\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('now'))\n{\n\t/**\n\t * Get \"now\" time\n\t *\n\t * Returns time() based on the timezone parameter or on the\n\t * \"time_reference\" setting\n\t *\n\t * @param\tstring\n\t * @return\tint\n\t */\n\tfunction now($timezone = NULL)\n\t{\n\t\tif (empty($timezone))\n\t\t{\n\t\t\t$timezone = config_item('time_reference');\n\t\t}\n\n\t\tif ($timezone === 'local' OR $timezone === date_default_timezone_get())\n\t\t{\n\t\t\treturn time();\n\t\t}\n\n\t\t$datetime = new DateTime('now', new DateTimeZone($timezone));\n\t\tsscanf($datetime->format('j-n-Y G:i:s'), '%d-%d-%d %d:%d:%d', $day, $month, $year, $hour, $minute, $second);\n\n\t\treturn mktime($hour, $minute, $second, $month, $day, $year);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('mdate'))\n{\n\t/**\n\t * Convert MySQL Style Datecodes\n\t *\n\t * This function is identical to PHPs date() function,\n\t * except that it allows date codes to be formatted using\n\t * the MySQL style, where each code letter is preceded\n\t * with a percent sign:  %Y %m %d etc...\n\t *\n\t * The benefit of doing dates this way is that you don't\n\t * have to worry about escaping your text letters that\n\t * match the date codes.\n\t *\n\t * @param\tstring\n\t * @param\tint\n\t * @return\tint\n\t */\n\tfunction mdate($datestr = '', $time = '')\n\t{\n\t\tif ($datestr === '')\n\t\t{\n\t\t\treturn '';\n\t\t}\n\t\telseif (empty($time))\n\t\t{\n\t\t\t$time = now();\n\t\t}\n\n\t\t$datestr = str_replace(\n\t\t\t'%\\\\',\n\t\t\t'',\n\t\t\tpreg_replace('/([a-z]+?){1}/i', '\\\\\\\\\\\\1', $datestr)\n\t\t);\n\n\t\treturn date($datestr, $time);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('standard_date'))\n{\n\t/**\n\t * Standard Date\n\t *\n\t * Returns a date formatted according to the submitted standard.\n\t *\n\t * As of PHP 5.2, the DateTime extension provides constants that\n\t * serve for the exact same purpose and are used with date().\n\t *\n\t * @todo\tRemove in version 3.1+.\n\t * @deprecated\t3.0.0\tUse PHP's native date() instead.\n\t * @link\thttp://www.php.net/manual/en/class.datetime.php#datetime.constants.types\n\t *\n\t * @example\tdate(DATE_RFC822, now()); // default\n\t * @example\tdate(DATE_W3C, $time); // a different format and time\n\t *\n\t * @param\tstring\t$fmt = 'DATE_RFC822'\tthe chosen format\n\t * @param\tint\t$time = NULL\t\tUnix timestamp\n\t * @return\tstring\n\t */\n\tfunction standard_date($fmt = 'DATE_RFC822', $time = NULL)\n\t{\n\t\tif (empty($time))\n\t\t{\n\t\t\t$time = now();\n\t\t}\n\n\t\t// Procedural style pre-defined constants from the DateTime extension\n\t\tif (strpos($fmt, 'DATE_') !== 0 OR defined($fmt) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn date(constant($fmt), $time);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('timespan'))\n{\n\t/**\n\t * Timespan\n\t *\n\t * Returns a span of seconds in this format:\n\t *\t10 days 14 hours 36 minutes 47 seconds\n\t *\n\t * @param\tint\ta number of seconds\n\t * @param\tint\tUnix timestamp\n\t * @param\tint\ta number of display units\n\t * @return\tstring\n\t */\n\tfunction timespan($seconds = 1, $time = '', $units = 7)\n\t{\n\t\t$CI =& get_instance();\n\t\t$CI->lang->load('date');\n\n\t\tis_numeric($seconds) OR $seconds = 1;\n\t\tis_numeric($time) OR $time = time();\n\t\tis_numeric($units) OR $units = 7;\n\n\t\t$seconds = ($time <= $seconds) ? 1 : $time - $seconds;\n\n\t\t$str = array();\n\t\t$years = floor($seconds / 31557600);\n\n\t\tif ($years > 0)\n\t\t{\n\t\t\t$str[] = $years.' '.$CI->lang->line($years > 1 ? 'date_years' : 'date_year');\n\t\t}\n\n\t\t$seconds -= $years * 31557600;\n\t\t$months = floor($seconds / 2629743);\n\n\t\tif (count($str) < $units && ($years > 0 OR $months > 0))\n\t\t{\n\t\t\tif ($months > 0)\n\t\t\t{\n\t\t\t\t$str[] = $months.' '.$CI->lang->line($months > 1 ? 'date_months' : 'date_month');\n\t\t\t}\n\n\t\t\t$seconds -= $months * 2629743;\n\t\t}\n\n\t\t$weeks = floor($seconds / 604800);\n\n\t\tif (count($str) < $units && ($years > 0 OR $months > 0 OR $weeks > 0))\n\t\t{\n\t\t\tif ($weeks > 0)\n\t\t\t{\n\t\t\t\t$str[] = $weeks.' '.$CI->lang->line($weeks > 1 ? 'date_weeks' : 'date_week');\n\t\t\t}\n\n\t\t\t$seconds -= $weeks * 604800;\n\t\t}\n\n\t\t$days = floor($seconds / 86400);\n\n\t\tif (count($str) < $units && ($months > 0 OR $weeks > 0 OR $days > 0))\n\t\t{\n\t\t\tif ($days > 0)\n\t\t\t{\n\t\t\t\t$str[] = $days.' '.$CI->lang->line($days > 1 ? 'date_days' : 'date_day');\n\t\t\t}\n\n\t\t\t$seconds -= $days * 86400;\n\t\t}\n\n\t\t$hours = floor($seconds / 3600);\n\n\t\tif (count($str) < $units && ($days > 0 OR $hours > 0))\n\t\t{\n\t\t\tif ($hours > 0)\n\t\t\t{\n\t\t\t\t$str[] = $hours.' '.$CI->lang->line($hours > 1 ? 'date_hours' : 'date_hour');\n\t\t\t}\n\n\t\t\t$seconds -= $hours * 3600;\n\t\t}\n\n\t\t$minutes = floor($seconds / 60);\n\n\t\tif (count($str) < $units && ($days > 0 OR $hours > 0 OR $minutes > 0))\n\t\t{\n\t\t\tif ($minutes > 0)\n\t\t\t{\n\t\t\t\t$str[] = $minutes.' '.$CI->lang->line($minutes > 1 ? 'date_minutes' : 'date_minute');\n\t\t\t}\n\n\t\t\t$seconds -= $minutes * 60;\n\t\t}\n\n\t\tif (count($str) === 0)\n\t\t{\n\t\t\t$str[] = $seconds.' '.$CI->lang->line($seconds > 1 ? 'date_seconds' : 'date_second');\n\t\t}\n\n\t\treturn implode(', ', $str);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('days_in_month'))\n{\n\t/**\n\t * Number of days in a month\n\t *\n\t * Takes a month/year as input and returns the number of days\n\t * for the given month/year. Takes leap years into consideration.\n\t *\n\t * @param\tint\ta numeric month\n\t * @param\tint\ta numeric year\n\t * @return\tint\n\t */\n\tfunction days_in_month($month = 0, $year = '')\n\t{\n\t\tif ($month < 1 OR $month > 12)\n\t\t{\n\t\t\treturn 0;\n\t\t}\n\t\telseif ( ! is_numeric($year) OR strlen($year) !== 4)\n\t\t{\n\t\t\t$year = date('Y');\n\t\t}\n\n\t\tif (defined('CAL_GREGORIAN'))\n\t\t{\n\t\t\treturn cal_days_in_month(CAL_GREGORIAN, $month, $year);\n\t\t}\n\n\t\tif ($year >= 1970)\n\t\t{\n\t\t\treturn (int) date('t', mktime(12, 0, 0, $month, 1, $year));\n\t\t}\n\n\t\tif ($month == 2)\n\t\t{\n\t\t\tif ($year % 400 === 0 OR ($year % 4 === 0 && $year % 100 !== 0))\n\t\t\t{\n\t\t\t\treturn 29;\n\t\t\t}\n\t\t}\n\n\t\t$days_in_month\t= array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);\n\t\treturn $days_in_month[$month - 1];\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('local_to_gmt'))\n{\n\t/**\n\t * Converts a local Unix timestamp to GMT\n\t *\n\t * @param\tint\tUnix timestamp\n\t * @return\tint\n\t */\n\tfunction local_to_gmt($time = '')\n\t{\n\t\tif ($time === '')\n\t\t{\n\t\t\t$time = time();\n\t\t}\n\n\t\treturn mktime(\n\t\t\tgmdate('G', $time),\n\t\t\tgmdate('i', $time),\n\t\t\tgmdate('s', $time),\n\t\t\tgmdate('n', $time),\n\t\t\tgmdate('j', $time),\n\t\t\tgmdate('Y', $time)\n\t\t);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('gmt_to_local'))\n{\n\t/**\n\t * Converts GMT time to a localized value\n\t *\n\t * Takes a Unix timestamp (in GMT) as input, and returns\n\t * at the local value based on the timezone and DST setting\n\t * submitted\n\t *\n\t * @param\tint\tUnix timestamp\n\t * @param\tstring\ttimezone\n\t * @param\tbool\twhether DST is active\n\t * @return\tint\n\t */\n\tfunction gmt_to_local($time = '', $timezone = 'UTC', $dst = FALSE)\n\t{\n\t\tif ($time === '')\n\t\t{\n\t\t\treturn now();\n\t\t}\n\n\t\t$time += timezones($timezone) * 3600;\n\n\t\treturn ($dst === TRUE) ? $time + 3600 : $time;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('mysql_to_unix'))\n{\n\t/**\n\t * Converts a MySQL Timestamp to Unix\n\t *\n\t * @param\tint\tMySQL timestamp YYYY-MM-DD HH:MM:SS\n\t * @return\tint\tUnix timstamp\n\t */\n\tfunction mysql_to_unix($time = '')\n\t{\n\t\t// We'll remove certain characters for backward compatibility\n\t\t// since the formatting changed with MySQL 4.1\n\t\t// YYYY-MM-DD HH:MM:SS\n\n\t\t$time = str_replace(array('-', ':', ' '), '', $time);\n\n\t\t// YYYYMMDDHHMMSS\n\t\treturn mktime(\n\t\t\tsubstr($time, 8, 2),\n\t\t\tsubstr($time, 10, 2),\n\t\t\tsubstr($time, 12, 2),\n\t\t\tsubstr($time, 4, 2),\n\t\t\tsubstr($time, 6, 2),\n\t\t\tsubstr($time, 0, 4)\n\t\t);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('unix_to_human'))\n{\n\t/**\n\t * Unix to \"Human\"\n\t *\n\t * Formats Unix timestamp to the following prototype: 2006-08-21 11:35 PM\n\t *\n\t * @param\tint\tUnix timestamp\n\t * @param\tbool\twhether to show seconds\n\t * @param\tstring\tformat: us or euro\n\t * @return\tstring\n\t */\n\tfunction unix_to_human($time = '', $seconds = FALSE, $fmt = 'us')\n\t{\n\t\t$r = date('Y', $time).'-'.date('m', $time).'-'.date('d', $time).' ';\n\n\t\tif ($fmt === 'us')\n\t\t{\n\t\t\t$r .= date('h', $time).':'.date('i', $time);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$r .= date('H', $time).':'.date('i', $time);\n\t\t}\n\n\t\tif ($seconds)\n\t\t{\n\t\t\t$r .= ':'.date('s', $time);\n\t\t}\n\n\t\tif ($fmt === 'us')\n\t\t{\n\t\t\treturn $r.' '.date('A', $time);\n\t\t}\n\n\t\treturn $r;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('human_to_unix'))\n{\n\t/**\n\t * Convert \"human\" date to GMT\n\t *\n\t * Reverses the above process\n\t *\n\t * @param\tstring\tformat: us or euro\n\t * @return\tint\n\t */\n\tfunction human_to_unix($datestr = '')\n\t{\n\t\tif ($datestr === '')\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$datestr = preg_replace('/\\040+/', ' ', trim($datestr));\n\n\t\tif ( ! 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))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tsscanf($datestr, '%d-%d-%d %s %s', $year, $month, $day, $time, $ampm);\n\t\tsscanf($time, '%d:%d:%d', $hour, $min, $sec);\n\t\tisset($sec) OR $sec = 0;\n\n\t\tif (isset($ampm))\n\t\t{\n\t\t\t$ampm = strtolower($ampm);\n\n\t\t\tif ($ampm[0] === 'p' && $hour < 12)\n\t\t\t{\n\t\t\t\t$hour += 12;\n\t\t\t}\n\t\t\telseif ($ampm[0] === 'a' && $hour === 12)\n\t\t\t{\n\t\t\t\t$hour = 0;\n\t\t\t}\n\t\t}\n\n\t\treturn mktime($hour, $min, $sec, $month, $day, $year);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('nice_date'))\n{\n\t/**\n\t * Turns many \"reasonably-date-like\" strings into something\n\t * that is actually useful. This only works for dates after unix epoch.\n\t *\n\t * @param\tstring\tThe terribly formatted date-like string\n\t * @param\tstring\tDate format to return (same as php date function)\n\t * @return\tstring\n\t */\n\tfunction nice_date($bad_date = '', $format = FALSE)\n\t{\n\t\tif (empty($bad_date))\n\t\t{\n\t\t\treturn 'Unknown';\n\t\t}\n\t\telseif (empty($format))\n\t\t{\n\t\t\t$format = 'U';\n\t\t}\n\n\t\t// Date like: YYYYMM\n\t\tif (preg_match('/^\\d{6}$/i', $bad_date))\n\t\t{\n\t\t\tif (in_array(substr($bad_date, 0, 2), array('19', '20')))\n\t\t\t{\n\t\t\t\t$year  = substr($bad_date, 0, 4);\n\t\t\t\t$month = substr($bad_date, 4, 2);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$month  = substr($bad_date, 0, 2);\n\t\t\t\t$year   = substr($bad_date, 2, 4);\n\t\t\t}\n\n\t\t\treturn date($format, strtotime($year.'-'.$month.'-01'));\n\t\t}\n\n\t\t// Date Like: YYYYMMDD\n\t\tif (preg_match('/^(\\d{2})\\d{2}(\\d{4})$/i', $bad_date, $matches))\n\t\t{\n\t\t\treturn date($format, strtotime($matches[1].'/01/'.$matches[2]));\n\t\t}\n\n\t\t// Date Like: MM-DD-YYYY __or__ M-D-YYYY (or anything in between)\n\t\tif (preg_match('/^(\\d{1,2})-(\\d{1,2})-(\\d{4})$/i', $bad_date, $matches))\n\t\t{\n\t\t\treturn date($format, strtotime($matches[3].'-'.$matches[1].'-'.$matches[2]));\n\t\t}\n\n\t\t// Any other kind of string, when converted into UNIX time,\n\t\t// produces \"0 seconds after epoc...\" is probably bad...\n\t\t// return \"Invalid Date\".\n\t\tif (date('U', strtotime($bad_date)) === '0')\n\t\t{\n\t\t\treturn 'Invalid Date';\n\t\t}\n\n\t\t// It's probably a valid-ish date format already\n\t\treturn date($format, strtotime($bad_date));\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('timezone_menu'))\n{\n\t/**\n\t * Timezone Menu\n\t *\n\t * Generates a drop-down menu of timezones.\n\t *\n\t * @param\tstring\ttimezone\n\t * @param\tstring\tclassname\n\t * @param\tstring\tmenu name\n\t * @param\tmixed\tattributes\n\t * @return\tstring\n\t */\n\tfunction timezone_menu($default = 'UTC', $class = '', $name = 'timezones', $attributes = '')\n\t{\n\t\t$CI =& get_instance();\n\t\t$CI->lang->load('date');\n\n\t\t$default = ($default === 'GMT') ? 'UTC' : $default;\n\n\t\t$menu = '<select name=\"'.$name.'\"';\n\n\t\tif ($class !== '')\n\t\t{\n\t\t\t$menu .= ' class=\"'.$class.'\"';\n\t\t}\n\n\t\t$menu .= _stringify_attributes($attributes).\">\\n\";\n\n\t\tforeach (timezones() as $key => $val)\n\t\t{\n\t\t\t$selected = ($default === $key) ? ' selected=\"selected\"' : '';\n\t\t\t$menu .= '<option value=\"'.$key.'\"'.$selected.'>'.$CI->lang->line($key).\"</option>\\n\";\n\t\t}\n\n\t\treturn $menu.'</select>';\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('timezones'))\n{\n\t/**\n\t * Timezones\n\t *\n\t * Returns an array of timezones. This is a helper function\n\t * for various other ones in this library\n\t *\n\t * @param\tstring\ttimezone\n\t * @return\tstring\n\t */\n\tfunction timezones($tz = '')\n\t{\n\t\t// Note: Don't change the order of these even though\n\t\t// some items appear to be in the wrong order\n\n\t\t$zones = array(\n\t\t\t'UM12'\t\t=> -12,\n\t\t\t'UM11'\t\t=> -11,\n\t\t\t'UM10'\t\t=> -10,\n\t\t\t'UM95'\t\t=> -9.5,\n\t\t\t'UM9'\t\t=> -9,\n\t\t\t'UM8'\t\t=> -8,\n\t\t\t'UM7'\t\t=> -7,\n\t\t\t'UM6'\t\t=> -6,\n\t\t\t'UM5'\t\t=> -5,\n\t\t\t'UM45'\t\t=> -4.5,\n\t\t\t'UM4'\t\t=> -4,\n\t\t\t'UM35'\t\t=> -3.5,\n\t\t\t'UM3'\t\t=> -3,\n\t\t\t'UM2'\t\t=> -2,\n\t\t\t'UM1'\t\t=> -1,\n\t\t\t'UTC'\t\t=> 0,\n\t\t\t'UP1'\t\t=> +1,\n\t\t\t'UP2'\t\t=> +2,\n\t\t\t'UP3'\t\t=> +3,\n\t\t\t'UP35'\t\t=> +3.5,\n\t\t\t'UP4'\t\t=> +4,\n\t\t\t'UP45'\t\t=> +4.5,\n\t\t\t'UP5'\t\t=> +5,\n\t\t\t'UP55'\t\t=> +5.5,\n\t\t\t'UP575'\t\t=> +5.75,\n\t\t\t'UP6'\t\t=> +6,\n\t\t\t'UP65'\t\t=> +6.5,\n\t\t\t'UP7'\t\t=> +7,\n\t\t\t'UP8'\t\t=> +8,\n\t\t\t'UP875'\t\t=> +8.75,\n\t\t\t'UP9'\t\t=> +9,\n\t\t\t'UP95'\t\t=> +9.5,\n\t\t\t'UP10'\t\t=> +10,\n\t\t\t'UP105'\t\t=> +10.5,\n\t\t\t'UP11'\t\t=> +11,\n\t\t\t'UP115'\t\t=> +11.5,\n\t\t\t'UP12'\t\t=> +12,\n\t\t\t'UP1275'\t=> +12.75,\n\t\t\t'UP13'\t\t=> +13,\n\t\t\t'UP14'\t\t=> +14\n\t\t);\n\n\t\tif ($tz === '')\n\t\t{\n\t\t\treturn $zones;\n\t\t}\n\n\t\treturn isset($zones[$tz]) ? $zones[$tz] : 0;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('date_range'))\n{\n\t/**\n\t * Date range\n\t *\n\t * Returns a list of dates within a specified period.\n\t *\n\t * @param\tint\tunix_start\tUNIX timestamp of period start date\n\t * @param\tint\tunix_end|days\tUNIX timestamp of period end date\n\t *\t\t\t\t\tor interval in days.\n\t * @param\tmixed\tis_unix\t\tSpecifies whether the second parameter\n\t *\t\t\t\t\tis a UNIX timestamp or a day interval\n\t *\t\t\t\t\t - TRUE or 'unix' for a timestamp\n\t *\t\t\t\t\t - FALSE or 'days' for an interval\n\t * @param\tstring  date_format\tOutput date format, same as in date()\n\t * @return\tarray\n\t */\n\tfunction date_range($unix_start = '', $mixed = '', $is_unix = TRUE, $format = 'Y-m-d')\n\t{\n\t\tif ($unix_start == '' OR $mixed == '' OR $format == '')\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$is_unix = ! ( ! $is_unix OR $is_unix === 'days');\n\n\t\t// Validate input and try strtotime() on invalid timestamps/intervals, just in case\n\t\tif ( ( ! ctype_digit((string) $unix_start) && ($unix_start = @strtotime($unix_start)) === FALSE)\n\t\t\tOR ( ! ctype_digit((string) $mixed) && ($is_unix === FALSE OR ($mixed = @strtotime($mixed)) === FALSE))\n\t\t\tOR ($is_unix === TRUE && $mixed < $unix_start))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ($is_unix && ($unix_start == $mixed OR date($format, $unix_start) === date($format, $mixed)))\n\t\t{\n\t\t\treturn array(date($format, $unix_start));\n\t\t}\n\n\t\t$range = array();\n\n\t\t/* NOTE: Even though the DateTime object has many useful features, it appears that\n\t\t *\t it doesn't always handle properly timezones, when timestamps are passed\n\t\t *\t directly to its constructor. Neither of the following gave proper results:\n\t\t *\n\t\t *\t\tnew DateTime('<timestamp>')\n\t\t *\t\tnew DateTime('<timestamp>', '<timezone>')\n\t\t *\n\t\t *\t --- available in PHP 5.3:\n\t\t *\n\t\t *\t\tDateTime::createFromFormat('<format>', '<timestamp>')\n\t\t *\t\tDateTime::createFromFormat('<format>', '<timestamp>', '<timezone')\n\t\t *\n\t\t *\t ... so we'll have to set the timestamp after the object is instantiated.\n\t\t *\t Furthermore, in PHP 5.3 we can use DateTime::setTimestamp() to do that and\n\t\t *\t given that we have UNIX timestamps - we should use it.\n\t\t*/\n\t\t$from = new DateTime();\n\n\t\tif (is_php('5.3'))\n\t\t{\n\t\t\t$from->setTimestamp($unix_start);\n\t\t\tif ($is_unix)\n\t\t\t{\n\t\t\t\t$arg = new DateTime();\n\t\t\t\t$arg->setTimestamp($mixed);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$arg = (int) $mixed;\n\t\t\t}\n\n\t\t\t$period = new DatePeriod($from, new DateInterval('P1D'), $arg);\n\t\t\tforeach ($period as $date)\n\t\t\t{\n\t\t\t\t$range[] = $date->format($format);\n\t\t\t}\n\n\t\t\t/* If a period end date was passed to the DatePeriod constructor, it might not\n\t\t\t * be in our results. Not sure if this is a bug or it's just possible because\n\t\t\t * the end date might actually be less than 24 hours away from the previously\n\t\t\t * generated DateTime object, but either way - we have to append it manually.\n\t\t\t */\n\t\t\tif ( ! is_int($arg) && $range[count($range) - 1] !== $arg->format($format))\n\t\t\t{\n\t\t\t\t$range[] = $arg->format($format);\n\t\t\t}\n\n\t\t\treturn $range;\n\t\t}\n\n\t\t$from->setDate(date('Y', $unix_start), date('n', $unix_start), date('j', $unix_start));\n\t\t$from->setTime(date('G', $unix_start), date('i', $unix_start), date('s', $unix_start));\n\t\tif ($is_unix)\n\t\t{\n\t\t\t$arg = new DateTime();\n\t\t\t$arg->setDate(date('Y', $mixed), date('n', $mixed), date('j', $mixed));\n\t\t\t$arg->setTime(date('G', $mixed), date('i', $mixed), date('s', $mixed));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$arg = (int) $mixed;\n\t\t}\n\t\t$range[] = $from->format($format);\n\n\t\tif (is_int($arg)) // Day intervals\n\t\t{\n\t\t\tdo\n\t\t\t{\n\t\t\t\t$from->modify('+1 day');\n\t\t\t\t$range[] = $from->format($format);\n\t\t\t}\n\t\t\twhile (--$arg > 0);\n\t\t}\n\t\telse // end date UNIX timestamp\n\t\t{\n\t\t\tfor ($from->modify('+1 day'), $end_check = $arg->format('Ymd'); $from->format('Ymd') < $end_check; $from->modify('+1 day'))\n\t\t\t{\n\t\t\t\t$range[] = $from->format($format);\n\t\t\t}\n\n\t\t\t// Our loop only appended dates prior to our end date\n\t\t\t$range[] = $arg->format($format);\n\t\t}\n\n\t\treturn $range;\n\t}\n}\n"
  },
  {
    "path": "system/helpers/directory_helper.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Directory Helpers\n *\n * @package\t\tCodeIgniter\n * @subpackage\tHelpers\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/helpers/directory_helper.html\n */\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('directory_map'))\n{\n\t/**\n\t * Create a Directory Map\n\t *\n\t * Reads the specified directory and builds an array\n\t * representation of it. Sub-folders contained with the\n\t * directory will be mapped as well.\n\t *\n\t * @param\tstring\t$source_dir\t\tPath to source\n\t * @param\tint\t$directory_depth\tDepth of directories to traverse\n\t *\t\t\t\t\t\t(0 = fully recursive, 1 = current dir, etc)\n\t * @param\tbool\t$hidden\t\t\tWhether to show hidden files\n\t * @return\tarray\n\t */\n\tfunction directory_map($source_dir, $directory_depth = 0, $hidden = FALSE)\n\t{\n\t\tif ($fp = @opendir($source_dir))\n\t\t{\n\t\t\t$filedata\t= array();\n\t\t\t$new_depth\t= $directory_depth - 1;\n\t\t\t$source_dir\t= rtrim($source_dir, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;\n\n\t\t\twhile (FALSE !== ($file = readdir($fp)))\n\t\t\t{\n\t\t\t\t// Remove '.', '..', and hidden files [optional]\n\t\t\t\tif ($file === '.' OR $file === '..' OR ($hidden === FALSE && $file[0] === '.'))\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tis_dir($source_dir.$file) && $file .= DIRECTORY_SEPARATOR;\n\n\t\t\t\tif (($directory_depth < 1 OR $new_depth > 0) && is_dir($source_dir.$file))\n\t\t\t\t{\n\t\t\t\t\t$filedata[$file] = directory_map($source_dir.$file, $new_depth, $hidden);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$filedata[] = $file;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclosedir($fp);\n\t\t\treturn $filedata;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n}\n"
  },
  {
    "path": "system/helpers/download_helper.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Download Helpers\n *\n * @package\t\tCodeIgniter\n * @subpackage\tHelpers\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/helpers/download_helper.html\n */\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('force_download'))\n{\n\t/**\n\t * Force Download\n\t *\n\t * Generates headers that force a download to happen\n\t *\n\t * @param\tstring\tfilename\n\t * @param\tmixed\tthe data to be downloaded\n\t * @param\tbool\twhether to try and send the actual file MIME type\n\t * @return\tvoid\n\t */\n\tfunction force_download($filename = '', $data = '', $set_mime = FALSE)\n\t{\n\t\tif ($filename === '' OR $data === '')\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\telseif ($data === NULL)\n\t\t{\n\t\t\tif ( ! @is_file($filename) OR ($filesize = @filesize($filename)) === FALSE)\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t$filepath = $filename;\n\t\t\t$filename = explode('/', str_replace(DIRECTORY_SEPARATOR, '/', $filename));\n\t\t\t$filename = end($filename);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$filesize = strlen($data);\n\t\t}\n\n\t\t// Set the default MIME type to send\n\t\t$mime = 'application/octet-stream';\n\n\t\t$x = explode('.', $filename);\n\t\t$extension = end($x);\n\n\t\tif ($set_mime === TRUE)\n\t\t{\n\t\t\tif (count($x) === 1 OR $extension === '')\n\t\t\t{\n\t\t\t\t/* If we're going to detect the MIME type,\n\t\t\t\t * we'll need a file extension.\n\t\t\t\t */\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Load the mime types\n\t\t\t$mimes =& get_mimes();\n\n\t\t\t// Only change the default MIME if we can find one\n\t\t\tif (isset($mimes[$extension]))\n\t\t\t{\n\t\t\t\t$mime = is_array($mimes[$extension]) ? $mimes[$extension][0] : $mimes[$extension];\n\t\t\t}\n\t\t}\n\n\t\t/* It was reported that browsers on Android 2.1 (and possibly older as well)\n\t\t * need to have the filename extension upper-cased in order to be able to\n\t\t * download it.\n\t\t *\n\t\t * Reference: http://digiblog.de/2011/04/19/android-and-the-download-file-headers/\n\t\t */\n\t\tif (count($x) !== 1 && isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/Android\\s(1|2\\.[01])/', $_SERVER['HTTP_USER_AGENT']))\n\t\t{\n\t\t\t$x[count($x) - 1] = strtoupper($extension);\n\t\t\t$filename = implode('.', $x);\n\t\t}\n\n\t\tif ($data === NULL && ($fp = @fopen($filepath, 'rb')) === FALSE)\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\t// Clean output buffer\n\t\tif (ob_get_level() !== 0 && @ob_end_clean() === FALSE)\n\t\t{\n\t\t\t@ob_clean();\n\t\t}\n\n\t\t// Generate the server headers\n\t\theader('Content-Type: '.$mime);\n\t\theader('Content-Disposition: attachment; filename=\"'.$filename.'\"');\n\t\theader('Expires: 0');\n\t\theader('Content-Transfer-Encoding: binary');\n\t\theader('Content-Length: '.$filesize);\n\t\theader('Cache-Control: private, no-transform, no-store, must-revalidate');\n\n\t\t// If we have raw data - just dump it\n\t\tif ($data !== NULL)\n\t\t{\n\t\t\texit($data);\n\t\t}\n\n\t\t// Flush 1MB chunks of data\n\t\twhile ( ! feof($fp) && ($data = fread($fp, 1048576)) !== FALSE)\n\t\t{\n\t\t\techo $data;\n\t\t}\n\n\t\tfclose($fp);\n\t\texit;\n\t}\n}\n"
  },
  {
    "path": "system/helpers/email_helper.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Email Helpers\n *\n * @package\t\tCodeIgniter\n * @subpackage\tHelpers\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/helpers/email_helper.html\n */\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('valid_email'))\n{\n\t/**\n\t * Validate email address\n\t *\n\t * @deprecated\t3.0.0\tUse PHP's filter_var() instead\n\t * @param\tstring\t$email\n\t * @return\tbool\n\t */\n\tfunction valid_email($email)\n\t{\n\t\treturn (bool) filter_var($email, FILTER_VALIDATE_EMAIL);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('send_email'))\n{\n\t/**\n\t * Send an email\n\t *\n\t * @deprecated\t3.0.0\tUse PHP's mail() instead\n\t * @param\tstring\t$recipient\n\t * @param\tstring\t$subject\n\t * @param\tstring\t$message\n\t * @return\tbool\n\t */\n\tfunction send_email($recipient, $subject, $message)\n\t{\n\t\treturn mail($recipient, $subject, $message);\n\t}\n}\n"
  },
  {
    "path": "system/helpers/file_helper.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter File Helpers\n *\n * @package\t\tCodeIgniter\n * @subpackage\tHelpers\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/helpers/file_helper.html\n */\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('read_file'))\n{\n\t/**\n\t * Read File\n\t *\n\t * Opens the file specified in the path and returns it as a string.\n\t *\n\t * @todo\tRemove in version 3.1+.\n\t * @deprecated\t3.0.0\tIt is now just an alias for PHP's native file_get_contents().\n\t * @param\tstring\t$file\tPath to file\n\t * @return\tstring\tFile contents\n\t */\n\tfunction read_file($file)\n\t{\n\t\treturn @file_get_contents($file);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('write_file'))\n{\n\t/**\n\t * Write File\n\t *\n\t * Writes data to the file specified in the path.\n\t * Creates a new file if non-existent.\n\t *\n\t * @param\tstring\t$path\tFile path\n\t * @param\tstring\t$data\tData to write\n\t * @param\tstring\t$mode\tfopen() mode (default: 'wb')\n\t * @return\tbool\n\t */\n\tfunction write_file($path, $data, $mode = 'wb')\n\t{\n\t\tif ( ! $fp = @fopen($path, $mode))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tflock($fp, LOCK_EX);\n\n\t\tfor ($result = $written = 0, $length = strlen($data); $written < $length; $written += $result)\n\t\t{\n\t\t\tif (($result = fwrite($fp, substr($data, $written))) === FALSE)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tflock($fp, LOCK_UN);\n\t\tfclose($fp);\n\n\t\treturn is_int($result);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('delete_files'))\n{\n\t/**\n\t * Delete Files\n\t *\n\t * Deletes all files contained in the supplied directory path.\n\t * Files must be writable or owned by the system in order to be deleted.\n\t * If the second parameter is set to TRUE, any directories contained\n\t * within the supplied base directory will be nuked as well.\n\t *\n\t * @param\tstring\t$path\t\tFile path\n\t * @param\tbool\t$del_dir\tWhether to delete any directories found in the path\n\t * @param\tbool\t$htdocs\t\tWhether to skip deleting .htaccess and index page files\n\t * @param\tint\t$_level\t\tCurrent directory depth level (default: 0; internal use only)\n\t * @return\tbool\n\t */\n\tfunction delete_files($path, $del_dir = FALSE, $htdocs = FALSE, $_level = 0)\n\t{\n\t\t// Trim the trailing slash\n\t\t$path = rtrim($path, '/\\\\');\n\n\t\tif ( ! $current_dir = @opendir($path))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\twhile (FALSE !== ($filename = @readdir($current_dir)))\n\t\t{\n\t\t\tif ($filename !== '.' && $filename !== '..')\n\t\t\t{\n\t\t\t\t$filepath = $path.DIRECTORY_SEPARATOR.$filename;\n\n\t\t\t\tif (is_dir($filepath) && $filename[0] !== '.' && ! is_link($filepath))\n\t\t\t\t{\n\t\t\t\t\tdelete_files($filepath, $del_dir, $htdocs, $_level + 1);\n\t\t\t\t}\n\t\t\t\telseif ($htdocs !== TRUE OR ! preg_match('/^(\\.htaccess|index\\.(html|htm|php)|web\\.config)$/i', $filename))\n\t\t\t\t{\n\t\t\t\t\t@unlink($filepath);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tclosedir($current_dir);\n\n\t\treturn ($del_dir === TRUE && $_level > 0)\n\t\t\t? @rmdir($path)\n\t\t\t: TRUE;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('get_filenames'))\n{\n\t/**\n\t * Get Filenames\n\t *\n\t * Reads the specified directory and builds an array containing the filenames.\n\t * Any sub-folders contained within the specified path are read as well.\n\t *\n\t * @param\tstring\tpath to source\n\t * @param\tbool\twhether to include the path as part of the filename\n\t * @param\tbool\tinternal variable to determine recursion status - do not use in calls\n\t * @return\tarray\n\t */\n\tfunction get_filenames($source_dir, $include_path = FALSE, $_recursion = FALSE)\n\t{\n\t\tstatic $_filedata = array();\n\n\t\tif ($fp = @opendir($source_dir))\n\t\t{\n\t\t\t// reset the array and make sure $source_dir has a trailing slash on the initial call\n\t\t\tif ($_recursion === FALSE)\n\t\t\t{\n\t\t\t\t$_filedata = array();\n\t\t\t\t$source_dir = rtrim(realpath($source_dir), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;\n\t\t\t}\n\n\t\t\twhile (FALSE !== ($file = readdir($fp)))\n\t\t\t{\n\t\t\t\tif (is_dir($source_dir.$file) && $file[0] !== '.')\n\t\t\t\t{\n\t\t\t\t\tget_filenames($source_dir.$file.DIRECTORY_SEPARATOR, $include_path, TRUE);\n\t\t\t\t}\n\t\t\t\telseif ($file[0] !== '.')\n\t\t\t\t{\n\t\t\t\t\t$_filedata[] = ($include_path === TRUE) ? $source_dir.$file : $file;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclosedir($fp);\n\t\t\treturn $_filedata;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n}\n\n// --------------------------------------------------------------------\n\nif ( ! function_exists('get_dir_file_info'))\n{\n\t/**\n\t * Get Directory File Information\n\t *\n\t * Reads the specified directory and builds an array containing the filenames,\n\t * filesize, dates, and permissions\n\t *\n\t * Any sub-folders contained within the specified path are read as well.\n\t *\n\t * @param\tstring\tpath to source\n\t * @param\tbool\tLook only at the top level directory specified?\n\t * @param\tbool\tinternal variable to determine recursion status - do not use in calls\n\t * @return\tarray\n\t */\n\tfunction get_dir_file_info($source_dir, $top_level_only = TRUE, $_recursion = FALSE)\n\t{\n\t\tstatic $_filedata = array();\n\t\t$relative_path = $source_dir;\n\n\t\tif ($fp = @opendir($source_dir))\n\t\t{\n\t\t\t// reset the array and make sure $source_dir has a trailing slash on the initial call\n\t\t\tif ($_recursion === FALSE)\n\t\t\t{\n\t\t\t\t$_filedata = array();\n\t\t\t\t$source_dir = rtrim(realpath($source_dir), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;\n\t\t\t}\n\n\t\t\t// Used to be foreach (scandir($source_dir, 1) as $file), but scandir() is simply not as fast\n\t\t\twhile (FALSE !== ($file = readdir($fp)))\n\t\t\t{\n\t\t\t\tif (is_dir($source_dir.$file) && $file[0] !== '.' && $top_level_only === FALSE)\n\t\t\t\t{\n\t\t\t\t\tget_dir_file_info($source_dir.$file.DIRECTORY_SEPARATOR, $top_level_only, TRUE);\n\t\t\t\t}\n\t\t\t\telseif ($file[0] !== '.')\n\t\t\t\t{\n\t\t\t\t\t$_filedata[$file] = get_file_info($source_dir.$file);\n\t\t\t\t\t$_filedata[$file]['relative_path'] = $relative_path;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tclosedir($fp);\n\t\t\treturn $_filedata;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n}\n\n// --------------------------------------------------------------------\n\nif ( ! function_exists('get_file_info'))\n{\n\t/**\n\t * Get File Info\n\t *\n\t * Given a file and path, returns the name, path, size, date modified\n\t * Second parameter allows you to explicitly declare what information you want returned\n\t * Options are: name, server_path, size, date, readable, writable, executable, fileperms\n\t * Returns FALSE if the file cannot be found.\n\t *\n\t * @param\tstring\tpath to file\n\t * @param\tmixed\tarray or comma separated string of information returned\n\t * @return\tarray\n\t */\n\tfunction get_file_info($file, $returned_values = array('name', 'server_path', 'size', 'date'))\n\t{\n\t\tif ( ! file_exists($file))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (is_string($returned_values))\n\t\t{\n\t\t\t$returned_values = explode(',', $returned_values);\n\t\t}\n\n\t\tforeach ($returned_values as $key)\n\t\t{\n\t\t\tswitch ($key)\n\t\t\t{\n\t\t\t\tcase 'name':\n\t\t\t\t\t$fileinfo['name'] = basename($file);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'server_path':\n\t\t\t\t\t$fileinfo['server_path'] = $file;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'size':\n\t\t\t\t\t$fileinfo['size'] = filesize($file);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'date':\n\t\t\t\t\t$fileinfo['date'] = filemtime($file);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'readable':\n\t\t\t\t\t$fileinfo['readable'] = is_readable($file);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'writable':\n\t\t\t\t\t$fileinfo['writable'] = is_really_writable($file);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'executable':\n\t\t\t\t\t$fileinfo['executable'] = is_executable($file);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'fileperms':\n\t\t\t\t\t$fileinfo['fileperms'] = fileperms($file);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn $fileinfo;\n\t}\n}\n\n// --------------------------------------------------------------------\n\nif ( ! function_exists('get_mime_by_extension'))\n{\n\t/**\n\t * Get Mime by Extension\n\t *\n\t * Translates a file extension into a mime type based on config/mimes.php.\n\t * Returns FALSE if it can't determine the type, or open the mime config file\n\t *\n\t * Note: this is NOT an accurate way of determining file mime types, and is here strictly as a convenience\n\t * It should NOT be trusted, and should certainly NOT be used for security\n\t *\n\t * @param\tstring\t$filename\tFile name\n\t * @return\tstring\n\t */\n\tfunction get_mime_by_extension($filename)\n\t{\n\t\tstatic $mimes;\n\n\t\tif ( ! is_array($mimes))\n\t\t{\n\t\t\t$mimes = get_mimes();\n\n\t\t\tif (empty($mimes))\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\t$extension = strtolower(substr(strrchr($filename, '.'), 1));\n\n\t\tif (isset($mimes[$extension]))\n\t\t{\n\t\t\treturn is_array($mimes[$extension])\n\t\t\t\t? current($mimes[$extension]) // Multiple mime types, just give the first one\n\t\t\t\t: $mimes[$extension];\n\t\t}\n\n\t\treturn FALSE;\n\t}\n}\n\n// --------------------------------------------------------------------\n\nif ( ! function_exists('symbolic_permissions'))\n{\n\t/**\n\t * Symbolic Permissions\n\t *\n\t * Takes a numeric value representing a file's permissions and returns\n\t * standard symbolic notation representing that value\n\t *\n\t * @param\tint\t$perms\tPermissions\n\t * @return\tstring\n\t */\n\tfunction symbolic_permissions($perms)\n\t{\n\t\tif (($perms & 0xC000) === 0xC000)\n\t\t{\n\t\t\t$symbolic = 's'; // Socket\n\t\t}\n\t\telseif (($perms & 0xA000) === 0xA000)\n\t\t{\n\t\t\t$symbolic = 'l'; // Symbolic Link\n\t\t}\n\t\telseif (($perms & 0x8000) === 0x8000)\n\t\t{\n\t\t\t$symbolic = '-'; // Regular\n\t\t}\n\t\telseif (($perms & 0x6000) === 0x6000)\n\t\t{\n\t\t\t$symbolic = 'b'; // Block special\n\t\t}\n\t\telseif (($perms & 0x4000) === 0x4000)\n\t\t{\n\t\t\t$symbolic = 'd'; // Directory\n\t\t}\n\t\telseif (($perms & 0x2000) === 0x2000)\n\t\t{\n\t\t\t$symbolic = 'c'; // Character special\n\t\t}\n\t\telseif (($perms & 0x1000) === 0x1000)\n\t\t{\n\t\t\t$symbolic = 'p'; // FIFO pipe\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$symbolic = 'u'; // Unknown\n\t\t}\n\n\t\t// Owner\n\t\t$symbolic .= (($perms & 0x0100) ? 'r' : '-')\n\t\t\t.(($perms & 0x0080) ? 'w' : '-')\n\t\t\t.(($perms & 0x0040) ? (($perms & 0x0800) ? 's' : 'x' ) : (($perms & 0x0800) ? 'S' : '-'));\n\n\t\t// Group\n\t\t$symbolic .= (($perms & 0x0020) ? 'r' : '-')\n\t\t\t.(($perms & 0x0010) ? 'w' : '-')\n\t\t\t.(($perms & 0x0008) ? (($perms & 0x0400) ? 's' : 'x' ) : (($perms & 0x0400) ? 'S' : '-'));\n\n\t\t// World\n\t\t$symbolic .= (($perms & 0x0004) ? 'r' : '-')\n\t\t\t.(($perms & 0x0002) ? 'w' : '-')\n\t\t\t.(($perms & 0x0001) ? (($perms & 0x0200) ? 't' : 'x' ) : (($perms & 0x0200) ? 'T' : '-'));\n\n\t\treturn $symbolic;\n\t}\n}\n\n// --------------------------------------------------------------------\n\nif ( ! function_exists('octal_permissions'))\n{\n\t/**\n\t * Octal Permissions\n\t *\n\t * Takes a numeric value representing a file's permissions and returns\n\t * a three character string representing the file's octal permissions\n\t *\n\t * @param\tint\t$perms\tPermissions\n\t * @return\tstring\n\t */\n\tfunction octal_permissions($perms)\n\t{\n\t\treturn substr(sprintf('%o', $perms), -3);\n\t}\n}\n"
  },
  {
    "path": "system/helpers/form_helper.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Form Helpers\n *\n * @package\t\tCodeIgniter\n * @subpackage\tHelpers\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/helpers/form_helper.html\n */\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('form_open'))\n{\n\t/**\n\t * Form Declaration\n\t *\n\t * Creates the opening portion of the form.\n\t *\n\t * @param\tstring\tthe URI segments of the form destination\n\t * @param\tarray\ta key/value pair of attributes\n\t * @param\tarray\ta key/value pair hidden data\n\t * @return\tstring\n\t */\n\tfunction form_open($action = '', $attributes = array(), $hidden = array())\n\t{\n\t\t$CI =& get_instance();\n\n\t\t// If no action is provided then set to the current url\n\t\tif ( ! $action)\n\t\t{\n\t\t\t$action = $CI->config->site_url($CI->uri->uri_string());\n\t\t}\n\t\t// If an action is not a full URL then turn it into one\n\t\telseif (strpos($action, '://') === FALSE)\n\t\t{\n\t\t\t$action = $CI->config->site_url($action);\n\t\t}\n\n\t\t$attributes = _attributes_to_string($attributes);\n\n\t\tif (stripos($attributes, 'method=') === FALSE)\n\t\t{\n\t\t\t$attributes .= ' method=\"post\"';\n\t\t}\n\n\t\tif (stripos($attributes, 'accept-charset=') === FALSE)\n\t\t{\n\t\t\t$attributes .= ' accept-charset=\"'.strtolower(config_item('charset')).'\"';\n\t\t}\n\n\t\t$form = '<form action=\"'.$action.'\"'.$attributes.\">\\n\";\n\n\t\t// Add CSRF field if enabled, but leave it out for GET requests and requests to external websites\n\t\tif ($CI->config->item('csrf_protection') === TRUE && strpos($action, $CI->config->base_url()) !== FALSE && ! stripos($form, 'method=\"get\"'))\n\t\t{\n\t\t\t$hidden[$CI->security->get_csrf_token_name()] = $CI->security->get_csrf_hash();\n\t\t}\n\n\t\tif (is_array($hidden))\n\t\t{\n\t\t\tforeach ($hidden as $name => $value)\n\t\t\t{\n\t\t\t\t$form .= '<input type=\"hidden\" name=\"'.$name.'\" value=\"'.html_escape($value).'\" style=\"display:none;\" />'.\"\\n\";\n\t\t\t}\n\t\t}\n\n\t\treturn $form;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('form_open_multipart'))\n{\n\t/**\n\t * Form Declaration - Multipart type\n\t *\n\t * Creates the opening portion of the form, but with \"multipart/form-data\".\n\t *\n\t * @param\tstring\tthe URI segments of the form destination\n\t * @param\tarray\ta key/value pair of attributes\n\t * @param\tarray\ta key/value pair hidden data\n\t * @return\tstring\n\t */\n\tfunction form_open_multipart($action = '', $attributes = array(), $hidden = array())\n\t{\n\t\tif (is_string($attributes))\n\t\t{\n\t\t\t$attributes .= ' enctype=\"multipart/form-data\"';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$attributes['enctype'] = 'multipart/form-data';\n\t\t}\n\n\t\treturn form_open($action, $attributes, $hidden);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('form_hidden'))\n{\n\t/**\n\t * Hidden Input Field\n\t *\n\t * Generates hidden fields. You can pass a simple key/value string or\n\t * an associative array with multiple values.\n\t *\n\t * @param\tmixed\t$name\t\tField name\n\t * @param\tstring\t$value\t\tField value\n\t * @param\tbool\t$recursing\n\t * @return\tstring\n\t */\n\tfunction form_hidden($name, $value = '', $recursing = FALSE)\n\t{\n\t\tstatic $form;\n\n\t\tif ($recursing === FALSE)\n\t\t{\n\t\t\t$form = \"\\n\";\n\t\t}\n\n\t\tif (is_array($name))\n\t\t{\n\t\t\tforeach ($name as $key => $val)\n\t\t\t{\n\t\t\t\tform_hidden($key, $val, TRUE);\n\t\t\t}\n\n\t\t\treturn $form;\n\t\t}\n\n\t\tif ( ! is_array($value))\n\t\t{\n\t\t\t$form .= '<input type=\"hidden\" name=\"'.$name.'\" value=\"'.html_escape($value).\"\\\" />\\n\";\n\t\t}\n\t\telse\n\t\t{\n\t\t\tforeach ($value as $k => $v)\n\t\t\t{\n\t\t\t\t$k = is_int($k) ? '' : $k;\n\t\t\t\tform_hidden($name.'['.$k.']', $v, TRUE);\n\t\t\t}\n\t\t}\n\n\t\treturn $form;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('form_input'))\n{\n\t/**\n\t * Text Input Field\n\t *\n\t * @param\tmixed\n\t * @param\tstring\n\t * @param\tmixed\n\t * @return\tstring\n\t */\n\tfunction form_input($data = '', $value = '', $extra = '')\n\t{\n\t\t$defaults = array(\n\t\t\t'type' => 'text',\n\t\t\t'name' => is_array($data) ? '' : $data,\n\t\t\t'value' => $value\n\t\t);\n\n\t\treturn '<input '._parse_form_attributes($data, $defaults)._attributes_to_string($extra).\" />\\n\";\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('form_password'))\n{\n\t/**\n\t * Password Field\n\t *\n\t * Identical to the input function but adds the \"password\" type\n\t *\n\t * @param\tmixed\n\t * @param\tstring\n\t * @param\tmixed\n\t * @return\tstring\n\t */\n\tfunction form_password($data = '', $value = '', $extra = '')\n\t{\n\t\tis_array($data) OR $data = array('name' => $data);\n\t\t$data['type'] = 'password';\n\t\treturn form_input($data, $value, $extra);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('form_upload'))\n{\n\t/**\n\t * Upload Field\n\t *\n\t * Identical to the input function but adds the \"file\" type\n\t *\n\t * @param\tmixed\n\t * @param\tstring\n\t * @param\tmixed\n\t * @return\tstring\n\t */\n\tfunction form_upload($data = '', $value = '', $extra = '')\n\t{\n\t\t$defaults = array('type' => 'file', 'name' => '');\n\t\tis_array($data) OR $data = array('name' => $data);\n\t\t$data['type'] = 'file';\n\n\t\treturn '<input '._parse_form_attributes($data, $defaults)._attributes_to_string($extra).\" />\\n\";\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('form_textarea'))\n{\n\t/**\n\t * Textarea field\n\t *\n\t * @param\tmixed\t$data\n\t * @param\tstring\t$value\n\t * @param\tmixed\t$extra\n\t * @return\tstring\n\t */\n\tfunction form_textarea($data = '', $value = '', $extra = '')\n\t{\n\t\t$defaults = array(\n\t\t\t'name' => is_array($data) ? '' : $data,\n\t\t\t'cols' => '40',\n\t\t\t'rows' => '10'\n\t\t);\n\n\t\tif ( ! is_array($data) OR ! isset($data['value']))\n\t\t{\n\t\t\t$val = $value;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$val = $data['value'];\n\t\t\tunset($data['value']); // textareas don't use the value attribute\n\t\t}\n\n\t\treturn '<textarea '._parse_form_attributes($data, $defaults)._attributes_to_string($extra).'>'\n\t\t\t.html_escape($val)\n\t\t\t.\"</textarea>\\n\";\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('form_multiselect'))\n{\n\t/**\n\t * Multi-select menu\n\t *\n\t * @param\tstring\n\t * @param\tarray\n\t * @param\tmixed\n\t * @param\tmixed\n\t * @return\tstring\n\t */\n\tfunction form_multiselect($name = '', $options = array(), $selected = array(), $extra = '')\n\t{\n\t\t$extra = _attributes_to_string($extra);\n\t\tif (stripos($extra, 'multiple') === FALSE)\n\t\t{\n\t\t\t$extra .= ' multiple=\"multiple\"';\n\t\t}\n\n\t\treturn form_dropdown($name, $options, $selected, $extra);\n\t}\n}\n\n// --------------------------------------------------------------------\n\nif ( ! function_exists('form_dropdown'))\n{\n\t/**\n\t * Drop-down Menu\n\t *\n\t * @param\tmixed\t$data\n\t * @param\tmixed\t$options\n\t * @param\tmixed\t$selected\n\t * @param\tmixed\t$extra\n\t * @return\tstring\n\t */\n\tfunction form_dropdown($data = '', $options = array(), $selected = array(), $extra = '')\n\t{\n\t\t$defaults = array();\n\n\t\tif (is_array($data))\n\t\t{\n\t\t\tif (isset($data['selected']))\n\t\t\t{\n\t\t\t\t$selected = $data['selected'];\n\t\t\t\tunset($data['selected']); // select tags don't have a selected attribute\n\t\t\t}\n\n\t\t\tif (isset($data['options']))\n\t\t\t{\n\t\t\t\t$options = $data['options'];\n\t\t\t\tunset($data['options']); // select tags don't use an options attribute\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$defaults = array('name' => $data);\n\t\t}\n\n\t\tis_array($selected) OR $selected = array($selected);\n\t\tis_array($options) OR $options = array($options);\n\n\t\t// If no selected state was submitted we will attempt to set it automatically\n\t\tif (empty($selected))\n\t\t{\n\t\t\tif (is_array($data))\n\t\t\t{\n\t\t\t\tif (isset($data['name'], $_POST[$data['name']]))\n\t\t\t\t{\n\t\t\t\t\t$selected = array($_POST[$data['name']]);\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif (isset($_POST[$data]))\n\t\t\t{\n\t\t\t\t$selected = array($_POST[$data]);\n\t\t\t}\n\t\t}\n\n\t\t$extra = _attributes_to_string($extra);\n\n\t\t$multiple = (count($selected) > 1 && stripos($extra, 'multiple') === FALSE) ? ' multiple=\"multiple\"' : '';\n\n\t\t$form = '<select '.rtrim(_parse_form_attributes($data, $defaults)).$extra.$multiple.\">\\n\";\n\n\t\tforeach ($options as $key => $val)\n\t\t{\n\t\t\t$key = (string) $key;\n\n\t\t\tif (is_array($val))\n\t\t\t{\n\t\t\t\tif (empty($val))\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t$form .= '<optgroup label=\"'.$key.\"\\\">\\n\";\n\n\t\t\t\tforeach ($val as $optgroup_key => $optgroup_val)\n\t\t\t\t{\n\t\t\t\t\t$sel = in_array($optgroup_key, $selected) ? ' selected=\"selected\"' : '';\n\t\t\t\t\t$form .= '<option value=\"'.html_escape($optgroup_key).'\"'.$sel.'>'\n\t\t\t\t\t\t.(string) $optgroup_val.\"</option>\\n\";\n\t\t\t\t}\n\n\t\t\t\t$form .= \"</optgroup>\\n\";\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$form .= '<option value=\"'.html_escape($key).'\"'\n\t\t\t\t\t.(in_array($key, $selected) ? ' selected=\"selected\"' : '').'>'\n\t\t\t\t\t.(string) $val.\"</option>\\n\";\n\t\t\t}\n\t\t}\n\n\t\treturn $form.\"</select>\\n\";\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('form_checkbox'))\n{\n\t/**\n\t * Checkbox Field\n\t *\n\t * @param\tmixed\n\t * @param\tstring\n\t * @param\tbool\n\t * @param\tmixed\n\t * @return\tstring\n\t */\n\tfunction form_checkbox($data = '', $value = '', $checked = FALSE, $extra = '')\n\t{\n\t\t$defaults = array('type' => 'checkbox', 'name' => ( ! is_array($data) ? $data : ''), 'value' => $value);\n\n\t\tif (is_array($data) && array_key_exists('checked', $data))\n\t\t{\n\t\t\t$checked = $data['checked'];\n\n\t\t\tif ($checked == FALSE)\n\t\t\t{\n\t\t\t\tunset($data['checked']);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$data['checked'] = 'checked';\n\t\t\t}\n\t\t}\n\n\t\tif ($checked == TRUE)\n\t\t{\n\t\t\t$defaults['checked'] = 'checked';\n\t\t}\n\t\telse\n\t\t{\n\t\t\tunset($defaults['checked']);\n\t\t}\n\n\t\treturn '<input '._parse_form_attributes($data, $defaults)._attributes_to_string($extra).\" />\\n\";\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('form_radio'))\n{\n\t/**\n\t * Radio Button\n\t *\n\t * @param\tmixed\n\t * @param\tstring\n\t * @param\tbool\n\t * @param\tmixed\n\t * @return\tstring\n\t */\n\tfunction form_radio($data = '', $value = '', $checked = FALSE, $extra = '')\n\t{\n\t\tis_array($data) OR $data = array('name' => $data);\n\t\t$data['type'] = 'radio';\n\n\t\treturn form_checkbox($data, $value, $checked, $extra);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('form_submit'))\n{\n\t/**\n\t * Submit Button\n\t *\n\t * @param\tmixed\n\t * @param\tstring\n\t * @param\tmixed\n\t * @return\tstring\n\t */\n\tfunction form_submit($data = '', $value = '', $extra = '')\n\t{\n\t\t$defaults = array(\n\t\t\t'type' => 'submit',\n\t\t\t'name' => is_array($data) ? '' : $data,\n\t\t\t'value' => $value\n\t\t);\n\n\t\treturn '<input '._parse_form_attributes($data, $defaults)._attributes_to_string($extra).\" />\\n\";\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('form_reset'))\n{\n\t/**\n\t * Reset Button\n\t *\n\t * @param\tmixed\n\t * @param\tstring\n\t * @param\tmixed\n\t * @return\tstring\n\t */\n\tfunction form_reset($data = '', $value = '', $extra = '')\n\t{\n\t\t$defaults = array(\n\t\t\t'type' => 'reset',\n\t\t\t'name' => is_array($data) ? '' : $data,\n\t\t\t'value' => $value\n\t\t);\n\n\t\treturn '<input '._parse_form_attributes($data, $defaults)._attributes_to_string($extra).\" />\\n\";\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('form_button'))\n{\n\t/**\n\t * Form Button\n\t *\n\t * @param\tmixed\n\t * @param\tstring\n\t * @param\tmixed\n\t * @return\tstring\n\t */\n\tfunction form_button($data = '', $content = '', $extra = '')\n\t{\n\t\t$defaults = array(\n\t\t\t'name' => is_array($data) ? '' : $data,\n\t\t\t'type' => 'button'\n\t\t);\n\n\t\tif (is_array($data) && isset($data['content']))\n\t\t{\n\t\t\t$content = $data['content'];\n\t\t\tunset($data['content']); // content is not an attribute\n\t\t}\n\n\t\treturn '<button '._parse_form_attributes($data, $defaults)._attributes_to_string($extra).'>'\n\t\t\t.$content\n\t\t\t.\"</button>\\n\";\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('form_label'))\n{\n\t/**\n\t * Form Label Tag\n\t *\n\t * @param\tstring\tThe text to appear onscreen\n\t * @param\tstring\tThe id the label applies to\n\t * @param\tarray\tAdditional attributes\n\t * @return\tstring\n\t */\n\tfunction form_label($label_text = '', $id = '', $attributes = array())\n\t{\n\n\t\t$label = '<label';\n\n\t\tif ($id !== '')\n\t\t{\n\t\t\t$label .= ' for=\"'.$id.'\"';\n\t\t}\n\n\t\tif (is_array($attributes) && count($attributes) > 0)\n\t\t{\n\t\t\tforeach ($attributes as $key => $val)\n\t\t\t{\n\t\t\t\t$label .= ' '.$key.'=\"'.$val.'\"';\n\t\t\t}\n\t\t}\n\n\t\treturn $label.'>'.$label_text.'</label>';\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('form_fieldset'))\n{\n\t/**\n\t * Fieldset Tag\n\t *\n\t * Used to produce <fieldset><legend>text</legend>.  To close fieldset\n\t * use form_fieldset_close()\n\t *\n\t * @param\tstring\tThe legend text\n\t * @param\tarray\tAdditional attributes\n\t * @return\tstring\n\t */\n\tfunction form_fieldset($legend_text = '', $attributes = array())\n\t{\n\t\t$fieldset = '<fieldset'._attributes_to_string($attributes).\">\\n\";\n\t\tif ($legend_text !== '')\n\t\t{\n\t\t\treturn $fieldset.'<legend>'.$legend_text.\"</legend>\\n\";\n\t\t}\n\n\t\treturn $fieldset;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('form_fieldset_close'))\n{\n\t/**\n\t * Fieldset Close Tag\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tfunction form_fieldset_close($extra = '')\n\t{\n\t\treturn '</fieldset>'.$extra;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('form_close'))\n{\n\t/**\n\t * Form Close Tag\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tfunction form_close($extra = '')\n\t{\n\t\treturn '</form>'.$extra;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('form_prep'))\n{\n\t/**\n\t * Form Prep\n\t *\n\t * Formats text so that it can be safely placed in a form field in the event it has HTML tags.\n\t *\n\t * @deprecated\t3.0.0\tAn alias for html_escape()\n\t * @param\tstring|string[]\t$str\t\tValue to escape\n\t * @return\tstring|string[]\tEscaped values\n\t */\n\tfunction form_prep($str)\n\t{\n\t\treturn html_escape($str, TRUE);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('set_value'))\n{\n\t/**\n\t * Form Value\n\t *\n\t * Grabs a value from the POST array for the specified field so you can\n\t * re-populate an input field or textarea. If Form Validation\n\t * is active it retrieves the info from the validation class\n\t *\n\t * @param\tstring\t$field\t\tField name\n\t * @param\tstring\t$default\tDefault value\n\t * @param\tbool\t$html_escape\tWhether to escape HTML special characters or not\n\t * @return\tstring\n\t */\n\tfunction set_value($field, $default = '', $html_escape = TRUE)\n\t{\n\t\t$CI =& get_instance();\n\n\t\t$value = (isset($CI->form_validation) && is_object($CI->form_validation) && $CI->form_validation->has_rule($field))\n\t\t\t? $CI->form_validation->set_value($field, $default)\n\t\t\t: $CI->input->post($field, FALSE);\n\n\t\tisset($value) OR $value = $default;\n\t\treturn ($html_escape) ? html_escape($value) : $value;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('set_select'))\n{\n\t/**\n\t * Set Select\n\t *\n\t * Let's you set the selected value of a <select> menu via data in the POST array.\n\t * If Form Validation is active it retrieves the info from the validation class\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @param\tbool\n\t * @return\tstring\n\t */\n\tfunction set_select($field, $value = '', $default = FALSE)\n\t{\n\t\t$CI =& get_instance();\n\n\t\tif (isset($CI->form_validation) && is_object($CI->form_validation) && $CI->form_validation->has_rule($field))\n\t\t{\n\t\t\treturn $CI->form_validation->set_select($field, $value, $default);\n\t\t}\n\t\telseif (($input = $CI->input->post($field, FALSE)) === NULL)\n\t\t{\n\t\t\treturn ($default === TRUE) ? ' selected=\"selected\"' : '';\n\t\t}\n\n\t\t$value = (string) $value;\n\t\tif (is_array($input))\n\t\t{\n\t\t\t// Note: in_array('', array(0)) returns TRUE, do not use it\n\t\t\tforeach ($input as &$v)\n\t\t\t{\n\t\t\t\tif ($value === $v)\n\t\t\t\t{\n\t\t\t\t\treturn ' selected=\"selected\"';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn '';\n\t\t}\n\n\t\treturn ($input === $value) ? ' selected=\"selected\"' : '';\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('set_checkbox'))\n{\n\t/**\n\t * Set Checkbox\n\t *\n\t * Let's you set the selected value of a checkbox via the value in the POST array.\n\t * If Form Validation is active it retrieves the info from the validation class\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @param\tbool\n\t * @return\tstring\n\t */\n\tfunction set_checkbox($field, $value = '', $default = FALSE)\n\t{\n\t\t$CI =& get_instance();\n\n\t\tif (isset($CI->form_validation) && is_object($CI->form_validation) && $CI->form_validation->has_rule($field))\n\t\t{\n\t\t\treturn $CI->form_validation->set_checkbox($field, $value, $default);\n\t\t}\n\n\t\t// Form inputs are always strings ...\n\t\t$value = (string) $value;\n\t\t$input = $CI->input->post($field, FALSE);\n\n\t\tif (is_array($input))\n\t\t{\n\t\t\t// Note: in_array('', array(0)) returns TRUE, do not use it\n\t\t\tforeach ($input as &$v)\n\t\t\t{\n\t\t\t\tif ($value === $v)\n\t\t\t\t{\n\t\t\t\t\treturn ' checked=\"checked\"';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn '';\n\t\t}\n\n\t\t// Unchecked checkbox and radio inputs are not even submitted by browsers ...\n\t\tif ($CI->input->method() === 'post')\n\t\t{\n\t\t\treturn ($input === $value) ? ' checked=\"checked\"' : '';\n\t\t}\n\n\t\treturn ($default === TRUE) ? ' checked=\"checked\"' : '';\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('set_radio'))\n{\n\t/**\n\t * Set Radio\n\t *\n\t * Let's you set the selected value of a radio field via info in the POST array.\n\t * If Form Validation is active it retrieves the info from the validation class\n\t *\n\t * @param\tstring\t$field\n\t * @param\tstring\t$value\n\t * @param\tbool\t$default\n\t * @return\tstring\n\t */\n\tfunction set_radio($field, $value = '', $default = FALSE)\n\t{\n\t\t$CI =& get_instance();\n\n\t\tif (isset($CI->form_validation) && is_object($CI->form_validation) && $CI->form_validation->has_rule($field))\n\t\t{\n\t\t\treturn $CI->form_validation->set_radio($field, $value, $default);\n\t\t}\n\n\t\t// Form inputs are always strings ...\n\t\t$value = (string) $value;\n\t\t$input = $CI->input->post($field, FALSE);\n\n\t\tif (is_array($input))\n\t\t{\n\t\t\t// Note: in_array('', array(0)) returns TRUE, do not use it\n\t\t\tforeach ($input as &$v)\n\t\t\t{\n\t\t\t\tif ($value === $v)\n\t\t\t\t{\n\t\t\t\t\treturn ' checked=\"checked\"';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn '';\n\t\t}\n\n\t\t// Unchecked checkbox and radio inputs are not even submitted by browsers ...\n\t\tif ($CI->input->method() === 'post')\n\t\t{\n\t\t\treturn ($input === $value) ? ' checked=\"checked\"' : '';\n\t\t}\n\n\t\treturn ($default === TRUE) ? ' checked=\"checked\"' : '';\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('form_error'))\n{\n\t/**\n\t * Form Error\n\t *\n\t * Returns the error for a specific form field. This is a helper for the\n\t * form validation class.\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tfunction form_error($field = '', $prefix = '', $suffix = '')\n\t{\n\t\tif (FALSE === ($OBJ =& _get_validation_object()))\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\treturn $OBJ->error($field, $prefix, $suffix);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('validation_errors'))\n{\n\t/**\n\t * Validation Error String\n\t *\n\t * Returns all the errors associated with a form submission. This is a helper\n\t * function for the form validation class.\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tfunction validation_errors($prefix = '', $suffix = '')\n\t{\n\t\tif (FALSE === ($OBJ =& _get_validation_object()))\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\treturn $OBJ->error_string($prefix, $suffix);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('_parse_form_attributes'))\n{\n\t/**\n\t * Parse the form attributes\n\t *\n\t * Helper function used by some of the form helpers\n\t *\n\t * @param\tarray\t$attributes\tList of attributes\n\t * @param\tarray\t$default\tDefault values\n\t * @return\tstring\n\t */\n\tfunction _parse_form_attributes($attributes, $default)\n\t{\n\t\tif (is_array($attributes))\n\t\t{\n\t\t\tforeach ($default as $key => $val)\n\t\t\t{\n\t\t\t\tif (isset($attributes[$key]))\n\t\t\t\t{\n\t\t\t\t\t$default[$key] = $attributes[$key];\n\t\t\t\t\tunset($attributes[$key]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (count($attributes) > 0)\n\t\t\t{\n\t\t\t\t$default = array_merge($default, $attributes);\n\t\t\t}\n\t\t}\n\n\t\t$att = '';\n\n\t\tforeach ($default as $key => $val)\n\t\t{\n\t\t\tif ($key === 'value')\n\t\t\t{\n\t\t\t\t$val = html_escape($val);\n\t\t\t}\n\t\t\telseif ($key === 'name' && ! strlen($default['name']))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t$att .= $key.'=\"'.$val.'\" ';\n\t\t}\n\n\t\treturn $att;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('_attributes_to_string'))\n{\n\t/**\n\t * Attributes To String\n\t *\n\t * Helper function used by some of the form helpers\n\t *\n\t * @param\tmixed\n\t * @return\tstring\n\t */\n\tfunction _attributes_to_string($attributes)\n\t{\n\t\tif (empty($attributes))\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\tif (is_object($attributes))\n\t\t{\n\t\t\t$attributes = (array) $attributes;\n\t\t}\n\n\t\tif (is_array($attributes))\n\t\t{\n\t\t\t$atts = '';\n\n\t\t\tforeach ($attributes as $key => $val)\n\t\t\t{\n\t\t\t\t$atts .= ' '.$key.'=\"'.$val.'\"';\n\t\t\t}\n\n\t\t\treturn $atts;\n\t\t}\n\n\t\tif (is_string($attributes))\n\t\t{\n\t\t\treturn ' '.$attributes;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('_get_validation_object'))\n{\n\t/**\n\t * Validation Object\n\t *\n\t * Determines what the form validation class was instantiated as, fetches\n\t * the object and returns it.\n\t *\n\t * @return\tmixed\n\t */\n\tfunction &_get_validation_object()\n\t{\n\t\t$CI =& get_instance();\n\n\t\t// We set this as a variable since we're returning by reference.\n\t\t$return = FALSE;\n\n\t\tif (FALSE !== ($object = $CI->load->is_loaded('Form_validation')))\n\t\t{\n\t\t\tif ( ! isset($CI->$object) OR ! is_object($CI->$object))\n\t\t\t{\n\t\t\t\treturn $return;\n\t\t\t}\n\n\t\t\treturn $CI->$object;\n\t\t}\n\n\t\treturn $return;\n\t}\n}\n"
  },
  {
    "path": "system/helpers/html_helper.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter HTML Helpers\n *\n * @package\t\tCodeIgniter\n * @subpackage\tHelpers\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/helpers/html_helper.html\n */\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('heading'))\n{\n\t/**\n\t * Heading\n\t *\n\t * Generates an HTML heading tag.\n\t *\n\t * @param\tstring\tcontent\n\t * @param\tint\theading level\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tfunction heading($data = '', $h = '1', $attributes = '')\n\t{\n\t\treturn '<h'.$h._stringify_attributes($attributes).'>'.$data.'</h'.$h.'>';\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('ul'))\n{\n\t/**\n\t * Unordered List\n\t *\n\t * Generates an HTML unordered list from an single or multi-dimensional array.\n\t *\n\t * @param\tarray\n\t * @param\tmixed\n\t * @return\tstring\n\t */\n\tfunction ul($list, $attributes = '')\n\t{\n\t\treturn _list('ul', $list, $attributes);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('ol'))\n{\n\t/**\n\t * Ordered List\n\t *\n\t * Generates an HTML ordered list from an single or multi-dimensional array.\n\t *\n\t * @param\tarray\n\t * @param\tmixed\n\t * @return\tstring\n\t */\n\tfunction ol($list, $attributes = '')\n\t{\n\t\treturn _list('ol', $list, $attributes);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('_list'))\n{\n\t/**\n\t * Generates the list\n\t *\n\t * Generates an HTML ordered list from an single or multi-dimensional array.\n\t *\n\t * @param\tstring\n\t * @param\tmixed\n\t * @param\tmixed\n\t * @param\tint\n\t * @return\tstring\n\t */\n\tfunction _list($type = 'ul', $list = array(), $attributes = '', $depth = 0)\n\t{\n\t\t// If an array wasn't submitted there's nothing to do...\n\t\tif ( ! is_array($list))\n\t\t{\n\t\t\treturn $list;\n\t\t}\n\n\t\t// Set the indentation based on the depth\n\t\t$out = str_repeat(' ', $depth)\n\t\t\t// Write the opening list tag\n\t\t\t.'<'.$type._stringify_attributes($attributes).\">\\n\";\n\n\n\t\t// Cycle through the list elements.  If an array is\n\t\t// encountered we will recursively call _list()\n\n\t\tstatic $_last_list_item = '';\n\t\tforeach ($list as $key => $val)\n\t\t{\n\t\t\t$_last_list_item = $key;\n\n\t\t\t$out .= str_repeat(' ', $depth + 2).'<li>';\n\n\t\t\tif ( ! is_array($val))\n\t\t\t{\n\t\t\t\t$out .= $val;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$out .= $_last_list_item.\"\\n\"._list($type, $val, '', $depth + 4).str_repeat(' ', $depth + 2);\n\t\t\t}\n\n\t\t\t$out .= \"</li>\\n\";\n\t\t}\n\n\t\t// Set the indentation for the closing tag and apply it\n\t\treturn $out.str_repeat(' ', $depth).'</'.$type.\">\\n\";\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('img'))\n{\n\t/**\n\t * Image\n\t *\n\t * Generates an <img /> element\n\t *\n\t * @param\tmixed\n\t * @param\tbool\n\t * @param\tmixed\n\t * @return\tstring\n\t */\n\tfunction img($src = '', $index_page = FALSE, $attributes = '')\n\t{\n\t\tif ( ! is_array($src) )\n\t\t{\n\t\t\t$src = array('src' => $src);\n\t\t}\n\n\t\t// If there is no alt attribute defined, set it to an empty string\n\t\tif ( ! isset($src['alt']))\n\t\t{\n\t\t\t$src['alt'] = '';\n\t\t}\n\n\t\t$img = '<img';\n\n\t\tforeach ($src as $k => $v)\n\t\t{\n\t\t\tif ($k === 'src' && ! preg_match('#^([a-z]+:)?//#i', $v))\n\t\t\t{\n\t\t\t\tif ($index_page === TRUE)\n\t\t\t\t{\n\t\t\t\t\t$img .= ' src=\"'.get_instance()->config->site_url($v).'\"';\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$img .= ' src=\"'.get_instance()->config->slash_item('base_url').$v.'\"';\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$img .= ' '.$k.'=\"'.$v.'\"';\n\t\t\t}\n\t\t}\n\n\t\treturn $img._stringify_attributes($attributes).' />';\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('doctype'))\n{\n\t/**\n\t * Doctype\n\t *\n\t * Generates a page document type declaration\n\t *\n\t * Examples of valid options: html5, xhtml-11, xhtml-strict, xhtml-trans,\n\t * xhtml-frame, html4-strict, html4-trans, and html4-frame.\n\t * All values are saved in the doctypes config file.\n\t *\n\t * @param\tstring\ttype\tThe doctype to be generated\n\t * @return\tstring\n\t */\n\tfunction doctype($type = 'xhtml1-strict')\n\t{\n\t\tstatic $doctypes;\n\n\t\tif ( ! is_array($doctypes))\n\t\t{\n\t\t\tif (file_exists(APPPATH.'config/doctypes.php'))\n\t\t\t{\n\t\t\t\tinclude(APPPATH.'config/doctypes.php');\n\t\t\t}\n\n\t\t\tif (file_exists(APPPATH.'config/'.ENVIRONMENT.'/doctypes.php'))\n\t\t\t{\n\t\t\t\tinclude(APPPATH.'config/'.ENVIRONMENT.'/doctypes.php');\n\t\t\t}\n\n\t\t\tif (empty($_doctypes) OR ! is_array($_doctypes))\n\t\t\t{\n\t\t\t\t$doctypes = array();\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$doctypes = $_doctypes;\n\t\t}\n\n\t\treturn isset($doctypes[$type]) ? $doctypes[$type] : FALSE;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('link_tag'))\n{\n\t/**\n\t * Link\n\t *\n\t * Generates link to a CSS file\n\t *\n\t * @param\tmixed\tstylesheet hrefs or an array\n\t * @param\tstring\trel\n\t * @param\tstring\ttype\n\t * @param\tstring\ttitle\n\t * @param\tstring\tmedia\n\t * @param\tbool\tshould index_page be added to the css path\n\t * @return\tstring\n\t */\n\tfunction link_tag($href = '', $rel = 'stylesheet', $type = 'text/css', $title = '', $media = '', $index_page = FALSE)\n\t{\n\t\t$CI =& get_instance();\n\t\t$link = '<link ';\n\n\t\tif (is_array($href))\n\t\t{\n\t\t\tforeach ($href as $k => $v)\n\t\t\t{\n\t\t\t\tif ($k === 'href' && ! preg_match('#^([a-z]+:)?//#i', $v))\n\t\t\t\t{\n\t\t\t\t\tif ($index_page === TRUE)\n\t\t\t\t\t{\n\t\t\t\t\t\t$link .= 'href=\"'.$CI->config->site_url($v).'\" ';\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$link .= 'href=\"'.$CI->config->slash_item('base_url').$v.'\" ';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$link .= $k.'=\"'.$v.'\" ';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (preg_match('#^([a-z]+:)?//#i', $href))\n\t\t\t{\n\t\t\t\t$link .= 'href=\"'.$href.'\" ';\n\t\t\t}\n\t\t\telseif ($index_page === TRUE)\n\t\t\t{\n\t\t\t\t$link .= 'href=\"'.$CI->config->site_url($href).'\" ';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$link .= 'href=\"'.$CI->config->slash_item('base_url').$href.'\" ';\n\t\t\t}\n\n\t\t\t$link .= 'rel=\"'.$rel.'\" type=\"'.$type.'\" ';\n\n\t\t\tif ($media !== '')\n\t\t\t{\n\t\t\t\t$link .= 'media=\"'.$media.'\" ';\n\t\t\t}\n\n\t\t\tif ($title !== '')\n\t\t\t{\n\t\t\t\t$link .= 'title=\"'.$title.'\" ';\n\t\t\t}\n\t\t}\n\n\t\treturn $link.\"/>\\n\";\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('meta'))\n{\n\t/**\n\t * Generates meta tags from an array of key/values\n\t *\n\t * @param\tarray\n\t * @param\tstring\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tfunction meta($name = '', $content = '', $type = 'name', $newline = \"\\n\")\n\t{\n\t\t// Since we allow the data to be passes as a string, a simple array\n\t\t// or a multidimensional one, we need to do a little prepping.\n\t\tif ( ! is_array($name))\n\t\t{\n\t\t\t$name = array(array('name' => $name, 'content' => $content, 'type' => $type, 'newline' => $newline));\n\t\t}\n\t\telseif (isset($name['name']))\n\t\t{\n\t\t\t// Turn single array into multidimensional\n\t\t\t$name = array($name);\n\t\t}\n\n\t\t$str = '';\n\t\tforeach ($name as $meta)\n\t\t{\n\t\t\t$type\t\t= (isset($meta['type']) && $meta['type'] !== 'name')\t? 'http-equiv' : 'name';\n\t\t\t$name\t\t= isset($meta['name'])\t\t\t\t\t? $meta['name'] : '';\n\t\t\t$content\t= isset($meta['content'])\t\t\t\t? $meta['content'] : '';\n\t\t\t$newline\t= isset($meta['newline'])\t\t\t\t? $meta['newline'] : \"\\n\";\n\n\t\t\t$str .= '<meta '.$type.'=\"'.$name.'\" content=\"'.$content.'\" />'.$newline;\n\t\t}\n\n\t\treturn $str;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('br'))\n{\n\t/**\n\t * Generates HTML BR tags based on number supplied\n\t *\n\t * @deprecated\t3.0.0\tUse str_repeat() instead\n\t * @param\tint\t$count\tNumber of times to repeat the tag\n\t * @return\tstring\n\t */\n\tfunction br($count = 1)\n\t{\n\t\treturn str_repeat('<br />', $count);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('nbs'))\n{\n\t/**\n\t * Generates non-breaking space entities based on number supplied\n\t *\n\t * @deprecated\t3.0.0\tUse str_repeat() instead\n\t * @param\tint\n\t * @return\tstring\n\t */\n\tfunction nbs($num = 1)\n\t{\n\t\treturn str_repeat('&nbsp;', $num);\n\t}\n}\n"
  },
  {
    "path": "system/helpers/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/helpers/inflector_helper.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Inflector Helpers\n *\n * @package\t\tCodeIgniter\n * @subpackage\tHelpers\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/helpers/inflector_helper.html\n */\n\n// --------------------------------------------------------------------\n\nif ( ! function_exists('singular'))\n{\n\t/**\n\t * Singular\n\t *\n\t * Takes a plural word and makes it singular\n\t *\n\t * @param\tstring\t$str\tInput string\n\t * @return\tstring\n\t */\n\tfunction singular($str)\n\t{\n\t\t$result = strval($str);\n\n\t\tif ( ! is_countable($result))\n\t\t{\n\t\t\treturn $result;\n\t\t}\n\n\t\t$singular_rules = array(\n\t\t\t'/(matr)ices$/'\t\t=> '\\1ix',\n\t\t\t'/(vert|ind)ices$/'\t=> '\\1ex',\n\t\t\t'/^(ox)en/'\t\t=> '\\1',\n\t\t\t'/(alias)es$/'\t\t=> '\\1',\n\t\t\t'/([octop|vir])i$/'\t=> '\\1us',\n\t\t\t'/(cris|ax|test)es$/'\t=> '\\1is',\n\t\t\t'/(shoe)s$/'\t\t=> '\\1',\n\t\t\t'/(o)es$/'\t\t=> '\\1',\n\t\t\t'/(bus|campus)es$/'\t=> '\\1',\n\t\t\t'/([m|l])ice$/'\t\t=> '\\1ouse',\n\t\t\t'/(x|ch|ss|sh)es$/'\t=> '\\1',\n\t\t\t'/(m)ovies$/'\t\t=> '\\1\\2ovie',\n\t\t\t'/(s)eries$/'\t\t=> '\\1\\2eries',\n\t\t\t'/([^aeiouy]|qu)ies$/'\t=> '\\1y',\n\t\t\t'/([lr])ves$/'\t\t=> '\\1f',\n\t\t\t'/(tive)s$/'\t\t=> '\\1',\n\t\t\t'/(hive)s$/'\t\t=> '\\1',\n\t\t\t'/([^f])ves$/'\t\t=> '\\1fe',\n\t\t\t'/(^analy)ses$/'\t=> '\\1sis',\n\t\t\t'/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/' => '\\1\\2sis',\n\t\t\t'/([ti])a$/'\t\t=> '\\1um',\n\t\t\t'/(p)eople$/'\t\t=> '\\1\\2erson',\n\t\t\t'/(m)en$/'\t\t=> '\\1an',\n\t\t\t'/(s)tatuses$/'\t\t=> '\\1\\2tatus',\n\t\t\t'/(c)hildren$/'\t\t=> '\\1\\2hild',\n\t\t\t'/(n)ews$/'\t\t=> '\\1\\2ews',\n\t\t\t'/([^us])s$/'\t\t=> '\\1'\n\t\t);\n\n\t\tforeach ($singular_rules as $rule => $replacement)\n\t\t{\n\t\t\tif (preg_match($rule, $result))\n\t\t\t{\n\t\t\t\t$result = preg_replace($rule, $replacement, $result);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn $result;\n\t}\n}\n\n// --------------------------------------------------------------------\n\nif ( ! function_exists('plural'))\n{\n\t/**\n\t * Plural\n\t *\n\t * Takes a singular word and makes it plural\n\t *\n\t * @param\tstring\t$str\tInput string\n\t * @return\tstring\n\t */\n\tfunction plural($str)\n\t{\n\t\t$result = strval($str);\n\n\t\tif ( ! is_countable($result))\n\t\t{\n\t\t\treturn $result;\n\t\t}\n\n\t\t$plural_rules = array(\n\t\t\t'/(quiz)$/'                => '\\1zes',      // quizzes\n\t\t\t'/^(ox)$/'                 => '\\1\\2en',     // ox\n\t\t\t'/([m|l])ouse$/'           => '\\1ice',      // mouse, louse\n\t\t\t'/(matr|vert|ind)ix|ex$/'  => '\\1ices',     // matrix, vertex, index\n\t\t\t'/(x|ch|ss|sh)$/'          => '\\1es',       // search, switch, fix, box, process, address\n\t\t\t'/([^aeiouy]|qu)y$/'       => '\\1ies',      // query, ability, agency\n\t\t\t'/(hive)$/'                => '\\1s',        // archive, hive\n\t\t\t'/(?:([^f])fe|([lr])f)$/'  => '\\1\\2ves',    // half, safe, wife\n\t\t\t'/sis$/'                   => 'ses',        // basis, diagnosis\n\t\t\t'/([ti])um$/'              => '\\1a',        // datum, medium\n\t\t\t'/(p)erson$/'              => '\\1eople',    // person, salesperson\n\t\t\t'/(m)an$/'                 => '\\1en',       // man, woman, spokesman\n\t\t\t'/(c)hild$/'               => '\\1hildren',  // child\n\t\t\t'/(buffal|tomat)o$/'       => '\\1\\2oes',    // buffalo, tomato\n\t\t\t'/(bu|campu)s$/'           => '\\1\\2ses',    // bus, campus\n\t\t\t'/(alias|status|virus)$/'  => '\\1es',       // alias\n\t\t\t'/(octop)us$/'             => '\\1i',        // octopus\n\t\t\t'/(ax|cris|test)is$/'      => '\\1es',       // axis, crisis\n\t\t\t'/s$/'                     => 's',          // no change (compatibility)\n\t\t\t'/$/'                      => 's',\n\t\t);\n\n\t\tforeach ($plural_rules as $rule => $replacement)\n\t\t{\n\t\t\tif (preg_match($rule, $result))\n\t\t\t{\n\t\t\t\t$result = preg_replace($rule, $replacement, $result);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn $result;\n\t}\n}\n\n// --------------------------------------------------------------------\n\nif ( ! function_exists('camelize'))\n{\n\t/**\n\t * Camelize\n\t *\n\t * Takes multiple words separated by spaces or underscores and camelizes them\n\t *\n\t * @param\tstring\t$str\tInput string\n\t * @return\tstring\n\t */\n\tfunction camelize($str)\n\t{\n\t\treturn strtolower($str[0]).substr(str_replace(' ', '', ucwords(preg_replace('/[\\s_]+/', ' ', $str))), 1);\n\t}\n}\n\n// --------------------------------------------------------------------\n\nif ( ! function_exists('underscore'))\n{\n\t/**\n\t * Underscore\n\t *\n\t * Takes multiple words separated by spaces and underscores them\n\t *\n\t * @param\tstring\t$str\tInput string\n\t * @return\tstring\n\t */\n\tfunction underscore($str)\n\t{\n\t\treturn preg_replace('/[\\s]+/', '_', trim(MB_ENABLED ? mb_strtolower($str) : strtolower($str)));\n\t}\n}\n\n// --------------------------------------------------------------------\n\nif ( ! function_exists('humanize'))\n{\n\t/**\n\t * Humanize\n\t *\n\t * Takes multiple words separated by the separator and changes them to spaces\n\t *\n\t * @param\tstring\t$str\t\tInput string\n\t * @param \tstring\t$separator\tInput separator\n\t * @return\tstring\n\t */\n\tfunction humanize($str, $separator = '_')\n\t{\n\t\treturn ucwords(preg_replace('/['.preg_quote($separator).']+/', ' ', trim(MB_ENABLED ? mb_strtolower($str) : strtolower($str))));\n\t}\n}\n\n// --------------------------------------------------------------------\n\nif ( ! function_exists('is_countable'))\n{\n\t/**\n\t * Checks if the given word has a plural version.\n\t *\n\t * @param\tstring\t$word\tWord to check\n\t * @return\tbool\n\t */\n\tfunction is_countable($word)\n\t{\n\t\treturn ! in_array(\n\t\t\tstrtolower($word),\n\t\t\tarray(\n\t\t\t\t'equipment', 'information', 'rice', 'money',\n\t\t\t\t'species', 'series', 'fish', 'meta'\n\t\t\t)\n\t\t);\n\t}\n}\n"
  },
  {
    "path": "system/helpers/language_helper.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Language Helpers\n *\n * @package\t\tCodeIgniter\n * @subpackage\tHelpers\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/helpers/language_helper.html\n */\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('lang'))\n{\n\t/**\n\t * Lang\n\t *\n\t * Fetches a language variable and optionally outputs a form label\n\t *\n\t * @param\tstring\t$line\t\tThe language line\n\t * @param\tstring\t$for\t\tThe \"for\" value (id of the form element)\n\t * @param\tarray\t$attributes\tAny additional HTML attributes\n\t * @return\tstring\n\t */\n\tfunction lang($line, $for = '', $attributes = array())\n\t{\n\t\t$line = get_instance()->lang->line($line);\n\n\t\tif ($for !== '')\n\t\t{\n\t\t\t$line = '<label for=\"'.$for.'\"'._stringify_attributes($attributes).'>'.$line.'</label>';\n\t\t}\n\n\t\treturn $line;\n\t}\n}\n"
  },
  {
    "path": "system/helpers/number_helper.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Number Helpers\n *\n * @package\t\tCodeIgniter\n * @subpackage\tHelpers\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/helpers/number_helper.html\n */\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('byte_format'))\n{\n\t/**\n\t * Formats a numbers as bytes, based on size, and adds the appropriate suffix\n\t *\n\t * @param\tmixed\twill be cast as int\n\t * @param\tint\n\t * @return\tstring\n\t */\n\tfunction byte_format($num, $precision = 1)\n\t{\n\t\t$CI =& get_instance();\n\t\t$CI->lang->load('number');\n\n\t\tif ($num >= 1000000000000)\n\t\t{\n\t\t\t$num = round($num / 1099511627776, $precision);\n\t\t\t$unit = $CI->lang->line('terabyte_abbr');\n\t\t}\n\t\telseif ($num >= 1000000000)\n\t\t{\n\t\t\t$num = round($num / 1073741824, $precision);\n\t\t\t$unit = $CI->lang->line('gigabyte_abbr');\n\t\t}\n\t\telseif ($num >= 1000000)\n\t\t{\n\t\t\t$num = round($num / 1048576, $precision);\n\t\t\t$unit = $CI->lang->line('megabyte_abbr');\n\t\t}\n\t\telseif ($num >= 1000)\n\t\t{\n\t\t\t$num = round($num / 1024, $precision);\n\t\t\t$unit = $CI->lang->line('kilobyte_abbr');\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$unit = $CI->lang->line('bytes');\n\t\t\treturn number_format($num).' '.$unit;\n\t\t}\n\n\t\treturn number_format($num, $precision).' '.$unit;\n\t}\n}\n"
  },
  {
    "path": "system/helpers/path_helper.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Path Helpers\n *\n * @package\t\tCodeIgniter\n * @subpackage\tHelpers\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/helpers/path_helper.html\n */\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('set_realpath'))\n{\n\t/**\n\t * Set Realpath\n\t *\n\t * @param\tstring\n\t * @param\tbool\tchecks to see if the path exists\n\t * @return\tstring\n\t */\n\tfunction set_realpath($path, $check_existance = FALSE)\n\t{\n\t\t// Security check to make sure the path is NOT a URL. No remote file inclusion!\n\t\tif (preg_match('#^(http:\\/\\/|https:\\/\\/|www\\.|ftp|php:\\/\\/)#i', $path) OR filter_var($path, FILTER_VALIDATE_IP) === $path)\n\t\t{\n\t\t\tshow_error('The path you submitted must be a local server path, not a URL');\n\t\t}\n\n\t\t// Resolve the path\n\t\tif (realpath($path) !== FALSE)\n\t\t{\n\t\t\t$path = realpath($path);\n\t\t}\n\t\telseif ($check_existance && ! is_dir($path) && ! is_file($path))\n\t\t{\n\t\t\tshow_error('Not a valid path: '.$path);\n\t\t}\n\n\t\t// Add a trailing slash, if this is a directory\n\t\treturn is_dir($path) ? rtrim($path, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR : $path;\n\t}\n}\n"
  },
  {
    "path": "system/helpers/security_helper.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Security Helpers\n *\n * @package\t\tCodeIgniter\n * @subpackage\tHelpers\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/helpers/security_helper.html\n */\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('xss_clean'))\n{\n\t/**\n\t * XSS Filtering\n\t *\n\t * @param\tstring\n\t * @param\tbool\twhether or not the content is an image file\n\t * @return\tstring\n\t */\n\tfunction xss_clean($str, $is_image = FALSE)\n\t{\n\t\treturn get_instance()->security->xss_clean($str, $is_image);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('sanitize_filename'))\n{\n\t/**\n\t * Sanitize Filename\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tfunction sanitize_filename($filename)\n\t{\n\t\treturn get_instance()->security->sanitize_filename($filename);\n\t}\n}\n\n// --------------------------------------------------------------------\n\nif ( ! function_exists('do_hash'))\n{\n\t/**\n\t * Hash encode a string\n\t *\n\t * @todo\tRemove in version 3.1+.\n\t * @deprecated\t3.0.0\tUse PHP's native hash() instead.\n\t * @param\tstring\t$str\n\t * @param\tstring\t$type = 'sha1'\n\t * @return\tstring\n\t */\n\tfunction do_hash($str, $type = 'sha1')\n\t{\n\t\tif ( ! in_array(strtolower($type), hash_algos()))\n\t\t{\n\t\t\t$type = 'md5';\n\t\t}\n\n\t\treturn hash($type, $str);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('strip_image_tags'))\n{\n\t/**\n\t * Strip Image Tags\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tfunction strip_image_tags($str)\n\t{\n\t\treturn get_instance()->security->strip_image_tags($str);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('encode_php_tags'))\n{\n\t/**\n\t * Convert PHP tags to entities\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tfunction encode_php_tags($str)\n\t{\n\t\treturn str_replace(array('<?', '?>'), array('&lt;?', '?&gt;'), $str);\n\t}\n}\n"
  },
  {
    "path": "system/helpers/smiley_helper.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Smiley Helpers\n *\n * @package\t\tCodeIgniter\n * @subpackage\tHelpers\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/helpers/smiley_helper.html\n * @deprecated\t3.0.0\tThis helper is too specific for CI.\n */\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('smiley_js'))\n{\n\t/**\n\t * Smiley Javascript\n\t *\n\t * Returns the javascript required for the smiley insertion.  Optionally takes\n\t * an array of aliases to loosely couple the smiley array to the view.\n\t *\n\t * @param\tmixed\talias name or array of alias->field_id pairs\n\t * @param\tstring\tfield_id if alias name was passed in\n\t * @param\tbool\n\t * @return\tarray\n\t */\n\tfunction smiley_js($alias = '', $field_id = '', $inline = TRUE)\n\t{\n\t\tstatic $do_setup = TRUE;\n\t\t$r = '';\n\n\t\tif ($alias !== '' && ! is_array($alias))\n\t\t{\n\t\t\t$alias = array($alias => $field_id);\n\t\t}\n\n\t\tif ($do_setup === TRUE)\n\t\t{\n\t\t\t$do_setup = FALSE;\n\t\t\t$m = array();\n\n\t\t\tif (is_array($alias))\n\t\t\t{\n\t\t\t\tforeach ($alias as $name => $id)\n\t\t\t\t{\n\t\t\t\t\t$m[] = '\"'.$name.'\" : \"'.$id.'\"';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$m = '{'.implode(',', $m).'}';\n\n\t\t\t$r .= <<<EOF\n\t\t\tvar smiley_map = {$m};\n\n\t\t\tfunction insert_smiley(smiley, field_id) {\n\t\t\t\tvar el = document.getElementById(field_id), newStart;\n\n\t\t\t\tif ( ! el && smiley_map[field_id]) {\n\t\t\t\t\tel = document.getElementById(smiley_map[field_id]);\n\n\t\t\t\t\tif ( ! el)\n\t\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tel.focus();\n\t\t\t\tsmiley = \" \" + smiley;\n\n\t\t\t\tif ('selectionStart' in el) {\n\t\t\t\t\tnewStart = el.selectionStart + smiley.length;\n\n\t\t\t\t\tel.value = el.value.substr(0, el.selectionStart) +\n\t\t\t\t\t\t\t\t\tsmiley +\n\t\t\t\t\t\t\t\t\tel.value.substr(el.selectionEnd, el.value.length);\n\t\t\t\t\tel.setSelectionRange(newStart, newStart);\n\t\t\t\t}\n\t\t\t\telse if (document.selection) {\n\t\t\t\t\tdocument.selection.createRange().text = smiley;\n\t\t\t\t}\n\t\t\t}\nEOF;\n\t\t}\n\t\telseif (is_array($alias))\n\t\t{\n\t\t\tforeach ($alias as $name => $id)\n\t\t\t{\n\t\t\t\t$r .= 'smiley_map[\"'.$name.'\"] = \"'.$id.\"\\\";\\n\";\n\t\t\t}\n\t\t}\n\n\t\treturn ($inline)\n\t\t\t? '<script type=\"text/javascript\" charset=\"utf-8\">/*<![CDATA[ */'.$r.'// ]]></script>'\n\t\t\t: $r;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('get_clickable_smileys'))\n{\n\t/**\n\t * Get Clickable Smileys\n\t *\n\t * Returns an array of image tag links that can be clicked to be inserted\n\t * into a form field.\n\t *\n\t * @param\tstring\tthe URL to the folder containing the smiley images\n\t * @param\tarray\n\t * @return\tarray\n\t */\n\tfunction get_clickable_smileys($image_url, $alias = '')\n\t{\n\t\t// For backward compatibility with js_insert_smiley\n\t\tif (is_array($alias))\n\t\t{\n\t\t\t$smileys = $alias;\n\t\t}\n\t\telseif (FALSE === ($smileys = _get_smiley_array()))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Add a trailing slash to the file path if needed\n\t\t$image_url = rtrim($image_url, '/').'/';\n\n\t\t$used = array();\n\t\tforeach ($smileys as $key => $val)\n\t\t{\n\t\t\t// Keep duplicates from being used, which can happen if the\n\t\t\t// mapping array contains multiple identical replacements. For example:\n\t\t\t// :-) and :) might be replaced with the same image so both smileys\n\t\t\t// will be in the array.\n\t\t\tif (isset($used[$smileys[$key][0]]))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t$link[] = '<a href=\"javascript:void(0);\" onclick=\"insert_smiley(\\''.$key.'\\', \\''.$alias.'\\')\"><img src=\"'.$image_url.$smileys[$key][0].'\" alt=\"'.$smileys[$key][3].'\" style=\"width: '.$smileys[$key][1].'; height: '.$smileys[$key][2].'; border: 0;\" /></a>';\n\t\t\t$used[$smileys[$key][0]] = TRUE;\n\t\t}\n\n\t\treturn $link;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('parse_smileys'))\n{\n\t/**\n\t * Parse Smileys\n\t *\n\t * Takes a string as input and swaps any contained smileys for the actual image\n\t *\n\t * @param\tstring\tthe text to be parsed\n\t * @param\tstring\tthe URL to the folder containing the smiley images\n\t * @param\tarray\n\t * @return\tstring\n\t */\n\tfunction parse_smileys($str = '', $image_url = '', $smileys = NULL)\n\t{\n\t\tif ($image_url === '' OR ( ! is_array($smileys) && FALSE === ($smileys = _get_smiley_array())))\n\t\t{\n\t\t\treturn $str;\n\t\t}\n\n\t\t// Add a trailing slash to the file path if needed\n\t\t$image_url = rtrim($image_url, '/').'/';\n\n\t\tforeach ($smileys as $key => $val)\n\t\t{\n\t\t\t$str = str_replace($key, '<img src=\"'.$image_url.$smileys[$key][0].'\" alt=\"'.$smileys[$key][3].'\" style=\"width: '.$smileys[$key][1].'; height: '.$smileys[$key][2].'; border: 0;\" />', $str);\n\t\t}\n\n\t\treturn $str;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('_get_smiley_array'))\n{\n\t/**\n\t * Get Smiley Array\n\t *\n\t * Fetches the config/smiley.php file\n\t *\n\t * @return\tmixed\n\t */\n\tfunction _get_smiley_array()\n\t{\n\t\tstatic $_smileys;\n\n\t\tif ( ! is_array($_smileys))\n\t\t{\n\t\t\tif (file_exists(APPPATH.'config/smileys.php'))\n\t\t\t{\n\t\t\t\tinclude(APPPATH.'config/smileys.php');\n\t\t\t}\n\n\t\t\tif (file_exists(APPPATH.'config/'.ENVIRONMENT.'/smileys.php'))\n\t\t\t{\n\t\t\t\tinclude(APPPATH.'config/'.ENVIRONMENT.'/smileys.php');\n\t\t\t}\n\n\t\t\tif (empty($smileys) OR ! is_array($smileys))\n\t\t\t{\n\t\t\t\t$_smileys = array();\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$_smileys = $smileys;\n\t\t}\n\n\t\treturn $_smileys;\n\t}\n}\n"
  },
  {
    "path": "system/helpers/string_helper.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter String Helpers\n *\n * @package\t\tCodeIgniter\n * @subpackage\tHelpers\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/helpers/string_helper.html\n */\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('trim_slashes'))\n{\n\t/**\n\t * Trim Slashes\n\t *\n\t * Removes any leading/trailing slashes from a string:\n\t *\n\t * /this/that/theother/\n\t *\n\t * becomes:\n\t *\n\t * this/that/theother\n\t *\n\t * @todo\tRemove in version 3.1+.\n\t * @deprecated\t3.0.0\tThis is just an alias for PHP's native trim()\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tfunction trim_slashes($str)\n\t{\n\t\treturn trim($str, '/');\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('strip_slashes'))\n{\n\t/**\n\t * Strip Slashes\n\t *\n\t * Removes slashes contained in a string or in an array\n\t *\n\t * @param\tmixed\tstring or array\n\t * @return\tmixed\tstring or array\n\t */\n\tfunction strip_slashes($str)\n\t{\n\t\tif ( ! is_array($str))\n\t\t{\n\t\t\treturn stripslashes($str);\n\t\t}\n\n\t\tforeach ($str as $key => $val)\n\t\t{\n\t\t\t$str[$key] = strip_slashes($val);\n\t\t}\n\n\t\treturn $str;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('strip_quotes'))\n{\n\t/**\n\t * Strip Quotes\n\t *\n\t * Removes single and double quotes from a string\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tfunction strip_quotes($str)\n\t{\n\t\treturn str_replace(array('\"', \"'\"), '', $str);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('quotes_to_entities'))\n{\n\t/**\n\t * Quotes to Entities\n\t *\n\t * Converts single and double quotes to entities\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tfunction quotes_to_entities($str)\n\t{\n\t\treturn str_replace(array(\"\\'\",\"\\\"\",\"'\",'\"'), array(\"&#39;\",\"&quot;\",\"&#39;\",\"&quot;\"), $str);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('reduce_double_slashes'))\n{\n\t/**\n\t * Reduce Double Slashes\n\t *\n\t * Converts double slashes in a string to a single slash,\n\t * except those found in http://\n\t *\n\t * http://www.some-site.com//index.php\n\t *\n\t * becomes:\n\t *\n\t * http://www.some-site.com/index.php\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tfunction reduce_double_slashes($str)\n\t{\n\t\treturn preg_replace('#(^|[^:])//+#', '\\\\1/', $str);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('reduce_multiples'))\n{\n\t/**\n\t * Reduce Multiples\n\t *\n\t * Reduces multiple instances of a particular character.  Example:\n\t *\n\t * Fred, Bill,, Joe, Jimmy\n\t *\n\t * becomes:\n\t *\n\t * Fred, Bill, Joe, Jimmy\n\t *\n\t * @param\tstring\n\t * @param\tstring\tthe character you wish to reduce\n\t * @param\tbool\tTRUE/FALSE - whether to trim the character from the beginning/end\n\t * @return\tstring\n\t */\n\tfunction reduce_multiples($str, $character = ',', $trim = FALSE)\n\t{\n\t\t$str = preg_replace('#'.preg_quote($character, '#').'{2,}#', $character, $str);\n\t\treturn ($trim === TRUE) ? trim($str, $character) : $str;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('random_string'))\n{\n\t/**\n\t * Create a Random String\n\t *\n\t * Useful for generating passwords or hashes.\n\t *\n\t * @param\tstring\ttype of random string.  basic, alpha, alnum, numeric, nozero, unique, md5, encrypt and sha1\n\t * @param\tint\tnumber of characters\n\t * @return\tstring\n\t */\n\tfunction random_string($type = 'alnum', $len = 8)\n\t{\n\t\tswitch ($type)\n\t\t{\n\t\t\tcase 'basic':\n\t\t\t\treturn mt_rand();\n\t\t\tcase 'alnum':\n\t\t\tcase 'numeric':\n\t\t\tcase 'nozero':\n\t\t\tcase 'alpha':\n\t\t\t\tswitch ($type)\n\t\t\t\t{\n\t\t\t\t\tcase 'alpha':\n\t\t\t\t\t\t$pool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'alnum':\n\t\t\t\t\t\t$pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'numeric':\n\t\t\t\t\t\t$pool = '0123456789';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'nozero':\n\t\t\t\t\t\t$pool = '123456789';\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\treturn substr(str_shuffle(str_repeat($pool, ceil($len / strlen($pool)))), 0, $len);\n\t\t\tcase 'unique': // todo: remove in 3.1+\n\t\t\tcase 'md5':\n\t\t\t\treturn md5(uniqid(mt_rand()));\n\t\t\tcase 'encrypt': // todo: remove in 3.1+\n\t\t\tcase 'sha1':\n\t\t\t\treturn sha1(uniqid(mt_rand(), TRUE));\n\t\t}\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('increment_string'))\n{\n\t/**\n\t * Add's _1 to a string or increment the ending number to allow _2, _3, etc\n\t *\n\t * @param\tstring\trequired\n\t * @param\tstring\tWhat should the duplicate number be appended with\n\t * @param\tstring\tWhich number should be used for the first dupe increment\n\t * @return\tstring\n\t */\n\tfunction increment_string($str, $separator = '_', $first = 1)\n\t{\n\t\tpreg_match('/(.+)'.preg_quote($separator, '/').'([0-9]+)$/', $str, $match);\n\t\treturn isset($match[2]) ? $match[1].$separator.($match[2] + 1) : $str.$separator.$first;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('alternator'))\n{\n\t/**\n\t * Alternator\n\t *\n\t * Allows strings to be alternated. See docs...\n\t *\n\t * @param\tstring (as many parameters as needed)\n\t * @return\tstring\n\t */\n\tfunction alternator()\n\t{\n\t\tstatic $i;\n\n\t\tif (func_num_args() === 0)\n\t\t{\n\t\t\t$i = 0;\n\t\t\treturn '';\n\t\t}\n\n\t\t$args = func_get_args();\n\t\treturn $args[($i++ % count($args))];\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('repeater'))\n{\n\t/**\n\t * Repeater function\n\t *\n\t * @todo\tRemove in version 3.1+.\n\t * @deprecated\t3.0.0\tThis is just an alias for PHP's native str_repeat()\n\t *\n\t * @param\tstring\t$data\tString to repeat\n\t * @param\tint\t$num\tNumber of repeats\n\t * @return\tstring\n\t */\n\tfunction repeater($data, $num = 1)\n\t{\n\t\treturn ($num > 0) ? str_repeat($data, $num) : '';\n\t}\n}\n"
  },
  {
    "path": "system/helpers/text_helper.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Text Helpers\n *\n * @package\t\tCodeIgniter\n * @subpackage\tHelpers\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/helpers/text_helper.html\n */\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('word_limiter'))\n{\n\t/**\n\t * Word Limiter\n\t *\n\t * Limits a string to X number of words.\n\t *\n\t * @param\tstring\n\t * @param\tint\n\t * @param\tstring\tthe end character. Usually an ellipsis\n\t * @return\tstring\n\t */\n\tfunction word_limiter($str, $limit = 100, $end_char = '&#8230;')\n\t{\n\t\tif (trim($str) === '')\n\t\t{\n\t\t\treturn $str;\n\t\t}\n\n\t\tpreg_match('/^\\s*+(?:\\S++\\s*+){1,'.(int) $limit.'}/', $str, $matches);\n\n\t\tif (strlen($str) === strlen($matches[0]))\n\t\t{\n\t\t\t$end_char = '';\n\t\t}\n\n\t\treturn rtrim($matches[0]).$end_char;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('character_limiter'))\n{\n\t/**\n\t * Character Limiter\n\t *\n\t * Limits the string based on the character count.  Preserves complete words\n\t * so the character count may not be exactly as specified.\n\t *\n\t * @param\tstring\n\t * @param\tint\n\t * @param\tstring\tthe end character. Usually an ellipsis\n\t * @return\tstring\n\t */\n\tfunction character_limiter($str, $n = 500, $end_char = '&#8230;')\n\t{\n\t\tif (mb_strlen($str) < $n)\n\t\t{\n\t\t\treturn $str;\n\t\t}\n\n\t\t// a bit complicated, but faster than preg_replace with \\s+\n\t\t$str = preg_replace('/ {2,}/', ' ', str_replace(array(\"\\r\", \"\\n\", \"\\t\", \"\\x0B\", \"\\x0C\"), ' ', $str));\n\n\t\tif (mb_strlen($str) <= $n)\n\t\t{\n\t\t\treturn $str;\n\t\t}\n\n\t\t$out = '';\n\t\tforeach (explode(' ', trim($str)) as $val)\n\t\t{\n\t\t\t$out .= $val.' ';\n\n\t\t\tif (mb_strlen($out) >= $n)\n\t\t\t{\n\t\t\t\t$out = trim($out);\n\t\t\t\treturn (mb_strlen($out) === mb_strlen($str)) ? $out : $out.$end_char;\n\t\t\t}\n\t\t}\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('ascii_to_entities'))\n{\n\t/**\n\t * High ASCII to Entities\n\t *\n\t * Converts high ASCII text and MS Word special characters to character entities\n\t *\n\t * @param\tstring\t$str\n\t * @return\tstring\n\t */\n\tfunction ascii_to_entities($str)\n\t{\n\t\t$out = '';\n\t\tfor ($i = 0, $s = strlen($str) - 1, $count = 1, $temp = array(); $i <= $s; $i++)\n\t\t{\n\t\t\t$ordinal = ord($str[$i]);\n\n\t\t\tif ($ordinal < 128)\n\t\t\t{\n\t\t\t\t/*\n\t\t\t\t\tIf the $temp array has a value but we have moved on, then it seems only\n\t\t\t\t\tfair that we output that entity and restart $temp before continuing. -Paul\n\t\t\t\t*/\n\t\t\t\tif (count($temp) === 1)\n\t\t\t\t{\n\t\t\t\t\t$out .= '&#'.array_shift($temp).';';\n\t\t\t\t\t$count = 1;\n\t\t\t\t}\n\n\t\t\t\t$out .= $str[$i];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (count($temp) === 0)\n\t\t\t\t{\n\t\t\t\t\t$count = ($ordinal < 224) ? 2 : 3;\n\t\t\t\t}\n\n\t\t\t\t$temp[] = $ordinal;\n\n\t\t\t\tif (count($temp) === $count)\n\t\t\t\t{\n\t\t\t\t\t$number = ($count === 3)\n\t\t\t\t\t\t? (($temp[0] % 16) * 4096) + (($temp[1] % 64) * 64) + ($temp[2] % 64)\n\t\t\t\t\t\t: (($temp[0] % 32) * 64) + ($temp[1] % 64);\n\n\t\t\t\t\t$out .= '&#'.$number.';';\n\t\t\t\t\t$count = 1;\n\t\t\t\t\t$temp = array();\n\t\t\t\t}\n\t\t\t\t// If this is the last iteration, just output whatever we have\n\t\t\t\telseif ($i === $s)\n\t\t\t\t{\n\t\t\t\t\t$out .= '&#'.implode(';', $temp).';';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn $out;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('entities_to_ascii'))\n{\n\t/**\n\t * Entities to ASCII\n\t *\n\t * Converts character entities back to ASCII\n\t *\n\t * @param\tstring\n\t * @param\tbool\n\t * @return\tstring\n\t */\n\tfunction entities_to_ascii($str, $all = TRUE)\n\t{\n\t\tif (preg_match_all('/\\&#(\\d+)\\;/', $str, $matches))\n\t\t{\n\t\t\tfor ($i = 0, $s = count($matches[0]); $i < $s; $i++)\n\t\t\t{\n\t\t\t\t$digits = $matches[1][$i];\n\t\t\t\t$out = '';\n\n\t\t\t\tif ($digits < 128)\n\t\t\t\t{\n\t\t\t\t\t$out .= chr($digits);\n\n\t\t\t\t}\n\t\t\t\telseif ($digits < 2048)\n\t\t\t\t{\n\t\t\t\t\t$out .= chr(192 + (($digits - ($digits % 64)) / 64)).chr(128 + ($digits % 64));\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$out .= chr(224 + (($digits - ($digits % 4096)) / 4096))\n\t\t\t\t\t\t.chr(128 + ((($digits % 4096) - ($digits % 64)) / 64))\n\t\t\t\t\t\t.chr(128 + ($digits % 64));\n\t\t\t\t}\n\n\t\t\t\t$str = str_replace($matches[0][$i], $out, $str);\n\t\t\t}\n\t\t}\n\n\t\tif ($all)\n\t\t{\n\t\t\treturn str_replace(\n\t\t\t\tarray('&amp;', '&lt;', '&gt;', '&quot;', '&apos;', '&#45;'),\n\t\t\t\tarray('&', '<', '>', '\"', \"'\", '-'),\n\t\t\t\t$str\n\t\t\t);\n\t\t}\n\n\t\treturn $str;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('word_censor'))\n{\n\t/**\n\t * Word Censoring Function\n\t *\n\t * Supply a string and an array of disallowed words and any\n\t * matched words will be converted to #### or to the replacement\n\t * word you've submitted.\n\t *\n\t * @param\tstring\tthe text string\n\t * @param\tstring\tthe array of censored words\n\t * @param\tstring\tthe optional replacement value\n\t * @return\tstring\n\t */\n\tfunction word_censor($str, $censored, $replacement = '')\n\t{\n\t\tif ( ! is_array($censored))\n\t\t{\n\t\t\treturn $str;\n\t\t}\n\n\t\t$str = ' '.$str.' ';\n\n\t\t// \\w, \\b and a few others do not match on a unicode character\n\t\t// set for performance reasons. As a result words like über\n\t\t// will not match on a word boundary. Instead, we'll assume that\n\t\t// a bad word will be bookeneded by any of these characters.\n\t\t$delim = '[-_\\'\\\"`(){}<>\\[\\]|!?@#%&,.:;^~*+=\\/ 0-9\\n\\r\\t]';\n\n\t\tforeach ($censored as $badword)\n\t\t{\n\t\t\t$badword = str_replace('\\*', '\\w*?', preg_quote($badword, '/'));\n\t\t\tif ($replacement !== '')\n\t\t\t{\n\t\t\t\t$str = preg_replace(\n\t\t\t\t\t\"/({$delim})(\".$badword.\")({$delim})/i\",\n\t\t\t\t\t\"\\\\1{$replacement}\\\\3\",\n\t\t\t\t\t$str\n\t\t\t\t);\n\t\t\t}\n\t\t\telseif (preg_match_all(\"/{$delim}(\".$badword.\"){$delim}/i\", $str, $matches, PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE))\n\t\t\t{\n\t\t\t\t$matches = $matches[1];\n\t\t\t\tfor ($i = count($matches) - 1; $i >= 0; $i--)\n\t\t\t\t{\n\t\t\t\t\t$length = strlen($matches[$i][0]);\n\t\t\t\t\t$str = substr_replace(\n\t\t\t\t\t\t$str,\n\t\t\t\t\t\tstr_repeat('#', $length),\n\t\t\t\t\t\t$matches[$i][1],\n\t\t\t\t\t\t$length\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn trim($str);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('highlight_code'))\n{\n\t/**\n\t * Code Highlighter\n\t *\n\t * Colorizes code strings\n\t *\n\t * @param\tstring\tthe text string\n\t * @return\tstring\n\t */\n\tfunction highlight_code($str)\n\t{\n\t\t/* The highlight string function encodes and highlights\n\t\t * brackets so we need them to start raw.\n\t\t *\n\t\t * Also replace any existing PHP tags to temporary markers\n\t\t * so they don't accidentally break the string out of PHP,\n\t\t * and thus, thwart the highlighting.\n\t\t */\n\t\t$str = str_replace(\n\t\t\tarray('&lt;', '&gt;', '<?', '?>', '<%', '%>', '\\\\', '</script>'),\n\t\t\tarray('<', '>', 'phptagopen', 'phptagclose', 'asptagopen', 'asptagclose', 'backslashtmp', 'scriptclose'),\n\t\t\t$str\n\t\t);\n\n\t\t// The highlight_string function requires that the text be surrounded\n\t\t// by PHP tags, which we will remove later\n\t\t$str = highlight_string('<?php '.$str.' ?>', TRUE);\n\n\t\t// Remove our artificially added PHP, and the syntax highlighting that came with it\n\t\t$str = preg_replace(\n\t\t\tarray(\n\t\t\t\t'/<span style=\"color: #([A-Z0-9]+)\">&lt;\\?php(&nbsp;| )/i',\n\t\t\t\t'/(<span style=\"color: #[A-Z0-9]+\">.*?)\\?&gt;<\\/span>\\n<\\/span>\\n<\\/code>/is',\n\t\t\t\t'/<span style=\"color: #[A-Z0-9]+\"\\><\\/span>/i'\n\t\t\t),\n\t\t\tarray(\n\t\t\t\t'<span style=\"color: #$1\">',\n\t\t\t\t\"$1</span>\\n</span>\\n</code>\",\n\t\t\t\t''\n\t\t\t),\n\t\t\t$str\n\t\t);\n\n\t\t// Replace our markers back to PHP tags.\n\t\treturn str_replace(\n\t\t\tarray('phptagopen', 'phptagclose', 'asptagopen', 'asptagclose', 'backslashtmp', 'scriptclose'),\n\t\t\tarray('&lt;?', '?&gt;', '&lt;%', '%&gt;', '\\\\', '&lt;/script&gt;'),\n\t\t\t$str\n\t\t);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('highlight_phrase'))\n{\n\t/**\n\t * Phrase Highlighter\n\t *\n\t * Highlights a phrase within a text string\n\t *\n\t * @param\tstring\t$str\t\tthe text string\n\t * @param\tstring\t$phrase\t\tthe phrase you'd like to highlight\n\t * @param\tstring\t$tag_open\tthe openging tag to precede the phrase with\n\t * @param\tstring\t$tag_close\tthe closing tag to end the phrase with\n\t * @return\tstring\n\t */\n\tfunction highlight_phrase($str, $phrase, $tag_open = '<mark>', $tag_close = '</mark>')\n\t{\n\t\treturn ($str !== '' && $phrase !== '')\n\t\t\t? preg_replace('/('.preg_quote($phrase, '/').')/i'.(UTF8_ENABLED ? 'u' : ''), $tag_open.'\\\\1'.$tag_close, $str)\n\t\t\t: $str;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('convert_accented_characters'))\n{\n\t/**\n\t * Convert Accented Foreign Characters to ASCII\n\t *\n\t * @param\tstring\t$str\tInput string\n\t * @return\tstring\n\t */\n\tfunction convert_accented_characters($str)\n\t{\n\t\tstatic $array_from, $array_to;\n\n\t\tif ( ! is_array($array_from))\n\t\t{\n\t\t\tif (file_exists(APPPATH.'config/foreign_chars.php'))\n\t\t\t{\n\t\t\t\tinclude(APPPATH.'config/foreign_chars.php');\n\t\t\t}\n\n\t\t\tif (file_exists(APPPATH.'config/'.ENVIRONMENT.'/foreign_chars.php'))\n\t\t\t{\n\t\t\t\tinclude(APPPATH.'config/'.ENVIRONMENT.'/foreign_chars.php');\n\t\t\t}\n\n\t\t\tif (empty($foreign_characters) OR ! is_array($foreign_characters))\n\t\t\t{\n\t\t\t\t$array_from = array();\n\t\t\t\t$array_to = array();\n\n\t\t\t\treturn $str;\n\t\t\t}\n\n\t\t\t$array_from = array_keys($foreign_characters);\n\t\t\t$array_to = array_values($foreign_characters);\n\t\t}\n\n\t\treturn preg_replace($array_from, $array_to, $str);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('word_wrap'))\n{\n\t/**\n\t * Word Wrap\n\t *\n\t * Wraps text at the specified character. Maintains the integrity of words.\n\t * Anything placed between {unwrap}{/unwrap} will not be word wrapped, nor\n\t * will URLs.\n\t *\n\t * @param\tstring\t$str\t\tthe text string\n\t * @param\tint\t$charlim = 76\tthe number of characters to wrap at\n\t * @return\tstring\n\t */\n\tfunction word_wrap($str, $charlim = 76)\n\t{\n\t\t// Set the character limit\n\t\tis_numeric($charlim) OR $charlim = 76;\n\n\t\t// Reduce multiple spaces\n\t\t$str = preg_replace('| +|', ' ', $str);\n\n\t\t// Standardize newlines\n\t\tif (strpos($str, \"\\r\") !== FALSE)\n\t\t{\n\t\t\t$str = str_replace(array(\"\\r\\n\", \"\\r\"), \"\\n\", $str);\n\t\t}\n\n\t\t// If the current word is surrounded by {unwrap} tags we'll\n\t\t// strip the entire chunk and replace it with a marker.\n\t\t$unwrap = array();\n\t\tif (preg_match_all('|\\{unwrap\\}(.+?)\\{/unwrap\\}|s', $str, $matches))\n\t\t{\n\t\t\tfor ($i = 0, $c = count($matches[0]); $i < $c; $i++)\n\t\t\t{\n\t\t\t\t$unwrap[] = $matches[1][$i];\n\t\t\t\t$str = str_replace($matches[0][$i], '{{unwrapped'.$i.'}}', $str);\n\t\t\t}\n\t\t}\n\n\t\t// Use PHP's native function to do the initial wordwrap.\n\t\t// We set the cut flag to FALSE so that any individual words that are\n\t\t// too long get left alone. In the next step we'll deal with them.\n\t\t$str = wordwrap($str, $charlim, \"\\n\", FALSE);\n\n\t\t// Split the string into individual lines of text and cycle through them\n\t\t$output = '';\n\t\tforeach (explode(\"\\n\", $str) as $line)\n\t\t{\n\t\t\t// Is the line within the allowed character count?\n\t\t\t// If so we'll join it to the output and continue\n\t\t\tif (mb_strlen($line) <= $charlim)\n\t\t\t{\n\t\t\t\t$output .= $line.\"\\n\";\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t$temp = '';\n\t\t\twhile (mb_strlen($line) > $charlim)\n\t\t\t{\n\t\t\t\t// If the over-length word is a URL we won't wrap it\n\t\t\t\tif (preg_match('!\\[url.+\\]|://|www\\.!', $line))\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// Trim the word down\n\t\t\t\t$temp .= mb_substr($line, 0, $charlim - 1);\n\t\t\t\t$line = mb_substr($line, $charlim - 1);\n\t\t\t}\n\n\t\t\t// If $temp contains data it means we had to split up an over-length\n\t\t\t// word into smaller chunks so we'll add it back to our current line\n\t\t\tif ($temp !== '')\n\t\t\t{\n\t\t\t\t$output .= $temp.\"\\n\".$line.\"\\n\";\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$output .= $line.\"\\n\";\n\t\t\t}\n\t\t}\n\n\t\t// Put our markers back\n\t\tif (count($unwrap) > 0)\n\t\t{\n\t\t\tforeach ($unwrap as $key => $val)\n\t\t\t{\n\t\t\t\t$output = str_replace('{{unwrapped'.$key.'}}', $val, $output);\n\t\t\t}\n\t\t}\n\n\t\treturn $output;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('ellipsize'))\n{\n\t/**\n\t * Ellipsize String\n\t *\n\t * This function will strip tags from a string, split it at its max_length and ellipsize\n\t *\n\t * @param\tstring\tstring to ellipsize\n\t * @param\tint\tmax length of string\n\t * @param\tmixed\tint (1|0) or float, .5, .2, etc for position to split\n\t * @param\tstring\tellipsis ; Default '...'\n\t * @return\tstring\tellipsized string\n\t */\n\tfunction ellipsize($str, $max_length, $position = 1, $ellipsis = '&hellip;')\n\t{\n\t\t// Strip tags\n\t\t$str = trim(strip_tags($str));\n\n\t\t// Is the string long enough to ellipsize?\n\t\tif (mb_strlen($str) <= $max_length)\n\t\t{\n\t\t\treturn $str;\n\t\t}\n\n\t\t$beg = mb_substr($str, 0, floor($max_length * $position));\n\t\t$position = ($position > 1) ? 1 : $position;\n\n\t\tif ($position === 1)\n\t\t{\n\t\t\t$end = mb_substr($str, 0, -($max_length - mb_strlen($beg)));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$end = mb_substr($str, -($max_length - mb_strlen($beg)));\n\t\t}\n\n\t\treturn $beg.$ellipsis.$end;\n\t}\n}\n"
  },
  {
    "path": "system/helpers/typography_helper.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Typography Helpers\n *\n * @package\t\tCodeIgniter\n * @subpackage\tHelpers\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/helpers/typography_helper.html\n */\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('nl2br_except_pre'))\n{\n\t/**\n\t * Convert newlines to HTML line breaks except within PRE tags\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tfunction nl2br_except_pre($str)\n\t{\n\t\t$CI =& get_instance();\n\t\t$CI->load->library('typography');\n\t\treturn $CI->typography->nl2br_except_pre($str);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('auto_typography'))\n{\n\t/**\n\t * Auto Typography Wrapper Function\n\t *\n\t * @param\tstring\t$str\n\t * @param\tbool\t$reduce_linebreaks = FALSE\twhether to reduce multiple instances of double newlines to two\n\t * @return\tstring\n\t */\n\tfunction auto_typography($str, $reduce_linebreaks = FALSE)\n\t{\n\t\t$CI =& get_instance();\n\t\t$CI->load->library('typography');\n\t\treturn $CI->typography->auto_typography($str, $reduce_linebreaks);\n\t}\n}\n\n// --------------------------------------------------------------------\n\nif ( ! function_exists('entity_decode'))\n{\n\t/**\n\t * HTML Entities Decode\n\t *\n\t * This function is a replacement for html_entity_decode()\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tfunction entity_decode($str, $charset = NULL)\n\t{\n\t\treturn get_instance()->security->entity_decode($str, $charset);\n\t}\n}\n"
  },
  {
    "path": "system/helpers/url_helper.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter URL Helpers\n *\n * @package\t\tCodeIgniter\n * @subpackage\tHelpers\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/helpers/url_helper.html\n */\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('site_url'))\n{\n\t/**\n\t * Site URL\n\t *\n\t * Create a local URL based on your basepath. Segments can be passed via the\n\t * first parameter either as a string or an array.\n\t *\n\t * @param\tstring\t$uri\n\t * @param\tstring\t$protocol\n\t * @return\tstring\n\t */\n\tfunction site_url($uri = '', $protocol = NULL)\n\t{\n\t\treturn get_instance()->config->site_url($uri, $protocol);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('base_url'))\n{\n\t/**\n\t * Base URL\n\t *\n\t * Create a local URL based on your basepath.\n\t * Segments can be passed in as a string or an array, same as site_url\n\t * or a URL to a file can be passed in, e.g. to an image file.\n\t *\n\t * @param\tstring\t$uri\n\t * @param\tstring\t$protocol\n\t * @return\tstring\n\t */\n\tfunction base_url($uri = '', $protocol = NULL)\n\t{\n\t\treturn get_instance()->config->base_url($uri, $protocol);\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('current_url'))\n{\n\t/**\n\t * Current URL\n\t *\n\t * Returns the full URL (including segments) of the page where this\n\t * function is placed\n\t *\n\t * @return\tstring\n\t */\n\tfunction current_url()\n\t{\n\t\t$CI =& get_instance();\n\t\treturn $CI->config->site_url($CI->uri->uri_string());\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('uri_string'))\n{\n\t/**\n\t * URL String\n\t *\n\t * Returns the URI segments.\n\t *\n\t * @return\tstring\n\t */\n\tfunction uri_string()\n\t{\n\t\treturn get_instance()->uri->uri_string();\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('index_page'))\n{\n\t/**\n\t * Index page\n\t *\n\t * Returns the \"index_page\" from your config file\n\t *\n\t * @return\tstring\n\t */\n\tfunction index_page()\n\t{\n\t\treturn get_instance()->config->item('index_page');\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('anchor'))\n{\n\t/**\n\t * Anchor Link\n\t *\n\t * Creates an anchor based on the local URL.\n\t *\n\t * @param\tstring\tthe URL\n\t * @param\tstring\tthe link title\n\t * @param\tmixed\tany attributes\n\t * @return\tstring\n\t */\n\tfunction anchor($uri = '', $title = '', $attributes = '')\n\t{\n\t\t$title = (string) $title;\n\n\t\t$site_url = is_array($uri)\n\t\t\t? site_url($uri)\n\t\t\t: (preg_match('#^(\\w+:)?//#i', $uri) ? $uri : site_url($uri));\n\n\t\tif ($title === '')\n\t\t{\n\t\t\t$title = $site_url;\n\t\t}\n\n\t\tif ($attributes !== '')\n\t\t{\n\t\t\t$attributes = _stringify_attributes($attributes);\n\t\t}\n\n\t\treturn '<a href=\"'.$site_url.'\"'.$attributes.'>'.$title.'</a>';\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('anchor_popup'))\n{\n\t/**\n\t * Anchor Link - Pop-up version\n\t *\n\t * Creates an anchor based on the local URL. The link\n\t * opens a new window based on the attributes specified.\n\t *\n\t * @param\tstring\tthe URL\n\t * @param\tstring\tthe link title\n\t * @param\tmixed\tany attributes\n\t * @return\tstring\n\t */\n\tfunction anchor_popup($uri = '', $title = '', $attributes = FALSE)\n\t{\n\t\t$title = (string) $title;\n\t\t$site_url = preg_match('#^(\\w+:)?//#i', $uri) ? $uri : site_url($uri);\n\n\t\tif ($title === '')\n\t\t{\n\t\t\t$title = $site_url;\n\t\t}\n\n\t\tif ($attributes === FALSE)\n\t\t{\n\t\t\treturn '<a href=\"'.$site_url.'\" onclick=\"window.open(\\''.$site_url.\"', '_blank'); return false;\\\">\".$title.'</a>';\n\t\t}\n\n\t\tif ( ! is_array($attributes))\n\t\t{\n\t\t\t$attributes = array($attributes);\n\n\t\t\t// Ref: http://www.w3schools.com/jsref/met_win_open.asp\n\t\t\t$window_name = '_blank';\n\t\t}\n\t\telseif ( ! empty($attributes['window_name']))\n\t\t{\n\t\t\t$window_name = $attributes['window_name'];\n\t\t\tunset($attributes['window_name']);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$window_name = '_blank';\n\t\t}\n\n\t\tforeach (array('width' => '800', 'height' => '600', 'scrollbars' => 'yes', 'menubar' => 'no', 'status' => 'yes', 'resizable' => 'yes', 'screenx' => '0', 'screeny' => '0') as $key => $val)\n\t\t{\n\t\t\t$atts[$key] = isset($attributes[$key]) ? $attributes[$key] : $val;\n\t\t\tunset($attributes[$key]);\n\t\t}\n\n\t\t$attributes = _stringify_attributes($attributes);\n\n\t\treturn '<a href=\"'.$site_url\n\t\t\t.'\" onclick=\"window.open(\\''.$site_url.\"', '\".$window_name.\"', '\"._stringify_attributes($atts, TRUE).\"'); return false;\\\"\"\n\t\t\t.$attributes.'>'.$title.'</a>';\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('mailto'))\n{\n\t/**\n\t * Mailto Link\n\t *\n\t * @param\tstring\tthe email address\n\t * @param\tstring\tthe link title\n\t * @param\tmixed\tany attributes\n\t * @return\tstring\n\t */\n\tfunction mailto($email, $title = '', $attributes = '')\n\t{\n\t\t$title = (string) $title;\n\n\t\tif ($title === '')\n\t\t{\n\t\t\t$title = $email;\n\t\t}\n\n\t\treturn '<a href=\"mailto:'.$email.'\"'._stringify_attributes($attributes).'>'.$title.'</a>';\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('safe_mailto'))\n{\n\t/**\n\t * Encoded Mailto Link\n\t *\n\t * Create a spam-protected mailto link written in Javascript\n\t *\n\t * @param\tstring\tthe email address\n\t * @param\tstring\tthe link title\n\t * @param\tmixed\tany attributes\n\t * @return\tstring\n\t */\n\tfunction safe_mailto($email, $title = '', $attributes = '')\n\t{\n\t\t$title = (string) $title;\n\n\t\tif ($title === '')\n\t\t{\n\t\t\t$title = $email;\n\t\t}\n\n\t\t$x = str_split('<a href=\"mailto:', 1);\n\n\t\tfor ($i = 0, $l = strlen($email); $i < $l; $i++)\n\t\t{\n\t\t\t$x[] = '|'.ord($email[$i]);\n\t\t}\n\n\t\t$x[] = '\"';\n\n\t\tif ($attributes !== '')\n\t\t{\n\t\t\tif (is_array($attributes))\n\t\t\t{\n\t\t\t\tforeach ($attributes as $key => $val)\n\t\t\t\t{\n\t\t\t\t\t$x[] = ' '.$key.'=\"';\n\t\t\t\t\tfor ($i = 0, $l = strlen($val); $i < $l; $i++)\n\t\t\t\t\t{\n\t\t\t\t\t\t$x[] = '|'.ord($val[$i]);\n\t\t\t\t\t}\n\t\t\t\t\t$x[] = '\"';\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfor ($i = 0, $l = strlen($attributes); $i < $l; $i++)\n\t\t\t\t{\n\t\t\t\t\t$x[] = $attributes[$i];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$x[] = '>';\n\n\t\t$temp = array();\n\t\tfor ($i = 0, $l = strlen($title); $i < $l; $i++)\n\t\t{\n\t\t\t$ordinal = ord($title[$i]);\n\n\t\t\tif ($ordinal < 128)\n\t\t\t{\n\t\t\t\t$x[] = '|'.$ordinal;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (count($temp) === 0)\n\t\t\t\t{\n\t\t\t\t\t$count = ($ordinal < 224) ? 2 : 3;\n\t\t\t\t}\n\n\t\t\t\t$temp[] = $ordinal;\n\t\t\t\tif (count($temp) === $count)\n\t\t\t\t{\n\t\t\t\t\t$number = ($count === 3)\n\t\t\t\t\t\t\t? (($temp[0] % 16) * 4096) + (($temp[1] % 64) * 64) + ($temp[2] % 64)\n\t\t\t\t\t\t\t: (($temp[0] % 32) * 64) + ($temp[1] % 64);\n\t\t\t\t\t$x[] = '|'.$number;\n\t\t\t\t\t$count = 1;\n\t\t\t\t\t$temp = array();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$x[] = '<'; $x[] = '/'; $x[] = 'a'; $x[] = '>';\n\n\t\t$x = array_reverse($x);\n\n\t\t$output = \"<script type=\\\"text/javascript\\\">\\n\"\n\t\t\t.\"\\t//<![CDATA[\\n\"\n\t\t\t.\"\\tvar l=new Array();\\n\";\n\n\t\tfor ($i = 0, $c = count($x); $i < $c; $i++)\n\t\t{\n\t\t\t$output .= \"\\tl[\".$i.\"] = '\".$x[$i].\"';\\n\";\n\t\t}\n\n\t\t$output .= \"\\n\\tfor (var i = l.length-1; i >= 0; i=i-1) {\\n\"\n\t\t\t.\"\\t\\tif (l[i].substring(0, 1) === '|') document.write(\\\"&#\\\"+unescape(l[i].substring(1))+\\\";\\\");\\n\"\n\t\t\t.\"\\t\\telse document.write(unescape(l[i]));\\n\"\n\t\t\t.\"\\t}\\n\"\n\t\t\t.\"\\t//]]>\\n\"\n\t\t\t.'</script>';\n\n\t\treturn $output;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('auto_link'))\n{\n\t/**\n\t * Auto-linker\n\t *\n\t * Automatically links URL and Email addresses.\n\t * Note: There's a bit of extra code here to deal with\n\t * URLs or emails that end in a period. We'll strip these\n\t * off and add them after the link.\n\t *\n\t * @param\tstring\tthe string\n\t * @param\tstring\tthe type: email, url, or both\n\t * @param\tbool\twhether to create pop-up links\n\t * @return\tstring\n\t */\n\tfunction auto_link($str, $type = 'both', $popup = FALSE)\n\t{\n\t\t// Find and replace any URLs.\n\t\tif ($type !== 'email' && preg_match_all('#(\\w*://|www\\.)[^\\s()<>;]+\\w#i', $str, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER))\n\t\t{\n\t\t\t// Set our target HTML if using popup links.\n\t\t\t$target = ($popup) ? ' target=\"_blank\"' : '';\n\n\t\t\t// We process the links in reverse order (last -> first) so that\n\t\t\t// the returned string offsets from preg_match_all() are not\n\t\t\t// moved as we add more HTML.\n\t\t\tforeach (array_reverse($matches) as $match)\n\t\t\t{\n\t\t\t\t// $match[0] is the matched string/link\n\t\t\t\t// $match[1] is either a protocol prefix or 'www.'\n\t\t\t\t//\n\t\t\t\t// With PREG_OFFSET_CAPTURE, both of the above is an array,\n\t\t\t\t// where the actual value is held in [0] and its offset at the [1] index.\n\t\t\t\t$a = '<a href=\"'.(strpos($match[1][0], '/') ? '' : 'http://').$match[0][0].'\"'.$target.'>'.$match[0][0].'</a>';\n\t\t\t\t$str = substr_replace($str, $a, $match[0][1], strlen($match[0][0]));\n\t\t\t}\n\t\t}\n\n\t\t// Find and replace any emails.\n\t\tif ($type !== 'url' && preg_match_all('#([\\w\\.\\-\\+]+@[a-z0-9\\-]+\\.[a-z0-9\\-\\.]+[^[:punct:]\\s])#i', $str, $matches, PREG_OFFSET_CAPTURE))\n\t\t{\n\t\t\tforeach (array_reverse($matches[0]) as $match)\n\t\t\t{\n\t\t\t\tif (filter_var($match[0], FILTER_VALIDATE_EMAIL) !== FALSE)\n\t\t\t\t{\n\t\t\t\t\t$str = substr_replace($str, safe_mailto($match[0]), $match[1], strlen($match[0]));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn $str;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('prep_url'))\n{\n\t/**\n\t * Prep URL\n\t *\n\t * Simply adds the http:// part if no scheme is included\n\t *\n\t * @param\tstring\tthe URL\n\t * @return\tstring\n\t */\n\tfunction prep_url($str = '')\n\t{\n\t\tif ($str === 'http://' OR $str === '')\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\t$url = parse_url($str);\n\n\t\tif ( ! $url OR ! isset($url['scheme']))\n\t\t{\n\t\t\treturn 'http://'.$str;\n\t\t}\n\n\t\treturn $str;\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('url_title'))\n{\n\t/**\n\t * Create URL Title\n\t *\n\t * Takes a \"title\" string as input and creates a\n\t * human-friendly URL string with a \"separator\" string\n\t * as the word separator.\n\t *\n\t * @todo\tRemove old 'dash' and 'underscore' usage in 3.1+.\n\t * @param\tstring\t$str\t\tInput string\n\t * @param\tstring\t$separator\tWord separator\n\t *\t\t\t(usually '-' or '_')\n\t * @param\tbool\t$lowercase\tWhether to transform the output string to lowercase\n\t * @return\tstring\n\t */\n\tfunction url_title($str, $separator = '-', $lowercase = FALSE)\n\t{\n\t\tif ($separator === 'dash')\n\t\t{\n\t\t\t$separator = '-';\n\t\t}\n\t\telseif ($separator === 'underscore')\n\t\t{\n\t\t\t$separator = '_';\n\t\t}\n\n\t\t$q_separator = preg_quote($separator, '#');\n\n\t\t$trans = array(\n\t\t\t'&.+?;'\t\t\t=> '',\n\t\t\t'[^\\w\\d _-]'\t\t=> '',\n\t\t\t'\\s+'\t\t\t=> $separator,\n\t\t\t'('.$q_separator.')+'\t=> $separator\n\t\t);\n\n\t\t$str = strip_tags($str);\n\t\tforeach ($trans as $key => $val)\n\t\t{\n\t\t\t$str = preg_replace('#'.$key.'#i'.(UTF8_ENABLED ? 'u' : ''), $val, $str);\n\t\t}\n\n\t\tif ($lowercase === TRUE)\n\t\t{\n\t\t\t$str = strtolower($str);\n\t\t}\n\n\t\treturn trim(trim($str, $separator));\n\t}\n}\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('redirect'))\n{\n\t/**\n\t * Header Redirect\n\t *\n\t * Header redirect in two flavors\n\t * For very fine grained control over headers, you could use the Output\n\t * Library's set_header() function.\n\t *\n\t * @param\tstring\t$uri\tURL\n\t * @param\tstring\t$method\tRedirect method\n\t *\t\t\t'auto', 'location' or 'refresh'\n\t * @param\tint\t$code\tHTTP Response status code\n\t * @return\tvoid\n\t */\n\tfunction redirect($uri = '', $method = 'auto', $code = NULL)\n\t{\n\t\tif ( ! preg_match('#^(\\w+:)?//#i', $uri))\n\t\t{\n\t\t\t$uri = site_url($uri);\n\t\t}\n\n\t\t// IIS environment likely? Use 'refresh' for better compatibility\n\t\tif ($method === 'auto' && isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== FALSE)\n\t\t{\n\t\t\t$method = 'refresh';\n\t\t}\n\t\telseif ($method !== 'refresh' && (empty($code) OR ! is_numeric($code)))\n\t\t{\n\t\t\tif (isset($_SERVER['SERVER_PROTOCOL'], $_SERVER['REQUEST_METHOD']) && $_SERVER['SERVER_PROTOCOL'] === 'HTTP/1.1')\n\t\t\t{\n\t\t\t\t$code = ($_SERVER['REQUEST_METHOD'] !== 'GET')\n\t\t\t\t\t? 303\t// reference: http://en.wikipedia.org/wiki/Post/Redirect/Get\n\t\t\t\t\t: 307;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$code = 302;\n\t\t\t}\n\t\t}\n\n\t\tswitch ($method)\n\t\t{\n\t\t\tcase 'refresh':\n\t\t\t\theader('Refresh:0;url='.$uri);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\theader('Location: '.$uri, TRUE, $code);\n\t\t\t\tbreak;\n\t\t}\n\t\texit;\n\t}\n}\n"
  },
  {
    "path": "system/helpers/xml_helper.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter XML Helpers\n *\n * @package\t\tCodeIgniter\n * @subpackage\tHelpers\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/helpers/xml_helper.html\n */\n\n// ------------------------------------------------------------------------\n\nif ( ! function_exists('xml_convert'))\n{\n\t/**\n\t * Convert Reserved XML characters to Entities\n\t *\n\t * @param\tstring\n\t * @param\tbool\n\t * @return\tstring\n\t */\n\tfunction xml_convert($str, $protect_all = FALSE)\n\t{\n\t\t$temp = '__TEMP_AMPERSANDS__';\n\n\t\t// Replace entities to temporary markers so that\n\t\t// ampersands won't get messed up\n\t\t$str = preg_replace('/&#(\\d+);/', $temp.'\\\\1;', $str);\n\n\t\tif ($protect_all === TRUE)\n\t\t{\n\t\t\t$str = preg_replace('/&(\\w+);/', $temp.'\\\\1;', $str);\n\t\t}\n\n\t\t$str = str_replace(\n\t\t\tarray('&', '<', '>', '\"', \"'\", '-'),\n\t\t\tarray('&amp;', '&lt;', '&gt;', '&quot;', '&apos;', '&#45;'),\n\t\t\t$str\n\t\t);\n\n\t\t// Decode the temp markers back to entities\n\t\t$str = preg_replace('/'.$temp.'(\\d+);/', '&#\\\\1;', $str);\n\n\t\tif ($protect_all === TRUE)\n\t\t{\n\t\t\treturn preg_replace('/'.$temp.'(\\w+);/', '&\\\\1;', $str);\n\t\t}\n\n\t\treturn $str;\n\t}\n}\n"
  },
  {
    "path": "system/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/language/english/calendar_lang.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n$lang['cal_su'] = 'Su';\n$lang['cal_mo'] = 'Mo';\n$lang['cal_tu'] = 'Tu';\n$lang['cal_we'] = 'We';\n$lang['cal_th'] = 'Th';\n$lang['cal_fr'] = 'Fr';\n$lang['cal_sa'] = 'Sa';\n$lang['cal_sun'] = 'Sun';\n$lang['cal_mon'] = 'Mon';\n$lang['cal_tue'] = 'Tue';\n$lang['cal_wed'] = 'Wed';\n$lang['cal_thu'] = 'Thu';\n$lang['cal_fri'] = 'Fri';\n$lang['cal_sat'] = 'Sat';\n$lang['cal_sunday'] = 'Sunday';\n$lang['cal_monday'] = 'Monday';\n$lang['cal_tuesday'] = 'Tuesday';\n$lang['cal_wednesday'] = 'Wednesday';\n$lang['cal_thursday'] = 'Thursday';\n$lang['cal_friday'] = 'Friday';\n$lang['cal_saturday'] = 'Saturday';\n$lang['cal_jan'] = 'Jan';\n$lang['cal_feb'] = 'Feb';\n$lang['cal_mar'] = 'Mar';\n$lang['cal_apr'] = 'Apr';\n$lang['cal_may'] = 'May';\n$lang['cal_jun'] = 'Jun';\n$lang['cal_jul'] = 'Jul';\n$lang['cal_aug'] = 'Aug';\n$lang['cal_sep'] = 'Sep';\n$lang['cal_oct'] = 'Oct';\n$lang['cal_nov'] = 'Nov';\n$lang['cal_dec'] = 'Dec';\n$lang['cal_january'] = 'January';\n$lang['cal_february'] = 'February';\n$lang['cal_march'] = 'March';\n$lang['cal_april'] = 'April';\n$lang['cal_mayl'] = 'May';\n$lang['cal_june'] = 'June';\n$lang['cal_july'] = 'July';\n$lang['cal_august'] = 'August';\n$lang['cal_september'] = 'September';\n$lang['cal_october'] = 'October';\n$lang['cal_november'] = 'November';\n$lang['cal_december'] = 'December';\n"
  },
  {
    "path": "system/language/english/date_lang.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n$lang['date_year'] = 'Year';\n$lang['date_years'] = 'Years';\n$lang['date_month'] = 'Month';\n$lang['date_months'] = 'Months';\n$lang['date_week'] = 'Week';\n$lang['date_weeks'] = 'Weeks';\n$lang['date_day'] = 'Day';\n$lang['date_days'] = 'Days';\n$lang['date_hour'] = 'Hour';\n$lang['date_hours'] = 'Hours';\n$lang['date_minute'] = 'Minute';\n$lang['date_minutes'] = 'Minutes';\n$lang['date_second'] = 'Second';\n$lang['date_seconds'] = 'Seconds';\n\n$lang['UM12']\t= '(UTC -12:00) Baker/Howland Island';\n$lang['UM11']\t= '(UTC -11:00) Niue';\n$lang['UM10']\t= '(UTC -10:00) Hawaii-Aleutian Standard Time, Cook Islands, Tahiti';\n$lang['UM95']\t= '(UTC -9:30) Marquesas Islands';\n$lang['UM9']\t= '(UTC -9:00) Alaska Standard Time, Gambier Islands';\n$lang['UM8']\t= '(UTC -8:00) Pacific Standard Time, Clipperton Island';\n$lang['UM7']\t= '(UTC -7:00) Mountain Standard Time';\n$lang['UM6']\t= '(UTC -6:00) Central Standard Time';\n$lang['UM5']\t= '(UTC -5:00) Eastern Standard Time, Western Caribbean Standard Time';\n$lang['UM45']\t= '(UTC -4:30) Venezuelan Standard Time';\n$lang['UM4']\t= '(UTC -4:00) Atlantic Standard Time, Eastern Caribbean Standard Time';\n$lang['UM35']\t= '(UTC -3:30) Newfoundland Standard Time';\n$lang['UM3']\t= '(UTC -3:00) Argentina, Brazil, French Guiana, Uruguay';\n$lang['UM2']\t= '(UTC -2:00) South Georgia/South Sandwich Islands';\n$lang['UM1']\t= '(UTC -1:00) Azores, Cape Verde Islands';\n$lang['UTC']\t= '(UTC) Greenwich Mean Time, Western European Time';\n$lang['UP1']\t= '(UTC +1:00) Central European Time, West Africa Time';\n$lang['UP2']\t= '(UTC +2:00) Central Africa Time, Eastern European Time, Kaliningrad Time';\n$lang['UP3']\t= '(UTC +3:00) Moscow Time, East Africa Time, Arabia Standard Time';\n$lang['UP35']\t= '(UTC +3:30) Iran Standard Time';\n$lang['UP4']\t= '(UTC +4:00) Azerbaijan Standard Time, Samara Time';\n$lang['UP45']\t= '(UTC +4:30) Afghanistan';\n$lang['UP5']\t= '(UTC +5:00) Pakistan Standard Time, Yekaterinburg Time';\n$lang['UP55']\t= '(UTC +5:30) Indian Standard Time, Sri Lanka Time';\n$lang['UP575']\t= '(UTC +5:45) Nepal Time';\n$lang['UP6']\t= '(UTC +6:00) Bangladesh Standard Time, Bhutan Time, Omsk Time';\n$lang['UP65']\t= '(UTC +6:30) Cocos Islands, Myanmar';\n$lang['UP7']\t= '(UTC +7:00) Krasnoyarsk Time, Cambodia, Laos, Thailand, Vietnam';\n$lang['UP8']\t= '(UTC +8:00) Australian Western Standard Time, Beijing Time, Irkutsk Time';\n$lang['UP875']\t= '(UTC +8:45) Australian Central Western Standard Time';\n$lang['UP9']\t= '(UTC +9:00) Japan Standard Time, Korea Standard Time, Yakutsk Time';\n$lang['UP95']\t= '(UTC +9:30) Australian Central Standard Time';\n$lang['UP10']\t= '(UTC +10:00) Australian Eastern Standard Time, Vladivostok Time';\n$lang['UP105']\t= '(UTC +10:30) Lord Howe Island';\n$lang['UP11']\t= '(UTC +11:00) Srednekolymsk Time, Solomon Islands, Vanuatu';\n$lang['UP115']\t= '(UTC +11:30) Norfolk Island';\n$lang['UP12']\t= '(UTC +12:00) Fiji, Gilbert Islands, Kamchatka Time, New Zealand Standard Time';\n$lang['UP1275']\t= '(UTC +12:45) Chatham Islands Standard Time';\n$lang['UP13']\t= '(UTC +13:00) Samoa Time Zone, Phoenix Islands Time, Tonga';\n$lang['UP14']\t= '(UTC +14:00) Line Islands';\n"
  },
  {
    "path": "system/language/english/db_lang.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n$lang['db_invalid_connection_str'] = 'Unable to determine the database settings based on the connection string you submitted.';\n$lang['db_unable_to_connect'] = 'Unable to connect to your database server using the provided settings.';\n$lang['db_unable_to_select'] = 'Unable to select the specified database: %s';\n$lang['db_unable_to_create'] = 'Unable to create the specified database: %s';\n$lang['db_invalid_query'] = 'The query you submitted is not valid.';\n$lang['db_must_set_table'] = 'You must set the database table to be used with your query.';\n$lang['db_must_use_set'] = 'You must use the \"set\" method to update an entry.';\n$lang['db_must_use_index'] = 'You must specify an index to match on for batch updates.';\n$lang['db_batch_missing_index'] = 'One or more rows submitted for batch updating is missing the specified index.';\n$lang['db_must_use_where'] = 'Updates are not allowed unless they contain a \"where\" clause.';\n$lang['db_del_must_use_where'] = 'Deletes are not allowed unless they contain a \"where\" or \"like\" clause.';\n$lang['db_field_param_missing'] = 'To fetch fields requires the name of the table as a parameter.';\n$lang['db_unsupported_function'] = 'This feature is not available for the database you are using.';\n$lang['db_transaction_failure'] = 'Transaction failure: Rollback performed.';\n$lang['db_unable_to_drop'] = 'Unable to drop the specified database.';\n$lang['db_unsupported_feature'] = 'Unsupported feature of the database platform you are using.';\n$lang['db_unsupported_compression'] = 'The file compression format you chose is not supported by your server.';\n$lang['db_filepath_error'] = 'Unable to write data to the file path you have submitted.';\n$lang['db_invalid_cache_path'] = 'The cache path you submitted is not valid or writable.';\n$lang['db_table_name_required'] = 'A table name is required for that operation.';\n$lang['db_column_name_required'] = 'A column name is required for that operation.';\n$lang['db_column_definition_required'] = 'A column definition is required for that operation.';\n$lang['db_unable_to_set_charset'] = 'Unable to set client connection character set: %s';\n$lang['db_error_heading'] = 'A Database Error Occurred';\n"
  },
  {
    "path": "system/language/english/email_lang.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n$lang['email_must_be_array'] = 'The email validation method must be passed an array.';\n$lang['email_invalid_address'] = 'Invalid email address: %s';\n$lang['email_attachment_missing'] = 'Unable to locate the following email attachment: %s';\n$lang['email_attachment_unreadable'] = 'Unable to open this attachment: %s';\n$lang['email_no_from'] = 'Cannot send mail with no \"From\" header.';\n$lang['email_no_recipients'] = 'You must include recipients: To, Cc, or Bcc';\n$lang['email_send_failure_phpmail'] = 'Unable to send email using PHP mail(). Your server might not be configured to send mail using this method.';\n$lang['email_send_failure_sendmail'] = 'Unable to send email using PHP Sendmail. Your server might not be configured to send mail using this method.';\n$lang['email_send_failure_smtp'] = 'Unable to send email using PHP SMTP. Your server might not be configured to send mail using this method.';\n$lang['email_sent'] = 'Your message has been successfully sent using the following protocol: %s';\n$lang['email_no_socket'] = 'Unable to open a socket to Sendmail. Please check settings.';\n$lang['email_no_hostname'] = 'You did not specify a SMTP hostname.';\n$lang['email_smtp_error'] = 'The following SMTP error was encountered: %s';\n$lang['email_no_smtp_unpw'] = 'Error: You must assign a SMTP username and password.';\n$lang['email_failed_smtp_login'] = 'Failed to send AUTH LOGIN command. Error: %s';\n$lang['email_smtp_auth_un'] = 'Failed to authenticate username. Error: %s';\n$lang['email_smtp_auth_pw'] = 'Failed to authenticate password. Error: %s';\n$lang['email_smtp_data_failure'] = 'Unable to send data: %s';\n$lang['email_exit_status'] = 'Exit status code: %s';\n"
  },
  {
    "path": "system/language/english/form_validation_lang.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n$lang['form_validation_required']\t\t= 'The {field} field is required.';\n$lang['form_validation_isset']\t\t\t= 'The {field} field must have a value.';\n$lang['form_validation_valid_email']\t\t= 'The {field} field must contain a valid email address.';\n$lang['form_validation_valid_emails']\t\t= 'The {field} field must contain all valid email addresses.';\n$lang['form_validation_valid_url']\t\t= 'The {field} field must contain a valid URL.';\n$lang['form_validation_valid_ip']\t\t= 'The {field} field must contain a valid IP.';\n$lang['form_validation_min_length']\t\t= 'The {field} field must be at least {param} characters in length.';\n$lang['form_validation_max_length']\t\t= 'The {field} field cannot exceed {param} characters in length.';\n$lang['form_validation_exact_length']\t\t= 'The {field} field must be exactly {param} characters in length.';\n$lang['form_validation_alpha']\t\t\t= 'The {field} field may only contain alphabetical characters.';\n$lang['form_validation_alpha_numeric']\t\t= 'The {field} field may only contain alpha-numeric characters.';\n$lang['form_validation_alpha_numeric_spaces']\t= 'The {field} field may only contain alpha-numeric characters and spaces.';\n$lang['form_validation_alpha_dash']\t\t= 'The {field} field may only contain alpha-numeric characters, underscores, and dashes.';\n$lang['form_validation_numeric']\t\t= 'The {field} field must contain only numbers.';\n$lang['form_validation_is_numeric']\t\t= 'The {field} field must contain only numeric characters.';\n$lang['form_validation_integer']\t\t= 'The {field} field must contain an integer.';\n$lang['form_validation_regex_match']\t\t= 'The {field} field is not in the correct format.';\n$lang['form_validation_matches']\t\t= 'The {field} field does not match the {param} field.';\n$lang['form_validation_differs']\t\t= 'The {field} field must differ from the {param} field.';\n$lang['form_validation_is_unique'] \t\t= 'The {field} field must contain a unique value.';\n$lang['form_validation_is_natural']\t\t= 'The {field} field must only contain digits.';\n$lang['form_validation_is_natural_no_zero']\t= 'The {field} field must only contain digits and must be greater than zero.';\n$lang['form_validation_decimal']\t\t= 'The {field} field must contain a decimal number.';\n$lang['form_validation_less_than']\t\t= 'The {field} field must contain a number less than {param}.';\n$lang['form_validation_less_than_equal_to']\t= 'The {field} field must contain a number less than or equal to {param}.';\n$lang['form_validation_greater_than']\t\t= 'The {field} field must contain a number greater than {param}.';\n$lang['form_validation_greater_than_equal_to']\t= 'The {field} field must contain a number greater than or equal to {param}.';\n$lang['form_validation_error_message_not_set']\t= 'Unable to access an error message corresponding to your field name {field}.';\n$lang['form_validation_in_list']\t\t= 'The {field} field must be one of: {param}.';\n"
  },
  {
    "path": "system/language/english/ftp_lang.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n$lang['ftp_no_connection']\t\t= 'Unable to locate a valid connection ID. Please make sure you are connected before performing any file routines.';\n$lang['ftp_unable_to_connect']\t\t= 'Unable to connect to your FTP server using the supplied hostname.';\n$lang['ftp_unable_to_login']\t\t= 'Unable to login to your FTP server. Please check your username and password.';\n$lang['ftp_unable_to_mkdir']\t\t= 'Unable to create the directory you have specified.';\n$lang['ftp_unable_to_changedir']\t= 'Unable to change directories.';\n$lang['ftp_unable_to_chmod']\t\t= 'Unable to set file permissions. Please check your path.';\n$lang['ftp_unable_to_upload']\t\t= 'Unable to upload the specified file. Please check your path.';\n$lang['ftp_unable_to_download']\t\t= 'Unable to download the specified file. Please check your path.';\n$lang['ftp_no_source_file']\t\t= 'Unable to locate the source file. Please check your path.';\n$lang['ftp_unable_to_rename']\t\t= 'Unable to rename the file.';\n$lang['ftp_unable_to_delete']\t\t= 'Unable to delete the file.';\n$lang['ftp_unable_to_move']\t\t= 'Unable to move the file. Please make sure the destination directory exists.';\n"
  },
  {
    "path": "system/language/english/imglib_lang.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n$lang['imglib_source_image_required'] = 'You must specify a source image in your preferences.';\n$lang['imglib_gd_required'] = 'The GD image library is required for this feature.';\n$lang['imglib_gd_required_for_props'] = 'Your server must support the GD image library in order to determine the image properties.';\n$lang['imglib_unsupported_imagecreate'] = 'Your server does not support the GD function required to process this type of image.';\n$lang['imglib_gif_not_supported'] = 'GIF images are often not supported due to licensing restrictions. You may have to use JPG or PNG images instead.';\n$lang['imglib_jpg_not_supported'] = 'JPG images are not supported.';\n$lang['imglib_png_not_supported'] = 'PNG images are not supported.';\n$lang['imglib_jpg_or_png_required'] = 'The image resize protocol specified in your preferences only works with JPEG or PNG image types.';\n$lang['imglib_copy_error'] = 'An error was encountered while attempting to replace the file. Please make sure your file directory is writable.';\n$lang['imglib_rotate_unsupported'] = 'Image rotation does not appear to be supported by your server.';\n$lang['imglib_libpath_invalid'] = 'The path to your image library is not correct. Please set the correct path in your image preferences.';\n$lang['imglib_image_process_failed'] = 'Image processing failed. Please verify that your server supports the chosen protocol and that the path to your image library is correct.';\n$lang['imglib_rotation_angle_required'] = 'An angle of rotation is required to rotate the image.';\n$lang['imglib_invalid_path'] = 'The path to the image is not correct.';\n$lang['imglib_copy_failed'] = 'The image copy routine failed.';\n$lang['imglib_missing_font'] = 'Unable to find a font to use.';\n$lang['imglib_save_failed'] = 'Unable to save the image. Please make sure the image and file directory are writable.';\n"
  },
  {
    "path": "system/language/english/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/language/english/migration_lang.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n$lang['migration_none_found'] = 'No migrations were found.';\n$lang['migration_not_found'] = 'No migration could be found with the version number: %s.';\n$lang['migration_sequence_gap'] = 'There is a gap in the migration sequence near version number: %s.';\n$lang['migration_multiple_version'] = 'There are multiple migrations with the same version number: %s.';\n$lang['migration_class_doesnt_exist'] = 'The migration class \"%s\" could not be found.';\n$lang['migration_missing_up_method'] = 'The migration class \"%s\" is missing an \"up\" method.';\n$lang['migration_missing_down_method'] = 'The migration class \"%s\" is missing a \"down\" method.';\n$lang['migration_invalid_filename'] = 'Migration \"%s\" has an invalid filename.';\n"
  },
  {
    "path": "system/language/english/number_lang.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n$lang['terabyte_abbr'] = 'TB';\n$lang['gigabyte_abbr'] = 'GB';\n$lang['megabyte_abbr'] = 'MB';\n$lang['kilobyte_abbr'] = 'KB';\n$lang['bytes'] = 'Bytes';\n"
  },
  {
    "path": "system/language/english/pagination_lang.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n$lang['pagination_first_link'] = '&lsaquo; First';\n$lang['pagination_next_link'] = '&gt;';\n$lang['pagination_prev_link'] = '&lt;';\n$lang['pagination_last_link'] = 'Last &rsaquo;';\n"
  },
  {
    "path": "system/language/english/profiler_lang.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n$lang['profiler_database'] = 'DATABASE';\n$lang['profiler_controller_info'] = 'CLASS/METHOD';\n$lang['profiler_benchmarks'] = 'BENCHMARKS';\n$lang['profiler_queries'] = 'QUERIES';\n$lang['profiler_get_data'] = 'GET DATA';\n$lang['profiler_post_data'] = 'POST DATA';\n$lang['profiler_uri_string'] = 'URI STRING';\n$lang['profiler_memory_usage'] = 'MEMORY USAGE';\n$lang['profiler_config'] = 'CONFIG VARIABLES';\n$lang['profiler_session_data'] = 'SESSION DATA';\n$lang['profiler_headers'] = 'HTTP HEADERS';\n$lang['profiler_no_db'] = 'Database driver is not currently loaded';\n$lang['profiler_no_queries'] = 'No queries were run';\n$lang['profiler_no_post'] = 'No POST data exists';\n$lang['profiler_no_get'] = 'No GET data exists';\n$lang['profiler_no_uri'] = 'No URI data exists';\n$lang['profiler_no_memory'] = 'Memory Usage Unavailable';\n$lang['profiler_no_profiles'] = 'No Profile data - all Profiler sections have been disabled.';\n$lang['profiler_section_hide'] = 'Hide';\n$lang['profiler_section_show'] = 'Show';\n$lang['profiler_seconds'] = 'seconds';\n"
  },
  {
    "path": "system/language/english/unit_test_lang.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n$lang['ut_test_name'] = 'Test Name';\n$lang['ut_test_datatype'] = 'Test Datatype';\n$lang['ut_res_datatype'] = 'Expected Datatype';\n$lang['ut_result'] = 'Result';\n$lang['ut_undefined'] = 'Undefined Test Name';\n$lang['ut_file'] = 'File Name';\n$lang['ut_line'] = 'Line Number';\n$lang['ut_passed'] = 'Passed';\n$lang['ut_failed'] = 'Failed';\n$lang['ut_boolean'] = 'Boolean';\n$lang['ut_integer'] = 'Integer';\n$lang['ut_float'] = 'Float';\n$lang['ut_double'] = 'Float'; // can be the same as float\n$lang['ut_string'] = 'String';\n$lang['ut_array'] = 'Array';\n$lang['ut_object'] = 'Object';\n$lang['ut_resource'] = 'Resource';\n$lang['ut_null'] = 'Null';\n$lang['ut_notes'] = 'Notes';\n"
  },
  {
    "path": "system/language/english/upload_lang.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n$lang['upload_userfile_not_set'] = 'Unable to find a post variable called userfile.';\n$lang['upload_file_exceeds_limit'] = 'The uploaded file exceeds the maximum allowed size in your PHP configuration file.';\n$lang['upload_file_exceeds_form_limit'] = 'The uploaded file exceeds the maximum size allowed by the submission form.';\n$lang['upload_file_partial'] = 'The file was only partially uploaded.';\n$lang['upload_no_temp_directory'] = 'The temporary folder is missing.';\n$lang['upload_unable_to_write_file'] = 'The file could not be written to disk.';\n$lang['upload_stopped_by_extension'] = 'The file upload was stopped by extension.';\n$lang['upload_no_file_selected'] = 'You did not select a file to upload.';\n$lang['upload_invalid_filetype'] = 'The filetype you are attempting to upload is not allowed.';\n$lang['upload_invalid_filesize'] = 'The file you are attempting to upload is larger than the permitted size.';\n$lang['upload_invalid_dimensions'] = 'The image you are attempting to upload doesn\\'t fit into the allowed dimensions.';\n$lang['upload_destination_error'] = 'A problem was encountered while attempting to move the uploaded file to the final destination.';\n$lang['upload_no_filepath'] = 'The upload path does not appear to be valid.';\n$lang['upload_no_file_types'] = 'You have not specified any allowed file types.';\n$lang['upload_bad_filename'] = 'The file name you submitted already exists on the server.';\n$lang['upload_not_writable'] = 'The upload destination folder does not appear to be writable.';\n"
  },
  {
    "path": "system/language/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/libraries/Cache/Cache.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 2.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Caching Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tCore\n * @author\t\tEllisLab Dev Team\n * @link\n */\nclass CI_Cache extends CI_Driver_Library {\n\n\t/**\n\t * Valid cache drivers\n\t *\n\t * @var array\n\t */\n\tprotected $valid_drivers = array(\n\t\t'apc',\n\t\t'dummy',\n\t\t'file',\n\t\t'memcached',\n\t\t'redis',\n\t\t'wincache'\n\t);\n\n\t/**\n\t * Path of cache files (if file-based cache)\n\t *\n\t * @var string\n\t */\n\tprotected $_cache_path = NULL;\n\n\t/**\n\t * Reference to the driver\n\t *\n\t * @var mixed\n\t */\n\tprotected $_adapter = 'dummy';\n\n\t/**\n\t * Fallback driver\n\t *\n\t * @var string\n\t */\n\tprotected $_backup_driver = 'dummy';\n\n\t/**\n\t * Cache key prefix\n\t *\n\t * @var\tstring\n\t */\n\tpublic $key_prefix = '';\n\n\t/**\n\t * Constructor\n\t *\n\t * Initialize class properties based on the configuration array.\n\t *\n\t * @param\tarray\t$config = array()\n\t * @return\tvoid\n\t */\n\tpublic function __construct($config = array())\n\t{\n\t\tisset($config['adapter']) && $this->_adapter = $config['adapter'];\n\t\tisset($config['backup']) && $this->_backup_driver = $config['backup'];\n\t\tisset($config['key_prefix']) && $this->key_prefix = $config['key_prefix'];\n\n\t\t// If the specified adapter isn't available, check the backup.\n\t\tif ( ! $this->is_supported($this->_adapter))\n\t\t{\n\t\t\tif ( ! $this->is_supported($this->_backup_driver))\n\t\t\t{\n\t\t\t\t// Backup isn't supported either. Default to 'Dummy' driver.\n\t\t\t\tlog_message('error', 'Cache adapter \"'.$this->_adapter.'\" and backup \"'.$this->_backup_driver.'\" are both unavailable. Cache is now using \"Dummy\" adapter.');\n\t\t\t\t$this->_adapter = 'dummy';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// Backup is supported. Set it to primary.\n\t\t\t\tlog_message('debug', 'Cache adapter \"'.$this->_adapter.'\" is unavailable. Falling back to \"'.$this->_backup_driver.'\" backup adapter.');\n\t\t\t\t$this->_adapter = $this->_backup_driver;\n\t\t\t}\n\t\t}\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get\n\t *\n\t * Look for a value in the cache. If it exists, return the data\n\t * if not, return FALSE\n\t *\n\t * @param\tstring\t$id\n\t * @return\tmixed\tvalue matching $id or FALSE on failure\n\t */\n\tpublic function get($id)\n\t{\n\t\treturn $this->{$this->_adapter}->get($this->key_prefix.$id);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Cache Save\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tmixed\t$data\tData to store\n\t * @param\tint\t$ttl\tCache TTL (in seconds)\n\t * @param\tbool\t$raw\tWhether to store the raw value\n\t * @return\tbool\tTRUE on success, FALSE on failure\n\t */\n\tpublic function save($id, $data, $ttl = 60, $raw = FALSE)\n\t{\n\t\treturn $this->{$this->_adapter}->save($this->key_prefix.$id, $data, $ttl, $raw);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Delete from Cache\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @return\tbool\tTRUE on success, FALSE on failure\n\t */\n\tpublic function delete($id)\n\t{\n\t\treturn $this->{$this->_adapter}->delete($this->key_prefix.$id);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Increment a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to add\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function increment($id, $offset = 1)\n\t{\n\t\treturn $this->{$this->_adapter}->increment($this->key_prefix.$id, $offset);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Decrement a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to reduce by\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function decrement($id, $offset = 1)\n\t{\n\t\treturn $this->{$this->_adapter}->decrement($this->key_prefix.$id, $offset);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Clean the cache\n\t *\n\t * @return\tbool\tTRUE on success, FALSE on failure\n\t */\n\tpublic function clean()\n\t{\n\t\treturn $this->{$this->_adapter}->clean();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Cache Info\n\t *\n\t * @param\tstring\t$type = 'user'\tuser/filehits\n\t * @return\tmixed\tarray containing cache info on success OR FALSE on failure\n\t */\n\tpublic function cache_info($type = 'user')\n\t{\n\t\treturn $this->{$this->_adapter}->cache_info($type);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get Cache Metadata\n\t *\n\t * @param\tstring\t$id\tkey to get cache metadata on\n\t * @return\tmixed\tcache item metadata\n\t */\n\tpublic function get_metadata($id)\n\t{\n\t\treturn $this->{$this->_adapter}->get_metadata($this->key_prefix.$id);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Is the requested driver supported in this environment?\n\t *\n\t * @param\tstring\t$driver\tThe driver to test\n\t * @return\tarray\n\t */\n\tpublic function is_supported($driver)\n\t{\n\t\tstatic $support;\n\n\t\tif ( ! isset($support, $support[$driver]))\n\t\t{\n\t\t\t$support[$driver] = $this->{$driver}->is_supported();\n\t\t}\n\n\t\treturn $support[$driver];\n\t}\n}\n"
  },
  {
    "path": "system/libraries/Cache/drivers/Cache_apc.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 2.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter APC Caching Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tCore\n * @author\t\tEllisLab Dev Team\n * @link\n */\nclass CI_Cache_apc extends CI_Driver {\n\n\t/**\n\t * Class constructor\n\t *\n\t * Only present so that an error message is logged\n\t * if APC is not available.\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\tif ( ! $this->is_supported())\n\t\t{\n\t\t\tlog_message('error', 'Cache: Failed to initialize APC; extension not loaded/enabled?');\n\t\t}\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get\n\t *\n\t * Look for a value in the cache. If it exists, return the data\n\t * if not, return FALSE\n\t *\n\t * @param\tstring\n\t * @return\tmixed\tvalue that is stored/FALSE on failure\n\t */\n\tpublic function get($id)\n\t{\n\t\t$success = FALSE;\n\t\t$data = apc_fetch($id, $success);\n\n\t\tif ($success === TRUE)\n\t\t{\n\t\t\treturn is_array($data)\n\t\t\t\t? unserialize($data[0])\n\t\t\t\t: $data;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Cache Save\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tmixed\t$data\tData to store\n\t * @param\tint\t$ttl\tLength of time (in seconds) to cache the data\n\t * @param\tbool\t$raw\tWhether to store the raw value\n\t * @return\tbool\tTRUE on success, FALSE on failure\n\t */\n\tpublic function save($id, $data, $ttl = 60, $raw = FALSE)\n\t{\n\t\t$ttl = (int) $ttl;\n\n\t\treturn apc_store(\n\t\t\t$id,\n\t\t\t($raw === TRUE ? $data : array(serialize($data), time(), $ttl)),\n\t\t\t$ttl\n\t\t);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Delete from Cache\n\t *\n\t * @param\tmixed\tunique identifier of the item in the cache\n\t * @return\tbool\ttrue on success/false on failure\n\t */\n\tpublic function delete($id)\n\t{\n\t\treturn apc_delete($id);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Increment a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to add\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function increment($id, $offset = 1)\n\t{\n\t\treturn apc_inc($id, $offset);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Decrement a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to reduce by\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function decrement($id, $offset = 1)\n\t{\n\t\treturn apc_dec($id, $offset);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Clean the cache\n\t *\n\t * @return\tbool\tfalse on failure/true on success\n\t */\n\tpublic function clean()\n\t{\n\t\treturn apc_clear_cache('user');\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Cache Info\n\t *\n\t * @param\tstring\tuser/filehits\n\t * @return\tmixed\tarray on success, false on failure\n\t */\n\t public function cache_info($type = NULL)\n\t {\n\t\t return apc_cache_info($type);\n\t }\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get Cache Metadata\n\t *\n\t * @param\tmixed\tkey to get cache metadata on\n\t * @return\tmixed\tarray on success/false on failure\n\t */\n\tpublic function get_metadata($id)\n\t{\n\t\t$success = FALSE;\n\t\t$stored = apc_fetch($id, $success);\n\n\t\tif ($success === FALSE OR count($stored) !== 3)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tlist($data, $time, $ttl) = $stored;\n\n\t\treturn array(\n\t\t\t'expire'\t=> $time + $ttl,\n\t\t\t'mtime'\t\t=> $time,\n\t\t\t'data'\t\t=> unserialize($data)\n\t\t);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * is_supported()\n\t *\n\t * Check to see if APC is available on this system, bail if it isn't.\n\t *\n\t * @return\tbool\n\t */\n\tpublic function is_supported()\n\t{\n\t\treturn (extension_loaded('apc') && ini_get('apc.enabled'));\n\t}\n}\n"
  },
  {
    "path": "system/libraries/Cache/drivers/Cache_dummy.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 2.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Dummy Caching Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tCore\n * @author\t\tEllisLab Dev Team\n * @link\n */\nclass CI_Cache_dummy extends CI_Driver {\n\n\t/**\n\t * Get\n\t *\n\t * Since this is the dummy class, it's always going to return FALSE.\n\t *\n\t * @param\tstring\n\t * @return\tbool\tFALSE\n\t */\n\tpublic function get($id)\n\t{\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Cache Save\n\t *\n\t * @param\tstring\tUnique Key\n\t * @param\tmixed\tData to store\n\t * @param\tint\tLength of time (in seconds) to cache the data\n\t * @param\tbool\tWhether to store the raw value\n\t * @return\tbool\tTRUE, Simulating success\n\t */\n\tpublic function save($id, $data, $ttl = 60, $raw = FALSE)\n\t{\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Delete from Cache\n\t *\n\t * @param\tmixed\tunique identifier of the item in the cache\n\t * @return\tbool\tTRUE, simulating success\n\t */\n\tpublic function delete($id)\n\t{\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Increment a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to add\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function increment($id, $offset = 1)\n\t{\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Decrement a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to reduce by\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function decrement($id, $offset = 1)\n\t{\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Clean the cache\n\t *\n\t * @return\tbool\tTRUE, simulating success\n\t */\n\tpublic function clean()\n\t{\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Cache Info\n\t *\n\t * @param\tstring\tuser/filehits\n\t * @return\tbool\tFALSE\n\t */\n\t public function cache_info($type = NULL)\n\t {\n\t\t return FALSE;\n\t }\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get Cache Metadata\n\t *\n\t * @param\tmixed\tkey to get cache metadata on\n\t * @return\tbool\tFALSE\n\t */\n\tpublic function get_metadata($id)\n\t{\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Is this caching driver supported on the system?\n\t * Of course this one is.\n\t *\n\t * @return\tbool\tTRUE\n\t */\n\tpublic function is_supported()\n\t{\n\t\treturn TRUE;\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/Cache/drivers/Cache_file.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 2.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter File Caching Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tCore\n * @author\t\tEllisLab Dev Team\n * @link\n */\nclass CI_Cache_file extends CI_Driver {\n\n\t/**\n\t * Directory in which to save cache files\n\t *\n\t * @var string\n\t */\n\tprotected $_cache_path;\n\n\t/**\n\t * Initialize file-based cache\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\t$CI =& get_instance();\n\t\t$CI->load->helper('file');\n\t\t$path = $CI->config->item('cache_path');\n\t\t$this->_cache_path = ($path === '') ? APPPATH.'cache/' : $path;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Fetch from cache\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @return\tmixed\tData on success, FALSE on failure\n\t */\n\tpublic function get($id)\n\t{\n\t\t$data = $this->_get($id);\n\t\treturn is_array($data) ? $data['data'] : FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Save into cache\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tmixed\t$data\tData to store\n\t * @param\tint\t$ttl\tTime to live in seconds\n\t * @param\tbool\t$raw\tWhether to store the raw value (unused)\n\t * @return\tbool\tTRUE on success, FALSE on failure\n\t */\n\tpublic function save($id, $data, $ttl = 60, $raw = FALSE)\n\t{\n\t\t$contents = array(\n\t\t\t'time'\t\t=> time(),\n\t\t\t'ttl'\t\t=> $ttl,\n\t\t\t'data'\t\t=> $data\n\t\t);\n\n\t\tif (write_file($this->_cache_path.$id, serialize($contents)))\n\t\t{\n\t\t\tchmod($this->_cache_path.$id, 0640);\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Delete from Cache\n\t *\n\t * @param\tmixed\tunique identifier of item in cache\n\t * @return\tbool\ttrue on success/false on failure\n\t */\n\tpublic function delete($id)\n\t{\n\t\treturn file_exists($this->_cache_path.$id) ? unlink($this->_cache_path.$id) : FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Increment a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to add\n\t * @return\tNew value on success, FALSE on failure\n\t */\n\tpublic function increment($id, $offset = 1)\n\t{\n\t\t$data = $this->_get($id);\n\n\t\tif ($data === FALSE)\n\t\t{\n\t\t\t$data = array('data' => 0, 'ttl' => 60);\n\t\t}\n\t\telseif ( ! is_int($data['data']))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$new_value = $data['data'] + $offset;\n\t\treturn $this->save($id, $new_value, $data['ttl'])\n\t\t\t? $new_value\n\t\t\t: FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Decrement a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to reduce by\n\t * @return\tNew value on success, FALSE on failure\n\t */\n\tpublic function decrement($id, $offset = 1)\n\t{\n\t\t$data = $this->_get($id);\n\n\t\tif ($data === FALSE)\n\t\t{\n\t\t\t$data = array('data' => 0, 'ttl' => 60);\n\t\t}\n\t\telseif ( ! is_int($data['data']))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$new_value = $data['data'] - $offset;\n\t\treturn $this->save($id, $new_value, $data['ttl'])\n\t\t\t? $new_value\n\t\t\t: FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Clean the Cache\n\t *\n\t * @return\tbool\tfalse on failure/true on success\n\t */\n\tpublic function clean()\n\t{\n\t\treturn delete_files($this->_cache_path, FALSE, TRUE);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Cache Info\n\t *\n\t * Not supported by file-based caching\n\t *\n\t * @param\tstring\tuser/filehits\n\t * @return\tmixed\tFALSE\n\t */\n\tpublic function cache_info($type = NULL)\n\t{\n\t\treturn get_dir_file_info($this->_cache_path);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get Cache Metadata\n\t *\n\t * @param\tmixed\tkey to get cache metadata on\n\t * @return\tmixed\tFALSE on failure, array on success.\n\t */\n\tpublic function get_metadata($id)\n\t{\n\t\tif ( ! file_exists($this->_cache_path.$id))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$data = unserialize(file_get_contents($this->_cache_path.$id));\n\n\t\tif (is_array($data))\n\t\t{\n\t\t\t$mtime = filemtime($this->_cache_path.$id);\n\n\t\t\tif ( ! isset($data['ttl']))\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\treturn array(\n\t\t\t\t'expire' => $mtime + $data['ttl'],\n\t\t\t\t'mtime'\t => $mtime\n\t\t\t);\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Is supported\n\t *\n\t * In the file driver, check to see that the cache directory is indeed writable\n\t *\n\t * @return\tbool\n\t */\n\tpublic function is_supported()\n\t{\n\t\treturn is_really_writable($this->_cache_path);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get all data\n\t *\n\t * Internal method to get all the relevant data about a cache item\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @return\tmixed\tData array on success or FALSE on failure\n\t */\n\tprotected function _get($id)\n\t{\n\t\tif ( ! is_file($this->_cache_path.$id))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$data = unserialize(file_get_contents($this->_cache_path.$id));\n\n\t\tif ($data['ttl'] > 0 && time() > $data['time'] + $data['ttl'])\n\t\t{\n\t\t\tunlink($this->_cache_path.$id);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn $data;\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/Cache/drivers/Cache_memcached.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 2.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Memcached Caching Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tCore\n * @author\t\tEllisLab Dev Team\n * @link\n */\nclass CI_Cache_memcached extends CI_Driver {\n\n\t/**\n\t * Holds the memcached object\n\t *\n\t * @var object\n\t */\n\tprotected $_memcached;\n\n\t/**\n\t * Memcached configuration\n\t *\n\t * @var array\n\t */\n\tprotected $_config = array(\n\t\t'default' => array(\n\t\t\t'host'\t\t=> '127.0.0.1',\n\t\t\t'port'\t\t=> 11211,\n\t\t\t'weight'\t=> 1\n\t\t)\n\t);\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Setup Memcache(d)\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\t// Try to load memcached server info from the config file.\n\t\t$CI =& get_instance();\n\t\t$defaults = $this->_config['default'];\n\n\t\tif ($CI->config->load('memcached', TRUE, TRUE))\n\t\t{\n\t\t\t$this->_config = $CI->config->config['memcached'];\n\t\t}\n\n\t\tif (class_exists('Memcached', FALSE))\n\t\t{\n\t\t\t$this->_memcached = new Memcached();\n\t\t}\n\t\telseif (class_exists('Memcache', FALSE))\n\t\t{\n\t\t\t$this->_memcached = new Memcache();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlog_message('error', 'Cache: Failed to create Memcache(d) object; extension not loaded?');\n\t\t\treturn;\n\t\t}\n\n\t\tforeach ($this->_config as $cache_server)\n\t\t{\n\t\t\tisset($cache_server['hostname']) OR $cache_server['hostname'] = $defaults['host'];\n\t\t\tisset($cache_server['port']) OR $cache_server['port'] = $defaults['port'];\n\t\t\tisset($cache_server['weight']) OR $cache_server['weight'] = $defaults['weight'];\n\n\t\t\tif ($this->_memcached instanceof Memcache)\n\t\t\t{\n\t\t\t\t// Third parameter is persistance and defaults to TRUE.\n\t\t\t\t$this->_memcached->addServer(\n\t\t\t\t\t$cache_server['hostname'],\n\t\t\t\t\t$cache_server['port'],\n\t\t\t\t\tTRUE,\n\t\t\t\t\t$cache_server['weight']\n\t\t\t\t);\n\t\t\t}\n\t\t\telseif ($this->_memcached instanceof Memcached)\n\t\t\t{\n\t\t\t\t$this->_memcached->addServer(\n\t\t\t\t\t$cache_server['hostname'],\n\t\t\t\t\t$cache_server['port'],\n\t\t\t\t\t$cache_server['weight']\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Fetch from cache\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @return\tmixed\tData on success, FALSE on failure\n\t */\n\tpublic function get($id)\n\t{\n\t\t$data = $this->_memcached->get($id);\n\n\t\treturn is_array($data) ? $data[0] : $data;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Save\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tmixed\t$data\tData being cached\n\t * @param\tint\t$ttl\tTime to live\n\t * @param\tbool\t$raw\tWhether to store the raw value\n\t * @return\tbool\tTRUE on success, FALSE on failure\n\t */\n\tpublic function save($id, $data, $ttl = 60, $raw = FALSE)\n\t{\n\t\tif ($raw !== TRUE)\n\t\t{\n\t\t\t$data = array($data, time(), $ttl);\n\t\t}\n\n\t\tif ($this->_memcached instanceof Memcached)\n\t\t{\n\t\t\treturn $this->_memcached->set($id, $data, $ttl);\n\t\t}\n\t\telseif ($this->_memcached instanceof Memcache)\n\t\t{\n\t\t\treturn $this->_memcached->set($id, $data, 0, $ttl);\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Delete from Cache\n\t *\n\t * @param\tmixed\t$id\tkey to be deleted.\n\t * @return\tbool\ttrue on success, false on failure\n\t */\n\tpublic function delete($id)\n\t{\n\t\treturn $this->_memcached->delete($id);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Increment a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to add\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function increment($id, $offset = 1)\n\t{\n\t\treturn $this->_memcached->increment($id, $offset);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Decrement a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to reduce by\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function decrement($id, $offset = 1)\n\t{\n\t\treturn $this->_memcached->decrement($id, $offset);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Clean the Cache\n\t *\n\t * @return\tbool\tfalse on failure/true on success\n\t */\n\tpublic function clean()\n\t{\n\t\treturn $this->_memcached->flush();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Cache Info\n\t *\n\t * @return\tmixed\tarray on success, false on failure\n\t */\n\tpublic function cache_info()\n\t{\n\t\treturn $this->_memcached->getStats();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get Cache Metadata\n\t *\n\t * @param\tmixed\t$id\tkey to get cache metadata on\n\t * @return\tmixed\tFALSE on failure, array on success.\n\t */\n\tpublic function get_metadata($id)\n\t{\n\t\t$stored = $this->_memcached->get($id);\n\n\t\tif (count($stored) !== 3)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tlist($data, $time, $ttl) = $stored;\n\n\t\treturn array(\n\t\t\t'expire'\t=> $time + $ttl,\n\t\t\t'mtime'\t\t=> $time,\n\t\t\t'data'\t\t=> $data\n\t\t);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Is supported\n\t *\n\t * Returns FALSE if memcached is not supported on the system.\n\t * If it is, we setup the memcached object & return TRUE\n\t *\n\t * @return\tbool\n\t */\n\tpublic function is_supported()\n\t{\n\t\treturn (extension_loaded('memcached') OR extension_loaded('memcache'));\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Class destructor\n\t *\n\t * Closes the connection to Memcache(d) if present.\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __destruct()\n\t{\n\t\tif ($this->_memcached instanceof Memcache)\n\t\t{\n\t\t\t$this->_memcached->close();\n\t\t}\n\t\telseif ($this->_memcached instanceof Memcached && method_exists($this->_memcached, 'quit'))\n\t\t{\n\t\t\t$this->_memcached->quit();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "system/libraries/Cache/drivers/Cache_redis.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Redis Caching Class\n *\n * @package\t   CodeIgniter\n * @subpackage Libraries\n * @category   Core\n * @author\t   Anton Lindqvist <anton@qvister.se>\n * @link\n */\nclass CI_Cache_redis extends CI_Driver\n{\n\t/**\n\t * Default config\n\t *\n\t * @static\n\t * @var\tarray\n\t */\n\tprotected static $_default_config = array(\n\t\t'socket_type' => 'tcp',\n\t\t'host' => '127.0.0.1',\n\t\t'password' => NULL,\n\t\t'port' => 6379,\n\t\t'timeout' => 0\n\t);\n\n\t/**\n\t * Redis connection\n\t *\n\t * @var\tRedis\n\t */\n\tprotected $_redis;\n\n\t/**\n\t * An internal cache for storing keys of serialized values.\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_serialized = array();\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Setup Redis\n\t *\n\t * Loads Redis config file if present. Will halt execution\n\t * if a Redis connection can't be established.\n\t *\n\t * @return\tvoid\n\t * @see\t\tRedis::connect()\n\t */\n\tpublic function __construct()\n\t{\n\t\tif ( ! $this->is_supported())\n\t\t{\n\t\t\tlog_message('error', 'Cache: Failed to create Redis object; extension not loaded?');\n\t\t\treturn;\n\t\t}\n\n\t\t$CI =& get_instance();\n\n\t\tif ($CI->config->load('redis', TRUE, TRUE))\n\t\t{\n\t\t\t$config = array_merge(self::$_default_config, $CI->config->item('redis'));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$config = self::$_default_config;\n\t\t}\n\n\t\t$this->_redis = new Redis();\n\n\t\ttry\n\t\t{\n\t\t\tif ($config['socket_type'] === 'unix')\n\t\t\t{\n\t\t\t\t$success = $this->_redis->connect($config['socket']);\n\t\t\t}\n\t\t\telse // tcp socket\n\t\t\t{\n\t\t\t\t$success = $this->_redis->connect($config['host'], $config['port'], $config['timeout']);\n\t\t\t}\n\n\t\t\tif ( ! $success)\n\t\t\t{\n\t\t\t\tlog_message('error', 'Cache: Redis connection failed. Check your configuration.');\n\t\t\t}\n\n\t\t\tif (isset($config['password']) && ! $this->_redis->auth($config['password']))\n\t\t\t{\n\t\t\t\tlog_message('error', 'Cache: Redis authentication failed.');\n\t\t\t}\n\t\t}\n\t\tcatch (RedisException $e)\n\t\t{\n\t\t\tlog_message('error', 'Cache: Redis connection refused ('.$e->getMessage().')');\n\t\t}\n\n\t\t// Initialize the index of serialized values.\n\t\t$serialized = $this->_redis->sMembers('_ci_redis_serialized');\n\t\tempty($serialized) OR $this->_serialized = array_flip($serialized);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get cache\n\t *\n\t * @param\tstring\t$key\tCache ID\n\t * @return\tmixed\n\t */\n\tpublic function get($key)\n\t{\n\t\t$value = $this->_redis->get($key);\n\n\t\tif ($value !== FALSE && isset($this->_serialized[$key]))\n\t\t{\n\t\t\treturn unserialize($value);\n\t\t}\n\n\t\treturn $value;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Save cache\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tmixed\t$data\tData to save\n\t * @param\tint\t$ttl\tTime to live in seconds\n\t * @param\tbool\t$raw\tWhether to store the raw value (unused)\n\t * @return\tbool\tTRUE on success, FALSE on failure\n\t */\n\tpublic function save($id, $data, $ttl = 60, $raw = FALSE)\n\t{\n\t\tif (is_array($data) OR is_object($data))\n\t\t{\n\t\t\tif ( ! $this->_redis->sIsMember('_ci_redis_serialized', $id) && ! $this->_redis->sAdd('_ci_redis_serialized', $id))\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tisset($this->_serialized[$id]) OR $this->_serialized[$id] = TRUE;\n\t\t\t$data = serialize($data);\n\t\t}\n\t\telseif (isset($this->_serialized[$id]))\n\t\t{\n\t\t\t$this->_serialized[$id] = NULL;\n\t\t\t$this->_redis->sRemove('_ci_redis_serialized', $id);\n\t\t}\n\n\t\treturn $this->_redis->set($id, $data, $ttl);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Delete from cache\n\t *\n\t * @param\tstring\t$key\tCache key\n\t * @return\tbool\n\t */\n\tpublic function delete($key)\n\t{\n\t\tif ($this->_redis->delete($key) !== 1)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (isset($this->_serialized[$key]))\n\t\t{\n\t\t\t$this->_serialized[$key] = NULL;\n\t\t\t$this->_redis->sRemove('_ci_redis_serialized', $key);\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Increment a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to add\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function increment($id, $offset = 1)\n\t{\n\t\treturn $this->_redis->incr($id, $offset);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Decrement a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to reduce by\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function decrement($id, $offset = 1)\n\t{\n\t\treturn $this->_redis->decr($id, $offset);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Clean cache\n\t *\n\t * @return\tbool\n\t * @see\t\tRedis::flushDB()\n\t */\n\tpublic function clean()\n\t{\n\t\treturn $this->_redis->flushDB();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get cache driver info\n\t *\n\t * @param\tstring\t$type\tNot supported in Redis.\n\t *\t\t\t\tOnly included in order to offer a\n\t *\t\t\t\tconsistent cache API.\n\t * @return\tarray\n\t * @see\t\tRedis::info()\n\t */\n\tpublic function cache_info($type = NULL)\n\t{\n\t\treturn $this->_redis->info();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get cache metadata\n\t *\n\t * @param\tstring\t$key\tCache key\n\t * @return\tarray\n\t */\n\tpublic function get_metadata($key)\n\t{\n\t\t$value = $this->get($key);\n\n\t\tif ($value !== FALSE)\n\t\t{\n\t\t\treturn array(\n\t\t\t\t'expire' => time() + $this->_redis->ttl($key),\n\t\t\t\t'data' => $value\n\t\t\t);\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Check if Redis driver is supported\n\t *\n\t * @return\tbool\n\t */\n\tpublic function is_supported()\n\t{\n\t\treturn extension_loaded('redis');\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Class destructor\n\t *\n\t * Closes the connection to Redis if present.\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __destruct()\n\t{\n\t\tif ($this->_redis)\n\t\t{\n\t\t\t$this->_redis->close();\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "system/libraries/Cache/drivers/Cache_wincache.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Wincache Caching Class\n *\n * Read more about Wincache functions here:\n * http://www.php.net/manual/en/ref.wincache.php\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tCore\n * @author\t\tMike Murkovic\n * @link\n */\nclass CI_Cache_wincache extends CI_Driver {\n\n\t/**\n\t * Class constructor\n\t *\n\t * Only present so that an error message is logged\n\t * if APC is not available.\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\tif ( ! $this->is_supported())\n\t\t{\n\t\t\tlog_message('error', 'Cache: Failed to initialize Wincache; extension not loaded/enabled?');\n\t\t}\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get\n\t *\n\t * Look for a value in the cache. If it exists, return the data,\n\t * if not, return FALSE\n\t *\n\t * @param\tstring\t$id\tCache Ide\n\t * @return\tmixed\tValue that is stored/FALSE on failure\n\t */\n\tpublic function get($id)\n\t{\n\t\t$success = FALSE;\n\t\t$data = wincache_ucache_get($id, $success);\n\n\t\t// Success returned by reference from wincache_ucache_get()\n\t\treturn ($success) ? $data : FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Cache Save\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tmixed\t$data\tData to store\n\t * @param\tint\t$ttl\tTime to live (in seconds)\n\t * @param\tbool\t$raw\tWhether to store the raw value (unused)\n\t * @return\tbool\ttrue on success/false on failure\n\t */\n\tpublic function save($id, $data, $ttl = 60, $raw = FALSE)\n\t{\n\t\treturn wincache_ucache_set($id, $data, $ttl);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Delete from Cache\n\t *\n\t * @param\tmixed\tunique identifier of the item in the cache\n\t * @return\tbool\ttrue on success/false on failure\n\t */\n\tpublic function delete($id)\n\t{\n\t\treturn wincache_ucache_delete($id);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Increment a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to add\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function increment($id, $offset = 1)\n\t{\n\t\t$success = FALSE;\n\t\t$value = wincache_ucache_inc($id, $offset, $success);\n\n\t\treturn ($success === TRUE) ? $value : FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Decrement a raw value\n\t *\n\t * @param\tstring\t$id\tCache ID\n\t * @param\tint\t$offset\tStep/value to reduce by\n\t * @return\tmixed\tNew value on success or FALSE on failure\n\t */\n\tpublic function decrement($id, $offset = 1)\n\t{\n\t\t$success = FALSE;\n\t\t$value = wincache_ucache_dec($id, $offset, $success);\n\n\t\treturn ($success === TRUE) ? $value : FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Clean the cache\n\t *\n\t * @return\tbool\tfalse on failure/true on success\n\t */\n\tpublic function clean()\n\t{\n\t\treturn wincache_ucache_clear();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Cache Info\n\t *\n\t * @return\tmixed\tarray on success, false on failure\n\t */\n\t public function cache_info()\n\t {\n\t\t return wincache_ucache_info(TRUE);\n\t }\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get Cache Metadata\n\t *\n\t * @param\tmixed\tkey to get cache metadata on\n\t * @return\tmixed\tarray on success/false on failure\n\t */\n\tpublic function get_metadata($id)\n\t{\n\t\tif ($stored = wincache_ucache_info(FALSE, $id))\n\t\t{\n\t\t\t$age = $stored['ucache_entries'][1]['age_seconds'];\n\t\t\t$ttl = $stored['ucache_entries'][1]['ttl_seconds'];\n\t\t\t$hitcount = $stored['ucache_entries'][1]['hitcount'];\n\n\t\t\treturn array(\n\t\t\t\t'expire'\t=> $ttl - $age,\n\t\t\t\t'hitcount'\t=> $hitcount,\n\t\t\t\t'age'\t\t=> $age,\n\t\t\t\t'ttl'\t\t=> $ttl\n\t\t\t);\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * is_supported()\n\t *\n\t * Check to see if WinCache is available on this system, bail if it isn't.\n\t *\n\t * @return\tbool\n\t */\n\tpublic function is_supported()\n\t{\n\t\treturn (extension_loaded('wincache') && ini_get('wincache.ucenabled'));\n\t}\n}\n"
  },
  {
    "path": "system/libraries/Cache/drivers/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/libraries/Cache/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/libraries/Calendar.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Calendar Class\n *\n * This class enables the creation of calendars\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/calendar.html\n */\nclass CI_Calendar {\n\n\t/**\n\t * Calendar layout template\n\t *\n\t * @var mixed\n\t */\n\tpublic $template = '';\n\n\t/**\n\t * Replacements array for template\n\t *\n\t * @var array\n\t */\n\tpublic $replacements = array();\n\n\t/**\n\t * Day of the week to start the calendar on\n\t *\n\t * @var string\n\t */\n\tpublic $start_day = 'sunday';\n\n\t/**\n\t * How to display months\n\t *\n\t * @var string\n\t */\n\tpublic $month_type = 'long';\n\n\t/**\n\t * How to display names of days\n\t *\n\t * @var string\n\t */\n\tpublic $day_type = 'abr';\n\n\t/**\n\t * Whether to show next/prev month links\n\t *\n\t * @var bool\n\t */\n\tpublic $show_next_prev = FALSE;\n\n\t/**\n\t * Url base to use for next/prev month links\n\t *\n\t * @var bool\n\t */\n\tpublic $next_prev_url = '';\n\n\t/**\n\t * Show days of other months\n\t *\n\t * @var bool\n\t */\n\tpublic $show_other_days = FALSE;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * CI Singleton\n\t *\n\t * @var object\n\t */\n\tprotected $CI;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Loads the calendar language file and sets the default time reference.\n\t *\n\t * @uses\tCI_Lang::$is_loaded\n\t *\n\t * @param\tarray\t$config\tCalendar options\n\t * @return\tvoid\n\t */\n\tpublic function __construct($config = array())\n\t{\n\t\t$this->CI =& get_instance();\n\t\t$this->CI->lang->load('calendar');\n\n\t\tempty($config) OR $this->initialize($config);\n\n\t\tlog_message('info', 'Calendar Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize the user preferences\n\t *\n\t * Accepts an associative array as input, containing display preferences\n\t *\n\t * @param\tarray\tconfig preferences\n\t * @return\tCI_Calendar\n\t */\n\tpublic function initialize($config = array())\n\t{\n\t\tforeach ($config as $key => $val)\n\t\t{\n\t\t\tif (isset($this->$key))\n\t\t\t{\n\t\t\t\t$this->$key = $val;\n\t\t\t}\n\t\t}\n\n\t\t// Set the next_prev_url to the controller if required but not defined\n\t\tif ($this->show_next_prev === TRUE && empty($this->next_prev_url))\n\t\t{\n\t\t\t$this->next_prev_url = $this->CI->config->site_url($this->CI->router->class.'/'.$this->CI->router->method);\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Generate the calendar\n\t *\n\t * @param\tint\tthe year\n\t * @param\tint\tthe month\n\t * @param\tarray\tthe data to be shown in the calendar cells\n\t * @return\tstring\n\t */\n\tpublic function generate($year = '', $month = '', $data = array())\n\t{\n\t\t$local_time = time();\n\n\t\t// Set and validate the supplied month/year\n\t\tif (empty($year))\n\t\t{\n\t\t\t$year = date('Y', $local_time);\n\t\t}\n\t\telseif (strlen($year) === 1)\n\t\t{\n\t\t\t$year = '200'.$year;\n\t\t}\n\t\telseif (strlen($year) === 2)\n\t\t{\n\t\t\t$year = '20'.$year;\n\t\t}\n\n\t\tif (empty($month))\n\t\t{\n\t\t\t$month = date('m', $local_time);\n\t\t}\n\t\telseif (strlen($month) === 1)\n\t\t{\n\t\t\t$month = '0'.$month;\n\t\t}\n\n\t\t$adjusted_date = $this->adjust_date($month, $year);\n\n\t\t$month\t= $adjusted_date['month'];\n\t\t$year\t= $adjusted_date['year'];\n\n\t\t// Determine the total days in the month\n\t\t$total_days = $this->get_total_days($month, $year);\n\n\t\t// Set the starting day of the week\n\t\t$start_days\t= array('sunday' => 0, 'monday' => 1, 'tuesday' => 2, 'wednesday' => 3, 'thursday' => 4, 'friday' => 5, 'saturday' => 6);\n\t\t$start_day\t= isset($start_days[$this->start_day]) ? $start_days[$this->start_day] : 0;\n\n\t\t// Set the starting day number\n\t\t$local_date = mktime(12, 0, 0, $month, 1, $year);\n\t\t$date = getdate($local_date);\n\t\t$day  = $start_day + 1 - $date['wday'];\n\n\t\twhile ($day > 1)\n\t\t{\n\t\t\t$day -= 7;\n\t\t}\n\n\t\t// Set the current month/year/day\n\t\t// We use this to determine the \"today\" date\n\t\t$cur_year\t= date('Y', $local_time);\n\t\t$cur_month\t= date('m', $local_time);\n\t\t$cur_day\t= date('j', $local_time);\n\n\t\t$is_current_month = ($cur_year == $year && $cur_month == $month);\n\n\t\t// Generate the template data array\n\t\t$this->parse_template();\n\n\t\t// Begin building the calendar output\n\t\t$out = $this->replacements['table_open'].\"\\n\\n\".$this->replacements['heading_row_start'].\"\\n\";\n\n\t\t// \"previous\" month link\n\t\tif ($this->show_next_prev === TRUE)\n\t\t{\n\t\t\t// Add a trailing slash to the URL if needed\n\t\t\t$this->next_prev_url = preg_replace('/(.+?)\\/*$/', '\\\\1/', $this->next_prev_url);\n\n\t\t\t$adjusted_date = $this->adjust_date($month - 1, $year);\n\t\t\t$out .= str_replace('{previous_url}', $this->next_prev_url.$adjusted_date['year'].'/'.$adjusted_date['month'], $this->replacements['heading_previous_cell']).\"\\n\";\n\t\t}\n\n\t\t// Heading containing the month/year\n\t\t$colspan = ($this->show_next_prev === TRUE) ? 5 : 7;\n\n\t\t$this->replacements['heading_title_cell'] = str_replace('{colspan}', $colspan,\n\t\t\t\t\t\t\t\tstr_replace('{heading}', $this->get_month_name($month).'&nbsp;'.$year, $this->replacements['heading_title_cell']));\n\n\t\t$out .= $this->replacements['heading_title_cell'].\"\\n\";\n\n\t\t// \"next\" month link\n\t\tif ($this->show_next_prev === TRUE)\n\t\t{\n\t\t\t$adjusted_date = $this->adjust_date($month + 1, $year);\n\t\t\t$out .= str_replace('{next_url}', $this->next_prev_url.$adjusted_date['year'].'/'.$adjusted_date['month'], $this->replacements['heading_next_cell']);\n\t\t}\n\n\t\t$out .= \"\\n\".$this->replacements['heading_row_end'].\"\\n\\n\"\n\t\t\t// Write the cells containing the days of the week\n\t\t\t.$this->replacements['week_row_start'].\"\\n\";\n\n\t\t$day_names = $this->get_day_names();\n\n\t\tfor ($i = 0; $i < 7; $i ++)\n\t\t{\n\t\t\t$out .= str_replace('{week_day}', $day_names[($start_day + $i) %7], $this->replacements['week_day_cell']);\n\t\t}\n\n\t\t$out .= \"\\n\".$this->replacements['week_row_end'].\"\\n\";\n\n\t\t// Build the main body of the calendar\n\t\twhile ($day <= $total_days)\n\t\t{\n\t\t\t$out .= \"\\n\".$this->replacements['cal_row_start'].\"\\n\";\n\n\t\t\tfor ($i = 0; $i < 7; $i++)\n\t\t\t{\n\t\t\t\tif ($day > 0 && $day <= $total_days)\n\t\t\t\t{\n\t\t\t\t\t$out .= ($is_current_month === TRUE && $day == $cur_day) ? $this->replacements['cal_cell_start_today'] : $this->replacements['cal_cell_start'];\n\n\t\t\t\t\tif (isset($data[$day]))\n\t\t\t\t\t{\n\t\t\t\t\t\t// Cells with content\n\t\t\t\t\t\t$temp = ($is_current_month === TRUE && $day == $cur_day) ?\n\t\t\t\t\t\t\t\t$this->replacements['cal_cell_content_today'] : $this->replacements['cal_cell_content'];\n\t\t\t\t\t\t$out .= str_replace(array('{content}', '{day}'), array($data[$day], $day), $temp);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// Cells with no content\n\t\t\t\t\t\t$temp = ($is_current_month === TRUE && $day == $cur_day) ?\n\t\t\t\t\t\t\t\t$this->replacements['cal_cell_no_content_today'] : $this->replacements['cal_cell_no_content'];\n\t\t\t\t\t\t$out .= str_replace('{day}', $day, $temp);\n\t\t\t\t\t}\n\n\t\t\t\t\t$out .= ($is_current_month === TRUE && $day == $cur_day) ? $this->replacements['cal_cell_end_today'] : $this->replacements['cal_cell_end'];\n\t\t\t\t}\n\t\t\t\telseif ($this->show_other_days === TRUE)\n\t\t\t\t{\n\t\t\t\t\t$out .= $this->replacements['cal_cell_start_other'];\n\n\t\t\t\t\tif ($day <= 0)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Day of previous month\n\t\t\t\t\t\t$prev_month = $this->adjust_date($month - 1, $year);\n\t\t\t\t\t\t$prev_month_days = $this->get_total_days($prev_month['month'], $prev_month['year']);\n\t\t\t\t\t\t$out .= str_replace('{day}', $prev_month_days + $day, $this->replacements['cal_cell_other']);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// Day of next month\n\t\t\t\t\t\t$out .= str_replace('{day}', $day - $total_days, $this->replacements['cal_cell_other']);\n\t\t\t\t\t}\n\n\t\t\t\t\t$out .= $this->replacements['cal_cell_end_other'];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// Blank cells\n\t\t\t\t\t$out .= $this->replacements['cal_cell_start'].$this->replacements['cal_cell_blank'].$this->replacements['cal_cell_end'];\n\t\t\t\t}\n\n\t\t\t\t$day++;\n\t\t\t}\n\n\t\t\t$out .= \"\\n\".$this->replacements['cal_row_end'].\"\\n\";\n\t\t}\n\n\t\treturn $out .= \"\\n\".$this->replacements['table_close'];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Month Name\n\t *\n\t * Generates a textual month name based on the numeric\n\t * month provided.\n\t *\n\t * @param\tint\tthe month\n\t * @return\tstring\n\t */\n\tpublic function get_month_name($month)\n\t{\n\t\tif ($this->month_type === 'short')\n\t\t{\n\t\t\t$month_names = array('01' => 'cal_jan', '02' => 'cal_feb', '03' => 'cal_mar', '04' => 'cal_apr', '05' => 'cal_may', '06' => 'cal_jun', '07' => 'cal_jul', '08' => 'cal_aug', '09' => 'cal_sep', '10' => 'cal_oct', '11' => 'cal_nov', '12' => 'cal_dec');\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$month_names = array('01' => 'cal_january', '02' => 'cal_february', '03' => 'cal_march', '04' => 'cal_april', '05' => 'cal_mayl', '06' => 'cal_june', '07' => 'cal_july', '08' => 'cal_august', '09' => 'cal_september', '10' => 'cal_october', '11' => 'cal_november', '12' => 'cal_december');\n\t\t}\n\n\t\treturn ($this->CI->lang->line($month_names[$month]) === FALSE)\n\t\t\t? ucfirst(substr($month_names[$month], 4))\n\t\t\t: $this->CI->lang->line($month_names[$month]);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Day Names\n\t *\n\t * Returns an array of day names (Sunday, Monday, etc.) based\n\t * on the type. Options: long, short, abr\n\t *\n\t * @param\tstring\n\t * @return\tarray\n\t */\n\tpublic function get_day_names($day_type = '')\n\t{\n\t\tif ($day_type !== '')\n\t\t{\n\t\t\t$this->day_type = $day_type;\n\t\t}\n\n\t\tif ($this->day_type === 'long')\n\t\t{\n\t\t\t$day_names = array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday');\n\t\t}\n\t\telseif ($this->day_type === 'short')\n\t\t{\n\t\t\t$day_names = array('sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat');\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$day_names = array('su', 'mo', 'tu', 'we', 'th', 'fr', 'sa');\n\t\t}\n\n\t\t$days = array();\n\t\tfor ($i = 0, $c = count($day_names); $i < $c; $i++)\n\t\t{\n\t\t\t$days[] = ($this->CI->lang->line('cal_'.$day_names[$i]) === FALSE) ? ucfirst($day_names[$i]) : $this->CI->lang->line('cal_'.$day_names[$i]);\n\t\t}\n\n\t\treturn $days;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Adjust Date\n\t *\n\t * This function makes sure that we have a valid month/year.\n\t * For example, if you submit 13 as the month, the year will\n\t * increment and the month will become January.\n\t *\n\t * @param\tint\tthe month\n\t * @param\tint\tthe year\n\t * @return\tarray\n\t */\n\tpublic function adjust_date($month, $year)\n\t{\n\t\t$date = array();\n\n\t\t$date['month']\t= $month;\n\t\t$date['year']\t= $year;\n\n\t\twhile ($date['month'] > 12)\n\t\t{\n\t\t\t$date['month'] -= 12;\n\t\t\t$date['year']++;\n\t\t}\n\n\t\twhile ($date['month'] <= 0)\n\t\t{\n\t\t\t$date['month'] += 12;\n\t\t\t$date['year']--;\n\t\t}\n\n\t\tif (strlen($date['month']) === 1)\n\t\t{\n\t\t\t$date['month'] = '0'.$date['month'];\n\t\t}\n\n\t\treturn $date;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Total days in a given month\n\t *\n\t * @param\tint\tthe month\n\t * @param\tint\tthe year\n\t * @return\tint\n\t */\n\tpublic function get_total_days($month, $year)\n\t{\n\t\t$this->CI->load->helper('date');\n\t\treturn days_in_month($month, $year);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Default Template Data\n\t *\n\t * This is used in the event that the user has not created their own template\n\t *\n\t * @return\tarray\n\t */\n\tpublic function default_template()\n\t{\n\t\treturn array(\n\t\t\t'table_open'\t\t\t\t=> '<table border=\"0\" cellpadding=\"4\" cellspacing=\"0\">',\n\t\t\t'heading_row_start'\t\t\t=> '<tr>',\n\t\t\t'heading_previous_cell'\t\t=> '<th><a href=\"{previous_url}\">&lt;&lt;</a></th>',\n\t\t\t'heading_title_cell'\t\t=> '<th colspan=\"{colspan}\">{heading}</th>',\n\t\t\t'heading_next_cell'\t\t\t=> '<th><a href=\"{next_url}\">&gt;&gt;</a></th>',\n\t\t\t'heading_row_end'\t\t\t=> '</tr>',\n\t\t\t'week_row_start'\t\t\t=> '<tr>',\n\t\t\t'week_day_cell'\t\t\t\t=> '<td>{week_day}</td>',\n\t\t\t'week_row_end'\t\t\t\t=> '</tr>',\n\t\t\t'cal_row_start'\t\t\t\t=> '<tr>',\n\t\t\t'cal_cell_start'\t\t\t=> '<td>',\n\t\t\t'cal_cell_start_today'\t\t=> '<td>',\n\t\t\t'cal_cell_start_other'\t\t=> '<td style=\"color: #666;\">',\n\t\t\t'cal_cell_content'\t\t\t=> '<a href=\"{content}\">{day}</a>',\n\t\t\t'cal_cell_content_today'\t=> '<a href=\"{content}\"><strong>{day}</strong></a>',\n\t\t\t'cal_cell_no_content'\t\t=> '{day}',\n\t\t\t'cal_cell_no_content_today'\t=> '<strong>{day}</strong>',\n\t\t\t'cal_cell_blank'\t\t\t=> '&nbsp;',\n\t\t\t'cal_cell_other'\t\t\t=> '{day}',\n\t\t\t'cal_cell_end'\t\t\t\t=> '</td>',\n\t\t\t'cal_cell_end_today'\t\t=> '</td>',\n\t\t\t'cal_cell_end_other'\t\t=> '</td>',\n\t\t\t'cal_row_end'\t\t\t\t=> '</tr>',\n\t\t\t'table_close'\t\t\t\t=> '</table>'\n\t\t);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse Template\n\t *\n\t * Harvests the data within the template {pseudo-variables}\n\t * used to display the calendar\n\t *\n\t * @return\tCI_Calendar\n\t */\n\tpublic function parse_template()\n\t{\n\t\t$this->replacements = $this->default_template();\n\n\t\tif (empty($this->template))\n\t\t{\n\t\t\treturn $this;\n\t\t}\n\n\t\tif (is_string($this->template))\n\t\t{\n\t\t\t$today = array('cal_cell_start_today', 'cal_cell_content_today', 'cal_cell_no_content_today', 'cal_cell_end_today');\n\n\t\t\tforeach (array('table_open', 'table_close', 'heading_row_start', 'heading_previous_cell', 'heading_title_cell', 'heading_next_cell', 'heading_row_end', 'week_row_start', 'week_day_cell', 'week_row_end', 'cal_row_start', 'cal_cell_start', 'cal_cell_content', 'cal_cell_no_content', 'cal_cell_blank', 'cal_cell_end', 'cal_row_end', 'cal_cell_start_today', 'cal_cell_content_today', 'cal_cell_no_content_today', 'cal_cell_end_today', 'cal_cell_start_other', 'cal_cell_other', 'cal_cell_end_other') as $val)\n\t\t\t{\n\t\t\t\tif (preg_match('/\\{'.$val.'\\}(.*?)\\{\\/'.$val.'\\}/si', $this->template, $match))\n\t\t\t\t{\n\t\t\t\t\t$this->replacements[$val] = $match[1];\n\t\t\t\t}\n\t\t\t\telseif (in_array($val, $today, TRUE))\n\t\t\t\t{\n\t\t\t\t\t$this->replacements[$val] = $this->replacements[substr($val, 0, -6)];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telseif (is_array($this->template))\n\t\t{\n\t\t\t$this->replacements = array_merge($this->replacements, $this->template);\n\t\t}\n\n\t\treturn $this;\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/Cart.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Shopping Cart Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tShopping Cart\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/cart.html\n * @deprecated\t3.0.0\tThis class is too specific for CI.\n */\nclass CI_Cart {\n\n\t/**\n\t * These are the regular expression rules that we use to validate the product ID and product name\n\t * alpha-numeric, dashes, underscores, or periods\n\t *\n\t * @var string\n\t */\n\tpublic $product_id_rules = '\\.a-z0-9_-';\n\n\t/**\n\t * These are the regular expression rules that we use to validate the product ID and product name\n\t * alpha-numeric, dashes, underscores, colons or periods\n\t *\n\t * @var string\n\t */\n\tpublic $product_name_rules = '\\w \\-\\.\\:';\n\n\t/**\n\t * only allow safe product names\n\t *\n\t * @var bool\n\t */\n\tpublic $product_name_safe = TRUE;\n\n\t// --------------------------------------------------------------------------\n\n\t/**\n\t * Reference to CodeIgniter instance\n\t *\n\t * @var object\n\t */\n\tprotected $CI;\n\n\t/**\n\t * Contents of the cart\n\t *\n\t * @var array\n\t */\n\tprotected $_cart_contents = array();\n\n\t/**\n\t * Shopping Class Constructor\n\t *\n\t * The constructor loads the Session class, used to store the shopping cart contents.\n\t *\n\t * @param\tarray\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params = array())\n\t{\n\t\t// Set the super object to a local variable for use later\n\t\t$this->CI =& get_instance();\n\n\t\t// Are any config settings being passed manually?  If so, set them\n\t\t$config = is_array($params) ? $params : array();\n\n\t\t// Load the Sessions class\n\t\t$this->CI->load->driver('session', $config);\n\n\t\t// Grab the shopping cart array from the session table\n\t\t$this->_cart_contents = $this->CI->session->userdata('cart_contents');\n\t\tif ($this->_cart_contents === NULL)\n\t\t{\n\t\t\t// No cart exists so we'll set some base values\n\t\t\t$this->_cart_contents = array('cart_total' => 0, 'total_items' => 0);\n\t\t}\n\n\t\tlog_message('info', 'Cart Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert items into the cart and save it to the session table\n\t *\n\t * @param\tarray\n\t * @return\tbool\n\t */\n\tpublic function insert($items = array())\n\t{\n\t\t// Was any cart data passed? No? Bah...\n\t\tif ( ! is_array($items) OR count($items) === 0)\n\t\t{\n\t\t\tlog_message('error', 'The insert method must be passed an array containing data.');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// You can either insert a single product using a one-dimensional array,\n\t\t// or multiple products using a multi-dimensional one. The way we\n\t\t// determine the array type is by looking for a required array key named \"id\"\n\t\t// at the top level. If it's not found, we will assume it's a multi-dimensional array.\n\n\t\t$save_cart = FALSE;\n\t\tif (isset($items['id']))\n\t\t{\n\t\t\tif (($rowid = $this->_insert($items)))\n\t\t\t{\n\t\t\t\t$save_cart = TRUE;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tforeach ($items as $val)\n\t\t\t{\n\t\t\t\tif (is_array($val) && isset($val['id']))\n\t\t\t\t{\n\t\t\t\t\tif ($this->_insert($val))\n\t\t\t\t\t{\n\t\t\t\t\t\t$save_cart = TRUE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Save the cart data if the insert was successful\n\t\tif ($save_cart === TRUE)\n\t\t{\n\t\t\t$this->_save_cart();\n\t\t\treturn isset($rowid) ? $rowid : TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Insert\n\t *\n\t * @param\tarray\n\t * @return\tbool\n\t */\n\tprotected function _insert($items = array())\n\t{\n\t\t// Was any cart data passed? No? Bah...\n\t\tif ( ! is_array($items) OR count($items) === 0)\n\t\t{\n\t\t\tlog_message('error', 'The insert method must be passed an array containing data.');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// --------------------------------------------------------------------\n\n\t\t// Does the $items array contain an id, quantity, price, and name?  These are required\n\t\tif ( ! isset($items['id'], $items['qty'], $items['price'], $items['name']))\n\t\t{\n\t\t\tlog_message('error', 'The cart array must contain a product ID, quantity, price, and name.');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// --------------------------------------------------------------------\n\n\t\t// Prep the quantity. It can only be a number.  Duh... also trim any leading zeros\n\t\t$items['qty'] = (float) $items['qty'];\n\n\t\t// If the quantity is zero or blank there's nothing for us to do\n\t\tif ($items['qty'] == 0)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// --------------------------------------------------------------------\n\n\t\t// Validate the product ID. It can only be alpha-numeric, dashes, underscores or periods\n\t\t// Not totally sure we should impose this rule, but it seems prudent to standardize IDs.\n\t\t// Note: These can be user-specified by setting the $this->product_id_rules variable.\n\t\tif ( ! preg_match('/^['.$this->product_id_rules.']+$/i', $items['id']))\n\t\t{\n\t\t\tlog_message('error', 'Invalid product ID.  The product ID can only contain alpha-numeric characters, dashes, and underscores');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// --------------------------------------------------------------------\n\n\t\t// Validate the product name. It can only be alpha-numeric, dashes, underscores, colons or periods.\n\t\t// Note: These can be user-specified by setting the $this->product_name_rules variable.\n\t\tif ($this->product_name_safe && ! preg_match('/^['.$this->product_name_rules.']+$/i'.(UTF8_ENABLED ? 'u' : ''), $items['name']))\n\t\t{\n\t\t\tlog_message('error', 'An invalid name was submitted as the product name: '.$items['name'].' The name can only contain alpha-numeric characters, dashes, underscores, colons, and spaces');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// --------------------------------------------------------------------\n\n\t\t// Prep the price. Remove leading zeros and anything that isn't a number or decimal point.\n\t\t$items['price'] = (float) $items['price'];\n\n\t\t// We now need to create a unique identifier for the item being inserted into the cart.\n\t\t// Every time something is added to the cart it is stored in the master cart array.\n\t\t// Each row in the cart array, however, must have a unique index that identifies not only\n\t\t// a particular product, but makes it possible to store identical products with different options.\n\t\t// For example, what if someone buys two identical t-shirts (same product ID), but in\n\t\t// different sizes?  The product ID (and other attributes, like the name) will be identical for\n\t\t// both sizes because it's the same shirt. The only difference will be the size.\n\t\t// Internally, we need to treat identical submissions, but with different options, as a unique product.\n\t\t// Our solution is to convert the options array to a string and MD5 it along with the product ID.\n\t\t// This becomes the unique \"row ID\"\n\t\tif (isset($items['options']) && count($items['options']) > 0)\n\t\t{\n\t\t\t$rowid = md5($items['id'].serialize($items['options']));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// No options were submitted so we simply MD5 the product ID.\n\t\t\t// Technically, we don't need to MD5 the ID in this case, but it makes\n\t\t\t// sense to standardize the format of array indexes for both conditions\n\t\t\t$rowid = md5($items['id']);\n\t\t}\n\n\t\t// --------------------------------------------------------------------\n\n\t\t// Now that we have our unique \"row ID\", we'll add our cart items to the master array\n\t\t// grab quantity if it's already there and add it on\n\t\t$old_quantity = isset($this->_cart_contents[$rowid]['qty']) ? (int) $this->_cart_contents[$rowid]['qty'] : 0;\n\n\t\t// Re-create the entry, just to make sure our index contains only the data from this submission\n\t\t$items['rowid'] = $rowid;\n\t\t$items['qty'] += $old_quantity;\n\t\t$this->_cart_contents[$rowid] = $items;\n\n\t\treturn $rowid;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update the cart\n\t *\n\t * This function permits the quantity of a given item to be changed.\n\t * Typically it is called from the \"view cart\" page if a user makes\n\t * changes to the quantity before checkout. That array must contain the\n\t * product ID and quantity for each item.\n\t *\n\t * @param\tarray\n\t * @return\tbool\n\t */\n\tpublic function update($items = array())\n\t{\n\t\t// Was any cart data passed?\n\t\tif ( ! is_array($items) OR count($items) === 0)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// You can either update a single product using a one-dimensional array,\n\t\t// or multiple products using a multi-dimensional one.  The way we\n\t\t// determine the array type is by looking for a required array key named \"rowid\".\n\t\t// If it's not found we assume it's a multi-dimensional array\n\t\t$save_cart = FALSE;\n\t\tif (isset($items['rowid']))\n\t\t{\n\t\t\tif ($this->_update($items) === TRUE)\n\t\t\t{\n\t\t\t\t$save_cart = TRUE;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tforeach ($items as $val)\n\t\t\t{\n\t\t\t\tif (is_array($val) && isset($val['rowid']))\n\t\t\t\t{\n\t\t\t\t\tif ($this->_update($val) === TRUE)\n\t\t\t\t\t{\n\t\t\t\t\t\t$save_cart = TRUE;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Save the cart data if the insert was successful\n\t\tif ($save_cart === TRUE)\n\t\t{\n\t\t\t$this->_save_cart();\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update the cart\n\t *\n\t * This function permits changing item properties.\n\t * Typically it is called from the \"view cart\" page if a user makes\n\t * changes to the quantity before checkout. That array must contain the\n\t * rowid and quantity for each item.\n\t *\n\t * @param\tarray\n\t * @return\tbool\n\t */\n\tprotected function _update($items = array())\n\t{\n\t\t// Without these array indexes there is nothing we can do\n\t\tif ( ! isset($items['rowid'], $this->_cart_contents[$items['rowid']]))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Prep the quantity\n\t\tif (isset($items['qty']))\n\t\t{\n\t\t\t$items['qty'] = (float) $items['qty'];\n\t\t\t// Is the quantity zero?  If so we will remove the item from the cart.\n\t\t\t// If the quantity is greater than zero we are updating\n\t\t\tif ($items['qty'] == 0)\n\t\t\t{\n\t\t\t\tunset($this->_cart_contents[$items['rowid']]);\n\t\t\t\treturn TRUE;\n\t\t\t}\n\t\t}\n\n\t\t// find updatable keys\n\t\t$keys = array_intersect(array_keys($this->_cart_contents[$items['rowid']]), array_keys($items));\n\t\t// if a price was passed, make sure it contains valid data\n\t\tif (isset($items['price']))\n\t\t{\n\t\t\t$items['price'] = (float) $items['price'];\n\t\t}\n\n\t\t// product id & name shouldn't be changed\n\t\tforeach (array_diff($keys, array('id', 'name')) as $key)\n\t\t{\n\t\t\t$this->_cart_contents[$items['rowid']][$key] = $items[$key];\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Save the cart array to the session DB\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _save_cart()\n\t{\n\t\t// Let's add up the individual prices and set the cart sub-total\n\t\t$this->_cart_contents['total_items'] = $this->_cart_contents['cart_total'] = 0;\n\t\tforeach ($this->_cart_contents as $key => $val)\n\t\t{\n\t\t\t// We make sure the array contains the proper indexes\n\t\t\tif ( ! is_array($val) OR ! isset($val['price'], $val['qty']))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t$this->_cart_contents['cart_total'] += ($val['price'] * $val['qty']);\n\t\t\t$this->_cart_contents['total_items'] += $val['qty'];\n\t\t\t$this->_cart_contents[$key]['subtotal'] = ($this->_cart_contents[$key]['price'] * $this->_cart_contents[$key]['qty']);\n\t\t}\n\n\t\t// Is our cart empty? If so we delete it from the session\n\t\tif (count($this->_cart_contents) <= 2)\n\t\t{\n\t\t\t$this->CI->session->unset_userdata('cart_contents');\n\n\t\t\t// Nothing more to do... coffee time!\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// If we made it this far it means that our cart has data.\n\t\t// Let's pass it to the Session class so it can be stored\n\t\t$this->CI->session->set_userdata(array('cart_contents' => $this->_cart_contents));\n\n\t\t// Woot!\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Cart Total\n\t *\n\t * @return\tint\n\t */\n\tpublic function total()\n\t{\n\t\treturn $this->_cart_contents['cart_total'];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Remove Item\n\t *\n\t * Removes an item from the cart\n\t *\n\t * @param\tint\n\t * @return\tbool\n\t */\n\t public function remove($rowid)\n\t {\n\t\t// unset & save\n\t\tunset($this->_cart_contents[$rowid]);\n\t\t$this->_save_cart();\n\t\treturn TRUE;\n\t }\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Total Items\n\t *\n\t * Returns the total item count\n\t *\n\t * @return\tint\n\t */\n\tpublic function total_items()\n\t{\n\t\treturn $this->_cart_contents['total_items'];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Cart Contents\n\t *\n\t * Returns the entire cart array\n\t *\n\t * @param\tbool\n\t * @return\tarray\n\t */\n\tpublic function contents($newest_first = FALSE)\n\t{\n\t\t// do we want the newest first?\n\t\t$cart = ($newest_first) ? array_reverse($this->_cart_contents) : $this->_cart_contents;\n\n\t\t// Remove these so they don't create a problem when showing the cart table\n\t\tunset($cart['total_items']);\n\t\tunset($cart['cart_total']);\n\n\t\treturn $cart;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get cart item\n\t *\n\t * Returns the details of a specific item in the cart\n\t *\n\t * @param\tstring\t$row_id\n\t * @return\tarray\n\t */\n\tpublic function get_item($row_id)\n\t{\n\t\treturn (in_array($row_id, array('total_items', 'cart_total'), TRUE) OR ! isset($this->_cart_contents[$row_id]))\n\t\t\t? FALSE\n\t\t\t: $this->_cart_contents[$row_id];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Has options\n\t *\n\t * Returns TRUE if the rowid passed to this function correlates to an item\n\t * that has options associated with it.\n\t *\n\t * @param\tstring\t$row_id = ''\n\t * @return\tbool\n\t */\n\tpublic function has_options($row_id = '')\n\t{\n\t\treturn (isset($this->_cart_contents[$row_id]['options']) && count($this->_cart_contents[$row_id]['options']) !== 0);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Product options\n\t *\n\t * Returns the an array of options, for a particular product row ID\n\t *\n\t * @param\tstring\t$row_id = ''\n\t * @return\tarray\n\t */\n\tpublic function product_options($row_id = '')\n\t{\n\t\treturn isset($this->_cart_contents[$row_id]['options']) ? $this->_cart_contents[$row_id]['options'] : array();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Format Number\n\t *\n\t * Returns the supplied number with commas and a decimal point.\n\t *\n\t * @param\tfloat\n\t * @return\tstring\n\t */\n\tpublic function format_number($n = '')\n\t{\n\t\treturn ($n === '') ? '' : number_format( (float) $n, 2, '.', ',');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Destroy the cart\n\t *\n\t * Empties the cart and kills the session\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function destroy()\n\t{\n\t\t$this->_cart_contents = array('cart_total' => 0, 'total_items' => 0);\n\t\t$this->CI->session->unset_userdata('cart_contents');\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/Driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Driver Library Class\n *\n * This class enables you to create \"Driver\" libraries that add runtime ability\n * to extend the capabilities of a class via additional driver objects\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tEllisLab Dev Team\n * @link\n */\nclass CI_Driver_Library {\n\n\t/**\n\t * Array of drivers that are available to use with the driver class\n\t *\n\t * @var array\n\t */\n\tprotected $valid_drivers = array();\n\n\t/**\n\t * Name of the current class - usually the driver class\n\t *\n\t * @var string\n\t */\n\tprotected $lib_name;\n\n\t/**\n\t * Get magic method\n\t *\n\t * The first time a child is used it won't exist, so we instantiate it\n\t * subsequents calls will go straight to the proper child.\n\t *\n\t * @param\tstring\tChild class name\n\t * @return\tobject\tChild class\n\t */\n\tpublic function __get($child)\n\t{\n\t\t// Try to load the driver\n\t\treturn $this->load_driver($child);\n\t}\n\n\t/**\n\t * Load driver\n\t *\n\t * Separate load_driver call to support explicit driver load by library or user\n\t *\n\t * @param\tstring\tDriver name (w/o parent prefix)\n\t * @return\tobject\tChild class\n\t */\n\tpublic function load_driver($child)\n\t{\n\t\t// Get CodeIgniter instance and subclass prefix\n\t\t$prefix = config_item('subclass_prefix');\n\n\t\tif ( ! isset($this->lib_name))\n\t\t{\n\t\t\t// Get library name without any prefix\n\t\t\t$this->lib_name = str_replace(array('CI_', $prefix), '', get_class($this));\n\t\t}\n\n\t\t// The child will be prefixed with the parent lib\n\t\t$child_name = $this->lib_name.'_'.$child;\n\n\t\t// See if requested child is a valid driver\n\t\tif ( ! in_array($child, $this->valid_drivers))\n\t\t{\n\t\t\t// The requested driver isn't valid!\n\t\t\t$msg = 'Invalid driver requested: '.$child_name;\n\t\t\tlog_message('error', $msg);\n\t\t\tshow_error($msg);\n\t\t}\n\n\t\t// Get package paths and filename case variations to search\n\t\t$CI = get_instance();\n\t\t$paths = $CI->load->get_package_paths(TRUE);\n\n\t\t// Is there an extension?\n\t\t$class_name = $prefix.$child_name;\n\t\t$found = class_exists($class_name, FALSE);\n\t\tif ( ! $found)\n\t\t{\n\t\t\t// Check for subclass file\n\t\t\tforeach ($paths as $path)\n\t\t\t{\n\t\t\t\t// Does the file exist?\n\t\t\t\t$file = $path.'libraries/'.$this->lib_name.'/drivers/'.$prefix.$child_name.'.php';\n\t\t\t\tif (file_exists($file))\n\t\t\t\t{\n\t\t\t\t\t// Yes - require base class from BASEPATH\n\t\t\t\t\t$basepath = BASEPATH.'libraries/'.$this->lib_name.'/drivers/'.$child_name.'.php';\n\t\t\t\t\tif ( ! file_exists($basepath))\n\t\t\t\t\t{\n\t\t\t\t\t\t$msg = 'Unable to load the requested class: CI_'.$child_name;\n\t\t\t\t\t\tlog_message('error', $msg);\n\t\t\t\t\t\tshow_error($msg);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Include both sources and mark found\n\t\t\t\t\tinclude_once($basepath);\n\t\t\t\t\tinclude_once($file);\n\t\t\t\t\t$found = TRUE;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Do we need to search for the class?\n\t\tif ( ! $found)\n\t\t{\n\t\t\t// Use standard class name\n\t\t\t$class_name = 'CI_'.$child_name;\n\t\t\tif ( ! class_exists($class_name, FALSE))\n\t\t\t{\n\t\t\t\t// Check package paths\n\t\t\t\tforeach ($paths as $path)\n\t\t\t\t{\n\t\t\t\t\t// Does the file exist?\n\t\t\t\t\t$file = $path.'libraries/'.$this->lib_name.'/drivers/'.$child_name.'.php';\n\t\t\t\t\tif (file_exists($file))\n\t\t\t\t\t{\n\t\t\t\t\t\t// Include source\n\t\t\t\t\t\tinclude_once($file);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Did we finally find the class?\n\t\tif ( ! class_exists($class_name, FALSE))\n\t\t{\n\t\t\tif (class_exists($child_name, FALSE))\n\t\t\t{\n\t\t\t\t$class_name = $child_name;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$msg = 'Unable to load the requested driver: '.$class_name;\n\t\t\t\tlog_message('error', $msg);\n\t\t\t\tshow_error($msg);\n\t\t\t}\n\t\t}\n\n\t\t// Instantiate, decorate and add child\n\t\t$obj = new $class_name();\n\t\t$obj->decorate($this);\n\t\t$this->$child = $obj;\n\t\treturn $this->$child;\n\t}\n\n}\n\n// --------------------------------------------------------------------------\n\n/**\n * CodeIgniter Driver Class\n *\n * This class enables you to create drivers for a Library based on the Driver Library.\n * It handles the drivers' access to the parent library\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tEllisLab Dev Team\n * @link\n */\nclass CI_Driver {\n\n\t/**\n\t * Instance of the parent class\n\t *\n\t * @var object\n\t */\n\tprotected $_parent;\n\n\t/**\n\t * List of methods in the parent class\n\t *\n\t * @var array\n\t */\n\tprotected $_methods = array();\n\n\t/**\n\t * List of properties in the parent class\n\t *\n\t * @var array\n\t */\n\tprotected $_properties = array();\n\n\t/**\n\t * Array of methods and properties for the parent class(es)\n\t *\n\t * @static\n\t * @var\tarray\n\t */\n\tprotected static $_reflections = array();\n\n\t/**\n\t * Decorate\n\t *\n\t * Decorates the child with the parent driver lib's methods and properties\n\t *\n\t * @param\tobject\n\t * @return\tvoid\n\t */\n\tpublic function decorate($parent)\n\t{\n\t\t$this->_parent = $parent;\n\n\t\t// Lock down attributes to what is defined in the class\n\t\t// and speed up references in magic methods\n\n\t\t$class_name = get_class($parent);\n\n\t\tif ( ! isset(self::$_reflections[$class_name]))\n\t\t{\n\t\t\t$r = new ReflectionObject($parent);\n\n\t\t\tforeach ($r->getMethods() as $method)\n\t\t\t{\n\t\t\t\tif ($method->isPublic())\n\t\t\t\t{\n\t\t\t\t\t$this->_methods[] = $method->getName();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tforeach ($r->getProperties() as $prop)\n\t\t\t{\n\t\t\t\tif ($prop->isPublic())\n\t\t\t\t{\n\t\t\t\t\t$this->_properties[] = $prop->getName();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tself::$_reflections[$class_name] = array($this->_methods, $this->_properties);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlist($this->_methods, $this->_properties) = self::$_reflections[$class_name];\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * __call magic method\n\t *\n\t * Handles access to the parent driver library's methods\n\t *\n\t * @param\tstring\n\t * @param\tarray\n\t * @return\tmixed\n\t */\n\tpublic function __call($method, $args = array())\n\t{\n\t\tif (in_array($method, $this->_methods))\n\t\t{\n\t\t\treturn call_user_func_array(array($this->_parent, $method), $args);\n\t\t}\n\n\t\tthrow new BadMethodCallException('No such method: '.$method.'()');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * __get magic method\n\t *\n\t * Handles reading of the parent driver library's properties\n\t *\n\t * @param\tstring\n\t * @return\tmixed\n\t */\n\tpublic function __get($var)\n\t{\n\t\tif (in_array($var, $this->_properties))\n\t\t{\n\t\t\treturn $this->_parent->$var;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * __set magic method\n\t *\n\t * Handles writing to the parent driver library's properties\n\t *\n\t * @param\tstring\n\t * @param\tarray\n\t * @return\tmixed\n\t */\n\tpublic function __set($var, $val)\n\t{\n\t\tif (in_array($var, $this->_properties))\n\t\t{\n\t\t\t$this->_parent->$var = $val;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/Email.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Email Class\n *\n * Permits email to be sent using Mail, Sendmail, or SMTP.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/email.html\n */\nclass CI_Email {\n\n\t/**\n\t * Used as the User-Agent and X-Mailer headers' value.\n\t *\n\t * @var\tstring\n\t */\n\tpublic $useragent\t= 'CodeIgniter';\n\n\t/**\n\t * Path to the Sendmail binary.\n\t *\n\t * @var\tstring\n\t */\n\tpublic $mailpath\t= '/usr/sbin/sendmail';\t// Sendmail path\n\n\t/**\n\t * Which method to use for sending e-mails.\n\t *\n\t * @var\tstring\t'mail', 'sendmail' or 'smtp'\n\t */\n\tpublic $protocol\t= 'mail';\t\t// mail/sendmail/smtp\n\n\t/**\n\t * STMP Server host\n\t *\n\t * @var\tstring\n\t */\n\tpublic $smtp_host\t= '';\n\n\t/**\n\t * SMTP Username\n\t *\n\t * @var\tstring\n\t */\n\tpublic $smtp_user\t= '';\n\n\t/**\n\t * SMTP Password\n\t *\n\t * @var\tstring\n\t */\n\tpublic $smtp_pass\t= '';\n\n\t/**\n\t * SMTP Server port\n\t *\n\t * @var\tint\n\t */\n\tpublic $smtp_port\t= 25;\n\n\t/**\n\t * SMTP connection timeout in seconds\n\t *\n\t * @var\tint\n\t */\n\tpublic $smtp_timeout\t= 5;\n\n\t/**\n\t * SMTP persistent connection\n\t *\n\t * @var\tbool\n\t */\n\tpublic $smtp_keepalive\t= FALSE;\n\n\t/**\n\t * SMTP Encryption\n\t *\n\t * @var\tstring\tempty, 'tls' or 'ssl'\n\t */\n\tpublic $smtp_crypto\t= '';\n\n\t/**\n\t * Whether to apply word-wrapping to the message body.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $wordwrap\t= TRUE;\n\n\t/**\n\t * Number of characters to wrap at.\n\t *\n\t * @see\tCI_Email::$wordwrap\n\t * @var\tint\n\t */\n\tpublic $wrapchars\t= 76;\n\n\t/**\n\t * Message format.\n\t *\n\t * @var\tstring\t'text' or 'html'\n\t */\n\tpublic $mailtype\t= 'text';\n\n\t/**\n\t * Character set (default: utf-8)\n\t *\n\t * @var\tstring\n\t */\n\tpublic $charset\t\t= 'UTF-8';\n\n\t/**\n\t * Alternative message (for HTML messages only)\n\t *\n\t * @var\tstring\n\t */\n\tpublic $alt_message\t= '';\n\n\t/**\n\t * Whether to validate e-mail addresses.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $validate\t= FALSE;\n\n\t/**\n\t * X-Priority header value.\n\t *\n\t * @var\tint\t1-5\n\t */\n\tpublic $priority\t= 3;\t\t\t// Default priority (1 - 5)\n\n\t/**\n\t * Newline character sequence.\n\t * Use \"\\r\\n\" to comply with RFC 822.\n\t *\n\t * @link\thttp://www.ietf.org/rfc/rfc822.txt\n\t * @var\tstring\t\"\\r\\n\" or \"\\n\"\n\t */\n\tpublic $newline\t\t= \"\\n\";\t\t\t// Default newline. \"\\r\\n\" or \"\\n\" (Use \"\\r\\n\" to comply with RFC 822)\n\n\t/**\n\t * CRLF character sequence\n\t *\n\t * RFC 2045 specifies that for 'quoted-printable' encoding,\n\t * \"\\r\\n\" must be used. However, it appears that some servers\n\t * (even on the receiving end) don't handle it properly and\n\t * switching to \"\\n\", while improper, is the only solution\n\t * that seems to work for all environments.\n\t *\n\t * @link\thttp://www.ietf.org/rfc/rfc822.txt\n\t * @var\tstring\n\t */\n\tpublic $crlf\t\t= \"\\n\";\n\n\t/**\n\t * Whether to use Delivery Status Notification.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $dsn\t\t= FALSE;\n\n\t/**\n\t * Whether to send multipart alternatives.\n\t * Yahoo! doesn't seem to like these.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $send_multipart\t= TRUE;\n\n\t/**\n\t * Whether to send messages to BCC recipients in batches.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $bcc_batch_mode\t= FALSE;\n\n\t/**\n\t * BCC Batch max number size.\n\t *\n\t * @see\tCI_Email::$bcc_batch_mode\n\t * @var\tint\n\t */\n\tpublic $bcc_batch_size\t= 200;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Whether PHP is running in safe mode. Initialized by the class constructor.\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_safe_mode\t\t= FALSE;\n\n\t/**\n\t * Subject header\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_subject\t\t= '';\n\n\t/**\n\t * Message body\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_body\t\t= '';\n\n\t/**\n\t * Final message body to be sent.\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_finalbody\t\t= '';\n\n\t/**\n\t * Final headers to send\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_header_str\t\t= '';\n\n\t/**\n\t * SMTP Connection socket placeholder\n\t *\n\t * @var\tresource\n\t */\n\tprotected $_smtp_connect\t= '';\n\n\t/**\n\t * Mail encoding\n\t *\n\t * @var\tstring\t'8bit' or '7bit'\n\t */\n\tprotected $_encoding\t\t= '8bit';\n\n\t/**\n\t * Whether to perform SMTP authentication\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_smtp_auth\t\t= FALSE;\n\n\t/**\n\t * Whether to send a Reply-To header\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_replyto_flag\t= FALSE;\n\n\t/**\n\t * Debug messages\n\t *\n\t * @see\tCI_Email::print_debugger()\n\t * @var\tstring\n\t */\n\tprotected $_debug_msg\t\t= array();\n\n\t/**\n\t * Recipients\n\t *\n\t * @var\tstring[]\n\t */\n\tprotected $_recipients\t\t= array();\n\n\t/**\n\t * CC Recipients\n\t *\n\t * @var\tstring[]\n\t */\n\tprotected $_cc_array\t\t= array();\n\n\t/**\n\t * BCC Recipients\n\t *\n\t * @var\tstring[]\n\t */\n\tprotected $_bcc_array\t\t= array();\n\n\t/**\n\t * Message headers\n\t *\n\t * @var\tstring[]\n\t */\n\tprotected $_headers\t\t= array();\n\n\t/**\n\t * Attachment data\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_attachments\t\t= array();\n\n\t/**\n\t * Valid $protocol values\n\t *\n\t * @see\tCI_Email::$protocol\n\t * @var\tstring[]\n\t */\n\tprotected $_protocols\t\t= array('mail', 'sendmail', 'smtp');\n\n\t/**\n\t * Base charsets\n\t *\n\t * Character sets valid for 7-bit encoding,\n\t * excluding language suffix.\n\t *\n\t * @var\tstring[]\n\t */\n\tprotected $_base_charsets\t= array('us-ascii', 'iso-2022-');\n\n\t/**\n\t * Bit depths\n\t *\n\t * Valid mail encodings\n\t *\n\t * @see\tCI_Email::$_encoding\n\t * @var\tstring[]\n\t */\n\tprotected $_bit_depths\t\t= array('7bit', '8bit');\n\n\t/**\n\t * $priority translations\n\t *\n\t * Actual values to send with the X-Priority header\n\t *\n\t * @var\tstring[]\n\t */\n\tprotected $_priorities = array(\n\t\t1 => '1 (Highest)',\n\t\t2 => '2 (High)',\n\t\t3 => '3 (Normal)',\n\t\t4 => '4 (Low)',\n\t\t5 => '5 (Lowest)'\n\t);\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor - Sets Email Preferences\n\t *\n\t * The constructor can be passed an array of config values\n\t *\n\t * @param\tarray\t$config = array()\n\t * @return\tvoid\n\t */\n\tpublic function __construct(array $config = array())\n\t{\n\t\t$this->charset = config_item('charset');\n\t\t$this->initialize($config);\n\t\t$this->_safe_mode = ( ! is_php('5.4') && ini_get('safe_mode'));\n\n\t\tlog_message('info', 'Email Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize preferences\n\t *\n\t * @param\tarray\t$config\n\t * @return\tCI_Email\n\t */\n\tpublic function initialize(array $config = array())\n\t{\n\t\t$this->clear();\n\n\t\tforeach ($config as $key => $val)\n\t\t{\n\t\t\tif (isset($this->$key))\n\t\t\t{\n\t\t\t\t$method = 'set_'.$key;\n\n\t\t\t\tif (method_exists($this, $method))\n\t\t\t\t{\n\t\t\t\t\t$this->$method($val);\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$this->$key = $val;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$this->charset = strtoupper($this->charset);\n\t\t$this->_smtp_auth = isset($this->smtp_user[0], $this->smtp_pass[0]);\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize the Email Data\n\t *\n\t * @param\tbool\n\t * @return\tCI_Email\n\t */\n\tpublic function clear($clear_attachments = FALSE)\n\t{\n\t\t$this->_subject\t\t= '';\n\t\t$this->_body\t\t= '';\n\t\t$this->_finalbody\t= '';\n\t\t$this->_header_str\t= '';\n\t\t$this->_replyto_flag\t= FALSE;\n\t\t$this->_recipients\t= array();\n\t\t$this->_cc_array\t= array();\n\t\t$this->_bcc_array\t= array();\n\t\t$this->_headers\t\t= array();\n\t\t$this->_debug_msg\t= array();\n\n\t\t$this->set_header('User-Agent', $this->useragent);\n\t\t$this->set_header('Date', $this->_set_date());\n\n\t\tif ($clear_attachments !== FALSE)\n\t\t{\n\t\t\t$this->_attachments = array();\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set FROM\n\t *\n\t * @param\tstring\t$from\n\t * @param\tstring\t$name\n\t * @param\tstring\t$return_path = NULL\tReturn-Path\n\t * @return\tCI_Email\n\t */\n\tpublic function from($from, $name = '', $return_path = NULL)\n\t{\n\t\tif (preg_match('/\\<(.*)\\>/', $from, $match))\n\t\t{\n\t\t\t$from = $match[1];\n\t\t}\n\n\t\tif ($this->validate)\n\t\t{\n\t\t\t$this->validate_email($this->_str_to_array($from));\n\t\t\tif ($return_path)\n\t\t\t{\n\t\t\t\t$this->validate_email($this->_str_to_array($return_path));\n\t\t\t}\n\t\t}\n\n\t\t// prepare the display name\n\t\tif ($name !== '')\n\t\t{\n\t\t\t// only use Q encoding if there are characters that would require it\n\t\t\tif ( ! preg_match('/[\\200-\\377]/', $name))\n\t\t\t{\n\t\t\t\t// add slashes for non-printing characters, slashes, and double quotes, and surround it in double quotes\n\t\t\t\t$name = '\"'.addcslashes($name, \"\\0..\\37\\177'\\\"\\\\\").'\"';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$name = $this->_prep_q_encoding($name);\n\t\t\t}\n\t\t}\n\n\t\t$this->set_header('From', $name.' <'.$from.'>');\n\n\t\tisset($return_path) OR $return_path = $from;\n\t\t$this->set_header('Return-Path', '<'.$return_path.'>');\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Reply-to\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function reply_to($replyto, $name = '')\n\t{\n\t\tif (preg_match('/\\<(.*)\\>/', $replyto, $match))\n\t\t{\n\t\t\t$replyto = $match[1];\n\t\t}\n\n\t\tif ($this->validate)\n\t\t{\n\t\t\t$this->validate_email($this->_str_to_array($replyto));\n\t\t}\n\n\t\tif ($name !== '')\n\t\t{\n\t\t\t// only use Q encoding if there are characters that would require it\n\t\t\tif ( ! preg_match('/[\\200-\\377]/', $name))\n\t\t\t{\n\t\t\t\t// add slashes for non-printing characters, slashes, and double quotes, and surround it in double quotes\n\t\t\t\t$name = '\"'.addcslashes($name, \"\\0..\\37\\177'\\\"\\\\\").'\"';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$name = $this->_prep_q_encoding($name);\n\t\t\t}\n\t\t}\n\n\t\t$this->set_header('Reply-To', $name.' <'.$replyto.'>');\n\t\t$this->_replyto_flag = TRUE;\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Recipients\n\t *\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function to($to)\n\t{\n\t\t$to = $this->_str_to_array($to);\n\t\t$to = $this->clean_email($to);\n\n\t\tif ($this->validate)\n\t\t{\n\t\t\t$this->validate_email($to);\n\t\t}\n\n\t\tif ($this->_get_protocol() !== 'mail')\n\t\t{\n\t\t\t$this->set_header('To', implode(', ', $to));\n\t\t}\n\n\t\t$this->_recipients = $to;\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set CC\n\t *\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function cc($cc)\n\t{\n\t\t$cc = $this->clean_email($this->_str_to_array($cc));\n\n\t\tif ($this->validate)\n\t\t{\n\t\t\t$this->validate_email($cc);\n\t\t}\n\n\t\t$this->set_header('Cc', implode(', ', $cc));\n\n\t\tif ($this->_get_protocol() === 'smtp')\n\t\t{\n\t\t\t$this->_cc_array = $cc;\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set BCC\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function bcc($bcc, $limit = '')\n\t{\n\t\tif ($limit !== '' && is_numeric($limit))\n\t\t{\n\t\t\t$this->bcc_batch_mode = TRUE;\n\t\t\t$this->bcc_batch_size = $limit;\n\t\t}\n\n\t\t$bcc = $this->clean_email($this->_str_to_array($bcc));\n\n\t\tif ($this->validate)\n\t\t{\n\t\t\t$this->validate_email($bcc);\n\t\t}\n\n\t\tif ($this->_get_protocol() === 'smtp' OR ($this->bcc_batch_mode && count($bcc) > $this->bcc_batch_size))\n\t\t{\n\t\t\t$this->_bcc_array = $bcc;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->set_header('Bcc', implode(', ', $bcc));\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Email Subject\n\t *\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function subject($subject)\n\t{\n\t\t$subject = $this->_prep_q_encoding($subject);\n\t\t$this->set_header('Subject', $subject);\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Body\n\t *\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function message($body)\n\t{\n\t\t$this->_body = rtrim(str_replace(\"\\r\", '', $body));\n\n\t\t/* strip slashes only if magic quotes is ON\n\t\t   if we do it with magic quotes OFF, it strips real, user-inputted chars.\n\n\t\t   NOTE: In PHP 5.4 get_magic_quotes_gpc() will always return 0 and\n\t\t\t it will probably not exist in future versions at all.\n\t\t*/\n\t\tif ( ! is_php('5.4') && get_magic_quotes_gpc())\n\t\t{\n\t\t\t$this->_body = stripslashes($this->_body);\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Assign file attachments\n\t *\n\t * @param\tstring\t$file\tCan be local path, URL or buffered content\n\t * @param\tstring\t$disposition = 'attachment'\n\t * @param\tstring\t$newname = NULL\n\t * @param\tstring\t$mime = ''\n\t * @return\tCI_Email\n\t */\n\tpublic function attach($file, $disposition = '', $newname = NULL, $mime = '')\n\t{\n\t\tif ($mime === '')\n\t\t{\n\t\t\tif (strpos($file, '://') === FALSE && ! file_exists($file))\n\t\t\t{\n\t\t\t\t$this->_set_error_message('lang:email_attachment_missing', $file);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tif ( ! $fp = @fopen($file, 'rb'))\n\t\t\t{\n\t\t\t\t$this->_set_error_message('lang:email_attachment_unreadable', $file);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$file_content = stream_get_contents($fp);\n\t\t\t$mime = $this->_mime_types(pathinfo($file, PATHINFO_EXTENSION));\n\t\t\tfclose($fp);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$file_content =& $file; // buffered file\n\t\t}\n\n\t\t$this->_attachments[] = array(\n\t\t\t'name'\t\t=> array($file, $newname),\n\t\t\t'disposition'\t=> empty($disposition) ? 'attachment' : $disposition,  // Can also be 'inline'  Not sure if it matters\n\t\t\t'type'\t\t=> $mime,\n\t\t\t'content'\t=> chunk_split(base64_encode($file_content)),\n\t\t\t'multipart'\t=> 'mixed'\n\t\t);\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set and return attachment Content-ID\n\t *\n\t * Useful for attached inline pictures\n\t *\n\t * @param\tstring\t$filename\n\t * @return\tstring\n\t */\n\tpublic function attachment_cid($filename)\n\t{\n\t\tfor ($i = 0, $c = count($this->_attachments); $i < $c; $i++)\n\t\t{\n\t\t\tif ($this->_attachments[$i]['name'][0] === $filename)\n\t\t\t{\n\t\t\t\t$this->_attachments[$i]['multipart'] = 'related';\n\t\t\t\t$this->_attachments[$i]['cid'] = uniqid(basename($this->_attachments[$i]['name'][0]).'@');\n\t\t\t\treturn $this->_attachments[$i]['cid'];\n\t\t\t}\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add a Header Item\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function set_header($header, $value)\n\t{\n\t\t$this->_headers[$header] = str_replace(array(\"\\n\", \"\\r\"), '', $value);\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Convert a String to an Array\n\t *\n\t * @param\tstring\n\t * @return\tarray\n\t */\n\tprotected function _str_to_array($email)\n\t{\n\t\tif ( ! is_array($email))\n\t\t{\n\t\t\treturn (strpos($email, ',') !== FALSE)\n\t\t\t\t? preg_split('/[\\s,]/', $email, -1, PREG_SPLIT_NO_EMPTY)\n\t\t\t\t: (array) trim($email);\n\t\t}\n\n\t\treturn $email;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Multipart Value\n\t *\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function set_alt_message($str)\n\t{\n\t\t$this->alt_message = (string) $str;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Mailtype\n\t *\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function set_mailtype($type = 'text')\n\t{\n\t\t$this->mailtype = ($type === 'html') ? 'html' : 'text';\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Wordwrap\n\t *\n\t * @param\tbool\n\t * @return\tCI_Email\n\t */\n\tpublic function set_wordwrap($wordwrap = TRUE)\n\t{\n\t\t$this->wordwrap = (bool) $wordwrap;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Protocol\n\t *\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function set_protocol($protocol = 'mail')\n\t{\n\t\t$this->protocol = in_array($protocol, $this->_protocols, TRUE) ? strtolower($protocol) : 'mail';\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Priority\n\t *\n\t * @param\tint\n\t * @return\tCI_Email\n\t */\n\tpublic function set_priority($n = 3)\n\t{\n\t\t$this->priority = preg_match('/^[1-5]$/', $n) ? (int) $n : 3;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Newline Character\n\t *\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function set_newline($newline = \"\\n\")\n\t{\n\t\t$this->newline = in_array($newline, array(\"\\n\", \"\\r\\n\", \"\\r\")) ? $newline : \"\\n\";\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set CRLF\n\t *\n\t * @param\tstring\n\t * @return\tCI_Email\n\t */\n\tpublic function set_crlf($crlf = \"\\n\")\n\t{\n\t\t$this->crlf = ($crlf !== \"\\n\" && $crlf !== \"\\r\\n\" && $crlf !== \"\\r\") ? \"\\n\" : $crlf;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get the Message ID\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _get_message_id()\n\t{\n\t\t$from = str_replace(array('>', '<'), '', $this->_headers['Return-Path']);\n\t\treturn '<'.uniqid('').strstr($from, '@').'>';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Mail Protocol\n\t *\n\t * @param\tbool\n\t * @return\tmixed\n\t */\n\tprotected function _get_protocol($return = TRUE)\n\t{\n\t\t$this->protocol = strtolower($this->protocol);\n\t\tin_array($this->protocol, $this->_protocols, TRUE) OR $this->protocol = 'mail';\n\n\t\tif ($return === TRUE)\n\t\t{\n\t\t\treturn $this->protocol;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Mail Encoding\n\t *\n\t * @param\tbool\n\t * @return\tstring\n\t */\n\tprotected function _get_encoding($return = TRUE)\n\t{\n\t\tin_array($this->_encoding, $this->_bit_depths) OR $this->_encoding = '8bit';\n\n\t\tforeach ($this->_base_charsets as $charset)\n\t\t{\n\t\t\tif (strpos($charset, $this->charset) === 0)\n\t\t\t{\n\t\t\t\t$this->_encoding = '7bit';\n\t\t\t}\n\t\t}\n\n\t\tif ($return === TRUE)\n\t\t{\n\t\t\treturn $this->_encoding;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get content type (text/html/attachment)\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _get_content_type()\n\t{\n\t\tif ($this->mailtype === 'html')\n\t\t{\n\t\t\treturn empty($this->_attachments) ? 'html' : 'html-attach';\n\t\t}\n\t\telseif\t($this->mailtype === 'text' && ! empty($this->_attachments))\n\t\t{\n\t\t\treturn 'plain-attach';\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn 'plain';\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set RFC 822 Date\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _set_date()\n\t{\n\t\t$timezone = date('Z');\n\t\t$operator = ($timezone[0] === '-') ? '-' : '+';\n\t\t$timezone = abs($timezone);\n\t\t$timezone = floor($timezone/3600) * 100 + ($timezone % 3600) / 60;\n\n\t\treturn sprintf('%s %s%04d', date('D, j M Y H:i:s'), $operator, $timezone);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Mime message\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _get_mime_message()\n\t{\n\t\treturn 'This is a multi-part message in MIME format.'.$this->newline.'Your email application may not support this format.';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Validate Email Address\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function validate_email($email)\n\t{\n\t\tif ( ! is_array($email))\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_must_be_array');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tforeach ($email as $val)\n\t\t{\n\t\t\tif ( ! $this->valid_email($val))\n\t\t\t{\n\t\t\t\t$this->_set_error_message('lang:email_invalid_address', $val);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Email Validation\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function valid_email($email)\n\t{\n\t\tif (function_exists('idn_to_ascii') && $atpos = strpos($email, '@'))\n\t\t{\n\t\t\t$email = substr($email, 0, ++$atpos).idn_to_ascii(substr($email, $atpos));\n\t\t}\n\n\t\treturn (bool) filter_var($email, FILTER_VALIDATE_EMAIL);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Clean Extended Email Address: Joe Smith <joe@smith.com>\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function clean_email($email)\n\t{\n\t\tif ( ! is_array($email))\n\t\t{\n\t\t\treturn preg_match('/\\<(.*)\\>/', $email, $match) ? $match[1] : $email;\n\t\t}\n\n\t\t$clean_email = array();\n\n\t\tforeach ($email as $addy)\n\t\t{\n\t\t\t$clean_email[] = preg_match('/\\<(.*)\\>/', $addy, $match) ? $match[1] : $addy;\n\t\t}\n\n\t\treturn $clean_email;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Build alternative plain text message\n\t *\n\t * Provides the raw message for use in plain-text headers of\n\t * HTML-formatted emails.\n\t * If the user hasn't specified his own alternative message\n\t * it creates one by stripping the HTML\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _get_alt_message()\n\t{\n\t\tif ( ! empty($this->alt_message))\n\t\t{\n\t\t\treturn ($this->wordwrap)\n\t\t\t\t? $this->word_wrap($this->alt_message, 76)\n\t\t\t\t: $this->alt_message;\n\t\t}\n\n\t\t$body = preg_match('/\\<body.*?\\>(.*)\\<\\/body\\>/si', $this->_body, $match) ? $match[1] : $this->_body;\n\t\t$body = str_replace(\"\\t\", '', preg_replace('#<!--(.*)--\\>#', '', trim(strip_tags($body))));\n\n\t\tfor ($i = 20; $i >= 3; $i--)\n\t\t{\n\t\t\t$body = str_replace(str_repeat(\"\\n\", $i), \"\\n\\n\", $body);\n\t\t}\n\n\t\t// Reduce multiple spaces\n\t\t$body = preg_replace('| +|', ' ', $body);\n\n\t\treturn ($this->wordwrap)\n\t\t\t? $this->word_wrap($body, 76)\n\t\t\t: $body;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Word Wrap\n\t *\n\t * @param\tstring\n\t * @param\tint\tline-length limit\n\t * @return\tstring\n\t */\n\tpublic function word_wrap($str, $charlim = NULL)\n\t{\n\t\t// Set the character limit, if not already present\n\t\tif (empty($charlim))\n\t\t{\n\t\t\t$charlim = empty($this->wrapchars) ? 76 : $this->wrapchars;\n\t\t}\n\n\t\t// Standardize newlines\n\t\tif (strpos($str, \"\\r\") !== FALSE)\n\t\t{\n\t\t\t$str = str_replace(array(\"\\r\\n\", \"\\r\"), \"\\n\", $str);\n\t\t}\n\n\t\t// Reduce multiple spaces at end of line\n\t\t$str = preg_replace('| +\\n|', \"\\n\", $str);\n\n\t\t// If the current word is surrounded by {unwrap} tags we'll\n\t\t// strip the entire chunk and replace it with a marker.\n\t\t$unwrap = array();\n\t\tif (preg_match_all('|\\{unwrap\\}(.+?)\\{/unwrap\\}|s', $str, $matches))\n\t\t{\n\t\t\tfor ($i = 0, $c = count($matches[0]); $i < $c; $i++)\n\t\t\t{\n\t\t\t\t$unwrap[] = $matches[1][$i];\n\t\t\t\t$str = str_replace($matches[0][$i], '{{unwrapped'.$i.'}}', $str);\n\t\t\t}\n\t\t}\n\n\t\t// Use PHP's native function to do the initial wordwrap.\n\t\t// We set the cut flag to FALSE so that any individual words that are\n\t\t// too long get left alone. In the next step we'll deal with them.\n\t\t$str = wordwrap($str, $charlim, \"\\n\", FALSE);\n\n\t\t// Split the string into individual lines of text and cycle through them\n\t\t$output = '';\n\t\tforeach (explode(\"\\n\", $str) as $line)\n\t\t{\n\t\t\t// Is the line within the allowed character count?\n\t\t\t// If so we'll join it to the output and continue\n\t\t\tif (mb_strlen($line) <= $charlim)\n\t\t\t{\n\t\t\t\t$output .= $line.$this->newline;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t$temp = '';\n\t\t\tdo\n\t\t\t{\n\t\t\t\t// If the over-length word is a URL we won't wrap it\n\t\t\t\tif (preg_match('!\\[url.+\\]|://|www\\.!', $line))\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// Trim the word down\n\t\t\t\t$temp .= mb_substr($line, 0, $charlim - 1);\n\t\t\t\t$line = mb_substr($line, $charlim - 1);\n\t\t\t}\n\t\t\twhile (mb_strlen($line) > $charlim);\n\n\t\t\t// If $temp contains data it means we had to split up an over-length\n\t\t\t// word into smaller chunks so we'll add it back to our current line\n\t\t\tif ($temp !== '')\n\t\t\t{\n\t\t\t\t$output .= $temp.$this->newline;\n\t\t\t}\n\n\t\t\t$output .= $line.$this->newline;\n\t\t}\n\n\t\t// Put our markers back\n\t\tif (count($unwrap) > 0)\n\t\t{\n\t\t\tforeach ($unwrap as $key => $val)\n\t\t\t{\n\t\t\t\t$output = str_replace('{{unwrapped'.$key.'}}', $val, $output);\n\t\t\t}\n\t\t}\n\n\t\treturn $output;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Build final headers\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _build_headers()\n\t{\n\t\t$this->set_header('X-Sender', $this->clean_email($this->_headers['From']));\n\t\t$this->set_header('X-Mailer', $this->useragent);\n\t\t$this->set_header('X-Priority', $this->_priorities[$this->priority]);\n\t\t$this->set_header('Message-ID', $this->_get_message_id());\n\t\t$this->set_header('Mime-Version', '1.0');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Write Headers as a string\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _write_headers()\n\t{\n\t\tif ($this->protocol === 'mail')\n\t\t{\n\t\t\tif (isset($this->_headers['Subject']))\n\t\t\t{\n\t\t\t\t$this->_subject = $this->_headers['Subject'];\n\t\t\t\tunset($this->_headers['Subject']);\n\t\t\t}\n\t\t}\n\n\t\treset($this->_headers);\n\t\t$this->_header_str = '';\n\n\t\tforeach ($this->_headers as $key => $val)\n\t\t{\n\t\t\t$val = trim($val);\n\n\t\t\tif ($val !== '')\n\t\t\t{\n\t\t\t\t$this->_header_str .= $key.': '.$val.$this->newline;\n\t\t\t}\n\t\t}\n\n\t\tif ($this->_get_protocol() === 'mail')\n\t\t{\n\t\t\t$this->_header_str = rtrim($this->_header_str);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Build Final Body and attachments\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _build_message()\n\t{\n\t\tif ($this->wordwrap === TRUE && $this->mailtype !== 'html')\n\t\t{\n\t\t\t$this->_body = $this->word_wrap($this->_body);\n\t\t}\n\n\t\t$this->_write_headers();\n\n\t\t$hdr = ($this->_get_protocol() === 'mail') ? $this->newline : '';\n\t\t$body = '';\n\n\t\tswitch ($this->_get_content_type())\n\t\t{\n\t\t\tcase 'plain':\n\n\t\t\t\t$hdr .= 'Content-Type: text/plain; charset='.$this->charset.$this->newline\n\t\t\t\t\t.'Content-Transfer-Encoding: '.$this->_get_encoding();\n\n\t\t\t\tif ($this->_get_protocol() === 'mail')\n\t\t\t\t{\n\t\t\t\t\t$this->_header_str .= $hdr;\n\t\t\t\t\t$this->_finalbody = $this->_body;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$this->_finalbody = $hdr.$this->newline.$this->newline.$this->_body;\n\t\t\t\t}\n\n\t\t\t\treturn;\n\n\t\t\tcase 'html':\n\n\t\t\t\tif ($this->send_multipart === FALSE)\n\t\t\t\t{\n\t\t\t\t\t$hdr .= 'Content-Type: text/html; charset='.$this->charset.$this->newline\n\t\t\t\t\t\t.'Content-Transfer-Encoding: quoted-printable';\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$boundary = uniqid('B_ALT_');\n\t\t\t\t\t$hdr .= 'Content-Type: multipart/alternative; boundary=\"'.$boundary.'\"';\n\n\t\t\t\t\t$body .= $this->_get_mime_message().$this->newline.$this->newline\n\t\t\t\t\t\t.'--'.$boundary.$this->newline\n\n\t\t\t\t\t\t.'Content-Type: text/plain; charset='.$this->charset.$this->newline\n\t\t\t\t\t\t.'Content-Transfer-Encoding: '.$this->_get_encoding().$this->newline.$this->newline\n\t\t\t\t\t\t.$this->_get_alt_message().$this->newline.$this->newline\n\t\t\t\t\t\t.'--'.$boundary.$this->newline\n\n\t\t\t\t\t\t.'Content-Type: text/html; charset='.$this->charset.$this->newline\n\t\t\t\t\t\t.'Content-Transfer-Encoding: quoted-printable'.$this->newline.$this->newline;\n\t\t\t\t}\n\n\t\t\t\t$this->_finalbody = $body.$this->_prep_quoted_printable($this->_body).$this->newline.$this->newline;\n\n\t\t\t\tif ($this->_get_protocol() === 'mail')\n\t\t\t\t{\n\t\t\t\t\t$this->_header_str .= $hdr;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$this->_finalbody = $hdr.$this->newline.$this->newline.$this->_finalbody;\n\t\t\t\t}\n\n\t\t\t\tif ($this->send_multipart !== FALSE)\n\t\t\t\t{\n\t\t\t\t\t$this->_finalbody .= '--'.$boundary.'--';\n\t\t\t\t}\n\n\t\t\t\treturn;\n\n\t\t\tcase 'plain-attach':\n\n\t\t\t\t$boundary = uniqid('B_ATC_');\n\t\t\t\t$hdr .= 'Content-Type: multipart/mixed; boundary=\"'.$boundary.'\"';\n\n\t\t\t\tif ($this->_get_protocol() === 'mail')\n\t\t\t\t{\n\t\t\t\t\t$this->_header_str .= $hdr;\n\t\t\t\t}\n\n\t\t\t\t$body .= $this->_get_mime_message().$this->newline\n\t\t\t\t\t.$this->newline\n\t\t\t\t\t.'--'.$boundary.$this->newline\n\t\t\t\t\t.'Content-Type: text/plain; charset='.$this->charset.$this->newline\n\t\t\t\t\t.'Content-Transfer-Encoding: '.$this->_get_encoding().$this->newline\n\t\t\t\t\t.$this->newline\n\t\t\t\t\t.$this->_body.$this->newline.$this->newline;\n\n\t\t\t\t$this->_append_attachments($body, $boundary);\n\n\t\t\t\tbreak;\n\t\t\tcase 'html-attach':\n\n\t\t\t\t$alt_boundary = uniqid('B_ALT_');\n\t\t\t\t$last_boundary = NULL;\n\n\t\t\t\tif ($this->_attachments_have_multipart('mixed'))\n\t\t\t\t{\n\t\t\t\t\t$atc_boundary = uniqid('B_ATC_');\n\t\t\t\t\t$hdr .= 'Content-Type: multipart/mixed; boundary=\"'.$atc_boundary.'\"';\n\t\t\t\t\t$last_boundary = $atc_boundary;\n\t\t\t\t}\n\n\t\t\t\tif ($this->_attachments_have_multipart('related'))\n\t\t\t\t{\n\t\t\t\t\t$rel_boundary = uniqid('B_REL_');\n\t\t\t\t\t$rel_boundary_header = 'Content-Type: multipart/related; boundary=\"'.$rel_boundary.'\"';\n\n\t\t\t\t\tif (isset($last_boundary))\n\t\t\t\t\t{\n\t\t\t\t\t\t$body .= '--'.$last_boundary.$this->newline.$rel_boundary_header;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$hdr .= $rel_boundary_header;\n\t\t\t\t\t}\n\n\t\t\t\t\t$last_boundary = $rel_boundary;\n\t\t\t\t}\n\n\t\t\t\tif ($this->_get_protocol() === 'mail')\n\t\t\t\t{\n\t\t\t\t\t$this->_header_str .= $hdr;\n\t\t\t\t}\n\n\t\t\t\tstrlen($body) && $body .= $this->newline.$this->newline;\n\t\t\t\t$body .= $this->_get_mime_message().$this->newline.$this->newline\n\t\t\t\t\t.'--'.$last_boundary.$this->newline\n\n\t\t\t\t\t.'Content-Type: multipart/alternative; boundary=\"'.$alt_boundary.'\"'.$this->newline.$this->newline\n\t\t\t\t\t.'--'.$alt_boundary.$this->newline\n\n\t\t\t\t\t.'Content-Type: text/plain; charset='.$this->charset.$this->newline\n\t\t\t\t\t.'Content-Transfer-Encoding: '.$this->_get_encoding().$this->newline.$this->newline\n\t\t\t\t\t.$this->_get_alt_message().$this->newline.$this->newline\n\t\t\t\t\t.'--'.$alt_boundary.$this->newline\n\n\t\t\t\t\t.'Content-Type: text/html; charset='.$this->charset.$this->newline\n\t\t\t\t\t.'Content-Transfer-Encoding: quoted-printable'.$this->newline.$this->newline\n\n\t\t\t\t\t.$this->_prep_quoted_printable($this->_body).$this->newline.$this->newline\n\t\t\t\t\t.'--'.$alt_boundary.'--'.$this->newline.$this->newline;\n\n\t\t\t\tif ( ! empty($rel_boundary))\n\t\t\t\t{\n\t\t\t\t\t$body .= $this->newline.$this->newline;\n\t\t\t\t\t$this->_append_attachments($body, $rel_boundary, 'related');\n\t\t\t\t}\n\n\t\t\t\t// multipart/mixed attachments\n\t\t\t\tif ( ! empty($atc_boundary))\n\t\t\t\t{\n\t\t\t\t\t$body .= $this->newline.$this->newline;\n\t\t\t\t\t$this->_append_attachments($body, $atc_boundary, 'mixed');\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t}\n\n\t\t$this->_finalbody = ($this->_get_protocol() === 'mail')\n\t\t\t? $body\n\t\t\t: $hdr.$this->newline.$this->newline.$body;\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\tprotected function _attachments_have_multipart($type)\n\t{\n\t\tforeach ($this->_attachments as &$attachment)\n\t\t{\n\t\t\tif ($attachment['multipart'] === $type)\n\t\t\t{\n\t\t\t\treturn TRUE;\n\t\t\t}\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prepares attachment string\n\t *\n\t * @param\tstring\t$body\t\tMessage body to append to\n\t * @param\tstring\t$boundary\tMultipart boundary\n\t * @param\tstring\t$multipart\tWhen provided, only attachments of this type will be processed\n\t * @return\tstring\n\t */\n\tprotected function _append_attachments(&$body, $boundary, $multipart = null)\n\t{\n\t\tfor ($i = 0, $c = count($this->_attachments); $i < $c; $i++)\n\t\t{\n\t\t\tif (isset($multipart) && $this->_attachments[$i]['multipart'] !== $multipart)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t$name = isset($this->_attachments[$i]['name'][1])\n\t\t\t\t? $this->_attachments[$i]['name'][1]\n\t\t\t\t: basename($this->_attachments[$i]['name'][0]);\n\n\t\t\t$body .= '--'.$boundary.$this->newline\n\t\t\t\t.'Content-Type: '.$this->_attachments[$i]['type'].'; name=\"'.$name.'\"'.$this->newline\n\t\t\t\t.'Content-Disposition: '.$this->_attachments[$i]['disposition'].';'.$this->newline\n\t\t\t\t.'Content-Transfer-Encoding: base64'.$this->newline\n\t\t\t\t.(empty($this->_attachments[$i]['cid']) ? '' : 'Content-ID: <'.$this->_attachments[$i]['cid'].'>'.$this->newline.$this->newline)\n\t\t\t\t.$this->_attachments[$i]['content'].$this->newline;\n\t\t}\n\n\t\t// $name won't be set if no attachments were appended,\n\t\t// and therefore a boundary wouldn't be necessary\n\t\tempty($name) OR $body .= '--'.$boundary.'--';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prep Quoted Printable\n\t *\n\t * Prepares string for Quoted-Printable Content-Transfer-Encoding\n\t * Refer to RFC 2045 http://www.ietf.org/rfc/rfc2045.txt\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _prep_quoted_printable($str)\n\t{\n\t\t// ASCII code numbers for \"safe\" characters that can always be\n\t\t// used literally, without encoding, as described in RFC 2049.\n\t\t// http://www.ietf.org/rfc/rfc2049.txt\n\t\tstatic $ascii_safe_chars = array(\n\t\t\t// ' (  )   +   ,   -   .   /   :   =   ?\n\t\t\t39, 40, 41, 43, 44, 45, 46, 47, 58, 61, 63,\n\t\t\t// numbers\n\t\t\t48, 49, 50, 51, 52, 53, 54, 55, 56, 57,\n\t\t\t// upper-case letters\n\t\t\t65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,\n\t\t\t// lower-case letters\n\t\t\t97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122\n\t\t);\n\n\t\t// We are intentionally wrapping so mail servers will encode characters\n\t\t// properly and MUAs will behave, so {unwrap} must go!\n\t\t$str = str_replace(array('{unwrap}', '{/unwrap}'), '', $str);\n\n\t\t// RFC 2045 specifies CRLF as \"\\r\\n\".\n\t\t// However, many developers choose to override that and violate\n\t\t// the RFC rules due to (apparently) a bug in MS Exchange,\n\t\t// which only works with \"\\n\".\n\t\tif ($this->crlf === \"\\r\\n\")\n\t\t{\n\t\t\tif (is_php('5.3'))\n\t\t\t{\n\t\t\t\treturn quoted_printable_encode($str);\n\t\t\t}\n\t\t\telseif (function_exists('imap_8bit'))\n\t\t\t{\n\t\t\t\treturn imap_8bit($str);\n\t\t\t}\n\t\t}\n\n\t\t// Reduce multiple spaces & remove nulls\n\t\t$str = preg_replace(array('| +|', '/\\x00+/'), array(' ', ''), $str);\n\n\t\t// Standardize newlines\n\t\tif (strpos($str, \"\\r\") !== FALSE)\n\t\t{\n\t\t\t$str = str_replace(array(\"\\r\\n\", \"\\r\"), \"\\n\", $str);\n\t\t}\n\n\t\t$escape = '=';\n\t\t$output = '';\n\n\t\tforeach (explode(\"\\n\", $str) as $line)\n\t\t{\n\t\t\t$length = strlen($line);\n\t\t\t$temp = '';\n\n\t\t\t// Loop through each character in the line to add soft-wrap\n\t\t\t// characters at the end of a line \" =\\r\\n\" and add the newly\n\t\t\t// processed line(s) to the output (see comment on $crlf class property)\n\t\t\tfor ($i = 0; $i < $length; $i++)\n\t\t\t{\n\t\t\t\t// Grab the next character\n\t\t\t\t$char = $line[$i];\n\t\t\t\t$ascii = ord($char);\n\n\t\t\t\t// Convert spaces and tabs but only if it's the end of the line\n\t\t\t\tif ($ascii === 32 OR $ascii === 9)\n\t\t\t\t{\n\t\t\t\t\tif ($i === ($length - 1))\n\t\t\t\t\t{\n\t\t\t\t\t\t$char = $escape.sprintf('%02s', dechex($ascii));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// DO NOT move this below the $ascii_safe_chars line!\n\t\t\t\t//\n\t\t\t\t// = (equals) signs are allowed by RFC2049, but must be encoded\n\t\t\t\t// as they are the encoding delimiter!\n\t\t\t\telseif ($ascii === 61)\n\t\t\t\t{\n\t\t\t\t\t$char = $escape.strtoupper(sprintf('%02s', dechex($ascii)));  // =3D\n\t\t\t\t}\n\t\t\t\telseif ( ! in_array($ascii, $ascii_safe_chars, TRUE))\n\t\t\t\t{\n\t\t\t\t\t$char = $escape.strtoupper(sprintf('%02s', dechex($ascii)));\n\t\t\t\t}\n\n\t\t\t\t// If we're at the character limit, add the line to the output,\n\t\t\t\t// reset our temp variable, and keep on chuggin'\n\t\t\t\tif ((strlen($temp) + strlen($char)) >= 76)\n\t\t\t\t{\n\t\t\t\t\t$output .= $temp.$escape.$this->crlf;\n\t\t\t\t\t$temp = '';\n\t\t\t\t}\n\n\t\t\t\t// Add the character to our temporary line\n\t\t\t\t$temp .= $char;\n\t\t\t}\n\n\t\t\t// Add our completed line to the output\n\t\t\t$output .= $temp.$this->crlf;\n\t\t}\n\n\t\t// get rid of extra CRLF tacked onto the end\n\t\treturn substr($output, 0, strlen($this->crlf) * -1);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prep Q Encoding\n\t *\n\t * Performs \"Q Encoding\" on a string for use in email headers.\n\t * It's related but not identical to quoted-printable, so it has its\n\t * own method.\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _prep_q_encoding($str)\n\t{\n\t\t$str = str_replace(array(\"\\r\", \"\\n\"), '', $str);\n\n\t\tif ($this->charset === 'UTF-8')\n\t\t{\n\t\t\t// Note: We used to have mb_encode_mimeheader() as the first choice\n\t\t\t//       here, but it turned out to be buggy and unreliable. DO NOT\n\t\t\t//       re-add it! -- Narf\n\t\t\tif (ICONV_ENABLED === TRUE)\n\t\t\t{\n\t\t\t\t$output = @iconv_mime_encode('', $str,\n\t\t\t\t\tarray(\n\t\t\t\t\t\t'scheme' => 'Q',\n\t\t\t\t\t\t'line-length' => 76,\n\t\t\t\t\t\t'input-charset' => $this->charset,\n\t\t\t\t\t\t'output-charset' => $this->charset,\n\t\t\t\t\t\t'line-break-chars' => $this->crlf\n\t\t\t\t\t)\n\t\t\t\t);\n\n\t\t\t\t// There are reports that iconv_mime_encode() might fail and return FALSE\n\t\t\t\tif ($output !== FALSE)\n\t\t\t\t{\n\t\t\t\t\t// iconv_mime_encode() will always put a header field name.\n\t\t\t\t\t// We've passed it an empty one, but it still prepends our\n\t\t\t\t\t// encoded string with ': ', so we need to strip it.\n\t\t\t\t\treturn substr($output, 2);\n\t\t\t\t}\n\n\t\t\t\t$chars = iconv_strlen($str, 'UTF-8');\n\t\t\t}\n\t\t\telseif (MB_ENABLED === TRUE)\n\t\t\t{\n\t\t\t\t$chars = mb_strlen($str, 'UTF-8');\n\t\t\t}\n\t\t}\n\n\t\t// We might already have this set for UTF-8\n\t\tisset($chars) OR $chars = strlen($str);\n\n\t\t$output = '=?'.$this->charset.'?Q?';\n\t\tfor ($i = 0, $length = strlen($output); $i < $chars; $i++)\n\t\t{\n\t\t\t$chr = ($this->charset === 'UTF-8' && ICONV_ENABLED === TRUE)\n\t\t\t\t? '='.implode('=', str_split(strtoupper(bin2hex(iconv_substr($str, $i, 1, $this->charset))), 2))\n\t\t\t\t: '='.strtoupper(bin2hex($str[$i]));\n\n\t\t\t// RFC 2045 sets a limit of 76 characters per line.\n\t\t\t// We'll append ?= to the end of each line though.\n\t\t\tif ($length + ($l = strlen($chr)) > 74)\n\t\t\t{\n\t\t\t\t$output .= '?='.$this->crlf // EOL\n\t\t\t\t\t.' =?'.$this->charset.'?Q?'.$chr; // New line\n\t\t\t\t$length = 6 + strlen($this->charset) + $l; // Reset the length for the new line\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$output .= $chr;\n\t\t\t\t$length += $l;\n\t\t\t}\n\t\t}\n\n\t\t// End the header\n\t\treturn $output.'?=';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send Email\n\t *\n\t * @param\tbool\t$auto_clear = TRUE\n\t * @return\tbool\n\t */\n\tpublic function send($auto_clear = TRUE)\n\t{\n\t\tif ( ! isset($this->_headers['From']))\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_no_from');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ($this->_replyto_flag === FALSE)\n\t\t{\n\t\t\t$this->reply_to($this->_headers['From']);\n\t\t}\n\n\t\tif ( ! isset($this->_recipients) && ! isset($this->_headers['To'])\n\t\t\t&& ! isset($this->_bcc_array) && ! isset($this->_headers['Bcc'])\n\t\t\t&& ! isset($this->_headers['Cc']))\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_no_recipients');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->_build_headers();\n\n\t\tif ($this->bcc_batch_mode && count($this->_bcc_array) > $this->bcc_batch_size)\n\t\t{\n\t\t\t$result = $this->batch_bcc_send();\n\n\t\t\tif ($result && $auto_clear)\n\t\t\t{\n\t\t\t\t$this->clear();\n\t\t\t}\n\n\t\t\treturn $result;\n\t\t}\n\n\t\tif ($this->_build_message() === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$result = $this->_spool_email();\n\n\t\tif ($result && $auto_clear)\n\t\t{\n\t\t\t$this->clear();\n\t\t}\n\n\t\treturn $result;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Batch Bcc Send. Sends groups of BCCs in batches\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function batch_bcc_send()\n\t{\n\t\t$float = $this->bcc_batch_size - 1;\n\t\t$set = '';\n\t\t$chunk = array();\n\n\t\tfor ($i = 0, $c = count($this->_bcc_array); $i < $c; $i++)\n\t\t{\n\t\t\tif (isset($this->_bcc_array[$i]))\n\t\t\t{\n\t\t\t\t$set .= ', '.$this->_bcc_array[$i];\n\t\t\t}\n\n\t\t\tif ($i === $float)\n\t\t\t{\n\t\t\t\t$chunk[] = substr($set, 1);\n\t\t\t\t$float += $this->bcc_batch_size;\n\t\t\t\t$set = '';\n\t\t\t}\n\n\t\t\tif ($i === $c-1)\n\t\t\t{\n\t\t\t\t$chunk[] = substr($set, 1);\n\t\t\t}\n\t\t}\n\n\t\tfor ($i = 0, $c = count($chunk); $i < $c; $i++)\n\t\t{\n\t\t\tunset($this->_headers['Bcc']);\n\n\t\t\t$bcc = $this->clean_email($this->_str_to_array($chunk[$i]));\n\n\t\t\tif ($this->protocol !== 'smtp')\n\t\t\t{\n\t\t\t\t$this->set_header('Bcc', implode(', ', $bcc));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->_bcc_array = $bcc;\n\t\t\t}\n\n\t\t\tif ($this->_build_message() === FALSE)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$this->_spool_email();\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Unwrap special elements\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _unwrap_specials()\n\t{\n\t\t$this->_finalbody = preg_replace_callback('/\\{unwrap\\}(.*?)\\{\\/unwrap\\}/si', array($this, '_remove_nl_callback'), $this->_finalbody);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Strip line-breaks via callback\n\t *\n\t * @param\tstring\t$matches\n\t * @return\tstring\n\t */\n\tprotected function _remove_nl_callback($matches)\n\t{\n\t\tif (strpos($matches[1], \"\\r\") !== FALSE OR strpos($matches[1], \"\\n\") !== FALSE)\n\t\t{\n\t\t\t$matches[1] = str_replace(array(\"\\r\\n\", \"\\r\", \"\\n\"), '', $matches[1]);\n\t\t}\n\n\t\treturn $matches[1];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Spool mail to the mail server\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _spool_email()\n\t{\n\t\t$this->_unwrap_specials();\n\n\t\t$method = '_send_with_'.$this->_get_protocol();\n\t\tif ( ! $this->$method())\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_send_failure_'.($this->_get_protocol() === 'mail' ? 'phpmail' : $this->_get_protocol()));\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->_set_error_message('lang:email_sent', $this->_get_protocol());\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send using mail()\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _send_with_mail()\n\t{\n\t\tif (is_array($this->_recipients))\n\t\t{\n\t\t\t$this->_recipients = implode(', ', $this->_recipients);\n\t\t}\n\n\t\tif ($this->_safe_mode === TRUE)\n\t\t{\n\t\t\treturn mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// most documentation of sendmail using the \"-f\" flag lacks a space after it, however\n\t\t\t// we've encountered servers that seem to require it to be in place.\n\t\t\treturn mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str, '-f '.$this->clean_email($this->_headers['Return-Path']));\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send using Sendmail\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _send_with_sendmail()\n\t{\n\t\t// is popen() enabled?\n\t\tif ( ! function_usable('popen')\n\t\t\tOR FALSE === ($fp = @popen(\n\t\t\t\t\t\t$this->mailpath.' -oi -f '.$this->clean_email($this->_headers['From']).' -t'\n\t\t\t\t\t\t, 'w'))\n\t\t) // server probably has popen disabled, so nothing we can do to get a verbose error.\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tfputs($fp, $this->_header_str);\n\t\tfputs($fp, $this->_finalbody);\n\n\t\t$status = pclose($fp);\n\n\t\tif ($status !== 0)\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_exit_status', $status);\n\t\t\t$this->_set_error_message('lang:email_no_socket');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send using SMTP\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _send_with_smtp()\n\t{\n\t\tif ($this->smtp_host === '')\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_no_hostname');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ( ! $this->_smtp_connect() OR ! $this->_smtp_authenticate())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ( ! $this->_send_command('from', $this->clean_email($this->_headers['From'])))\n\t\t{\n\t\t\t$this->_smtp_end();\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tforeach ($this->_recipients as $val)\n\t\t{\n\t\t\tif ( ! $this->_send_command('to', $val))\n\t\t\t{\n\t\t\t\t$this->_smtp_end();\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\tif (count($this->_cc_array) > 0)\n\t\t{\n\t\t\tforeach ($this->_cc_array as $val)\n\t\t\t{\n\t\t\t\tif ($val !== '' && ! $this->_send_command('to', $val))\n\t\t\t\t{\n\t\t\t\t\t$this->_smtp_end();\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (count($this->_bcc_array) > 0)\n\t\t{\n\t\t\tforeach ($this->_bcc_array as $val)\n\t\t\t{\n\t\t\t\tif ($val !== '' && ! $this->_send_command('to', $val))\n\t\t\t\t{\n\t\t\t\t\t$this->_smtp_end();\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( ! $this->_send_command('data'))\n\t\t{\n\t\t\t$this->_smtp_end();\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// perform dot transformation on any lines that begin with a dot\n\t\t$this->_send_data($this->_header_str.preg_replace('/^\\./m', '..$1', $this->_finalbody));\n\n\t\t$this->_send_data('.');\n\n\t\t$reply = $this->_get_smtp_data();\n\t\t$this->_set_error_message($reply);\n\n\t\t$this->_smtp_end();\n\n\t\tif (strpos($reply, '250') !== 0)\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_smtp_error', $reply);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * SMTP End\n\t *\n\t * Shortcut to send RSET or QUIT depending on keep-alive\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _smtp_end()\n\t{\n\t\t($this->smtp_keepalive)\n\t\t\t? $this->_send_command('reset')\n\t\t\t: $this->_send_command('quit');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * SMTP Connect\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _smtp_connect()\n\t{\n\t\tif (is_resource($this->_smtp_connect))\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\t$ssl = ($this->smtp_crypto === 'ssl') ? 'ssl://' : '';\n\n\t\t$this->_smtp_connect = fsockopen($ssl.$this->smtp_host,\n\t\t\t\t\t\t\t$this->smtp_port,\n\t\t\t\t\t\t\t$errno,\n\t\t\t\t\t\t\t$errstr,\n\t\t\t\t\t\t\t$this->smtp_timeout);\n\n\t\tif ( ! is_resource($this->_smtp_connect))\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_smtp_error', $errno.' '.$errstr);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tstream_set_timeout($this->_smtp_connect, $this->smtp_timeout);\n\t\t$this->_set_error_message($this->_get_smtp_data());\n\n\t\tif ($this->smtp_crypto === 'tls')\n\t\t{\n\t\t\t$this->_send_command('hello');\n\t\t\t$this->_send_command('starttls');\n\n\t\t\t$crypto = stream_socket_enable_crypto($this->_smtp_connect, TRUE, STREAM_CRYPTO_METHOD_TLS_CLIENT);\n\n\t\t\tif ($crypto !== TRUE)\n\t\t\t{\n\t\t\t\t$this->_set_error_message('lang:email_smtp_error', $this->_get_smtp_data());\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\treturn $this->_send_command('hello');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send SMTP command\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _send_command($cmd, $data = '')\n\t{\n\t\tswitch ($cmd)\n\t\t{\n\t\t\tcase 'hello' :\n\n\t\t\t\t\t\tif ($this->_smtp_auth OR $this->_get_encoding() === '8bit')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$this->_send_data('EHLO '.$this->_get_hostname());\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$this->_send_data('HELO '.$this->_get_hostname());\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$resp = 250;\n\t\t\tbreak;\n\t\t\tcase 'starttls'\t:\n\n\t\t\t\t\t\t$this->_send_data('STARTTLS');\n\t\t\t\t\t\t$resp = 220;\n\t\t\tbreak;\n\t\t\tcase 'from' :\n\n\t\t\t\t\t\t$this->_send_data('MAIL FROM:<'.$data.'>');\n\t\t\t\t\t\t$resp = 250;\n\t\t\tbreak;\n\t\t\tcase 'to' :\n\n\t\t\t\t\t\tif ($this->dsn)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$this->_send_data('RCPT TO:<'.$data.'> NOTIFY=SUCCESS,DELAY,FAILURE ORCPT=rfc822;'.$data);\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$this->_send_data('RCPT TO:<'.$data.'>');\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$resp = 250;\n\t\t\tbreak;\n\t\t\tcase 'data'\t:\n\n\t\t\t\t\t\t$this->_send_data('DATA');\n\t\t\t\t\t\t$resp = 354;\n\t\t\tbreak;\n\t\t\tcase 'reset':\n\n\t\t\t\t\t\t$this->_send_data('RSET');\n\t\t\t\t\t\t$resp = 250;\n\t\t\tbreak;\n\t\t\tcase 'quit'\t:\n\n\t\t\t\t\t\t$this->_send_data('QUIT');\n\t\t\t\t\t\t$resp = 221;\n\t\t\tbreak;\n\t\t}\n\n\t\t$reply = $this->_get_smtp_data();\n\n\t\t$this->_debug_msg[] = '<pre>'.$cmd.': '.$reply.'</pre>';\n\n\t\tif ((int) substr($reply, 0, 3) !== $resp)\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_smtp_error', $reply);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ($cmd === 'quit')\n\t\t{\n\t\t\tfclose($this->_smtp_connect);\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * SMTP Authenticate\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _smtp_authenticate()\n\t{\n\t\tif ( ! $this->_smtp_auth)\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\tif ($this->smtp_user === '' && $this->smtp_pass === '')\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_no_smtp_unpw');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->_send_data('AUTH LOGIN');\n\n\t\t$reply = $this->_get_smtp_data();\n\n\t\tif (strpos($reply, '503') === 0)\t// Already authenticated\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\t\telseif (strpos($reply, '334') !== 0)\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_failed_smtp_login', $reply);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->_send_data(base64_encode($this->smtp_user));\n\n\t\t$reply = $this->_get_smtp_data();\n\n\t\tif (strpos($reply, '334') !== 0)\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_smtp_auth_un', $reply);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->_send_data(base64_encode($this->smtp_pass));\n\n\t\t$reply = $this->_get_smtp_data();\n\n\t\tif (strpos($reply, '235') !== 0)\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_smtp_auth_pw', $reply);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ($this->smtp_keepalive)\n\t\t{\n\t\t\t$this->_smtp_auth = FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send SMTP data\n\t *\n\t * @param\tstring\t$data\n\t * @return\tbool\n\t */\n\tprotected function _send_data($data)\n\t{\n\t\t$data .= $this->newline;\n\t\tfor ($written = $timestamp = 0, $length = strlen($data); $written < $length; $written += $result)\n\t\t{\n\t\t\tif (($result = fwrite($this->_smtp_connect, substr($data, $written))) === FALSE)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// See https://bugs.php.net/bug.php?id=39598 and http://php.net/manual/en/function.fwrite.php#96951\n\t\t\telseif ($result === 0)\n\t\t\t{\n\t\t\t\tif ($timestamp === 0)\n\t\t\t\t{\n\t\t\t\t\t$timestamp = time();\n\t\t\t\t}\n\t\t\t\telseif ($timestamp < (time() - $this->smtp_timeout))\n\t\t\t\t{\n\t\t\t\t\t$result = FALSE;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tusleep(250000);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$timestamp = 0;\n\t\t\t}\n\t\t}\n\n\t\tif ($result === FALSE)\n\t\t{\n\t\t\t$this->_set_error_message('lang:email_smtp_data_failure', $data);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get SMTP data\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _get_smtp_data()\n\t{\n\t\t$data = '';\n\n\t\twhile ($str = fgets($this->_smtp_connect, 512))\n\t\t{\n\t\t\t$data .= $str;\n\n\t\t\tif ($str[3] === ' ')\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn $data;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Hostname\n\t *\n\t * There are only two legal types of hostname - either a fully\n\t * qualified domain name (eg: \"mail.example.com\") or an IP literal\n\t * (eg: \"[1.2.3.4]\").\n\t *\n\t * @link\thttps://tools.ietf.org/html/rfc5321#section-2.3.5\n\t * @link\thttp://cbl.abuseat.org/namingproblems.html\n\t * @return\tstring\n\t */\n\tprotected function _get_hostname()\n\t{\n\t\tif (isset($_SERVER['SERVER_NAME']))\n\t\t{\n\t\t\treturn $_SERVER['SERVER_NAME'];\n\t\t}\n\n\t\treturn isset($_SERVER['SERVER_ADDR']) ? '['.$_SERVER['SERVER_ADDR'].']' : '[127.0.0.1]';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Debug Message\n\t *\n\t * @param\tarray\t$include\tList of raw data chunks to include in the output\n\t *\t\t\t\t\tValid options are: 'headers', 'subject', 'body'\n\t * @return\tstring\n\t */\n\tpublic function print_debugger($include = array('headers', 'subject', 'body'))\n\t{\n\t\t$msg = '';\n\n\t\tif (count($this->_debug_msg) > 0)\n\t\t{\n\t\t\tforeach ($this->_debug_msg as $val)\n\t\t\t{\n\t\t\t\t$msg .= $val;\n\t\t\t}\n\t\t}\n\n\t\t// Determine which parts of our raw data needs to be printed\n\t\t$raw_data = '';\n\t\tis_array($include) OR $include = array($include);\n\n\t\tif (in_array('headers', $include, TRUE))\n\t\t{\n\t\t\t$raw_data = htmlspecialchars($this->_header_str).\"\\n\";\n\t\t}\n\n\t\tif (in_array('subject', $include, TRUE))\n\t\t{\n\t\t\t$raw_data .= htmlspecialchars($this->_subject).\"\\n\";\n\t\t}\n\n\t\tif (in_array('body', $include, TRUE))\n\t\t{\n\t\t\t$raw_data .= htmlspecialchars($this->_finalbody);\n\t\t}\n\n\t\treturn $msg.($raw_data === '' ? '' : '<pre>'.$raw_data.'</pre>');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Message\n\t *\n\t * @param\tstring\t$msg\n\t * @param\tstring\t$val = ''\n\t * @return\tvoid\n\t */\n\tprotected function _set_error_message($msg, $val = '')\n\t{\n\t\t$CI =& get_instance();\n\t\t$CI->lang->load('email');\n\n\t\tif (sscanf($msg, 'lang:%s', $line) !== 1 OR FALSE === ($line = $CI->lang->line($line)))\n\t\t{\n\t\t\t$this->_debug_msg[] = str_replace('%s', $val, $msg).'<br />';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->_debug_msg[] = str_replace('%s', $val, $line).'<br />';\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Mime Types\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _mime_types($ext = '')\n\t{\n\t\t$ext = strtolower($ext);\n\n\t\t$mimes =& get_mimes();\n\n\t\tif (isset($mimes[$ext]))\n\t\t{\n\t\t\treturn is_array($mimes[$ext])\n\t\t\t\t? current($mimes[$ext])\n\t\t\t\t: $mimes[$ext];\n\t\t}\n\n\t\treturn 'application/x-unknown-content-type';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Destructor\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __destruct()\n\t{\n\t\tis_resource($this->_smtp_connect) && $this->_send_command('quit');\n\t}\n}\n"
  },
  {
    "path": "system/libraries/Encrypt.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Encryption Class\n *\n * Provides two-way keyed encoding using Mcrypt\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/encryption.html\n */\nclass CI_Encrypt {\n\n\t/**\n\t * Reference to the user's encryption key\n\t *\n\t * @var string\n\t */\n\tpublic $encryption_key\t\t= '';\n\n\t/**\n\t * Type of hash operation\n\t *\n\t * @var string\n\t */\n\tprotected $_hash_type\t\t= 'sha1';\n\n\t/**\n\t * Flag for the existence of mcrypt\n\t *\n\t * @var bool\n\t */\n\tprotected $_mcrypt_exists\t= FALSE;\n\n\t/**\n\t * Current cipher to be used with mcrypt\n\t *\n\t * @var string\n\t */\n\tprotected $_mcrypt_cipher;\n\n\t/**\n\t * Method for encrypting/decrypting data\n\t *\n\t * @var int\n\t */\n\tprotected $_mcrypt_mode;\n\n\t/**\n\t * Initialize Encryption class\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\tif (($this->_mcrypt_exists = function_exists('mcrypt_encrypt')) === FALSE)\n\t\t{\n\t\t\tshow_error('The Encrypt library requires the Mcrypt extension.');\n\t\t}\n\n\t\tlog_message('info', 'Encrypt Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch the encryption key\n\t *\n\t * Returns it as MD5 in order to have an exact-length 128 bit key.\n\t * Mcrypt is sensitive to keys that are not the correct length\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function get_key($key = '')\n\t{\n\t\tif ($key === '')\n\t\t{\n\t\t\tif ($this->encryption_key !== '')\n\t\t\t{\n\t\t\t\treturn $this->encryption_key;\n\t\t\t}\n\n\t\t\t$key = config_item('encryption_key');\n\n\t\t\tif ( ! strlen($key))\n\t\t\t{\n\t\t\t\tshow_error('In order to use the encryption class requires that you set an encryption key in your config file.');\n\t\t\t}\n\t\t}\n\n\t\treturn md5($key);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the encryption key\n\t *\n\t * @param\tstring\n\t * @return\tCI_Encrypt\n\t */\n\tpublic function set_key($key = '')\n\t{\n\t\t$this->encryption_key = $key;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Encode\n\t *\n\t * Encodes the message string using bitwise XOR encoding.\n\t * The key is combined with a random hash, and then it\n\t * too gets converted using XOR. The whole thing is then run\n\t * through mcrypt using the randomized key. The end result\n\t * is a double-encrypted message string that is randomized\n\t * with each call to this function, even if the supplied\n\t * message and key are the same.\n\t *\n\t * @param\tstring\tthe string to encode\n\t * @param\tstring\tthe key\n\t * @return\tstring\n\t */\n\tpublic function encode($string, $key = '')\n\t{\n\t\treturn base64_encode($this->mcrypt_encode($string, $this->get_key($key)));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Decode\n\t *\n\t * Reverses the above process\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function decode($string, $key = '')\n\t{\n\t\tif (preg_match('/[^a-zA-Z0-9\\/\\+=]/', $string) OR base64_encode(base64_decode($string)) !== $string)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn $this->mcrypt_decode(base64_decode($string), $this->get_key($key));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Encode from Legacy\n\t *\n\t * Takes an encoded string from the original Encryption class algorithms and\n\t * returns a newly encoded string using the improved method added in 2.0.0\n\t * This allows for backwards compatibility and a method to transition to the\n\t * new encryption algorithms.\n\t *\n\t * For more details, see https://codeigniter.com/user_guide/installation/upgrade_200.html#encryption\n\t *\n\t * @param\tstring\n\t * @param\tint\t\t(mcrypt mode constant)\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function encode_from_legacy($string, $legacy_mode = MCRYPT_MODE_ECB, $key = '')\n\t{\n\t\tif (preg_match('/[^a-zA-Z0-9\\/\\+=]/', $string))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// decode it first\n\t\t// set mode temporarily to what it was when string was encoded with the legacy\n\t\t// algorithm - typically MCRYPT_MODE_ECB\n\t\t$current_mode = $this->_get_mode();\n\t\t$this->set_mode($legacy_mode);\n\n\t\t$key = $this->get_key($key);\n\t\t$dec = base64_decode($string);\n\t\tif (($dec = $this->mcrypt_decode($dec, $key)) === FALSE)\n\t\t{\n\t\t\t$this->set_mode($current_mode);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$dec = $this->_xor_decode($dec, $key);\n\n\t\t// set the mcrypt mode back to what it should be, typically MCRYPT_MODE_CBC\n\t\t$this->set_mode($current_mode);\n\n\t\t// and re-encode\n\t\treturn base64_encode($this->mcrypt_encode($dec, $key));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * XOR Decode\n\t *\n\t * Takes an encoded string and key as input and generates the\n\t * plain-text original message\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _xor_decode($string, $key)\n\t{\n\t\t$string = $this->_xor_merge($string, $key);\n\n\t\t$dec = '';\n\t\tfor ($i = 0, $l = strlen($string); $i < $l; $i++)\n\t\t{\n\t\t\t$dec .= ($string[$i++] ^ $string[$i]);\n\t\t}\n\n\t\treturn $dec;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * XOR key + string Combiner\n\t *\n\t * Takes a string and key as input and computes the difference using XOR\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _xor_merge($string, $key)\n\t{\n\t\t$hash = $this->hash($key);\n\t\t$str = '';\n\t\tfor ($i = 0, $ls = strlen($string), $lh = strlen($hash); $i < $ls; $i++)\n\t\t{\n\t\t\t$str .= $string[$i] ^ $hash[($i % $lh)];\n\t\t}\n\n\t\treturn $str;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Encrypt using Mcrypt\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function mcrypt_encode($data, $key)\n\t{\n\t\t$init_size = mcrypt_get_iv_size($this->_get_cipher(), $this->_get_mode());\n\t\t$init_vect = mcrypt_create_iv($init_size, MCRYPT_RAND);\n\t\treturn $this->_add_cipher_noise($init_vect.mcrypt_encrypt($this->_get_cipher(), $key, $data, $this->_get_mode(), $init_vect), $key);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Decrypt using Mcrypt\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function mcrypt_decode($data, $key)\n\t{\n\t\t$data = $this->_remove_cipher_noise($data, $key);\n\t\t$init_size = mcrypt_get_iv_size($this->_get_cipher(), $this->_get_mode());\n\n\t\tif ($init_size > strlen($data))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$init_vect = substr($data, 0, $init_size);\n\t\t$data = substr($data, $init_size);\n\t\treturn rtrim(mcrypt_decrypt($this->_get_cipher(), $key, $data, $this->_get_mode(), $init_vect), \"\\0\");\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Adds permuted noise to the IV + encrypted data to protect\n\t * against Man-in-the-middle attacks on CBC mode ciphers\n\t * http://www.ciphersbyritter.com/GLOSSARY.HTM#IV\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _add_cipher_noise($data, $key)\n\t{\n\t\t$key = $this->hash($key);\n\t\t$str = '';\n\n\t\tfor ($i = 0, $j = 0, $ld = strlen($data), $lk = strlen($key); $i < $ld; ++$i, ++$j)\n\t\t{\n\t\t\tif ($j >= $lk)\n\t\t\t{\n\t\t\t\t$j = 0;\n\t\t\t}\n\n\t\t\t$str .= chr((ord($data[$i]) + ord($key[$j])) % 256);\n\t\t}\n\n\t\treturn $str;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Removes permuted noise from the IV + encrypted data, reversing\n\t * _add_cipher_noise()\n\t *\n\t * Function description\n\t *\n\t * @param\tstring\t$data\n\t * @param\tstring\t$key\n\t * @return\tstring\n\t */\n\tprotected function _remove_cipher_noise($data, $key)\n\t{\n\t\t$key = $this->hash($key);\n\t\t$str = '';\n\n\t\tfor ($i = 0, $j = 0, $ld = strlen($data), $lk = strlen($key); $i < $ld; ++$i, ++$j)\n\t\t{\n\t\t\tif ($j >= $lk)\n\t\t\t{\n\t\t\t\t$j = 0;\n\t\t\t}\n\n\t\t\t$temp = ord($data[$i]) - ord($key[$j]);\n\n\t\t\tif ($temp < 0)\n\t\t\t{\n\t\t\t\t$temp += 256;\n\t\t\t}\n\n\t\t\t$str .= chr($temp);\n\t\t}\n\n\t\treturn $str;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the Mcrypt Cipher\n\t *\n\t * @param\tint\n\t * @return\tCI_Encrypt\n\t */\n\tpublic function set_cipher($cipher)\n\t{\n\t\t$this->_mcrypt_cipher = $cipher;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the Mcrypt Mode\n\t *\n\t * @param\tint\n\t * @return\tCI_Encrypt\n\t */\n\tpublic function set_mode($mode)\n\t{\n\t\t$this->_mcrypt_mode = $mode;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Mcrypt cipher Value\n\t *\n\t * @return\tint\n\t */\n\tprotected function _get_cipher()\n\t{\n\t\tif ($this->_mcrypt_cipher === NULL)\n\t\t{\n\t\t\treturn $this->_mcrypt_cipher = MCRYPT_RIJNDAEL_256;\n\t\t}\n\n\t\treturn $this->_mcrypt_cipher;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Mcrypt Mode Value\n\t *\n\t * @return\tint\n\t */\n\tprotected function _get_mode()\n\t{\n\t\tif ($this->_mcrypt_mode === NULL)\n\t\t{\n\t\t\treturn $this->_mcrypt_mode = MCRYPT_MODE_CBC;\n\t\t}\n\n\t\treturn $this->_mcrypt_mode;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the Hash type\n\t *\n\t * @param\tstring\n\t * @return\tvoid\n\t */\n\tpublic function set_hash($type = 'sha1')\n\t{\n\t\t$this->_hash_type = in_array($type, hash_algos()) ? $type : 'sha1';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Hash encode a string\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function hash($str)\n\t{\n\t\treturn hash($this->_hash_type, $str);\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/Encryption.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Encryption Class\n *\n * Provides two-way keyed encryption via PHP's MCrypt and/or OpenSSL extensions.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tAndrey Andreev\n * @link\t\thttps://codeigniter.com/user_guide/libraries/encryption.html\n */\nclass CI_Encryption {\n\n\t/**\n\t * Encryption cipher\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_cipher = 'aes-128';\n\n\t/**\n\t * Cipher mode\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_mode = 'cbc';\n\n\t/**\n\t * Cipher handle\n\t *\n\t * @var\tmixed\n\t */\n\tprotected $_handle;\n\n\t/**\n\t * Encryption key\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_key;\n\n\t/**\n\t * PHP extension to be used\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_driver;\n\n\t/**\n\t * List of usable drivers (PHP extensions)\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_drivers = array();\n\n\t/**\n\t * List of available modes\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_modes = array(\n\t\t'mcrypt' => array(\n\t\t\t'cbc' => 'cbc',\n\t\t\t'ecb' => 'ecb',\n\t\t\t'ofb' => 'nofb',\n\t\t\t'ofb8' => 'ofb',\n\t\t\t'cfb' => 'ncfb',\n\t\t\t'cfb8' => 'cfb',\n\t\t\t'ctr' => 'ctr',\n\t\t\t'stream' => 'stream'\n\t\t),\n\t\t'openssl' => array(\n\t\t\t'cbc' => 'cbc',\n\t\t\t'ecb' => 'ecb',\n\t\t\t'ofb' => 'ofb',\n\t\t\t'cfb' => 'cfb',\n\t\t\t'cfb8' => 'cfb8',\n\t\t\t'ctr' => 'ctr',\n\t\t\t'stream' => '',\n\t\t\t'xts' => 'xts'\n\t\t)\n\t);\n\n\t/**\n\t * List of supported HMAC algorithms\n\t *\n\t * name => digest size pairs\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_digests = array(\n\t\t'sha224' => 28,\n\t\t'sha256' => 32,\n\t\t'sha384' => 48,\n\t\t'sha512' => 64\n\t);\n\n\t/**\n\t * mbstring.func_override flag\n\t *\n\t * @var\tbool\n\t */\n\tprotected static $func_override;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tarray\t$params\tConfiguration parameters\n\t * @return\tvoid\n\t */\n\tpublic function __construct(array $params = array())\n\t{\n\t\t$this->_drivers = array(\n\t\t\t'mcrypt' => defined('MCRYPT_DEV_URANDOM'),\n\t\t\t// While OpenSSL is available for PHP 5.3.0, an IV parameter\n\t\t\t// for the encrypt/decrypt functions is only available since 5.3.3\n\t\t\t'openssl' => (is_php('5.3.3') && extension_loaded('openssl'))\n\t\t);\n\n\t\tif ( ! $this->_drivers['mcrypt'] && ! $this->_drivers['openssl'])\n\t\t{\n\t\t\tshow_error('Encryption: Unable to find an available encryption driver.');\n\t\t}\n\n\t\tisset(self::$func_override) OR self::$func_override = (extension_loaded('mbstring') && ini_get('mbstring.func_override'));\n\t\t$this->initialize($params);\n\n\t\tif ( ! isset($this->_key) && self::strlen($key = config_item('encryption_key')) > 0)\n\t\t{\n\t\t\t$this->_key = $key;\n\t\t}\n\n\t\tlog_message('info', 'Encryption Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize\n\t *\n\t * @param\tarray\t$params\tConfiguration parameters\n\t * @return\tCI_Encryption\n\t */\n\tpublic function initialize(array $params)\n\t{\n\t\tif ( ! empty($params['driver']))\n\t\t{\n\t\t\tif (isset($this->_drivers[$params['driver']]))\n\t\t\t{\n\t\t\t\tif ($this->_drivers[$params['driver']])\n\t\t\t\t{\n\t\t\t\t\t$this->_driver = $params['driver'];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tlog_message('error', \"Encryption: Driver '\".$params['driver'].\"' is not available.\");\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tlog_message('error', \"Encryption: Unknown driver '\".$params['driver'].\"' cannot be configured.\");\n\t\t\t}\n\t\t}\n\n\t\tif (empty($this->_driver))\n\t\t{\n\t\t\t$this->_driver = ($this->_drivers['openssl'] === TRUE)\n\t\t\t\t? 'openssl'\n\t\t\t\t: 'mcrypt';\n\n\t\t\tlog_message('debug', \"Encryption: Auto-configured driver '\".$this->_driver.\"'.\");\n\t\t}\n\n\t\tempty($params['cipher']) && $params['cipher'] = $this->_cipher;\n\t\tempty($params['key']) OR $this->_key = $params['key'];\n\t\t$this->{'_'.$this->_driver.'_initialize'}($params);\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize MCrypt\n\t *\n\t * @param\tarray\t$params\tConfiguration parameters\n\t * @return\tvoid\n\t */\n\tprotected function _mcrypt_initialize($params)\n\t{\n\t\tif ( ! empty($params['cipher']))\n\t\t{\n\t\t\t$params['cipher'] = strtolower($params['cipher']);\n\t\t\t$this->_cipher_alias($params['cipher']);\n\n\t\t\tif ( ! in_array($params['cipher'], mcrypt_list_algorithms(), TRUE))\n\t\t\t{\n\t\t\t\tlog_message('error', 'Encryption: MCrypt cipher '.strtoupper($params['cipher']).' is not available.');\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->_cipher = $params['cipher'];\n\t\t\t}\n\t\t}\n\n\t\tif ( ! empty($params['mode']))\n\t\t{\n\t\t\t$params['mode'] = strtolower($params['mode']);\n\t\t\tif ( ! isset($this->_modes['mcrypt'][$params['mode']]))\n\t\t\t{\n\t\t\t\tlog_message('error', 'Encryption: MCrypt mode '.strtoupper($params['mode']).' is not available.');\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->_mode = $this->_modes['mcrypt'][$params['mode']];\n\t\t\t}\n\t\t}\n\n\t\tif (isset($this->_cipher, $this->_mode))\n\t\t{\n\t\t\tif (is_resource($this->_handle)\n\t\t\t\t&& (strtolower(mcrypt_enc_get_algorithms_name($this->_handle)) !== $this->_cipher\n\t\t\t\t\tOR strtolower(mcrypt_enc_get_modes_name($this->_handle)) !== $this->_mode)\n\t\t\t)\n\t\t\t{\n\t\t\t\tmcrypt_module_close($this->_handle);\n\t\t\t}\n\n\t\t\tif ($this->_handle = mcrypt_module_open($this->_cipher, '', $this->_mode, ''))\n\t\t\t{\n\t\t\t\tlog_message('info', 'Encryption: MCrypt cipher '.strtoupper($this->_cipher).' initialized in '.strtoupper($this->_mode).' mode.');\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tlog_message('error', 'Encryption: Unable to initialize MCrypt with cipher '.strtoupper($this->_cipher).' in '.strtoupper($this->_mode).' mode.');\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize OpenSSL\n\t *\n\t * @param\tarray\t$params\tConfiguration parameters\n\t * @return\tvoid\n\t */\n\tprotected function _openssl_initialize($params)\n\t{\n\t\tif ( ! empty($params['cipher']))\n\t\t{\n\t\t\t$params['cipher'] = strtolower($params['cipher']);\n\t\t\t$this->_cipher_alias($params['cipher']);\n\t\t\t$this->_cipher = $params['cipher'];\n\t\t}\n\n\t\tif ( ! empty($params['mode']))\n\t\t{\n\t\t\t$params['mode'] = strtolower($params['mode']);\n\t\t\tif ( ! isset($this->_modes['openssl'][$params['mode']]))\n\t\t\t{\n\t\t\t\tlog_message('error', 'Encryption: OpenSSL mode '.strtoupper($params['mode']).' is not available.');\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->_mode = $this->_modes['openssl'][$params['mode']];\n\t\t\t}\n\t\t}\n\n\t\tif (isset($this->_cipher, $this->_mode))\n\t\t{\n\t\t\t// This is mostly for the stream mode, which doesn't get suffixed in OpenSSL\n\t\t\t$handle = empty($this->_mode)\n\t\t\t\t? $this->_cipher\n\t\t\t\t: $this->_cipher.'-'.$this->_mode;\n\n\t\t\tif ( ! in_array($handle, openssl_get_cipher_methods(), TRUE))\n\t\t\t{\n\t\t\t\t$this->_handle = NULL;\n\t\t\t\tlog_message('error', 'Encryption: Unable to initialize OpenSSL with method '.strtoupper($handle).'.');\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->_handle = $handle;\n\t\t\t\tlog_message('info', 'Encryption: OpenSSL initialized with method '.strtoupper($handle).'.');\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Create a random key\n\t *\n\t * @param\tint\t$length\tOutput length\n\t * @return\tstring\n\t */\n\tpublic function create_key($length)\n\t{\n\t\tif (function_exists('random_bytes'))\n\t\t{\n\t\t\ttry\n\t\t\t{\n\t\t\t\treturn random_bytes((int) $length);\n\t\t\t}\n\t\t\tcatch (Exception $e)\n\t\t\t{\n\t\t\t\tlog_message('error', $e->getMessage());\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\t\telseif (defined('MCRYPT_DEV_URANDOM'))\n\t\t{\n\t\t\treturn mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);\n\t\t}\n\n\t\t$is_secure = NULL;\n\t\t$key = openssl_random_pseudo_bytes($length, $is_secure);\n\t\treturn ($is_secure === TRUE)\n\t\t\t? $key\n\t\t\t: FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Encrypt\n\t *\n\t * @param\tstring\t$data\tInput data\n\t * @param\tarray\t$params\tInput parameters\n\t * @return\tstring\n\t */\n\tpublic function encrypt($data, array $params = NULL)\n\t{\n\t\tif (($params = $this->_get_params($params)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tisset($params['key']) OR $params['key'] = $this->hkdf($this->_key, 'sha512', NULL, self::strlen($this->_key), 'encryption');\n\n\t\tif (($data = $this->{'_'.$this->_driver.'_encrypt'}($data, $params)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$params['base64'] && $data = base64_encode($data);\n\n\t\tif (isset($params['hmac_digest']))\n\t\t{\n\t\t\tisset($params['hmac_key']) OR $params['hmac_key'] = $this->hkdf($this->_key, 'sha512', NULL, NULL, 'authentication');\n\t\t\treturn hash_hmac($params['hmac_digest'], $data, $params['hmac_key'], ! $params['base64']).$data;\n\t\t}\n\n\t\treturn $data;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Encrypt via MCrypt\n\t *\n\t * @param\tstring\t$data\tInput data\n\t * @param\tarray\t$params\tInput parameters\n\t * @return\tstring\n\t */\n\tprotected function _mcrypt_encrypt($data, $params)\n\t{\n\t\tif ( ! is_resource($params['handle']))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// The greater-than-1 comparison is mostly a work-around for a bug,\n\t\t// where 1 is returned for ARCFour instead of 0.\n\t\t$iv = (($iv_size = mcrypt_enc_get_iv_size($params['handle'])) > 1)\n\t\t\t? $this->create_key($iv_size)\n\t\t\t: NULL;\n\n\t\tif (mcrypt_generic_init($params['handle'], $params['key'], $iv) < 0)\n\t\t{\n\t\t\tif ($params['handle'] !== $this->_handle)\n\t\t\t{\n\t\t\t\tmcrypt_module_close($params['handle']);\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Use PKCS#7 padding in order to ensure compatibility with OpenSSL\n\t\t// and other implementations outside of PHP.\n\t\tif (in_array(strtolower(mcrypt_enc_get_modes_name($params['handle'])), array('cbc', 'ecb'), TRUE))\n\t\t{\n\t\t\t$block_size = mcrypt_enc_get_block_size($params['handle']);\n\t\t\t$pad = $block_size - (self::strlen($data) % $block_size);\n\t\t\t$data .= str_repeat(chr($pad), $pad);\n\t\t}\n\n\t\t// Work-around for yet another strange behavior in MCrypt.\n\t\t//\n\t\t// When encrypting in ECB mode, the IV is ignored. Yet\n\t\t// mcrypt_enc_get_iv_size() returns a value larger than 0\n\t\t// even if ECB is used AND mcrypt_generic_init() complains\n\t\t// if you don't pass an IV with length equal to the said\n\t\t// return value.\n\t\t//\n\t\t// This probably would've been fine (even though still wasteful),\n\t\t// but OpenSSL isn't that dumb and we need to make the process\n\t\t// portable, so ...\n\t\t$data = (mcrypt_enc_get_modes_name($params['handle']) !== 'ECB')\n\t\t\t? $iv.mcrypt_generic($params['handle'], $data)\n\t\t\t: mcrypt_generic($params['handle'], $data);\n\n\t\tmcrypt_generic_deinit($params['handle']);\n\t\tif ($params['handle'] !== $this->_handle)\n\t\t{\n\t\t\tmcrypt_module_close($params['handle']);\n\t\t}\n\n\t\treturn $data;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Encrypt via OpenSSL\n\t *\n\t * @param\tstring\t$data\tInput data\n\t * @param\tarray\t$params\tInput parameters\n\t * @return\tstring\n\t */\n\tprotected function _openssl_encrypt($data, $params)\n\t{\n\t\tif (empty($params['handle']))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$iv = ($iv_size = openssl_cipher_iv_length($params['handle']))\n\t\t\t? $this->create_key($iv_size)\n\t\t\t: NULL;\n\n\t\t$data = openssl_encrypt(\n\t\t\t$data,\n\t\t\t$params['handle'],\n\t\t\t$params['key'],\n\t\t\t1, // DO NOT TOUCH!\n\t\t\t$iv\n\t\t);\n\n\t\tif ($data === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn $iv.$data;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Decrypt\n\t *\n\t * @param\tstring\t$data\tEncrypted data\n\t * @param\tarray\t$params\tInput parameters\n\t * @return\tstring\n\t */\n\tpublic function decrypt($data, array $params = NULL)\n\t{\n\t\tif (($params = $this->_get_params($params)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (isset($params['hmac_digest']))\n\t\t{\n\t\t\t// This might look illogical, but it is done during encryption as well ...\n\t\t\t// The 'base64' value is effectively an inverted \"raw data\" parameter\n\t\t\t$digest_size = ($params['base64'])\n\t\t\t\t? $this->_digests[$params['hmac_digest']] * 2\n\t\t\t\t: $this->_digests[$params['hmac_digest']];\n\n\t\t\tif (self::strlen($data) <= $digest_size)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$hmac_input = self::substr($data, 0, $digest_size);\n\t\t\t$data = self::substr($data, $digest_size);\n\n\t\t\tisset($params['hmac_key']) OR $params['hmac_key'] = $this->hkdf($this->_key, 'sha512', NULL, NULL, 'authentication');\n\t\t\t$hmac_check = hash_hmac($params['hmac_digest'], $data, $params['hmac_key'], ! $params['base64']);\n\n\t\t\t// Time-attack-safe comparison\n\t\t\t$diff = 0;\n\t\t\tfor ($i = 0; $i < $digest_size; $i++)\n\t\t\t{\n\t\t\t\t$diff |= ord($hmac_input[$i]) ^ ord($hmac_check[$i]);\n\t\t\t}\n\n\t\t\tif ($diff !== 0)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\tif ($params['base64'])\n\t\t{\n\t\t\t$data = base64_decode($data);\n\t\t}\n\n\t\tisset($params['key']) OR $params['key'] = $this->hkdf($this->_key, 'sha512', NULL, self::strlen($this->_key), 'encryption');\n\n\t\treturn $this->{'_'.$this->_driver.'_decrypt'}($data, $params);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Decrypt via MCrypt\n\t *\n\t * @param\tstring\t$data\tEncrypted data\n\t * @param\tarray\t$params\tInput parameters\n\t * @return\tstring\n\t */\n\tprotected function _mcrypt_decrypt($data, $params)\n\t{\n\t\tif ( ! is_resource($params['handle']))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// The greater-than-1 comparison is mostly a work-around for a bug,\n\t\t// where 1 is returned for ARCFour instead of 0.\n\t\tif (($iv_size = mcrypt_enc_get_iv_size($params['handle'])) > 1)\n\t\t{\n\t\t\tif (mcrypt_enc_get_modes_name($params['handle']) !== 'ECB')\n\t\t\t{\n\t\t\t\t$iv = self::substr($data, 0, $iv_size);\n\t\t\t\t$data = self::substr($data, $iv_size);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// MCrypt is dumb and this is ignored, only size matters\n\t\t\t\t$iv = str_repeat(\"\\x0\", $iv_size);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$iv = NULL;\n\t\t}\n\n\t\tif (mcrypt_generic_init($params['handle'], $params['key'], $iv) < 0)\n\t\t{\n\t\t\tif ($params['handle'] !== $this->_handle)\n\t\t\t{\n\t\t\t\tmcrypt_module_close($params['handle']);\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$data = mdecrypt_generic($params['handle'], $data);\n\t\t// Remove PKCS#7 padding, if necessary\n\t\tif (in_array(strtolower(mcrypt_enc_get_modes_name($params['handle'])), array('cbc', 'ecb'), TRUE))\n\t\t{\n\t\t\t$data = self::substr($data, 0, -ord($data[self::strlen($data)-1]));\n\t\t}\n\n\t\tmcrypt_generic_deinit($params['handle']);\n\t\tif ($params['handle'] !== $this->_handle)\n\t\t{\n\t\t\tmcrypt_module_close($params['handle']);\n\t\t}\n\n\t\treturn $data;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Decrypt via OpenSSL\n\t *\n\t * @param\tstring\t$data\tEncrypted data\n\t * @param\tarray\t$params\tInput parameters\n\t * @return\tstring\n\t */\n\tprotected function _openssl_decrypt($data, $params)\n\t{\n\t\tif ($iv_size = openssl_cipher_iv_length($params['handle']))\n\t\t{\n\t\t\t$iv = self::substr($data, 0, $iv_size);\n\t\t\t$data = self::substr($data, $iv_size);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$iv = NULL;\n\t\t}\n\n\t\treturn empty($params['handle'])\n\t\t\t? FALSE\n\t\t\t: openssl_decrypt(\n\t\t\t\t$data,\n\t\t\t\t$params['handle'],\n\t\t\t\t$params['key'],\n\t\t\t\t1, // DO NOT TOUCH!\n\t\t\t\t$iv\n\t\t\t);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get params\n\t *\n\t * @param\tarray\t$params\tInput parameters\n\t * @return\tarray\n\t */\n\tprotected function _get_params($params)\n\t{\n\t\tif (empty($params))\n\t\t{\n\t\t\treturn isset($this->_cipher, $this->_mode, $this->_key, $this->_handle)\n\t\t\t\t? array(\n\t\t\t\t\t'handle' => $this->_handle,\n\t\t\t\t\t'cipher' => $this->_cipher,\n\t\t\t\t\t'mode' => $this->_mode,\n\t\t\t\t\t'key' => NULL,\n\t\t\t\t\t'base64' => TRUE,\n\t\t\t\t\t'hmac_digest' => 'sha512',\n\t\t\t\t\t'hmac_key' => NULL\n\t\t\t\t)\n\t\t\t\t: FALSE;\n\t\t}\n\t\telseif ( ! isset($params['cipher'], $params['mode'], $params['key']))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (isset($params['mode']))\n\t\t{\n\t\t\t$params['mode'] = strtolower($params['mode']);\n\t\t\tif ( ! isset($this->_modes[$this->_driver][$params['mode']]))\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$params['mode'] = $this->_modes[$this->_driver][$params['mode']];\n\t\t\t}\n\t\t}\n\n\t\tif (isset($params['hmac']) && $params['hmac'] === FALSE)\n\t\t{\n\t\t\t$params['hmac_digest'] = $params['hmac_key'] = NULL;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif ( ! isset($params['hmac_key']))\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t\telseif (isset($params['hmac_digest']))\n\t\t\t{\n\t\t\t\t$params['hmac_digest'] = strtolower($params['hmac_digest']);\n\t\t\t\tif ( ! isset($this->_digests[$params['hmac_digest']]))\n\t\t\t\t{\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$params['hmac_digest'] = 'sha512';\n\t\t\t}\n\t\t}\n\n\t\t$params = array(\n\t\t\t'handle' => NULL,\n\t\t\t'cipher' => $params['cipher'],\n\t\t\t'mode' => $params['mode'],\n\t\t\t'key' => $params['key'],\n\t\t\t'base64' => isset($params['raw_data']) ? ! $params['raw_data'] : FALSE,\n\t\t\t'hmac_digest' => $params['hmac_digest'],\n\t\t\t'hmac_key' => $params['hmac_key']\n\t\t);\n\n\t\t$this->_cipher_alias($params['cipher']);\n\t\t$params['handle'] = ($params['cipher'] !== $this->_cipher OR $params['mode'] !== $this->_mode)\n\t\t\t? $this->{'_'.$this->_driver.'_get_handle'}($params['cipher'], $params['mode'])\n\t\t\t: $this->_handle;\n\n\t\treturn $params;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get MCrypt handle\n\t *\n\t * @param\tstring\t$cipher\tCipher name\n\t * @param\tstring\t$mode\tEncryption mode\n\t * @return\tresource\n\t */\n\tprotected function _mcrypt_get_handle($cipher, $mode)\n\t{\n\t\treturn mcrypt_module_open($cipher, '', $mode, '');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get OpenSSL handle\n\t *\n\t * @param\tstring\t$cipher\tCipher name\n\t * @param\tstring\t$mode\tEncryption mode\n\t * @return\tstring\n\t */\n\tprotected function _openssl_get_handle($cipher, $mode)\n\t{\n\t\t// OpenSSL methods aren't suffixed with '-stream' for this mode\n\t\treturn ($mode === 'stream')\n\t\t\t? $cipher\n\t\t\t: $cipher.'-'.$mode;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Cipher alias\n\t *\n\t * Tries to translate cipher names between MCrypt and OpenSSL's \"dialects\".\n\t *\n\t * @param\tstring\t$cipher\tCipher name\n\t * @return\tvoid\n\t */\n\tprotected function _cipher_alias(&$cipher)\n\t{\n\t\tstatic $dictionary;\n\n\t\tif (empty($dictionary))\n\t\t{\n\t\t\t$dictionary = array(\n\t\t\t\t'mcrypt' => array(\n\t\t\t\t\t'aes-128' => 'rijndael-128',\n\t\t\t\t\t'aes-192' => 'rijndael-128',\n\t\t\t\t\t'aes-256' => 'rijndael-128',\n\t\t\t\t\t'des3-ede3' => 'tripledes',\n\t\t\t\t\t'bf' => 'blowfish',\n\t\t\t\t\t'cast5' => 'cast-128',\n\t\t\t\t\t'rc4' => 'arcfour',\n\t\t\t\t\t'rc4-40' => 'arcfour'\n\t\t\t\t),\n\t\t\t\t'openssl' => array(\n\t\t\t\t\t'rijndael-128' => 'aes-128',\n\t\t\t\t\t'tripledes' => 'des-ede3',\n\t\t\t\t\t'blowfish' => 'bf',\n\t\t\t\t\t'cast-128' => 'cast5',\n\t\t\t\t\t'arcfour' => 'rc4-40',\n\t\t\t\t\t'rc4' => 'rc4-40'\n\t\t\t\t)\n\t\t\t);\n\n\t\t\t// Notes:\n\t\t\t//\n\t\t\t// - Rijndael-128 is, at the same time all three of AES-128,\n\t\t\t//   AES-192 and AES-256. The only difference between them is\n\t\t\t//   the key size. Rijndael-192, Rijndael-256 on the other hand\n\t\t\t//   also have different block sizes and are NOT AES-compatible.\n\t\t\t//\n\t\t\t// - Blowfish is said to be supporting key sizes between\n\t\t\t//   4 and 56 bytes, but it appears that between MCrypt and\n\t\t\t//   OpenSSL, only those of 16 and more bytes are compatible.\n\t\t\t//   Also, don't know what MCrypt's 'blowfish-compat' is.\n\t\t\t//\n\t\t\t// - CAST-128/CAST5 produces a longer cipher when encrypted via\n\t\t\t//   OpenSSL, but (strangely enough) can be decrypted by either\n\t\t\t//   extension anyway.\n\t\t\t//   Also, it appears that OpenSSL uses 16 rounds regardless of\n\t\t\t//   the key size, while RFC2144 says that for key sizes lower\n\t\t\t//   than 11 bytes, only 12 rounds should be used. This makes\n\t\t\t//   it portable only with keys of between 11 and 16 bytes.\n\t\t\t//\n\t\t\t// - RC4 (ARCFour) has a strange implementation under OpenSSL.\n\t\t\t//   Its 'rc4-40' cipher method seems to work flawlessly, yet\n\t\t\t//   there's another one, 'rc4' that only works with a 16-byte key.\n\t\t\t//\n\t\t\t// - DES is compatible, but doesn't need an alias.\n\t\t\t//\n\t\t\t// Other seemingly matching ciphers between MCrypt, OpenSSL:\n\t\t\t//\n\t\t\t// - RC2 is NOT compatible and only an obscure forum post\n\t\t\t//   confirms that it is MCrypt's fault.\n\t\t}\n\n\t\tif (isset($dictionary[$this->_driver][$cipher]))\n\t\t{\n\t\t\t$cipher = $dictionary[$this->_driver][$cipher];\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * HKDF\n\t *\n\t * @link\thttps://tools.ietf.org/rfc/rfc5869.txt\n\t * @param\t$key\tInput key\n\t * @param\t$digest\tA SHA-2 hashing algorithm\n\t * @param\t$salt\tOptional salt\n\t * @param\t$length\tOutput length (defaults to the selected digest size)\n\t * @param\t$info\tOptional context/application-specific info\n\t * @return\tstring\tA pseudo-random key\n\t */\n\tpublic function hkdf($key, $digest = 'sha512', $salt = NULL, $length = NULL, $info = '')\n\t{\n\t\tif ( ! isset($this->_digests[$digest]))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (empty($length) OR ! is_int($length))\n\t\t{\n\t\t\t$length = $this->_digests[$digest];\n\t\t}\n\t\telseif ($length > (255 * $this->_digests[$digest]))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tself::strlen($salt) OR $salt = str_repeat(\"\\0\", $this->_digests[$digest]);\n\n\t\t$prk = hash_hmac($digest, $key, $salt, TRUE);\n\t\t$key = '';\n\t\tfor ($key_block = '', $block_index = 1; self::strlen($key) < $length; $block_index++)\n\t\t{\n\t\t\t$key_block = hash_hmac($digest, $key_block.$info.chr($block_index), $prk, TRUE);\n\t\t\t$key .= $key_block;\n\t\t}\n\n\t\treturn self::substr($key, 0, $length);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * __get() magic\n\t *\n\t * @param\tstring\t$key\tProperty name\n\t * @return\tmixed\n\t */\n\tpublic function __get($key)\n\t{\n\t\t// Because aliases\n\t\tif ($key === 'mode')\n\t\t{\n\t\t\treturn array_search($this->_mode, $this->_modes[$this->_driver], TRUE);\n\t\t}\n\t\telseif (in_array($key, array('cipher', 'driver', 'drivers', 'digests'), TRUE))\n\t\t{\n\t\t\treturn $this->{'_'.$key};\n\t\t}\n\n\t\treturn NULL;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Byte-safe strlen()\n\t *\n\t * @param\tstring\t$str\n\t * @return\tinteger\n\t */\n\tprotected static function strlen($str)\n\t{\n\t\treturn (self::$func_override)\n\t\t\t? mb_strlen($str, '8bit')\n\t\t\t: strlen($str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Byte-safe substr()\n\t *\n\t * @param\tstring\t$str\n\t * @param\tint\t$start\n\t * @param\tint\t$length\n\t * @return\tstring\n\t */\n\tprotected static function substr($str, $start, $length = NULL)\n\t{\n\t\tif (self::$func_override)\n\t\t{\n\t\t\t// mb_substr($str, $start, null, '8bit') returns an empty\n\t\t\t// string on PHP 5.3\n\t\t\tisset($length) OR $length = ($start >= 0 ? self::strlen($str) - $start : -$start);\n\t\t\treturn mb_substr($str, $start, $length, '8bit');\n\t\t}\n\n\t\treturn isset($length)\n\t\t\t? substr($str, $start, $length)\n\t\t\t: substr($str, $start);\n\t}\n}\n"
  },
  {
    "path": "system/libraries/Form_validation.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Form Validation Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tValidation\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/form_validation.html\n */\nclass CI_Form_validation {\n\n\t/**\n\t * Reference to the CodeIgniter instance\n\t *\n\t * @var object\n\t */\n\tprotected $CI;\n\n\t/**\n\t * Validation data for the current form submission\n\t *\n\t * @var array\n\t */\n\tprotected $_field_data\t\t= array();\n\n\t/**\n\t * Validation rules for the current form\n\t *\n\t * @var array\n\t */\n\tprotected $_config_rules\t= array();\n\n\t/**\n\t * Array of validation errors\n\t *\n\t * @var array\n\t */\n\tprotected $_error_array\t\t= array();\n\n\t/**\n\t * Array of custom error messages\n\t *\n\t * @var array\n\t */\n\tprotected $_error_messages\t= array();\n\n\t/**\n\t * Start tag for error wrapping\n\t *\n\t * @var string\n\t */\n\tprotected $_error_prefix\t= '<p>';\n\n\t/**\n\t * End tag for error wrapping\n\t *\n\t * @var string\n\t */\n\tprotected $_error_suffix\t= '</p>';\n\n\t/**\n\t * Custom error message\n\t *\n\t * @var string\n\t */\n\tprotected $error_string\t\t= '';\n\n\t/**\n\t * Whether the form data has been validated as safe\n\t *\n\t * @var bool\n\t */\n\tprotected $_safe_form_data\t= FALSE;\n\n\t/**\n\t * Custom data to validate\n\t *\n\t * @var array\n\t */\n\tpublic $validation_data\t= array();\n\n\t/**\n\t * Initialize Form_Validation class\n\t *\n\t * @param\tarray\t$rules\n\t * @return\tvoid\n\t */\n\tpublic function __construct($rules = array())\n\t{\n\t\t$this->CI =& get_instance();\n\n\t\t// applies delimiters set in config file.\n\t\tif (isset($rules['error_prefix']))\n\t\t{\n\t\t\t$this->_error_prefix = $rules['error_prefix'];\n\t\t\tunset($rules['error_prefix']);\n\t\t}\n\t\tif (isset($rules['error_suffix']))\n\t\t{\n\t\t\t$this->_error_suffix = $rules['error_suffix'];\n\t\t\tunset($rules['error_suffix']);\n\t\t}\n\n\t\t// Validation rules can be stored in a config file.\n\t\t$this->_config_rules = $rules;\n\n\t\t// Automatically load the form helper\n\t\t$this->CI->load->helper('form');\n\n\t\tlog_message('info', 'Form Validation Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Rules\n\t *\n\t * This function takes an array of field names and validation\n\t * rules as input, any custom error messages, validates the info,\n\t * and stores it\n\t *\n\t * @param\tmixed\t$field\n\t * @param\tstring\t$label\n\t * @param\tmixed\t$rules\n\t * @param\tarray\t$errors\n\t * @return\tCI_Form_validation\n\t */\n\tpublic function set_rules($field, $label = '', $rules = array(), $errors = array())\n\t{\n\t\t// No reason to set rules if we have no POST data\n\t\t// or a validation array has not been specified\n\t\tif ($this->CI->input->method() !== 'post' && empty($this->validation_data))\n\t\t{\n\t\t\treturn $this;\n\t\t}\n\n\t\t// If an array was passed via the first parameter instead of individual string\n\t\t// values we cycle through it and recursively call this function.\n\t\tif (is_array($field))\n\t\t{\n\t\t\tforeach ($field as $row)\n\t\t\t{\n\t\t\t\t// Houston, we have a problem...\n\t\t\t\tif ( ! isset($row['field'], $row['rules']))\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// If the field label wasn't passed we use the field name\n\t\t\t\t$label = isset($row['label']) ? $row['label'] : $row['field'];\n\n\t\t\t\t// Add the custom error message array\n\t\t\t\t$errors = (isset($row['errors']) && is_array($row['errors'])) ? $row['errors'] : array();\n\n\t\t\t\t// Here we go!\n\t\t\t\t$this->set_rules($row['field'], $label, $row['rules'], $errors);\n\t\t\t}\n\n\t\t\treturn $this;\n\t\t}\n\n\t\t// No fields or no rules? Nothing to do...\n\t\tif ( ! is_string($field) OR $field === '' OR empty($rules))\n\t\t{\n\t\t\treturn $this;\n\t\t}\n\t\telseif ( ! is_array($rules))\n\t\t{\n\t\t\t// BC: Convert pipe-separated rules string to an array\n\t\t\tif ( ! is_string($rules))\n\t\t\t{\n\t\t\t\treturn $this;\n\t\t\t}\n\n\t\t\t$rules = preg_split('/\\|(?![^\\[]*\\])/', $rules);\n\t\t}\n\n\t\t// If the field label wasn't passed we use the field name\n\t\t$label = ($label === '') ? $field : $label;\n\n\t\t$indexes = array();\n\n\t\t// Is the field name an array? If it is an array, we break it apart\n\t\t// into its components so that we can fetch the corresponding POST data later\n\t\tif (($is_array = (bool) preg_match_all('/\\[(.*?)\\]/', $field, $matches)) === TRUE)\n\t\t{\n\t\t\tsscanf($field, '%[^[][', $indexes[0]);\n\n\t\t\tfor ($i = 0, $c = count($matches[0]); $i < $c; $i++)\n\t\t\t{\n\t\t\t\tif ($matches[1][$i] !== '')\n\t\t\t\t{\n\t\t\t\t\t$indexes[] = $matches[1][$i];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Build our master array\n\t\t$this->_field_data[$field] = array(\n\t\t\t'field'\t\t=> $field,\n\t\t\t'label'\t\t=> $label,\n\t\t\t'rules'\t\t=> $rules,\n\t\t\t'errors'\t=> $errors,\n\t\t\t'is_array'\t=> $is_array,\n\t\t\t'keys'\t\t=> $indexes,\n\t\t\t'postdata'\t=> NULL,\n\t\t\t'error'\t\t=> ''\n\t\t);\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * By default, form validation uses the $_POST array to validate\n\t *\n\t * If an array is set through this method, then this array will\n\t * be used instead of the $_POST array\n\t *\n\t * Note that if you are validating multiple arrays, then the\n\t * reset_validation() function should be called after validating\n\t * each array due to the limitations of CI's singleton\n\t *\n\t * @param\tarray\t$data\n\t * @return\tCI_Form_validation\n\t */\n\tpublic function set_data(array $data)\n\t{\n\t\tif ( ! empty($data))\n\t\t{\n\t\t\t$this->validation_data = $data;\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Error Message\n\t *\n\t * Lets users set their own error messages on the fly. Note:\n\t * The key name has to match the function name that it corresponds to.\n\t *\n\t * @param\tarray\n\t * @param\tstring\n\t * @return\tCI_Form_validation\n\t */\n\tpublic function set_message($lang, $val = '')\n\t{\n\t\tif ( ! is_array($lang))\n\t\t{\n\t\t\t$lang = array($lang => $val);\n\t\t}\n\n\t\t$this->_error_messages = array_merge($this->_error_messages, $lang);\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set The Error Delimiter\n\t *\n\t * Permits a prefix/suffix to be added to each error message\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tCI_Form_validation\n\t */\n\tpublic function set_error_delimiters($prefix = '<p>', $suffix = '</p>')\n\t{\n\t\t$this->_error_prefix = $prefix;\n\t\t$this->_error_suffix = $suffix;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Error Message\n\t *\n\t * Gets the error message associated with a particular field\n\t *\n\t * @param\tstring\t$field\tField name\n\t * @param\tstring\t$prefix\tHTML start tag\n\t * @param \tstring\t$suffix\tHTML end tag\n\t * @return\tstring\n\t */\n\tpublic function error($field, $prefix = '', $suffix = '')\n\t{\n\t\tif (empty($this->_field_data[$field]['error']))\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\tif ($prefix === '')\n\t\t{\n\t\t\t$prefix = $this->_error_prefix;\n\t\t}\n\n\t\tif ($suffix === '')\n\t\t{\n\t\t\t$suffix = $this->_error_suffix;\n\t\t}\n\n\t\treturn $prefix.$this->_field_data[$field]['error'].$suffix;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Array of Error Messages\n\t *\n\t * Returns the error messages as an array\n\t *\n\t * @return\tarray\n\t */\n\tpublic function error_array()\n\t{\n\t\treturn $this->_error_array;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Error String\n\t *\n\t * Returns the error messages as a string, wrapped in the error delimiters\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function error_string($prefix = '', $suffix = '')\n\t{\n\t\t// No errors, validation passes!\n\t\tif (count($this->_error_array) === 0)\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\tif ($prefix === '')\n\t\t{\n\t\t\t$prefix = $this->_error_prefix;\n\t\t}\n\n\t\tif ($suffix === '')\n\t\t{\n\t\t\t$suffix = $this->_error_suffix;\n\t\t}\n\n\t\t// Generate the error string\n\t\t$str = '';\n\t\tforeach ($this->_error_array as $val)\n\t\t{\n\t\t\tif ($val !== '')\n\t\t\t{\n\t\t\t\t$str .= $prefix.$val.$suffix.\"\\n\";\n\t\t\t}\n\t\t}\n\n\t\treturn $str;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Run the Validator\n\t *\n\t * This function does all the work.\n\t *\n\t * @param\tstring\t$group\n\t * @return\tbool\n\t */\n\tpublic function run($group = '')\n\t{\n\t\t$validation_array = empty($this->validation_data)\n\t\t\t? $_POST\n\t\t\t: $this->validation_data;\n\n\t\t// Does the _field_data array containing the validation rules exist?\n\t\t// If not, we look to see if they were assigned via a config file\n\t\tif (count($this->_field_data) === 0)\n\t\t{\n\t\t\t// No validation rules?  We're done...\n\t\t\tif (count($this->_config_rules) === 0)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tif (empty($group))\n\t\t\t{\n\t\t\t\t// Is there a validation rule for the particular URI being accessed?\n\t\t\t\t$group = trim($this->CI->uri->ruri_string(), '/');\n\t\t\t\tisset($this->_config_rules[$group]) OR $group = $this->CI->router->class.'/'.$this->CI->router->method;\n\t\t\t}\n\n\t\t\t$this->set_rules(isset($this->_config_rules[$group]) ? $this->_config_rules[$group] : $this->_config_rules);\n\n\t\t\t// Were we able to set the rules correctly?\n\t\t\tif (count($this->_field_data) === 0)\n\t\t\t{\n\t\t\t\tlog_message('debug', 'Unable to find validation rules');\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\t// Load the language file containing error messages\n\t\t$this->CI->lang->load('form_validation');\n\n\t\t// Cycle through the rules for each field and match the corresponding $validation_data item\n\t\tforeach ($this->_field_data as $field => &$row)\n\t\t{\n\t\t\t// Fetch the data from the validation_data array item and cache it in the _field_data array.\n\t\t\t// Depending on whether the field name is an array or a string will determine where we get it from.\n\t\t\tif ($row['is_array'] === TRUE)\n\t\t\t{\n\t\t\t\t$this->_field_data[$field]['postdata'] = $this->_reduce_array($validation_array, $row['keys']);\n\t\t\t}\n\t\t\telseif (isset($validation_array[$field]))\n\t\t\t{\n\t\t\t\t$this->_field_data[$field]['postdata'] = $validation_array[$field];\n\t\t\t}\n\t\t}\n\n\t\t// Execute validation rules\n\t\t// Note: A second foreach (for now) is required in order to avoid false-positives\n\t\t//\t for rules like 'matches', which correlate to other validation fields.\n\t\tforeach ($this->_field_data as $field => &$row)\n\t\t{\n\t\t\t// Don't try to validate if we have no rules set\n\t\t\tif (empty($row['rules']))\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t$this->_execute($row, $row['rules'], $row['postdata']);\n\t\t}\n\n\t\t// Did we end up with any errors?\n\t\t$total_errors = count($this->_error_array);\n\t\tif ($total_errors > 0)\n\t\t{\n\t\t\t$this->_safe_form_data = TRUE;\n\t\t}\n\n\t\t// Now we need to re-set the POST data with the new, processed data\n\t\tempty($this->validation_data) && $this->_reset_post_array();\n\n\t\treturn ($total_errors === 0);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prepare rules\n\t *\n\t * Re-orders the provided rules in order of importance, so that\n\t * they can easily be executed later without weird checks ...\n\t *\n\t * \"Callbacks\" are given the highest priority (always called),\n\t * followed by 'required' (called if callbacks didn't fail),\n\t * and then every next rule depends on the previous one passing.\n\t *\n\t * @param\tarray\t$rules\n\t * @return\tarray\n\t */\n\tprotected function _prepare_rules($rules)\n\t{\n\t\t$new_rules = array();\n\t\t$callbacks = array();\n\n\t\tforeach ($rules as &$rule)\n\t\t{\n\t\t\t// Let 'required' always be the first (non-callback) rule\n\t\t\tif ($rule === 'required')\n\t\t\t{\n\t\t\t\tarray_unshift($new_rules, 'required');\n\t\t\t}\n\t\t\t// 'isset' is a kind of a weird alias for 'required' ...\n\t\t\telseif ($rule === 'isset' && (empty($new_rules) OR $new_rules[0] !== 'required'))\n\t\t\t{\n\t\t\t\tarray_unshift($new_rules, 'isset');\n\t\t\t}\n\t\t\t// The old/classic 'callback_'-prefixed rules\n\t\t\telseif (is_string($rule) && strncmp('callback_', $rule, 9) === 0)\n\t\t\t{\n\t\t\t\t$callbacks[] = $rule;\n\t\t\t}\n\t\t\t// Proper callables\n\t\t\telseif (is_callable($rule))\n\t\t\t{\n\t\t\t\t$callbacks[] = $rule;\n\t\t\t}\n\t\t\t// \"Named\" callables; i.e. array('name' => $callable)\n\t\t\telseif (is_array($rule) && isset($rule[0], $rule[1]) && is_callable($rule[1]))\n\t\t\t{\n\t\t\t\t$callbacks[] = $rule;\n\t\t\t}\n\t\t\t// Everything else goes at the end of the queue\n\t\t\telse\n\t\t\t{\n\t\t\t\t$new_rules[] = $rule;\n\t\t\t}\n\t\t}\n\n\t\treturn array_merge($callbacks, $new_rules);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Traverse a multidimensional $_POST array index until the data is found\n\t *\n\t * @param\tarray\n\t * @param\tarray\n\t * @param\tint\n\t * @return\tmixed\n\t */\n\tprotected function _reduce_array($array, $keys, $i = 0)\n\t{\n\t\tif (is_array($array) && isset($keys[$i]))\n\t\t{\n\t\t\treturn isset($array[$keys[$i]]) ? $this->_reduce_array($array[$keys[$i]], $keys, ($i+1)) : NULL;\n\t\t}\n\n\t\t// NULL must be returned for empty fields\n\t\treturn ($array === '') ? NULL : $array;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Re-populate the _POST array with our finalized and processed data\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _reset_post_array()\n\t{\n\t\tforeach ($this->_field_data as $field => $row)\n\t\t{\n\t\t\tif ($row['postdata'] !== NULL)\n\t\t\t{\n\t\t\t\tif ($row['is_array'] === FALSE)\n\t\t\t\t{\n\t\t\t\t\tisset($_POST[$field]) && $_POST[$field] = $row['postdata'];\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// start with a reference\n\t\t\t\t\t$post_ref =& $_POST;\n\n\t\t\t\t\t// before we assign values, make a reference to the right POST key\n\t\t\t\t\tif (count($row['keys']) === 1)\n\t\t\t\t\t{\n\t\t\t\t\t\t$post_ref =& $post_ref[current($row['keys'])];\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tforeach ($row['keys'] as $val)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$post_ref =& $post_ref[$val];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t$post_ref = $row['postdata'];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Executes the Validation routines\n\t *\n\t * @param\tarray\n\t * @param\tarray\n\t * @param\tmixed\n\t * @param\tint\n\t * @return\tmixed\n\t */\n\tprotected function _execute($row, $rules, $postdata = NULL, $cycles = 0)\n\t{\n\t\t// If the $_POST data is an array we will run a recursive call\n\t\t//\n\t\t// Note: We MUST check if the array is empty or not!\n\t\t//       Otherwise empty arrays will always pass validation.\n\t\tif (is_array($postdata) && ! empty($postdata))\n\t\t{\n\t\t\tforeach ($postdata as $key => $val)\n\t\t\t{\n\t\t\t\t$this->_execute($row, $rules, $val, $key);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t$rules = $this->_prepare_rules($rules);\n\t\tforeach ($rules as $rule)\n\t\t{\n\t\t\t$_in_array = FALSE;\n\n\t\t\t// We set the $postdata variable with the current data in our master array so that\n\t\t\t// each cycle of the loop is dealing with the processed data from the last cycle\n\t\t\tif ($row['is_array'] === TRUE && is_array($this->_field_data[$row['field']]['postdata']))\n\t\t\t{\n\t\t\t\t// We shouldn't need this safety, but just in case there isn't an array index\n\t\t\t\t// associated with this cycle we'll bail out\n\t\t\t\tif ( ! isset($this->_field_data[$row['field']]['postdata'][$cycles]))\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t$postdata = $this->_field_data[$row['field']]['postdata'][$cycles];\n\t\t\t\t$_in_array = TRUE;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// If we get an array field, but it's not expected - then it is most likely\n\t\t\t\t// somebody messing with the form on the client side, so we'll just consider\n\t\t\t\t// it an empty field\n\t\t\t\t$postdata = is_array($this->_field_data[$row['field']]['postdata'])\n\t\t\t\t\t? NULL\n\t\t\t\t\t: $this->_field_data[$row['field']]['postdata'];\n\t\t\t}\n\n\t\t\t// Is the rule a callback?\n\t\t\t$callback = $callable = FALSE;\n\t\t\tif (is_string($rule))\n\t\t\t{\n\t\t\t\tif (strpos($rule, 'callback_') === 0)\n\t\t\t\t{\n\t\t\t\t\t$rule = substr($rule, 9);\n\t\t\t\t\t$callback = TRUE;\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif (is_callable($rule))\n\t\t\t{\n\t\t\t\t$callable = TRUE;\n\t\t\t}\n\t\t\telseif (is_array($rule) && isset($rule[0], $rule[1]) && is_callable($rule[1]))\n\t\t\t{\n\t\t\t\t// We have a \"named\" callable, so save the name\n\t\t\t\t$callable = $rule[0];\n\t\t\t\t$rule = $rule[1];\n\t\t\t}\n\n\t\t\t// Strip the parameter (if exists) from the rule\n\t\t\t// Rules can contain a parameter: max_length[5]\n\t\t\t$param = FALSE;\n\t\t\tif ( ! $callable && preg_match('/(.*?)\\[(.*)\\]/', $rule, $match))\n\t\t\t{\n\t\t\t\t$rule = $match[1];\n\t\t\t\t$param = $match[2];\n\t\t\t}\n\n\t\t\t// Ignore empty, non-required inputs with a few exceptions ...\n\t\t\tif (\n\t\t\t\t($postdata === NULL OR $postdata === '')\n\t\t\t\t&& $callback === FALSE\n\t\t\t\t&& $callable === FALSE\n\t\t\t\t&& ! in_array($rule, array('required', 'isset', 'matches'), TRUE)\n\t\t\t)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Call the function that corresponds to the rule\n\t\t\tif ($callback OR $callable !== FALSE)\n\t\t\t{\n\t\t\t\tif ($callback)\n\t\t\t\t{\n\t\t\t\t\tif ( ! method_exists($this->CI, $rule))\n\t\t\t\t\t{\n\t\t\t\t\t\tlog_message('debug', 'Unable to find callback validation rule: '.$rule);\n\t\t\t\t\t\t$result = FALSE;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t// Run the function and grab the result\n\t\t\t\t\t\t$result = $this->CI->$rule($postdata, $param);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$result = is_array($rule)\n\t\t\t\t\t\t? $rule[0]->{$rule[1]}($postdata)\n\t\t\t\t\t\t: $rule($postdata);\n\n\t\t\t\t\t// Is $callable set to a rule name?\n\t\t\t\t\tif ($callable !== FALSE)\n\t\t\t\t\t{\n\t\t\t\t\t\t$rule = $callable;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Re-assign the result to the master data array\n\t\t\t\tif ($_in_array === TRUE)\n\t\t\t\t{\n\t\t\t\t\t$this->_field_data[$row['field']]['postdata'][$cycles] = is_bool($result) ? $postdata : $result;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$this->_field_data[$row['field']]['postdata'] = is_bool($result) ? $postdata : $result;\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif ( ! method_exists($this, $rule))\n\t\t\t{\n\t\t\t\t// If our own wrapper function doesn't exist we see if a native PHP function does.\n\t\t\t\t// Users can use any native PHP function call that has one param.\n\t\t\t\tif (function_exists($rule))\n\t\t\t\t{\n\t\t\t\t\t// Native PHP functions issue warnings if you pass them more parameters than they use\n\t\t\t\t\t$result = ($param !== FALSE) ? $rule($postdata, $param) : $rule($postdata);\n\n\t\t\t\t\tif ($_in_array === TRUE)\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->_field_data[$row['field']]['postdata'][$cycles] = is_bool($result) ? $postdata : $result;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->_field_data[$row['field']]['postdata'] = is_bool($result) ? $postdata : $result;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tlog_message('debug', 'Unable to find validation rule: '.$rule);\n\t\t\t\t\t$result = FALSE;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$result = $this->$rule($postdata, $param);\n\n\t\t\t\tif ($_in_array === TRUE)\n\t\t\t\t{\n\t\t\t\t\t$this->_field_data[$row['field']]['postdata'][$cycles] = is_bool($result) ? $postdata : $result;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$this->_field_data[$row['field']]['postdata'] = is_bool($result) ? $postdata : $result;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Did the rule test negatively? If so, grab the error.\n\t\t\tif ($result === FALSE)\n\t\t\t{\n\t\t\t\t// Callable rules might not have named error messages\n\t\t\t\tif ( ! is_string($rule))\n\t\t\t\t{\n\t\t\t\t\t$line = $this->CI->lang->line('form_validation_error_message_not_set').'(Anonymous function)';\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$line = $this->_get_error_message($rule, $row['field']);\n\t\t\t\t}\n\n\t\t\t\t// Is the parameter we are inserting into the error message the name\n\t\t\t\t// of another field? If so we need to grab its \"field label\"\n\t\t\t\tif (isset($this->_field_data[$param], $this->_field_data[$param]['label']))\n\t\t\t\t{\n\t\t\t\t\t$param = $this->_translate_fieldname($this->_field_data[$param]['label']);\n\t\t\t\t}\n\n\t\t\t\t// Build the error message\n\t\t\t\t$message = $this->_build_error_msg($line, $this->_translate_fieldname($row['label']), $param);\n\n\t\t\t\t// Save the error message\n\t\t\t\t$this->_field_data[$row['field']]['error'] = $message;\n\n\t\t\t\tif ( ! isset($this->_error_array[$row['field']]))\n\t\t\t\t{\n\t\t\t\t\t$this->_error_array[$row['field']] = $message;\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get the error message for the rule\n\t *\n\t * @param \tstring $rule \tThe rule name\n\t * @param \tstring $field\tThe field name\n\t * @return \tstring\n\t */\n\tprotected function _get_error_message($rule, $field)\n\t{\n\t\t// check if a custom message is defined through validation config row.\n\t\tif (isset($this->_field_data[$field]['errors'][$rule]))\n\t\t{\n\t\t\treturn $this->_field_data[$field]['errors'][$rule];\n\t\t}\n\t\t// check if a custom message has been set using the set_message() function\n\t\telseif (isset($this->_error_messages[$rule]))\n\t\t{\n\t\t\treturn $this->_error_messages[$rule];\n\t\t}\n\t\telseif (FALSE !== ($line = $this->CI->lang->line('form_validation_'.$rule)))\n\t\t{\n\t\t\treturn $line;\n\t\t}\n\t\t// DEPRECATED support for non-prefixed keys, lang file again\n\t\telseif (FALSE !== ($line = $this->CI->lang->line($rule, FALSE)))\n\t\t{\n\t\t\treturn $line;\n\t\t}\n\n\t\treturn $this->CI->lang->line('form_validation_error_message_not_set').'('.$rule.')';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Translate a field name\n\t *\n\t * @param\tstring\tthe field name\n\t * @return\tstring\n\t */\n\tprotected function _translate_fieldname($fieldname)\n\t{\n\t\t// Do we need to translate the field name? We look for the prefix 'lang:' to determine this\n\t\t// If we find one, but there's no translation for the string - just return it\n\t\tif (sscanf($fieldname, 'lang:%s', $line) === 1 && FALSE === ($fieldname = $this->CI->lang->line($line, FALSE)))\n\t\t{\n\t\t\treturn $line;\n\t\t}\n\n\t\treturn $fieldname;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Build an error message using the field and param.\n\t *\n\t * @param\tstring\tThe error message line\n\t * @param\tstring\tA field's human name\n\t * @param\tmixed\tA rule's optional parameter\n\t * @return\tstring\n\t */\n\tprotected function _build_error_msg($line, $field = '', $param = '')\n\t{\n\t\t// Check for %s in the string for legacy support.\n\t\tif (strpos($line, '%s') !== FALSE)\n\t\t{\n\t\t\treturn sprintf($line, $field, $param);\n\t\t}\n\n\t\treturn str_replace(array('{field}', '{param}'), array($field, $param), $line);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Checks if the rule is present within the validator\n\t *\n\t * Permits you to check if a rule is present within the validator\n\t *\n\t * @param\tstring\tthe field name\n\t * @return\tbool\n\t */\n\tpublic function has_rule($field)\n\t{\n\t\treturn isset($this->_field_data[$field]);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get the value from a form\n\t *\n\t * Permits you to repopulate a form field with the value it was submitted\n\t * with, or, if that value doesn't exist, with the default\n\t *\n\t * @param\tstring\tthe field name\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function set_value($field = '', $default = '')\n\t{\n\t\tif ( ! isset($this->_field_data[$field], $this->_field_data[$field]['postdata']))\n\t\t{\n\t\t\treturn $default;\n\t\t}\n\n\t\t// If the data is an array output them one at a time.\n\t\t//\tE.g: form_input('name[]', set_value('name[]');\n\t\tif (is_array($this->_field_data[$field]['postdata']))\n\t\t{\n\t\t\treturn array_shift($this->_field_data[$field]['postdata']);\n\t\t}\n\n\t\treturn $this->_field_data[$field]['postdata'];\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Select\n\t *\n\t * Enables pull-down lists to be set to the value the user\n\t * selected in the event of an error\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @param\tbool\n\t * @return\tstring\n\t */\n\tpublic function set_select($field = '', $value = '', $default = FALSE)\n\t{\n\t\tif ( ! isset($this->_field_data[$field], $this->_field_data[$field]['postdata']))\n\t\t{\n\t\t\treturn ($default === TRUE && count($this->_field_data) === 0) ? ' selected=\"selected\"' : '';\n\t\t}\n\n\t\t$field = $this->_field_data[$field]['postdata'];\n\t\t$value = (string) $value;\n\t\tif (is_array($field))\n\t\t{\n\t\t\t// Note: in_array('', array(0)) returns TRUE, do not use it\n\t\t\tforeach ($field as &$v)\n\t\t\t{\n\t\t\t\tif ($value === $v)\n\t\t\t\t{\n\t\t\t\t\treturn ' selected=\"selected\"';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn '';\n\t\t}\n\t\telseif (($field === '' OR $value === '') OR ($field !== $value))\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\treturn ' selected=\"selected\"';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Radio\n\t *\n\t * Enables radio buttons to be set to the value the user\n\t * selected in the event of an error\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @param\tbool\n\t * @return\tstring\n\t */\n\tpublic function set_radio($field = '', $value = '', $default = FALSE)\n\t{\n\t\tif ( ! isset($this->_field_data[$field], $this->_field_data[$field]['postdata']))\n\t\t{\n\t\t\treturn ($default === TRUE && count($this->_field_data) === 0) ? ' checked=\"checked\"' : '';\n\t\t}\n\n\t\t$field = $this->_field_data[$field]['postdata'];\n\t\t$value = (string) $value;\n\t\tif (is_array($field))\n\t\t{\n\t\t\t// Note: in_array('', array(0)) returns TRUE, do not use it\n\t\t\tforeach ($field as &$v)\n\t\t\t{\n\t\t\t\tif ($value === $v)\n\t\t\t\t{\n\t\t\t\t\treturn ' checked=\"checked\"';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn '';\n\t\t}\n\t\telseif (($field === '' OR $value === '') OR ($field !== $value))\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\treturn ' checked=\"checked\"';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Checkbox\n\t *\n\t * Enables checkboxes to be set to the value the user\n\t * selected in the event of an error\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @param\tbool\n\t * @return\tstring\n\t */\n\tpublic function set_checkbox($field = '', $value = '', $default = FALSE)\n\t{\n\t\t// Logic is exactly the same as for radio fields\n\t\treturn $this->set_radio($field, $value, $default);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Required\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function required($str)\n\t{\n\t\treturn is_array($str)\n\t\t\t? (empty($str) === FALSE)\n\t\t\t: (trim($str) !== '');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Performs a Regular Expression match test.\n\t *\n\t * @param\tstring\n\t * @param\tstring\tregex\n\t * @return\tbool\n\t */\n\tpublic function regex_match($str, $regex)\n\t{\n\t\treturn (bool) preg_match($regex, $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Match one field to another\n\t *\n\t * @param\tstring\t$str\tstring to compare against\n\t * @param\tstring\t$field\n\t * @return\tbool\n\t */\n\tpublic function matches($str, $field)\n\t{\n\t\treturn isset($this->_field_data[$field], $this->_field_data[$field]['postdata'])\n\t\t\t? ($str === $this->_field_data[$field]['postdata'])\n\t\t\t: FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Differs from another field\n\t *\n\t * @param\tstring\n\t * @param\tstring\tfield\n\t * @return\tbool\n\t */\n\tpublic function differs($str, $field)\n\t{\n\t\treturn ! (isset($this->_field_data[$field]) && $this->_field_data[$field]['postdata'] === $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is Unique\n\t *\n\t * Check if the input value doesn't already exist\n\t * in the specified database field.\n\t *\n\t * @param\tstring\t$str\n\t * @param\tstring\t$field\n\t * @return\tbool\n\t */\n\tpublic function is_unique($str, $field)\n\t{\n\t\tsscanf($field, '%[^.].%[^.]', $table, $field);\n\t\treturn isset($this->CI->db)\n\t\t\t? ($this->CI->db->limit(1)->get_where($table, array($field => $str))->num_rows() === 0)\n\t\t\t: FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Minimum Length\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function min_length($str, $val)\n\t{\n\t\tif ( ! is_numeric($val))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn ($val <= mb_strlen($str));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Max Length\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function max_length($str, $val)\n\t{\n\t\tif ( ! is_numeric($val))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn ($val >= mb_strlen($str));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Exact Length\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function exact_length($str, $val)\n\t{\n\t\tif ( ! is_numeric($val))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn (mb_strlen($str) === (int) $val);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Valid URL\n\t *\n\t * @param\tstring\t$str\n\t * @return\tbool\n\t */\n\tpublic function valid_url($str)\n\t{\n\t\tif (empty($str))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\t\telseif (preg_match('/^(?:([^:]*)\\:)?\\/\\/(.+)$/', $str, $matches))\n\t\t{\n\t\t\tif (empty($matches[2]))\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t\telseif ( ! in_array($matches[1], array('http', 'https'), TRUE))\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$str = $matches[2];\n\t\t}\n\n\t\t// PHP 7 accepts IPv6 addresses within square brackets as hostnames,\n\t\t// but it appears that the PR that came in with https://bugs.php.net/bug.php?id=68039\n\t\t// was never merged into a PHP 5 branch ... https://3v4l.org/8PsSN\n\t\tif (preg_match('/^\\[([^\\]]+)\\]/', $str, $matches) && ! is_php('7') && filter_var($matches[1], FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== FALSE)\n\t\t{\n\t\t\t$str = 'ipv6.host'.substr($str, strlen($matches[1]) + 2);\n\t\t}\n\n\t\t$str = 'http://'.$str;\n\n\t\t// There's a bug affecting PHP 5.2.13, 5.3.2 that considers the\n\t\t// underscore to be a valid hostname character instead of a dash.\n\t\t// Reference: https://bugs.php.net/bug.php?id=51192\n\t\tif (version_compare(PHP_VERSION, '5.2.13', '==') OR version_compare(PHP_VERSION, '5.3.2', '=='))\n\t\t{\n\t\t\tsscanf($str, 'http://%[^/]', $host);\n\t\t\t$str = substr_replace($str, strtr($host, array('_' => '-', '-' => '_')), 7, strlen($host));\n\t\t}\n\n\t\treturn (filter_var($str, FILTER_VALIDATE_URL) !== FALSE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Valid Email\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function valid_email($str)\n\t{\n\t\tif (function_exists('idn_to_ascii') && $atpos = strpos($str, '@'))\n\t\t{\n\t\t\t$str = substr($str, 0, ++$atpos).idn_to_ascii(substr($str, $atpos));\n\t\t}\n\n\t\treturn (bool) filter_var($str, FILTER_VALIDATE_EMAIL);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Valid Emails\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function valid_emails($str)\n\t{\n\t\tif (strpos($str, ',') === FALSE)\n\t\t{\n\t\t\treturn $this->valid_email(trim($str));\n\t\t}\n\n\t\tforeach (explode(',', $str) as $email)\n\t\t{\n\t\t\tif (trim($email) !== '' && $this->valid_email(trim($email)) === FALSE)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Validate IP Address\n\t *\n\t * @param\tstring\n\t * @param\tstring\t'ipv4' or 'ipv6' to validate a specific IP format\n\t * @return\tbool\n\t */\n\tpublic function valid_ip($ip, $which = '')\n\t{\n\t\treturn $this->CI->input->valid_ip($ip, $which);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Alpha\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function alpha($str)\n\t{\n\t\treturn ctype_alpha($str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Alpha-numeric\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function alpha_numeric($str)\n\t{\n\t\treturn ctype_alnum((string) $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Alpha-numeric w/ spaces\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function alpha_numeric_spaces($str)\n\t{\n\t\treturn (bool) preg_match('/^[A-Z0-9 ]+$/i', $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Alpha-numeric with underscores and dashes\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function alpha_dash($str)\n\t{\n\t\treturn (bool) preg_match('/^[a-z0-9_-]+$/i', $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Numeric\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function numeric($str)\n\t{\n\t\treturn (bool) preg_match('/^[\\-+]?[0-9]*\\.?[0-9]+$/', $str);\n\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Integer\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function integer($str)\n\t{\n\t\treturn (bool) preg_match('/^[\\-+]?[0-9]+$/', $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Decimal number\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function decimal($str)\n\t{\n\t\treturn (bool) preg_match('/^[\\-+]?[0-9]+\\.[0-9]+$/', $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Greater than\n\t *\n\t * @param\tstring\n\t * @param\tint\n\t * @return\tbool\n\t */\n\tpublic function greater_than($str, $min)\n\t{\n\t\treturn is_numeric($str) ? ($str > $min) : FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Equal to or Greater than\n\t *\n\t * @param\tstring\n\t * @param\tint\n\t * @return\tbool\n\t */\n\tpublic function greater_than_equal_to($str, $min)\n\t{\n\t\treturn is_numeric($str) ? ($str >= $min) : FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Less than\n\t *\n\t * @param\tstring\n\t * @param\tint\n\t * @return\tbool\n\t */\n\tpublic function less_than($str, $max)\n\t{\n\t\treturn is_numeric($str) ? ($str < $max) : FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Equal to or Less than\n\t *\n\t * @param\tstring\n\t * @param\tint\n\t * @return\tbool\n\t */\n\tpublic function less_than_equal_to($str, $max)\n\t{\n\t\treturn is_numeric($str) ? ($str <= $max) : FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Value should be within an array of values\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function in_list($value, $list)\n\t{\n\t\treturn in_array($value, explode(',', $list), TRUE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is a Natural number  (0,1,2,3, etc.)\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function is_natural($str)\n\t{\n\t\treturn ctype_digit((string) $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is a Natural number, but not a zero  (1,2,3, etc.)\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function is_natural_no_zero($str)\n\t{\n\t\treturn ($str != 0 && ctype_digit((string) $str));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Valid Base64\n\t *\n\t * Tests a string for characters outside of the Base64 alphabet\n\t * as defined by RFC 2045 http://www.faqs.org/rfcs/rfc2045\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function valid_base64($str)\n\t{\n\t\treturn (base64_encode(base64_decode($str)) === $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prep data for form\n\t *\n\t * This function allows HTML to be safely shown in a form.\n\t * Special characters are converted.\n\t *\n\t * @deprecated\t3.0.6\tNot used anywhere within the framework and pretty much useless\n\t * @param\tmixed\t$data\tInput data\n\t * @return\tmixed\n\t */\n\tpublic function prep_for_form($data)\n\t{\n\t\tif ($this->_safe_form_data === FALSE OR empty($data))\n\t\t{\n\t\t\treturn $data;\n\t\t}\n\n\t\tif (is_array($data))\n\t\t{\n\t\t\tforeach ($data as $key => $val)\n\t\t\t{\n\t\t\t\t$data[$key] = $this->prep_for_form($val);\n\t\t\t}\n\n\t\t\treturn $data;\n\t\t}\n\n\t\treturn str_replace(array(\"'\", '\"', '<', '>'), array('&#39;', '&quot;', '&lt;', '&gt;'), stripslashes($data));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prep URL\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function prep_url($str = '')\n\t{\n\t\tif ($str === 'http://' OR $str === '')\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\tif (strpos($str, 'http://') !== 0 && strpos($str, 'https://') !== 0)\n\t\t{\n\t\t\treturn 'http://'.$str;\n\t\t}\n\n\t\treturn $str;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Strip Image Tags\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function strip_image_tags($str)\n\t{\n\t\treturn $this->CI->security->strip_image_tags($str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Convert PHP tags to entities\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function encode_php_tags($str)\n\t{\n\t\treturn str_replace(array('<?', '?>'), array('&lt;?', '?&gt;'), $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Reset validation vars\n\t *\n\t * Prevents subsequent validation routines from being affected by the\n\t * results of any previous validation routine due to the CI singleton.\n\t *\n\t * @return\tCI_Form_validation\n\t */\n\tpublic function reset_validation()\n\t{\n\t\t$this->_field_data = array();\n\t\t$this->_error_array = array();\n\t\t$this->_error_messages = array();\n\t\t$this->error_string = '';\n\t\treturn $this;\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/Ftp.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * FTP Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/ftp.html\n */\nclass CI_FTP {\n\n\t/**\n\t * FTP Server hostname\n\t *\n\t * @var\tstring\n\t */\n\tpublic $hostname = '';\n\n\t/**\n\t * FTP Username\n\t *\n\t * @var\tstring\n\t */\n\tpublic $username = '';\n\n\t/**\n\t * FTP Password\n\t *\n\t * @var\tstring\n\t */\n\tpublic $password = '';\n\n\t/**\n\t * FTP Server port\n\t *\n\t * @var\tint\n\t */\n\tpublic $port = 21;\n\n\t/**\n\t * Passive mode flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $passive = TRUE;\n\n\t/**\n\t * Debug flag\n\t *\n\t * Specifies whether to display error messages.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $debug = FALSE;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Connection ID\n\t *\n\t * @var\tresource\n\t */\n\tprotected $conn_id;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @param\tarray\t$config\n\t * @return\tvoid\n\t */\n\tpublic function __construct($config = array())\n\t{\n\t\tempty($config) OR $this->initialize($config);\n\t\tlog_message('info', 'FTP Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize preferences\n\t *\n\t * @param\tarray\t$config\n\t * @return\tvoid\n\t */\n\tpublic function initialize($config = array())\n\t{\n\t\tforeach ($config as $key => $val)\n\t\t{\n\t\t\tif (isset($this->$key))\n\t\t\t{\n\t\t\t\t$this->$key = $val;\n\t\t\t}\n\t\t}\n\n\t\t// Prep the hostname\n\t\t$this->hostname = preg_replace('|.+?://|', '', $this->hostname);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * FTP Connect\n\t *\n\t * @param\tarray\t $config\tConnection values\n\t * @return\tbool\n\t */\n\tpublic function connect($config = array())\n\t{\n\t\tif (count($config) > 0)\n\t\t{\n\t\t\t$this->initialize($config);\n\t\t}\n\n\t\tif (FALSE === ($this->conn_id = @ftp_connect($this->hostname, $this->port)))\n\t\t{\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\t$this->_error('ftp_unable_to_connect');\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ( ! $this->_login())\n\t\t{\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\t$this->_error('ftp_unable_to_login');\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Set passive mode if needed\n\t\tif ($this->passive === TRUE)\n\t\t{\n\t\t\tftp_pasv($this->conn_id, TRUE);\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * FTP Login\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _login()\n\t{\n\t\treturn @ftp_login($this->conn_id, $this->username, $this->password);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Validates the connection ID\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _is_conn()\n\t{\n\t\tif ( ! is_resource($this->conn_id))\n\t\t{\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\t$this->_error('ftp_no_connection');\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Change directory\n\t *\n\t * The second parameter lets us momentarily turn off debugging so that\n\t * this function can be used to test for the existence of a folder\n\t * without throwing an error. There's no FTP equivalent to is_dir()\n\t * so we do it by trying to change to a particular directory.\n\t * Internally, this parameter is only used by the \"mirror\" function below.\n\t *\n\t * @param\tstring\t$path\n\t * @param\tbool\t$suppress_debug\n\t * @return\tbool\n\t */\n\tpublic function changedir($path, $suppress_debug = FALSE)\n\t{\n\t\tif ( ! $this->_is_conn())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$result = @ftp_chdir($this->conn_id, $path);\n\n\t\tif ($result === FALSE)\n\t\t{\n\t\t\tif ($this->debug === TRUE && $suppress_debug === FALSE)\n\t\t\t{\n\t\t\t\t$this->_error('ftp_unable_to_changedir');\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Create a directory\n\t *\n\t * @param\tstring\t$path\n\t * @param\tint\t$permissions\n\t * @return\tbool\n\t */\n\tpublic function mkdir($path, $permissions = NULL)\n\t{\n\t\tif ($path === '' OR ! $this->_is_conn())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$result = @ftp_mkdir($this->conn_id, $path);\n\n\t\tif ($result === FALSE)\n\t\t{\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\t$this->_error('ftp_unable_to_mkdir');\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Set file permissions if needed\n\t\tif ($permissions !== NULL)\n\t\t{\n\t\t\t$this->chmod($path, (int) $permissions);\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Upload a file to the server\n\t *\n\t * @param\tstring\t$locpath\n\t * @param\tstring\t$rempath\n\t * @param\tstring\t$mode\n\t * @param\tint\t$permissions\n\t * @return\tbool\n\t */\n\tpublic function upload($locpath, $rempath, $mode = 'auto', $permissions = NULL)\n\t{\n\t\tif ( ! $this->_is_conn())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ( ! file_exists($locpath))\n\t\t{\n\t\t\t$this->_error('ftp_no_source_file');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Set the mode if not specified\n\t\tif ($mode === 'auto')\n\t\t{\n\t\t\t// Get the file extension so we can set the upload type\n\t\t\t$ext = $this->_getext($locpath);\n\t\t\t$mode = $this->_settype($ext);\n\t\t}\n\n\t\t$mode = ($mode === 'ascii') ? FTP_ASCII : FTP_BINARY;\n\n\t\t$result = @ftp_put($this->conn_id, $rempath, $locpath, $mode);\n\n\t\tif ($result === FALSE)\n\t\t{\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\t$this->_error('ftp_unable_to_upload');\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Set file permissions if needed\n\t\tif ($permissions !== NULL)\n\t\t{\n\t\t\t$this->chmod($rempath, (int) $permissions);\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Download a file from a remote server to the local server\n\t *\n\t * @param\tstring\t$rempath\n\t * @param\tstring\t$locpath\n\t * @param\tstring\t$mode\n\t * @return\tbool\n\t */\n\tpublic function download($rempath, $locpath, $mode = 'auto')\n\t{\n\t\tif ( ! $this->_is_conn())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Set the mode if not specified\n\t\tif ($mode === 'auto')\n\t\t{\n\t\t\t// Get the file extension so we can set the upload type\n\t\t\t$ext = $this->_getext($rempath);\n\t\t\t$mode = $this->_settype($ext);\n\t\t}\n\n\t\t$mode = ($mode === 'ascii') ? FTP_ASCII : FTP_BINARY;\n\n\t\t$result = @ftp_get($this->conn_id, $locpath, $rempath, $mode);\n\n\t\tif ($result === FALSE)\n\t\t{\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\t$this->_error('ftp_unable_to_download');\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Rename (or move) a file\n\t *\n\t * @param\tstring\t$old_file\n\t * @param\tstring\t$new_file\n\t * @param\tbool\t$move\n\t * @return\tbool\n\t */\n\tpublic function rename($old_file, $new_file, $move = FALSE)\n\t{\n\t\tif ( ! $this->_is_conn())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$result = @ftp_rename($this->conn_id, $old_file, $new_file);\n\n\t\tif ($result === FALSE)\n\t\t{\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\t$this->_error('ftp_unable_to_'.($move === FALSE ? 'rename' : 'move'));\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Move a file\n\t *\n\t * @param\tstring\t$old_file\n\t * @param\tstring\t$new_file\n\t * @return\tbool\n\t */\n\tpublic function move($old_file, $new_file)\n\t{\n\t\treturn $this->rename($old_file, $new_file, TRUE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Rename (or move) a file\n\t *\n\t * @param\tstring\t$filepath\n\t * @return\tbool\n\t */\n\tpublic function delete_file($filepath)\n\t{\n\t\tif ( ! $this->_is_conn())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$result = @ftp_delete($this->conn_id, $filepath);\n\n\t\tif ($result === FALSE)\n\t\t{\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\t$this->_error('ftp_unable_to_delete');\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Delete a folder and recursively delete everything (including sub-folders)\n\t * contained within it.\n\t *\n\t * @param\tstring\t$filepath\n\t * @return\tbool\n\t */\n\tpublic function delete_dir($filepath)\n\t{\n\t\tif ( ! $this->_is_conn())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Add a trailing slash to the file path if needed\n\t\t$filepath = preg_replace('/(.+?)\\/*$/', '\\\\1/', $filepath);\n\n\t\t$list = $this->list_files($filepath);\n\t\tif ( ! empty($list))\n\t\t{\n\t\t\tfor ($i = 0, $c = count($list); $i < $c; $i++)\n\t\t\t{\n\t\t\t\t// If we can't delete the item it's probaly a directory,\n\t\t\t\t// so we'll recursively call delete_dir()\n\t\t\t\tif ( ! preg_match('#/\\.\\.?$#', $list[$i]) && ! @ftp_delete($this->conn_id, $list[$i]))\n\t\t\t\t{\n\t\t\t\t\t$this->delete_dir($filepath.$list[$i]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (@ftp_rmdir($this->conn_id, $filepath) === FALSE)\n\t\t{\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\t$this->_error('ftp_unable_to_delete');\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set file permissions\n\t *\n\t * @param\tstring\t$path\tFile path\n\t * @param\tint\t$perm\tPermissions\n\t * @return\tbool\n\t */\n\tpublic function chmod($path, $perm)\n\t{\n\t\tif ( ! $this->_is_conn())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (@ftp_chmod($this->conn_id, $perm, $path) === FALSE)\n\t\t{\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\t$this->_error('ftp_unable_to_chmod');\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * FTP List files in the specified directory\n\t *\n\t * @param\tstring\t$path\n\t * @return\tarray\n\t */\n\tpublic function list_files($path = '.')\n\t{\n\t\treturn $this->_is_conn()\n\t\t\t? ftp_nlist($this->conn_id, $path)\n\t\t\t: FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Read a directory and recreate it remotely\n\t *\n\t * This function recursively reads a folder and everything it contains\n\t * (including sub-folders) and creates a mirror via FTP based on it.\n\t * Whatever the directory structure of the original file path will be\n\t * recreated on the server.\n\t *\n\t * @param\tstring\t$locpath\tPath to source with trailing slash\n\t * @param\tstring\t$rempath\tPath to destination - include the base folder with trailing slash\n\t * @return\tbool\n\t */\n\tpublic function mirror($locpath, $rempath)\n\t{\n\t\tif ( ! $this->_is_conn())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Open the local file path\n\t\tif ($fp = @opendir($locpath))\n\t\t{\n\t\t\t// Attempt to open the remote file path and try to create it, if it doesn't exist\n\t\t\tif ( ! $this->changedir($rempath, TRUE) && ( ! $this->mkdir($rempath) OR ! $this->changedir($rempath)))\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t// Recursively read the local directory\n\t\t\twhile (FALSE !== ($file = readdir($fp)))\n\t\t\t{\n\t\t\t\tif (is_dir($locpath.$file) && $file[0] !== '.')\n\t\t\t\t{\n\t\t\t\t\t$this->mirror($locpath.$file.'/', $rempath.$file.'/');\n\t\t\t\t}\n\t\t\t\telseif ($file[0] !== '.')\n\t\t\t\t{\n\t\t\t\t\t// Get the file extension so we can se the upload type\n\t\t\t\t\t$ext = $this->_getext($file);\n\t\t\t\t\t$mode = $this->_settype($ext);\n\n\t\t\t\t\t$this->upload($locpath.$file, $rempath.$file, $mode);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Extract the file extension\n\t *\n\t * @param\tstring\t$filename\n\t * @return\tstring\n\t */\n\tprotected function _getext($filename)\n\t{\n\t\treturn (($dot = strrpos($filename, '.')) === FALSE)\n\t\t\t? 'txt'\n\t\t\t: substr($filename, $dot + 1);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the upload type\n\t *\n\t * @param\tstring\t$ext\tFilename extension\n\t * @return\tstring\n\t */\n\tprotected function _settype($ext)\n\t{\n\t\treturn in_array($ext, array('txt', 'text', 'php', 'phps', 'php4', 'js', 'css', 'htm', 'html', 'phtml', 'shtml', 'log', 'xml'), TRUE)\n\t\t\t? 'ascii'\n\t\t\t: 'binary';\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Close the connection\n\t *\n\t * @return\tbool\n\t */\n\tpublic function close()\n\t{\n\t\treturn $this->_is_conn()\n\t\t\t? @ftp_close($this->conn_id)\n\t\t\t: FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Display error message\n\t *\n\t * @param\tstring\t$line\n\t * @return\tvoid\n\t */\n\tprotected function _error($line)\n\t{\n\t\t$CI =& get_instance();\n\t\t$CI->lang->load('ftp');\n\t\tshow_error($CI->lang->line($line));\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/Image_lib.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Image Manipulation class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tImage_lib\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/image_lib.html\n */\nclass CI_Image_lib {\n\n\t/**\n\t * PHP extension/library to use for image manipulation\n\t * Can be: imagemagick, netpbm, gd, gd2\n\t *\n\t * @var string\n\t */\n\tpublic $image_library\t\t= 'gd2';\n\n\t/**\n\t * Path to the graphic library (if applicable)\n\t *\n\t * @var string\n\t */\n\tpublic $library_path\t\t= '';\n\n\t/**\n\t * Whether to send to browser or write to disk\n\t *\n\t * @var bool\n\t */\n\tpublic $dynamic_output\t\t= FALSE;\n\n\t/**\n\t * Path to original image\n\t *\n\t * @var string\n\t */\n\tpublic $source_image\t\t= '';\n\n\t/**\n\t * Path to the modified image\n\t *\n\t * @var string\n\t */\n\tpublic $new_image\t\t= '';\n\n\t/**\n\t * Image width\n\t *\n\t * @var int\n\t */\n\tpublic $width\t\t\t= '';\n\n\t/**\n\t * Image height\n\t *\n\t * @var int\n\t */\n\tpublic $height\t\t\t= '';\n\n\t/**\n\t * Quality percentage of new image\n\t *\n\t * @var int\n\t */\n\tpublic $quality\t\t\t= 90;\n\n\t/**\n\t * Whether to create a thumbnail\n\t *\n\t * @var bool\n\t */\n\tpublic $create_thumb\t\t= FALSE;\n\n\t/**\n\t * String to add to thumbnail version of image\n\t *\n\t * @var string\n\t */\n\tpublic $thumb_marker\t\t= '_thumb';\n\n\t/**\n\t * Whether to maintain aspect ratio when resizing or use hard values\n\t *\n\t * @var bool\n\t */\n\tpublic $maintain_ratio\t\t= TRUE;\n\n\t/**\n\t * auto, height, or width.  Determines what to use as the master dimension\n\t *\n\t * @var string\n\t */\n\tpublic $master_dim\t\t= 'auto';\n\n\t/**\n\t * Angle at to rotate image\n\t *\n\t * @var string\n\t */\n\tpublic $rotation_angle\t\t= '';\n\n\t/**\n\t * X Coordinate for manipulation of the current image\n\t *\n\t * @var int\n\t */\n\tpublic $x_axis\t\t\t= '';\n\n\t/**\n\t * Y Coordinate for manipulation of the current image\n\t *\n\t * @var int\n\t */\n\tpublic $y_axis\t\t\t= '';\n\n\t// --------------------------------------------------------------------------\n\t// Watermark Vars\n\t// --------------------------------------------------------------------------\n\n\t/**\n\t * Watermark text if graphic is not used\n\t *\n\t * @var string\n\t */\n\tpublic $wm_text\t\t\t= '';\n\n\t/**\n\t * Type of watermarking.  Options:  text/overlay\n\t *\n\t * @var string\n\t */\n\tpublic $wm_type\t\t\t= 'text';\n\n\t/**\n\t * Default transparency for watermark\n\t *\n\t * @var int\n\t */\n\tpublic $wm_x_transp\t\t= 4;\n\n\t/**\n\t * Default transparency for watermark\n\t *\n\t * @var int\n\t */\n\tpublic $wm_y_transp\t\t= 4;\n\n\t/**\n\t * Watermark image path\n\t *\n\t * @var string\n\t */\n\tpublic $wm_overlay_path\t\t= '';\n\n\t/**\n\t * TT font\n\t *\n\t * @var string\n\t */\n\tpublic $wm_font_path\t\t= '';\n\n\t/**\n\t * Font size (different versions of GD will either use points or pixels)\n\t *\n\t * @var int\n\t */\n\tpublic $wm_font_size\t\t= 17;\n\n\t/**\n\t * Vertical alignment:   T M B\n\t *\n\t * @var string\n\t */\n\tpublic $wm_vrt_alignment\t= 'B';\n\n\t/**\n\t * Horizontal alignment: L R C\n\t *\n\t * @var string\n\t */\n\tpublic $wm_hor_alignment\t= 'C';\n\n\t/**\n\t * Padding around text\n\t *\n\t * @var int\n\t */\n\tpublic $wm_padding\t\t\t= 0;\n\n\t/**\n\t * Lets you push text to the right\n\t *\n\t * @var int\n\t */\n\tpublic $wm_hor_offset\t\t= 0;\n\n\t/**\n\t * Lets you push text down\n\t *\n\t * @var int\n\t */\n\tpublic $wm_vrt_offset\t\t= 0;\n\n\t/**\n\t * Text color\n\t *\n\t * @var string\n\t */\n\tprotected $wm_font_color\t= '#ffffff';\n\n\t/**\n\t * Dropshadow color\n\t *\n\t * @var string\n\t */\n\tprotected $wm_shadow_color\t= '';\n\n\t/**\n\t * Dropshadow distance\n\t *\n\t * @var int\n\t */\n\tpublic $wm_shadow_distance\t= 2;\n\n\t/**\n\t * Image opacity: 1 - 100  Only works with image\n\t *\n\t * @var int\n\t */\n\tpublic $wm_opacity\t\t= 50;\n\n\t// --------------------------------------------------------------------------\n\t// Private Vars\n\t// --------------------------------------------------------------------------\n\n\t/**\n\t * Source image folder\n\t *\n\t * @var string\n\t */\n\tpublic $source_folder\t\t= '';\n\n\t/**\n\t * Destination image folder\n\t *\n\t * @var string\n\t */\n\tpublic $dest_folder\t\t= '';\n\n\t/**\n\t * Image mime-type\n\t *\n\t * @var string\n\t */\n\tpublic $mime_type\t\t= '';\n\n\t/**\n\t * Original image width\n\t *\n\t * @var int\n\t */\n\tpublic $orig_width\t\t= '';\n\n\t/**\n\t * Original image height\n\t *\n\t * @var int\n\t */\n\tpublic $orig_height\t\t= '';\n\n\t/**\n\t * Image format\n\t *\n\t * @var string\n\t */\n\tpublic $image_type\t\t= '';\n\n\t/**\n\t * Size of current image\n\t *\n\t * @var string\n\t */\n\tpublic $size_str\t\t= '';\n\n\t/**\n\t * Full path to source image\n\t *\n\t * @var string\n\t */\n\tpublic $full_src_path\t\t= '';\n\n\t/**\n\t * Full path to destination image\n\t *\n\t * @var string\n\t */\n\tpublic $full_dst_path\t\t= '';\n\n\t/**\n\t * File permissions\n\t *\n\t * @var\tint\n\t */\n\tpublic $file_permissions = 0644;\n\n\t/**\n\t * Name of function to create image\n\t *\n\t * @var string\n\t */\n\tpublic $create_fnc\t\t= 'imagecreatetruecolor';\n\n\t/**\n\t * Name of function to copy image\n\t *\n\t * @var string\n\t */\n\tpublic $copy_fnc\t\t= 'imagecopyresampled';\n\n\t/**\n\t * Error messages\n\t *\n\t * @var array\n\t */\n\tpublic $error_msg\t\t= array();\n\n\t/**\n\t * Whether to have a drop shadow on watermark\n\t *\n\t * @var bool\n\t */\n\tprotected $wm_use_drop_shadow\t= FALSE;\n\n\t/**\n\t * Whether to use truetype fonts\n\t *\n\t * @var bool\n\t */\n\tpublic $wm_use_truetype\t= FALSE;\n\n\t/**\n\t * Initialize Image Library\n\t *\n\t * @param\tarray\t$props\n\t * @return\tvoid\n\t */\n\tpublic function __construct($props = array())\n\t{\n\t\tif (count($props) > 0)\n\t\t{\n\t\t\t$this->initialize($props);\n\t\t}\n\n\t\tlog_message('info', 'Image Lib Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize image properties\n\t *\n\t * Resets values in case this class is used in a loop\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function clear()\n\t{\n\t\t$props = array('thumb_marker', 'library_path', 'source_image', 'new_image', 'width', 'height', 'rotation_angle', 'x_axis', 'y_axis', 'wm_text', 'wm_overlay_path', 'wm_font_path', 'wm_shadow_color', 'source_folder', 'dest_folder', 'mime_type', 'orig_width', 'orig_height', 'image_type', 'size_str', 'full_src_path', 'full_dst_path');\n\n\t\tforeach ($props as $val)\n\t\t{\n\t\t\t$this->$val = '';\n\t\t}\n\n\t\t$this->image_library \t\t= 'gd2';\n\t\t$this->dynamic_output \t\t= FALSE;\n\t\t$this->quality \t\t\t\t= 90;\n\t\t$this->create_thumb \t\t= FALSE;\n\t\t$this->thumb_marker \t\t= '_thumb';\n\t\t$this->maintain_ratio \t\t= TRUE;\n\t\t$this->master_dim \t\t\t= 'auto';\n\t\t$this->wm_type \t\t\t\t= 'text';\n\t\t$this->wm_x_transp \t\t\t= 4;\n\t\t$this->wm_y_transp \t\t\t= 4;\n\t\t$this->wm_font_size \t\t= 17;\n\t\t$this->wm_vrt_alignment \t= 'B';\n\t\t$this->wm_hor_alignment \t= 'C';\n\t\t$this->wm_padding \t\t\t= 0;\n\t\t$this->wm_hor_offset \t\t= 0;\n\t\t$this->wm_vrt_offset \t\t= 0;\n\t\t$this->wm_font_color\t\t= '#ffffff';\n\t\t$this->wm_shadow_distance \t= 2;\n\t\t$this->wm_opacity \t\t\t= 50;\n\t\t$this->create_fnc \t\t\t= 'imagecreatetruecolor';\n\t\t$this->copy_fnc \t\t\t= 'imagecopyresampled';\n\t\t$this->error_msg \t\t\t= array();\n\t\t$this->wm_use_drop_shadow \t= FALSE;\n\t\t$this->wm_use_truetype \t\t= FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * initialize image preferences\n\t *\n\t * @param\tarray\n\t * @return\tbool\n\t */\n\tpublic function initialize($props = array())\n\t{\n\t\t// Convert array elements into class variables\n\t\tif (count($props) > 0)\n\t\t{\n\t\t\tforeach ($props as $key => $val)\n\t\t\t{\n\t\t\t\tif (property_exists($this, $key))\n\t\t\t\t{\n\t\t\t\t\tif (in_array($key, array('wm_font_color', 'wm_shadow_color'), TRUE))\n\t\t\t\t\t{\n\t\t\t\t\t\tif (preg_match('/^#?([0-9a-f]{3}|[0-9a-f]{6})$/i', $val, $matches))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t/* $matches[1] contains our hex color value, but it might be\n\t\t\t\t\t\t\t * both in the full 6-length format or the shortened 3-length\n\t\t\t\t\t\t\t * value.\n\t\t\t\t\t\t\t * We'll later need the full version, so we keep it if it's\n\t\t\t\t\t\t\t * already there and if not - we'll convert to it. We can\n\t\t\t\t\t\t\t * access string characters by their index as in an array,\n\t\t\t\t\t\t\t * so we'll do that and use concatenation to form the final\n\t\t\t\t\t\t\t * value:\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\t$val = (strlen($matches[1]) === 6)\n\t\t\t\t\t\t\t\t? '#'.$matches[1]\n\t\t\t\t\t\t\t\t: '#'.$matches[1][0].$matches[1][0].$matches[1][1].$matches[1][1].$matches[1][2].$matches[1][2];\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telseif (in_array($key, array('width', 'height'), TRUE) && ! ctype_digit((string) $val))\n\t\t\t\t\t{\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t$this->$key = $val;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Is there a source image? If not, there's no reason to continue\n\t\tif ($this->source_image === '')\n\t\t{\n\t\t\t$this->set_error('imglib_source_image_required');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t/* Is getimagesize() available?\n\t\t *\n\t\t * We use it to determine the image properties (width/height).\n\t\t * Note: We need to figure out how to determine image\n\t\t * properties using ImageMagick and NetPBM\n\t\t */\n\t\tif ( ! function_exists('getimagesize'))\n\t\t{\n\t\t\t$this->set_error('imglib_gd_required_for_props');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->image_library = strtolower($this->image_library);\n\n\t\t/* Set the full server path\n\t\t *\n\t\t * The source image may or may not contain a path.\n\t\t * Either way, we'll try use realpath to generate the\n\t\t * full server path in order to more reliably read it.\n\t\t */\n\t\tif (($full_source_path = realpath($this->source_image)) !== FALSE)\n\t\t{\n\t\t\t$full_source_path = str_replace('\\\\', '/', $full_source_path);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$full_source_path = $this->source_image;\n\t\t}\n\n\t\t$x = explode('/', $full_source_path);\n\t\t$this->source_image = end($x);\n\t\t$this->source_folder = str_replace($this->source_image, '', $full_source_path);\n\n\t\t// Set the Image Properties\n\t\tif ( ! $this->get_image_properties($this->source_folder.$this->source_image))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t/*\n\t\t * Assign the \"new\" image name/path\n\t\t *\n\t\t * If the user has set a \"new_image\" name it means\n\t\t * we are making a copy of the source image. If not\n\t\t * it means we are altering the original. We'll\n\t\t * set the destination filename and path accordingly.\n\t\t */\n\t\tif ($this->new_image === '')\n\t\t{\n\t\t\t$this->dest_image = $this->source_image;\n\t\t\t$this->dest_folder = $this->source_folder;\n\t\t}\n\t\telseif (strpos($this->new_image, '/') === FALSE)\n\t\t{\n\t\t\t$this->dest_folder = $this->source_folder;\n\t\t\t$this->dest_image = $this->new_image;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (strpos($this->new_image, '/') === FALSE && strpos($this->new_image, '\\\\') === FALSE)\n\t\t\t{\n\t\t\t\t$full_dest_path = str_replace('\\\\', '/', realpath($this->new_image));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$full_dest_path = $this->new_image;\n\t\t\t}\n\n\t\t\t// Is there a file name?\n\t\t\tif ( ! preg_match('#\\.(jpg|jpeg|gif|png)$#i', $full_dest_path))\n\t\t\t{\n\t\t\t\t$this->dest_folder = $full_dest_path.'/';\n\t\t\t\t$this->dest_image = $this->source_image;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$x = explode('/', $full_dest_path);\n\t\t\t\t$this->dest_image = end($x);\n\t\t\t\t$this->dest_folder = str_replace($this->dest_image, '', $full_dest_path);\n\t\t\t}\n\t\t}\n\n\t\t/* Compile the finalized filenames/paths\n\t\t *\n\t\t * We'll create two master strings containing the\n\t\t * full server path to the source image and the\n\t\t * full server path to the destination image.\n\t\t * We'll also split the destination image name\n\t\t * so we can insert the thumbnail marker if needed.\n\t\t */\n\t\tif ($this->create_thumb === FALSE OR $this->thumb_marker === '')\n\t\t{\n\t\t\t$this->thumb_marker = '';\n\t\t}\n\n\t\t$xp = $this->explode_name($this->dest_image);\n\n\t\t$filename = $xp['name'];\n\t\t$file_ext = $xp['ext'];\n\n\t\t$this->full_src_path = $this->source_folder.$this->source_image;\n\t\t$this->full_dst_path = $this->dest_folder.$filename.$this->thumb_marker.$file_ext;\n\n\t\t/* Should we maintain image proportions?\n\t\t *\n\t\t * When creating thumbs or copies, the target width/height\n\t\t * might not be in correct proportion with the source\n\t\t * image's width/height. We'll recalculate it here.\n\t\t */\n\t\tif ($this->maintain_ratio === TRUE && ($this->width !== 0 OR $this->height !== 0))\n\t\t{\n\t\t\t$this->image_reproportion();\n\t\t}\n\n\t\t/* Was a width and height specified?\n\t\t *\n\t\t * If the destination width/height was not submitted we\n\t\t * will use the values from the actual file\n\t\t */\n\t\tif ($this->width === '')\n\t\t{\n\t\t\t$this->width = $this->orig_width;\n\t\t}\n\n\t\tif ($this->height === '')\n\t\t{\n\t\t\t$this->height = $this->orig_height;\n\t\t}\n\n\t\t// Set the quality\n\t\t$this->quality = trim(str_replace('%', '', $this->quality));\n\n\t\tif ($this->quality === '' OR $this->quality === 0 OR ! ctype_digit($this->quality))\n\t\t{\n\t\t\t$this->quality = 90;\n\t\t}\n\n\t\t// Set the x/y coordinates\n\t\tis_numeric($this->x_axis) OR $this->x_axis = 0;\n\t\tis_numeric($this->y_axis) OR $this->y_axis = 0;\n\n\t\t// Watermark-related Stuff...\n\t\tif ($this->wm_overlay_path !== '')\n\t\t{\n\t\t\t$this->wm_overlay_path = str_replace('\\\\', '/', realpath($this->wm_overlay_path));\n\t\t}\n\n\t\tif ($this->wm_shadow_color !== '')\n\t\t{\n\t\t\t$this->wm_use_drop_shadow = TRUE;\n\t\t}\n\t\telseif ($this->wm_use_drop_shadow === TRUE && $this->wm_shadow_color === '')\n\t\t{\n\t\t\t$this->wm_use_drop_shadow = FALSE;\n\t\t}\n\n\t\tif ($this->wm_font_path !== '')\n\t\t{\n\t\t\t$this->wm_use_truetype = TRUE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Image Resize\n\t *\n\t * This is a wrapper function that chooses the proper\n\t * resize function based on the protocol specified\n\t *\n\t * @return\tbool\n\t */\n\tpublic function resize()\n\t{\n\t\t$protocol = ($this->image_library === 'gd2') ? 'image_process_gd' : 'image_process_'.$this->image_library;\n\t\treturn $this->$protocol('resize');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Image Crop\n\t *\n\t * This is a wrapper function that chooses the proper\n\t * cropping function based on the protocol specified\n\t *\n\t * @return\tbool\n\t */\n\tpublic function crop()\n\t{\n\t\t$protocol = ($this->image_library === 'gd2') ? 'image_process_gd' : 'image_process_'.$this->image_library;\n\t\treturn $this->$protocol('crop');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Image Rotate\n\t *\n\t * This is a wrapper function that chooses the proper\n\t * rotation function based on the protocol specified\n\t *\n\t * @return\tbool\n\t */\n\tpublic function rotate()\n\t{\n\t\t// Allowed rotation values\n\t\t$degs = array(90, 180, 270, 'vrt', 'hor');\n\n\t\tif ($this->rotation_angle === '' OR ! in_array($this->rotation_angle, $degs))\n\t\t{\n\t\t\t$this->set_error('imglib_rotation_angle_required');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Reassign the width and height\n\t\tif ($this->rotation_angle === 90 OR $this->rotation_angle === 270)\n\t\t{\n\t\t\t$this->width\t= $this->orig_height;\n\t\t\t$this->height\t= $this->orig_width;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->width\t= $this->orig_width;\n\t\t\t$this->height\t= $this->orig_height;\n\t\t}\n\n\t\t// Choose resizing function\n\t\tif ($this->image_library === 'imagemagick' OR $this->image_library === 'netpbm')\n\t\t{\n\t\t\t$protocol = 'image_process_'.$this->image_library;\n\t\t\treturn $this->$protocol('rotate');\n\t\t}\n\n\t\treturn ($this->rotation_angle === 'hor' OR $this->rotation_angle === 'vrt')\n\t\t\t? $this->image_mirror_gd()\n\t\t\t: $this->image_rotate_gd();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Image Process Using GD/GD2\n\t *\n\t * This function will resize or crop\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function image_process_gd($action = 'resize')\n\t{\n\t\t$v2_override = FALSE;\n\n\t\t// If the target width/height match the source, AND if the new file name is not equal to the old file name\n\t\t// we'll simply make a copy of the original with the new name... assuming dynamic rendering is off.\n\t\tif ($this->dynamic_output === FALSE && $this->orig_width === $this->width && $this->orig_height === $this->height)\n\t\t{\n\t\t\tif ($this->source_image !== $this->new_image && @copy($this->full_src_path, $this->full_dst_path))\n\t\t\t{\n\t\t\t\tchmod($this->full_dst_path, $this->file_permissions);\n\t\t\t}\n\n\t\t\treturn TRUE;\n\t\t}\n\n\t\t// Let's set up our values based on the action\n\t\tif ($action === 'crop')\n\t\t{\n\t\t\t// Reassign the source width/height if cropping\n\t\t\t$this->orig_width  = $this->width;\n\t\t\t$this->orig_height = $this->height;\n\n\t\t\t// GD 2.0 has a cropping bug so we'll test for it\n\t\t\tif ($this->gd_version() !== FALSE)\n\t\t\t{\n\t\t\t\t$gd_version = str_replace('0', '', $this->gd_version());\n\t\t\t\t$v2_override = ($gd_version == 2);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// If resizing the x/y axis must be zero\n\t\t\t$this->x_axis = 0;\n\t\t\t$this->y_axis = 0;\n\t\t}\n\n\t\t// Create the image handle\n\t\tif ( ! ($src_img = $this->image_create_gd()))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t/* Create the image\n\t\t *\n\t\t * Old conditional which users report cause problems with shared GD libs who report themselves as \"2.0 or greater\"\n\t\t * it appears that this is no longer the issue that it was in 2004, so we've removed it, retaining it in the comment\n\t\t * below should that ever prove inaccurate.\n\t\t *\n\t\t * if ($this->image_library === 'gd2' && function_exists('imagecreatetruecolor') && $v2_override === FALSE)\n\t\t */\n\t\tif ($this->image_library === 'gd2' && function_exists('imagecreatetruecolor'))\n\t\t{\n\t\t\t$create\t= 'imagecreatetruecolor';\n\t\t\t$copy\t= 'imagecopyresampled';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$create\t= 'imagecreate';\n\t\t\t$copy\t= 'imagecopyresized';\n\t\t}\n\n\t\t$dst_img = $create($this->width, $this->height);\n\n\t\tif ($this->image_type === 3) // png we can actually preserve transparency\n\t\t{\n\t\t\timagealphablending($dst_img, FALSE);\n\t\t\timagesavealpha($dst_img, TRUE);\n\t\t}\n\n\t\t$copy($dst_img, $src_img, 0, 0, $this->x_axis, $this->y_axis, $this->width, $this->height, $this->orig_width, $this->orig_height);\n\n\t\t// Show the image\n\t\tif ($this->dynamic_output === TRUE)\n\t\t{\n\t\t\t$this->image_display_gd($dst_img);\n\t\t}\n\t\telseif ( ! $this->image_save_gd($dst_img)) // Or save it\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Kill the file handles\n\t\timagedestroy($dst_img);\n\t\timagedestroy($src_img);\n\n\t\tchmod($this->full_dst_path, $this->file_permissions);\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Image Process Using ImageMagick\n\t *\n\t * This function will resize, crop or rotate\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function image_process_imagemagick($action = 'resize')\n\t{\n\t\t// Do we have a vaild library path?\n\t\tif ($this->library_path === '')\n\t\t{\n\t\t\t$this->set_error('imglib_libpath_invalid');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ( ! preg_match('/convert$/i', $this->library_path))\n\t\t{\n\t\t\t$this->library_path = rtrim($this->library_path, '/').'/convert';\n\t\t}\n\n\t\t// Execute the command\n\t\t$cmd = $this->library_path.' -quality '.$this->quality;\n\n\t\tif ($action === 'crop')\n\t\t{\n\t\t\t$cmd .= ' -crop '.$this->width.'x'.$this->height.'+'.$this->x_axis.'+'.$this->y_axis;\n\t\t}\n\t\telseif ($action === 'rotate')\n\t\t{\n\t\t\t$cmd .= ($this->rotation_angle === 'hor' OR $this->rotation_angle === 'vrt')\n\t\t\t\t\t? ' -flop'\n\t\t\t\t\t: ' -rotate '.$this->rotation_angle;\n\t\t}\n\t\telse // Resize\n\t\t{\n\t\t\tif($this->maintain_ratio === TRUE)\n\t\t\t{\n\t\t\t\t$cmd .= ' -resize '.$this->width.'x'.$this->height;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$cmd .= ' -resize '.$this->width.'x'.$this->height.'\\!';\n\t\t\t}\n\t\t}\n\n\t\t$cmd .= ' \"'.escapeshellarg($this->full_src_path).'\" \"'.escapeshellarg($this->full_dst_path).'\" 2>&1';\n\n\t\t$retval = 1;\n\t\t// exec() might be disabled\n\t\tif (function_usable('exec'))\n\t\t{\n\t\t\t@exec($cmd, $output, $retval);\n\t\t}\n\n\t\t// Did it work?\n\t\tif ($retval > 0)\n\t\t{\n\t\t\t$this->set_error('imglib_image_process_failed');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tchmod($this->full_dst_path, $this->file_permissions);\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Image Process Using NetPBM\n\t *\n\t * This function will resize, crop or rotate\n\t *\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function image_process_netpbm($action = 'resize')\n\t{\n\t\tif ($this->library_path === '')\n\t\t{\n\t\t\t$this->set_error('imglib_libpath_invalid');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Build the resizing command\n\t\tswitch ($this->image_type)\n\t\t{\n\t\t\tcase 1 :\n\t\t\t\t$cmd_in\t\t= 'giftopnm';\n\t\t\t\t$cmd_out\t= 'ppmtogif';\n\t\t\t\tbreak;\n\t\t\tcase 2 :\n\t\t\t\t$cmd_in\t\t= 'jpegtopnm';\n\t\t\t\t$cmd_out\t= 'ppmtojpeg';\n\t\t\t\tbreak;\n\t\t\tcase 3 :\n\t\t\t\t$cmd_in\t\t= 'pngtopnm';\n\t\t\t\t$cmd_out\t= 'ppmtopng';\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif ($action === 'crop')\n\t\t{\n\t\t\t$cmd_inner = 'pnmcut -left '.$this->x_axis.' -top '.$this->y_axis.' -width '.$this->width.' -height '.$this->height;\n\t\t}\n\t\telseif ($action === 'rotate')\n\t\t{\n\t\t\tswitch ($this->rotation_angle)\n\t\t\t{\n\t\t\t\tcase 90:\t$angle = 'r270';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 180:\t$angle = 'r180';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 270:\t$angle = 'r90';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'vrt':\t$angle = 'tb';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'hor':\t$angle = 'lr';\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t$cmd_inner = 'pnmflip -'.$angle.' ';\n\t\t}\n\t\telse // Resize\n\t\t{\n\t\t\t$cmd_inner = 'pnmscale -xysize '.$this->width.' '.$this->height;\n\t\t}\n\n\t\t$cmd = $this->library_path.$cmd_in.' '.$this->full_src_path.' | '.$cmd_inner.' | '.$cmd_out.' > '.$this->dest_folder.'netpbm.tmp';\n\n\t\t$retval = 1;\n\t\t// exec() might be disabled\n\t\tif (function_usable('exec'))\n\t\t{\n\t\t\t@exec($cmd, $output, $retval);\n\t\t}\n\n\t\t// Did it work?\n\t\tif ($retval > 0)\n\t\t{\n\t\t\t$this->set_error('imglib_image_process_failed');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// With NetPBM we have to create a temporary image.\n\t\t// If you try manipulating the original it fails so\n\t\t// we have to rename the temp file.\n\t\tcopy($this->dest_folder.'netpbm.tmp', $this->full_dst_path);\n\t\tunlink($this->dest_folder.'netpbm.tmp');\n\t\tchmod($this->full_dst_path, $this->file_permissions);\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Image Rotate Using GD\n\t *\n\t * @return\tbool\n\t */\n\tpublic function image_rotate_gd()\n\t{\n\t\t// Create the image handle\n\t\tif ( ! ($src_img = $this->image_create_gd()))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Set the background color\n\t\t// This won't work with transparent PNG files so we are\n\t\t// going to have to figure out how to determine the color\n\t\t// of the alpha channel in a future release.\n\n\t\t$white = imagecolorallocate($src_img, 255, 255, 255);\n\n\t\t// Rotate it!\n\t\t$dst_img = imagerotate($src_img, $this->rotation_angle, $white);\n\n\t\t// Show the image\n\t\tif ($this->dynamic_output === TRUE)\n\t\t{\n\t\t\t$this->image_display_gd($dst_img);\n\t\t}\n\t\telseif ( ! $this->image_save_gd($dst_img)) // ... or save it\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Kill the file handles\n\t\timagedestroy($dst_img);\n\t\timagedestroy($src_img);\n\n\t\tchmod($this->full_dst_path, $this->file_permissions);\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Create Mirror Image using GD\n\t *\n\t * This function will flip horizontal or vertical\n\t *\n\t * @return\tbool\n\t */\n\tpublic function image_mirror_gd()\n\t{\n\t\tif ( ! $src_img = $this->image_create_gd())\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$width  = $this->orig_width;\n\t\t$height = $this->orig_height;\n\n\t\tif ($this->rotation_angle === 'hor')\n\t\t{\n\t\t\tfor ($i = 0; $i < $height; $i++)\n\t\t\t{\n\t\t\t\t$left = 0;\n\t\t\t\t$right = $width - 1;\n\n\t\t\t\twhile ($left < $right)\n\t\t\t\t{\n\t\t\t\t\t$cl = imagecolorat($src_img, $left, $i);\n\t\t\t\t\t$cr = imagecolorat($src_img, $right, $i);\n\n\t\t\t\t\timagesetpixel($src_img, $left, $i, $cr);\n\t\t\t\t\timagesetpixel($src_img, $right, $i, $cl);\n\n\t\t\t\t\t$left++;\n\t\t\t\t\t$right--;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor ($i = 0; $i < $width; $i++)\n\t\t\t{\n\t\t\t\t$top = 0;\n\t\t\t\t$bottom = $height - 1;\n\n\t\t\t\twhile ($top < $bottom)\n\t\t\t\t{\n\t\t\t\t\t$ct = imagecolorat($src_img, $i, $top);\n\t\t\t\t\t$cb = imagecolorat($src_img, $i, $bottom);\n\n\t\t\t\t\timagesetpixel($src_img, $i, $top, $cb);\n\t\t\t\t\timagesetpixel($src_img, $i, $bottom, $ct);\n\n\t\t\t\t\t$top++;\n\t\t\t\t\t$bottom--;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Show the image\n\t\tif ($this->dynamic_output === TRUE)\n\t\t{\n\t\t\t$this->image_display_gd($src_img);\n\t\t}\n\t\telseif ( ! $this->image_save_gd($src_img)) // ... or save it\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Kill the file handles\n\t\timagedestroy($src_img);\n\n\t\tchmod($this->full_dst_path, $this->file_permissions);\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Image Watermark\n\t *\n\t * This is a wrapper function that chooses the type\n\t * of watermarking based on the specified preference.\n\t *\n\t * @return\tbool\n\t */\n\tpublic function watermark()\n\t{\n\t\treturn ($this->wm_type === 'overlay') ? $this->overlay_watermark() : $this->text_watermark();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Watermark - Graphic Version\n\t *\n\t * @return\tbool\n\t */\n\tpublic function overlay_watermark()\n\t{\n\t\tif ( ! function_exists('imagecolortransparent'))\n\t\t{\n\t\t\t$this->set_error('imglib_gd_required');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Fetch source image properties\n\t\t$this->get_image_properties();\n\n\t\t// Fetch watermark image properties\n\t\t$props\t\t= $this->get_image_properties($this->wm_overlay_path, TRUE);\n\t\t$wm_img_type\t= $props['image_type'];\n\t\t$wm_width\t= $props['width'];\n\t\t$wm_height\t= $props['height'];\n\n\t\t// Create two image resources\n\t\t$wm_img  = $this->image_create_gd($this->wm_overlay_path, $wm_img_type);\n\t\t$src_img = $this->image_create_gd($this->full_src_path);\n\n\t\t// Reverse the offset if necessary\n\t\t// When the image is positioned at the bottom\n\t\t// we don't want the vertical offset to push it\n\t\t// further down. We want the reverse, so we'll\n\t\t// invert the offset. Same with the horizontal\n\t\t// offset when the image is at the right\n\n\t\t$this->wm_vrt_alignment = strtoupper($this->wm_vrt_alignment[0]);\n\t\t$this->wm_hor_alignment = strtoupper($this->wm_hor_alignment[0]);\n\n\t\tif ($this->wm_vrt_alignment === 'B')\n\t\t\t$this->wm_vrt_offset = $this->wm_vrt_offset * -1;\n\n\t\tif ($this->wm_hor_alignment === 'R')\n\t\t\t$this->wm_hor_offset = $this->wm_hor_offset * -1;\n\n\t\t// Set the base x and y axis values\n\t\t$x_axis = $this->wm_hor_offset + $this->wm_padding;\n\t\t$y_axis = $this->wm_vrt_offset + $this->wm_padding;\n\n\t\t// Set the vertical position\n\t\tif ($this->wm_vrt_alignment === 'M')\n\t\t{\n\t\t\t$y_axis += ($this->orig_height / 2) - ($wm_height / 2);\n\t\t}\n\t\telseif ($this->wm_vrt_alignment === 'B')\n\t\t{\n\t\t\t$y_axis += $this->orig_height - $wm_height;\n\t\t}\n\n\t\t// Set the horizontal position\n\t\tif ($this->wm_hor_alignment === 'C')\n\t\t{\n\t\t\t$x_axis += ($this->orig_width / 2) - ($wm_width / 2);\n\t\t}\n\t\telseif ($this->wm_hor_alignment === 'R')\n\t\t{\n\t\t\t$x_axis += $this->orig_width - $wm_width;\n\t\t}\n\n\t\t// Build the finalized image\n\t\tif ($wm_img_type === 3 && function_exists('imagealphablending'))\n\t\t{\n\t\t\t@imagealphablending($src_img, TRUE);\n\t\t}\n\n\t\t// Set RGB values for text and shadow\n\t\t$rgba = imagecolorat($wm_img, $this->wm_x_transp, $this->wm_y_transp);\n\t\t$alpha = ($rgba & 0x7F000000) >> 24;\n\n\t\t// make a best guess as to whether we're dealing with an image with alpha transparency or no/binary transparency\n\t\tif ($alpha > 0)\n\t\t{\n\t\t\t// copy the image directly, the image's alpha transparency being the sole determinant of blending\n\t\t\timagecopy($src_img, $wm_img, $x_axis, $y_axis, 0, 0, $wm_width, $wm_height);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// set our RGB value from above to be transparent and merge the images with the specified opacity\n\t\t\timagecolortransparent($wm_img, imagecolorat($wm_img, $this->wm_x_transp, $this->wm_y_transp));\n\t\t\timagecopymerge($src_img, $wm_img, $x_axis, $y_axis, 0, 0, $wm_width, $wm_height, $this->wm_opacity);\n\t\t}\n\n\t\t// We can preserve transparency for PNG images\n\t\tif ($this->image_type === 3)\n\t\t{\n\t\t\timagealphablending($src_img, FALSE);\n\t\t\timagesavealpha($src_img, TRUE);\n\t\t}\n\n\t\t// Output the image\n\t\tif ($this->dynamic_output === TRUE)\n\t\t{\n\t\t\t$this->image_display_gd($src_img);\n\t\t}\n\t\telseif ( ! $this->image_save_gd($src_img)) // ... or save it\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\timagedestroy($src_img);\n\t\timagedestroy($wm_img);\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Watermark - Text Version\n\t *\n\t * @return\tbool\n\t */\n\tpublic function text_watermark()\n\t{\n\t\tif ( ! ($src_img = $this->image_create_gd()))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ($this->wm_use_truetype === TRUE && ! file_exists($this->wm_font_path))\n\t\t{\n\t\t\t$this->set_error('imglib_missing_font');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Fetch source image properties\n\t\t$this->get_image_properties();\n\n\t\t// Reverse the vertical offset\n\t\t// When the image is positioned at the bottom\n\t\t// we don't want the vertical offset to push it\n\t\t// further down. We want the reverse, so we'll\n\t\t// invert the offset. Note: The horizontal\n\t\t// offset flips itself automatically\n\n\t\tif ($this->wm_vrt_alignment === 'B')\n\t\t{\n\t\t\t$this->wm_vrt_offset = $this->wm_vrt_offset * -1;\n\t\t}\n\n\t\tif ($this->wm_hor_alignment === 'R')\n\t\t{\n\t\t\t$this->wm_hor_offset = $this->wm_hor_offset * -1;\n\t\t}\n\n\t\t// Set font width and height\n\t\t// These are calculated differently depending on\n\t\t// whether we are using the true type font or not\n\t\tif ($this->wm_use_truetype === TRUE)\n\t\t{\n\t\t\tif (empty($this->wm_font_size))\n\t\t\t{\n\t\t\t\t$this->wm_font_size = 17;\n\t\t\t}\n\n\t\t\tif (function_exists('imagettfbbox'))\n\t\t\t{\n\t\t\t\t$temp = imagettfbbox($this->wm_font_size, 0, $this->wm_font_path, $this->wm_text);\n\t\t\t\t$temp = $temp[2] - $temp[0];\n\n\t\t\t\t$fontwidth = $temp / strlen($this->wm_text);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$fontwidth = $this->wm_font_size - ($this->wm_font_size / 4);\n\t\t\t}\n\n\t\t\t$fontheight = $this->wm_font_size;\n\t\t\t$this->wm_vrt_offset += $this->wm_font_size;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$fontwidth  = imagefontwidth($this->wm_font_size);\n\t\t\t$fontheight = imagefontheight($this->wm_font_size);\n\t\t}\n\n\t\t// Set base X and Y axis values\n\t\t$x_axis = $this->wm_hor_offset + $this->wm_padding;\n\t\t$y_axis = $this->wm_vrt_offset + $this->wm_padding;\n\n\t\tif ($this->wm_use_drop_shadow === FALSE)\n\t\t{\n\t\t\t$this->wm_shadow_distance = 0;\n\t\t}\n\n\t\t$this->wm_vrt_alignment = strtoupper($this->wm_vrt_alignment[0]);\n\t\t$this->wm_hor_alignment = strtoupper($this->wm_hor_alignment[0]);\n\n\t\t// Set vertical alignment\n\t\tif ($this->wm_vrt_alignment === 'M')\n\t\t{\n\t\t\t$y_axis += ($this->orig_height / 2) + ($fontheight / 2);\n\t\t}\n\t\telseif ($this->wm_vrt_alignment === 'B')\n\t\t{\n\t\t\t$y_axis += $this->orig_height - $fontheight - $this->wm_shadow_distance - ($fontheight / 2);\n\t\t}\n\n\t\t// Set horizontal alignment\n\t\tif ($this->wm_hor_alignment === 'R')\n\t\t{\n\t\t\t$x_axis += $this->orig_width - ($fontwidth * strlen($this->wm_text)) - $this->wm_shadow_distance;\n\t\t}\n\t\telseif ($this->wm_hor_alignment === 'C')\n\t\t{\n\t\t\t$x_axis += floor(($this->orig_width - ($fontwidth * strlen($this->wm_text))) / 2);\n\t\t}\n\n\t\tif ($this->wm_use_drop_shadow)\n\t\t{\n\t\t\t// Offset from text\n\t\t\t$x_shad = $x_axis + $this->wm_shadow_distance;\n\t\t\t$y_shad = $y_axis + $this->wm_shadow_distance;\n\n\t\t\t/* Set RGB values for shadow\n\t\t\t *\n\t\t\t * First character is #, so we don't really need it.\n\t\t\t * Get the rest of the string and split it into 2-length\n\t\t\t * hex values:\n\t\t\t */\n\t\t\t$drp_color = str_split(substr($this->wm_shadow_color, 1, 6), 2);\n\t\t\t$drp_color = imagecolorclosest($src_img, hexdec($drp_color[0]), hexdec($drp_color[1]), hexdec($drp_color[2]));\n\n\t\t\t// Add the shadow to the source image\n\t\t\tif ($this->wm_use_truetype)\n\t\t\t{\n\t\t\t\timagettftext($src_img, $this->wm_font_size, 0, $x_shad, $y_shad, $drp_color, $this->wm_font_path, $this->wm_text);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\timagestring($src_img, $this->wm_font_size, $x_shad, $y_shad, $this->wm_text, $drp_color);\n\t\t\t}\n\t\t}\n\n\t\t/* Set RGB values for text\n\t\t *\n\t\t * First character is #, so we don't really need it.\n\t\t * Get the rest of the string and split it into 2-length\n\t\t * hex values:\n\t\t */\n\t\t$txt_color = str_split(substr($this->wm_font_color, 1, 6), 2);\n\t\t$txt_color = imagecolorclosest($src_img, hexdec($txt_color[0]), hexdec($txt_color[1]), hexdec($txt_color[2]));\n\n\t\t// Add the text to the source image\n\t\tif ($this->wm_use_truetype)\n\t\t{\n\t\t\timagettftext($src_img, $this->wm_font_size, 0, $x_axis, $y_axis, $txt_color, $this->wm_font_path, $this->wm_text);\n\t\t}\n\t\telse\n\t\t{\n\t\t\timagestring($src_img, $this->wm_font_size, $x_axis, $y_axis, $this->wm_text, $txt_color);\n\t\t}\n\n\t\t// We can preserve transparency for PNG images\n\t\tif ($this->image_type === 3)\n\t\t{\n\t\t\timagealphablending($src_img, FALSE);\n\t\t\timagesavealpha($src_img, TRUE);\n\t\t}\n\n\t\t// Output the final image\n\t\tif ($this->dynamic_output === TRUE)\n\t\t{\n\t\t\t$this->image_display_gd($src_img);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->image_save_gd($src_img);\n\t\t}\n\n\t\timagedestroy($src_img);\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Create Image - GD\n\t *\n\t * This simply creates an image resource handle\n\t * based on the type of image being processed\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tresource\n\t */\n\tpublic function image_create_gd($path = '', $image_type = '')\n\t{\n\t\tif ($path === '')\n\t\t{\n\t\t\t$path = $this->full_src_path;\n\t\t}\n\n\t\tif ($image_type === '')\n\t\t{\n\t\t\t$image_type = $this->image_type;\n\t\t}\n\n\t\tswitch ($image_type)\n\t\t{\n\t\t\tcase 1:\n\t\t\t\tif ( ! function_exists('imagecreatefromgif'))\n\t\t\t\t{\n\t\t\t\t\t$this->set_error(array('imglib_unsupported_imagecreate', 'imglib_gif_not_supported'));\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\n\t\t\t\treturn imagecreatefromgif($path);\n\t\t\tcase 2:\n\t\t\t\tif ( ! function_exists('imagecreatefromjpeg'))\n\t\t\t\t{\n\t\t\t\t\t$this->set_error(array('imglib_unsupported_imagecreate', 'imglib_jpg_not_supported'));\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\n\t\t\t\treturn imagecreatefromjpeg($path);\n\t\t\tcase 3:\n\t\t\t\tif ( ! function_exists('imagecreatefrompng'))\n\t\t\t\t{\n\t\t\t\t\t$this->set_error(array('imglib_unsupported_imagecreate', 'imglib_png_not_supported'));\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\n\t\t\t\treturn imagecreatefrompng($path);\n\t\t\tdefault:\n\t\t\t\t$this->set_error(array('imglib_unsupported_imagecreate'));\n\t\t\t\treturn FALSE;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Write image file to disk - GD\n\t *\n\t * Takes an image resource as input and writes the file\n\t * to the specified destination\n\t *\n\t * @param\tresource\n\t * @return\tbool\n\t */\n\tpublic function image_save_gd($resource)\n\t{\n\t\tswitch ($this->image_type)\n\t\t{\n\t\t\tcase 1:\n\t\t\t\tif ( ! function_exists('imagegif'))\n\t\t\t\t{\n\t\t\t\t\t$this->set_error(array('imglib_unsupported_imagecreate', 'imglib_gif_not_supported'));\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\n\t\t\t\tif ( ! @imagegif($resource, $this->full_dst_path))\n\t\t\t\t{\n\t\t\t\t\t$this->set_error('imglib_save_failed');\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tif ( ! function_exists('imagejpeg'))\n\t\t\t\t{\n\t\t\t\t\t$this->set_error(array('imglib_unsupported_imagecreate', 'imglib_jpg_not_supported'));\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\n\t\t\t\tif ( ! @imagejpeg($resource, $this->full_dst_path, $this->quality))\n\t\t\t\t{\n\t\t\t\t\t$this->set_error('imglib_save_failed');\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tif ( ! function_exists('imagepng'))\n\t\t\t\t{\n\t\t\t\t\t$this->set_error(array('imglib_unsupported_imagecreate', 'imglib_png_not_supported'));\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\n\t\t\t\tif ( ! @imagepng($resource, $this->full_dst_path))\n\t\t\t\t{\n\t\t\t\t\t$this->set_error('imglib_save_failed');\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t$this->set_error(array('imglib_unsupported_imagecreate'));\n\t\t\t\treturn FALSE;\n\t\t\tbreak;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Dynamically outputs an image\n\t *\n\t * @param\tresource\n\t * @return\tvoid\n\t */\n\tpublic function image_display_gd($resource)\n\t{\n\t\theader('Content-Disposition: filename='.$this->source_image.';');\n\t\theader('Content-Type: '.$this->mime_type);\n\t\theader('Content-Transfer-Encoding: binary');\n\t\theader('Last-Modified: '.gmdate('D, d M Y H:i:s', time()).' GMT');\n\n\t\tswitch ($this->image_type)\n\t\t{\n\t\t\tcase 1\t:\timagegif($resource);\n\t\t\t\tbreak;\n\t\t\tcase 2\t:\timagejpeg($resource, NULL, $this->quality);\n\t\t\t\tbreak;\n\t\t\tcase 3\t:\timagepng($resource);\n\t\t\t\tbreak;\n\t\t\tdefault:\techo 'Unable to display the image';\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Re-proportion Image Width/Height\n\t *\n\t * When creating thumbs, the desired width/height\n\t * can end up warping the image due to an incorrect\n\t * ratio between the full-sized image and the thumb.\n\t *\n\t * This function lets us re-proportion the width/height\n\t * if users choose to maintain the aspect ratio when resizing.\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function image_reproportion()\n\t{\n\t\tif (($this->width === 0 && $this->height === 0) OR $this->orig_width === 0 OR $this->orig_height === 0\n\t\t\tOR ( ! ctype_digit((string) $this->width) && ! ctype_digit((string) $this->height))\n\t\t\tOR ! ctype_digit((string) $this->orig_width) OR ! ctype_digit((string) $this->orig_height))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\t// Sanitize\n\t\t$this->width = (int) $this->width;\n\t\t$this->height = (int) $this->height;\n\n\t\tif ($this->master_dim !== 'width' && $this->master_dim !== 'height')\n\t\t{\n\t\t\tif ($this->width > 0 && $this->height > 0)\n\t\t\t{\n\t\t\t\t$this->master_dim = ((($this->orig_height/$this->orig_width) - ($this->height/$this->width)) < 0)\n\t\t\t\t\t\t\t? 'width' : 'height';\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$this->master_dim = ($this->height === 0) ? 'width' : 'height';\n\t\t\t}\n\t\t}\n\t\telseif (($this->master_dim === 'width' && $this->width === 0)\n\t\t\tOR ($this->master_dim === 'height' && $this->height === 0))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tif ($this->master_dim === 'width')\n\t\t{\n\t\t\t$this->height = (int) ceil($this->width*$this->orig_height/$this->orig_width);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->width = (int) ceil($this->orig_width*$this->height/$this->orig_height);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get image properties\n\t *\n\t * A helper function that gets info about the file\n\t *\n\t * @param\tstring\n\t * @param\tbool\n\t * @return\tmixed\n\t */\n\tpublic function get_image_properties($path = '', $return = FALSE)\n\t{\n\t\t// For now we require GD but we should\n\t\t// find a way to determine this using IM or NetPBM\n\n\t\tif ($path === '')\n\t\t{\n\t\t\t$path = $this->full_src_path;\n\t\t}\n\n\t\tif ( ! file_exists($path))\n\t\t{\n\t\t\t$this->set_error('imglib_invalid_path');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$vals = getimagesize($path);\n\t\t$types = array(1 => 'gif', 2 => 'jpeg', 3 => 'png');\n\t\t$mime = (isset($types[$vals[2]])) ? 'image/'.$types[$vals[2]] : 'image/jpg';\n\n\t\tif ($return === TRUE)\n\t\t{\n\t\t\treturn array(\n\t\t\t\t\t'width' =>\t$vals[0],\n\t\t\t\t\t'height' =>\t$vals[1],\n\t\t\t\t\t'image_type' =>\t$vals[2],\n\t\t\t\t\t'size_str' =>\t$vals[3],\n\t\t\t\t\t'mime_type' =>\t$mime\n\t\t\t\t);\n\t\t}\n\n\t\t$this->orig_width\t= $vals[0];\n\t\t$this->orig_height\t= $vals[1];\n\t\t$this->image_type\t= $vals[2];\n\t\t$this->size_str\t\t= $vals[3];\n\t\t$this->mime_type\t= $mime;\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Size calculator\n\t *\n\t * This function takes a known width x height and\n\t * recalculates it to a new size. Only one\n\t * new variable needs to be known\n\t *\n\t *\t$props = array(\n\t *\t\t\t'width'\t\t=> $width,\n\t *\t\t\t'height'\t=> $height,\n\t *\t\t\t'new_width'\t=> 40,\n\t *\t\t\t'new_height'\t=> ''\n\t *\t\t);\n\t *\n\t * @param\tarray\n\t * @return\tarray\n\t */\n\tpublic function size_calculator($vals)\n\t{\n\t\tif ( ! is_array($vals))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\t$allowed = array('new_width', 'new_height', 'width', 'height');\n\n\t\tforeach ($allowed as $item)\n\t\t{\n\t\t\tif (empty($vals[$item]))\n\t\t\t{\n\t\t\t\t$vals[$item] = 0;\n\t\t\t}\n\t\t}\n\n\t\tif ($vals['width'] === 0 OR $vals['height'] === 0)\n\t\t{\n\t\t\treturn $vals;\n\t\t}\n\n\t\tif ($vals['new_width'] === 0)\n\t\t{\n\t\t\t$vals['new_width'] = ceil($vals['width']*$vals['new_height']/$vals['height']);\n\t\t}\n\t\telseif ($vals['new_height'] === 0)\n\t\t{\n\t\t\t$vals['new_height'] = ceil($vals['new_width']*$vals['height']/$vals['width']);\n\t\t}\n\n\t\treturn $vals;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Explode source_image\n\t *\n\t * This is a helper function that extracts the extension\n\t * from the source_image.  This function lets us deal with\n\t * source_images with multiple periods, like: my.cool.jpg\n\t * It returns an associative array with two elements:\n\t * $array['ext']  = '.jpg';\n\t * $array['name'] = 'my.cool';\n\t *\n\t * @param\tarray\n\t * @return\tarray\n\t */\n\tpublic function explode_name($source_image)\n\t{\n\t\t$ext = strrchr($source_image, '.');\n\t\t$name = ($ext === FALSE) ? $source_image : substr($source_image, 0, -strlen($ext));\n\n\t\treturn array('ext' => $ext, 'name' => $name);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is GD Installed?\n\t *\n\t * @return\tbool\n\t */\n\tpublic function gd_loaded()\n\t{\n\t\tif ( ! extension_loaded('gd'))\n\t\t{\n\t\t\t/* As it is stated in the PHP manual, dl() is not always available\n\t\t\t * and even if so - it could generate an E_WARNING message on failure\n\t\t\t */\n\t\t\treturn (function_exists('dl') && @dl('gd.so'));\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get GD version\n\t *\n\t * @return\tmixed\n\t */\n\tpublic function gd_version()\n\t{\n\t\tif (function_exists('gd_info'))\n\t\t{\n\t\t\t$gd_version = @gd_info();\n\t\t\treturn preg_replace('/\\D/', '', $gd_version['GD Version']);\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set error message\n\t *\n\t * @param\tstring\n\t * @return\tvoid\n\t */\n\tpublic function set_error($msg)\n\t{\n\t\t$CI =& get_instance();\n\t\t$CI->lang->load('imglib');\n\n\t\tif (is_array($msg))\n\t\t{\n\t\t\tforeach ($msg as $val)\n\t\t\t{\n\t\t\t\t$msg = ($CI->lang->line($val) === FALSE) ? $val : $CI->lang->line($val);\n\t\t\t\t$this->error_msg[] = $msg;\n\t\t\t\tlog_message('error', $msg);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$msg = ($CI->lang->line($msg) === FALSE) ? $msg : $CI->lang->line($msg);\n\t\t\t$this->error_msg[] = $msg;\n\t\t\tlog_message('error', $msg);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show error messages\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function display_errors($open = '<p>', $close = '</p>')\n\t{\n\t\treturn (count($this->error_msg) > 0) ? $open.implode($close.$open, $this->error_msg).$close : '';\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/Javascript/Jquery.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Jquery Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLoader\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/javascript.html\n */\nclass CI_Jquery extends CI_Javascript {\n\n\t/**\n\t * JavaScript directory location\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_javascript_folder = 'js';\n\n\t/**\n\t * JQuery code for load\n\t *\n\t * @var\tarray\n\t */\n\tpublic $jquery_code_for_load = array();\n\n\t/**\n\t * JQuery code for compile\n\t *\n\t * @var\tarray\n\t */\n\tpublic $jquery_code_for_compile = array();\n\n\t/**\n\t * JQuery corner active flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $jquery_corner_active = FALSE;\n\n\t/**\n\t * JQuery table sorter active flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $jquery_table_sorter_active = FALSE;\n\n\t/**\n\t * JQuery table sorter pager active\n\t *\n\t * @var\tbool\n\t */\n\tpublic $jquery_table_sorter_pager_active = FALSE;\n\n\t/**\n\t * JQuery AJAX image\n\t *\n\t * @var\tstring\n\t */\n\tpublic $jquery_ajax_img = '';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params)\n\t{\n\t\t$this->CI =& get_instance();\n\t\textract($params);\n\n\t\tif ($autoload === TRUE)\n\t\t{\n\t\t\t$this->script();\n\t\t}\n\n\t\tlog_message('info', 'Jquery Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\t// Event Code\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Blur\n\t *\n\t * Outputs a jQuery blur event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _blur($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'blur');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Change\n\t *\n\t * Outputs a jQuery change event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _change($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'change');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Click\n\t *\n\t * Outputs a jQuery click event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @param\tbool\twhether or not to return false\n\t * @return\tstring\n\t */\n\tprotected function _click($element = 'this', $js = '', $ret_false = TRUE)\n\t{\n\t\tis_array($js) OR $js = array($js);\n\n\t\tif ($ret_false)\n\t\t{\n\t\t\t$js[] = 'return false;';\n\t\t}\n\n\t\treturn $this->_add_event($element, $js, 'click');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Double Click\n\t *\n\t * Outputs a jQuery dblclick event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _dblclick($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'dblclick');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Error\n\t *\n\t * Outputs a jQuery error event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _error($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'error');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Focus\n\t *\n\t * Outputs a jQuery focus event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _focus($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'focus');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Hover\n\t *\n\t * Outputs a jQuery hover event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- Javascript code for mouse over\n\t * @param\tstring\t- Javascript code for mouse out\n\t * @return\tstring\n\t */\n\tprotected function _hover($element = 'this', $over = '', $out = '')\n\t{\n\t\t$event = \"\\n\\t$(\".$this->_prep_element($element).\").hover(\\n\\t\\tfunction()\\n\\t\\t{\\n\\t\\t\\t{$over}\\n\\t\\t}, \\n\\t\\tfunction()\\n\\t\\t{\\n\\t\\t\\t{$out}\\n\\t\\t});\\n\";\n\n\t\t$this->jquery_code_for_compile[] = $event;\n\n\t\treturn $event;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Keydown\n\t *\n\t * Outputs a jQuery keydown event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _keydown($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'keydown');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Keyup\n\t *\n\t * Outputs a jQuery keydown event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _keyup($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'keyup');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Load\n\t *\n\t * Outputs a jQuery load event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _load($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'load');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Mousedown\n\t *\n\t * Outputs a jQuery mousedown event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _mousedown($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'mousedown');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Mouse Out\n\t *\n\t * Outputs a jQuery mouseout event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _mouseout($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'mouseout');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Mouse Over\n\t *\n\t * Outputs a jQuery mouseover event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _mouseover($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'mouseover');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Mouseup\n\t *\n\t * Outputs a jQuery mouseup event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _mouseup($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'mouseup');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Output\n\t *\n\t * Outputs script directly\n\t *\n\t * @param\tarray\t$array_js = array()\n\t * @return\tvoid\n\t */\n\tprotected function _output($array_js = array())\n\t{\n\t\tif ( ! is_array($array_js))\n\t\t{\n\t\t\t$array_js = array($array_js);\n\t\t}\n\n\t\tforeach ($array_js as $js)\n\t\t{\n\t\t\t$this->jquery_code_for_compile[] = \"\\t\".$js.\"\\n\";\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Resize\n\t *\n\t * Outputs a jQuery resize event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _resize($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'resize');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Scroll\n\t *\n\t * Outputs a jQuery scroll event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _scroll($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'scroll');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Unload\n\t *\n\t * Outputs a jQuery unload event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tprotected function _unload($element = 'this', $js = '')\n\t{\n\t\treturn $this->_add_event($element, $js, 'unload');\n\t}\n\n\t// --------------------------------------------------------------------\n\t// Effects\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add Class\n\t *\n\t * Outputs a jQuery addClass event\n\t *\n\t * @param\tstring\t$element\n\t * @param\tstring\t$class\n\t * @return\tstring\n\t */\n\tprotected function _addClass($element = 'this', $class = '')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\treturn '$('.$element.').addClass(\"'.$class.'\");';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Animate\n\t *\n\t * Outputs a jQuery animate event\n\t *\n\t * @param\tstring\t$element\n\t * @param\tarray\t$params\n\t * @param\tstring\t$speed\t'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t$extra\n\t * @return\tstring\n\t */\n\tprotected function _animate($element = 'this', $params = array(), $speed = '', $extra = '')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\t$speed = $this->_validate_speed($speed);\n\n\t\t$animations = \"\\t\\t\\t\";\n\n\t\tforeach ($params as $param => $value)\n\t\t{\n\t\t\t$animations .= $param.\": '\".$value.\"', \";\n\t\t}\n\n\t\t$animations = substr($animations, 0, -2); // remove the last \", \"\n\n\t\tif ($speed !== '')\n\t\t{\n\t\t\t$speed = ', '.$speed;\n\t\t}\n\n\t\tif ($extra !== '')\n\t\t{\n\t\t\t$extra = ', '.$extra;\n\t\t}\n\n\t\treturn \"$({$element}).animate({\\n$animations\\n\\t\\t}\".$speed.$extra.');';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fade In\n\t *\n\t * Outputs a jQuery hide event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tprotected function _fadeIn($element = 'this', $speed = '', $callback = '')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\t$speed = $this->_validate_speed($speed);\n\n\t\tif ($callback !== '')\n\t\t{\n\t\t\t$callback = \", function(){\\n{$callback}\\n}\";\n\t\t}\n\n\t\treturn \"$({$element}).fadeIn({$speed}{$callback});\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fade Out\n\t *\n\t * Outputs a jQuery hide event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tprotected function _fadeOut($element = 'this', $speed = '', $callback = '')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\t$speed = $this->_validate_speed($speed);\n\n\t\tif ($callback !== '')\n\t\t{\n\t\t\t$callback = \", function(){\\n{$callback}\\n}\";\n\t\t}\n\n\t\treturn '$('.$element.').fadeOut('.$speed.$callback.');';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Hide\n\t *\n\t * Outputs a jQuery hide action\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tprotected function _hide($element = 'this', $speed = '', $callback = '')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\t$speed = $this->_validate_speed($speed);\n\n\t\tif ($callback !== '')\n\t\t{\n\t\t\t$callback = \", function(){\\n{$callback}\\n}\";\n\t\t}\n\n\t\treturn \"$({$element}).hide({$speed}{$callback});\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Remove Class\n\t *\n\t * Outputs a jQuery remove class event\n\t *\n\t * @param\tstring\t$element\n\t * @param\tstring\t$class\n\t * @return\tstring\n\t */\n\tprotected function _removeClass($element = 'this', $class = '')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\treturn '$('.$element.').removeClass(\"'.$class.'\");';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Slide Up\n\t *\n\t * Outputs a jQuery slideUp event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tprotected function _slideUp($element = 'this', $speed = '', $callback = '')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\t$speed = $this->_validate_speed($speed);\n\n\t\tif ($callback !== '')\n\t\t{\n\t\t\t$callback = \", function(){\\n{$callback}\\n}\";\n\t\t}\n\n\t\treturn '$('.$element.').slideUp('.$speed.$callback.');';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Slide Down\n\t *\n\t * Outputs a jQuery slideDown event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tprotected function _slideDown($element = 'this', $speed = '', $callback = '')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\t$speed = $this->_validate_speed($speed);\n\n\t\tif ($callback !== '')\n\t\t{\n\t\t\t$callback = \", function(){\\n{$callback}\\n}\";\n\t\t}\n\n\t\treturn '$('.$element.').slideDown('.$speed.$callback.');';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Slide Toggle\n\t *\n\t * Outputs a jQuery slideToggle event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tprotected function _slideToggle($element = 'this', $speed = '', $callback = '')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\t$speed = $this->_validate_speed($speed);\n\n\t\tif ($callback !== '')\n\t\t{\n\t\t\t$callback = \", function(){\\n{$callback}\\n}\";\n\t\t}\n\n\t\treturn '$('.$element.').slideToggle('.$speed.$callback.');';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Toggle\n\t *\n\t * Outputs a jQuery toggle event\n\t *\n\t * @param\tstring\t- element\n\t * @return\tstring\n\t */\n\tprotected function _toggle($element = 'this')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\treturn '$('.$element.').toggle();';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Toggle Class\n\t *\n\t * Outputs a jQuery toggle class event\n\t *\n\t * @param\tstring\t$element\n\t * @param\tstring\t$class\n\t * @return\tstring\n\t */\n\tprotected function _toggleClass($element = 'this', $class = '')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\treturn '$('.$element.').toggleClass(\"'.$class.'\");';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show\n\t *\n\t * Outputs a jQuery show event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tprotected function _show($element = 'this', $speed = '', $callback = '')\n\t{\n\t\t$element = $this->_prep_element($element);\n\t\t$speed = $this->_validate_speed($speed);\n\n\t\tif ($callback !== '')\n\t\t{\n\t\t\t$callback = \", function(){\\n{$callback}\\n}\";\n\t\t}\n\n\t\treturn '$('.$element.').show('.$speed.$callback.');';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Updater\n\t *\n\t * An Ajax call that populates the designated DOM node with\n\t * returned content\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tthe controller to run the call against\n\t * @param\tstring\toptional parameters\n\t * @return\tstring\n\t */\n\n\tprotected function _updater($container = 'this', $controller = '', $options = '')\n\t{\n\t\t$container = $this->_prep_element($container);\n\t\t$controller = (strpos('://', $controller) === FALSE) ? $controller : $this->CI->config->site_url($controller);\n\n\t\t// ajaxStart and ajaxStop are better choices here... but this is a stop gap\n\t\tif ($this->CI->config->item('javascript_ajax_img') === '')\n\t\t{\n\t\t\t$loading_notifier = 'Loading...';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$loading_notifier = '<img src=\"'.$this->CI->config->slash_item('base_url').$this->CI->config->item('javascript_ajax_img').'\" alt=\"Loading\" />';\n\t\t}\n\n\t\t$updater = '$('.$container.\").empty();\\n\" // anything that was in... get it out\n\t\t\t.\"\\t\\t$(\".$container.').prepend(\"'.$loading_notifier.\"\\\");\\n\"; // to replace with an image\n\n\t\t$request_options = '';\n\t\tif ($options !== '')\n\t\t{\n\t\t\t$request_options .= ', {'\n\t\t\t\t\t.(is_array($options) ? \"'\".implode(\"', '\", $options).\"'\" : \"'\".str_replace(':', \"':'\", $options).\"'\")\n\t\t\t\t\t.'}';\n\t\t}\n\n\t\treturn $updater.\"\\t\\t$($container).load('$controller'$request_options);\";\n\t}\n\n\t// --------------------------------------------------------------------\n\t// Pre-written handy stuff\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Zebra tables\n\t *\n\t * @param\tstring\t$class\n\t * @param\tstring\t$odd\n\t * @param\tstring\t$hover\n\t * @return\tstring\n\t */\n\tprotected function _zebraTables($class = '', $odd = 'odd', $hover = '')\n\t{\n\t\t$class = ($class !== '') ? '.'.$class : '';\n\t\t$zebra = \"\\t\\$(\\\"table{$class} tbody tr:nth-child(even)\\\").addClass(\\\"{$odd}\\\");\";\n\n\t\t$this->jquery_code_for_compile[] = $zebra;\n\n\t\tif ($hover !== '')\n\t\t{\n\t\t\t$hover = $this->hover(\"table{$class} tbody tr\", \"$(this).addClass('hover');\", \"$(this).removeClass('hover');\");\n\t\t}\n\n\t\treturn $zebra;\n\t}\n\n\t// --------------------------------------------------------------------\n\t// Plugins\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Corner Plugin\n\t *\n\t * @link\thttp://www.malsup.com/jquery/corner/\n\t * @param\tstring\t$element\n\t * @param\tstring\t$corner_style\n\t * @return\tstring\n\t */\n\tpublic function corner($element = '', $corner_style = '')\n\t{\n\t\t// may want to make this configurable down the road\n\t\t$corner_location = '/plugins/jquery.corner.js';\n\n\t\tif ($corner_style !== '')\n\t\t{\n\t\t\t$corner_style = '\"'.$corner_style.'\"';\n\t\t}\n\n\t\treturn '$('.$this->_prep_element($element).').corner('.$corner_style.');';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Modal window\n\t *\n\t * Load a thickbox modal window\n\t *\n\t * @param\tstring\t$src\n\t * @param\tbool\t$relative\n\t * @return\tvoid\n\t */\n\tpublic function modal($src, $relative = FALSE)\n\t{\n\t\t$this->jquery_code_for_load[] = $this->external($src, $relative);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Effect\n\t *\n\t * Load an Effect library\n\t *\n\t * @param\tstring\t$src\n\t * @param\tbool\t$relative\n\t * @return\tvoid\n\t */\n\tpublic function effect($src, $relative = FALSE)\n\t{\n\t\t$this->jquery_code_for_load[] = $this->external($src, $relative);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Plugin\n\t *\n\t * Load a plugin library\n\t *\n\t * @param\tstring\t$src\n\t * @param\tbool\t$relative\n\t * @return\tvoid\n\t */\n\tpublic function plugin($src, $relative = FALSE)\n\t{\n\t\t$this->jquery_code_for_load[] = $this->external($src, $relative);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * UI\n\t *\n\t * Load a user interface library\n\t *\n\t * @param\tstring\t$src\n\t * @param\tbool\t$relative\n\t * @return\tvoid\n\t */\n\tpublic function ui($src, $relative = FALSE)\n\t{\n\t\t$this->jquery_code_for_load[] = $this->external($src, $relative);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Sortable\n\t *\n\t * Creates a jQuery sortable\n\t *\n\t * @param\tstring\t$element\n\t * @param\tarray\t$options\n\t * @return\tstring\n\t */\n\tpublic function sortable($element, $options = array())\n\t{\n\t\tif (count($options) > 0)\n\t\t{\n\t\t\t$sort_options = array();\n\t\t\tforeach ($options as $k=>$v)\n\t\t\t{\n\t\t\t\t$sort_options[] = \"\\n\\t\\t\".$k.': '.$v;\n\t\t\t}\n\t\t\t$sort_options = implode(',', $sort_options);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$sort_options = '';\n\t\t}\n\n\t\treturn '$('.$this->_prep_element($element).').sortable({'.$sort_options.\"\\n\\t});\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Table Sorter Plugin\n\t *\n\t * @param\tstring\ttable name\n\t * @param\tstring\tplugin location\n\t * @return\tstring\n\t */\n\tpublic function tablesorter($table = '', $options = '')\n\t{\n\t\t$this->jquery_code_for_compile[] = \"\\t$(\".$this->_prep_element($table).').tablesorter('.$options.\");\\n\";\n\t}\n\n\t// --------------------------------------------------------------------\n\t// Class functions\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add Event\n\t *\n\t * Constructs the syntax for an event, and adds to into the array for compilation\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @param\tstring\tThe event to pass\n\t * @return\tstring\n\t */\n\tprotected function _add_event($element, $js, $event)\n\t{\n\t\tif (is_array($js))\n\t\t{\n\t\t\t$js = implode(\"\\n\\t\\t\", $js);\n\t\t}\n\n\t\t$event = \"\\n\\t$(\".$this->_prep_element($element).').'.$event.\"(function(){\\n\\t\\t{$js}\\n\\t});\\n\";\n\t\t$this->jquery_code_for_compile[] = $event;\n\t\treturn $event;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile\n\t *\n\t * As events are specified, they are stored in an array\n\t * This function compiles them all for output on a page\n\t *\n\t * @param\tstring\t$view_var\n\t * @param\tbool\t$script_tags\n\t * @return\tvoid\n\t */\n\tprotected function _compile($view_var = 'script_foot', $script_tags = TRUE)\n\t{\n\t\t// External references\n\t\t$external_scripts = implode('', $this->jquery_code_for_load);\n\t\t$this->CI->load->vars(array('library_src' => $external_scripts));\n\n\t\tif (count($this->jquery_code_for_compile) === 0)\n\t\t{\n\t\t\t// no inline references, let's just return\n\t\t\treturn;\n\t\t}\n\n\t\t// Inline references\n\t\t$script = '$(document).ready(function() {'.\"\\n\"\n\t\t\t.implode('', $this->jquery_code_for_compile)\n\t\t\t.'});';\n\n\t\t$output = ($script_tags === FALSE) ? $script : $this->inline($script);\n\n\t\t$this->CI->load->vars(array($view_var => $output));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Clear Compile\n\t *\n\t * Clears the array of script events collected for output\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _clear_compile()\n\t{\n\t\t$this->jquery_code_for_compile = array();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Document Ready\n\t *\n\t * A wrapper for writing document.ready()\n\t *\n\t * @param\tarray\t$js\n\t * @return\tvoid\n\t */\n\tprotected function _document_ready($js)\n\t{\n\t\tis_array($js) OR $js = array($js);\n\n\t\tforeach ($js as $script)\n\t\t{\n\t\t\t$this->jquery_code_for_compile[] = $script;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Script Tag\n\t *\n\t * Outputs the script tag that loads the jquery.js file into an HTML document\n\t *\n\t * @param\tstring\t$library_src\n\t * @param\tbool\t$relative\n\t * @return\tstring\n\t */\n\tpublic function script($library_src = '', $relative = FALSE)\n\t{\n\t\t$library_src = $this->external($library_src, $relative);\n\t\t$this->jquery_code_for_load[] = $library_src;\n\t\treturn $library_src;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prep Element\n\t *\n\t * Puts HTML element in quotes for use in jQuery code\n\t * unless the supplied element is the Javascript 'this'\n\t * object, in which case no quotes are added\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _prep_element($element)\n\t{\n\t\tif ($element !== 'this')\n\t\t{\n\t\t\t$element = '\"'.$element.'\"';\n\t\t}\n\n\t\treturn $element;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Validate Speed\n\t *\n\t * Ensures the speed parameter is valid for jQuery\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _validate_speed($speed)\n\t{\n\t\tif (in_array($speed, array('slow', 'normal', 'fast')))\n\t\t{\n\t\t\treturn '\"'.$speed.'\"';\n\t\t}\n\t\telseif (preg_match('/[^0-9]/', $speed))\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\treturn $speed;\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/Javascript/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/libraries/Javascript.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Javascript Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tJavascript\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/javascript.html\n * @deprecated\t3.0.0\tThis was never a good idea in the first place.\n */\nclass CI_Javascript {\n\n\t/**\n\t * JavaScript location\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_javascript_location = 'js';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @param\tarray\t$params\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params = array())\n\t{\n\t\t$defaults = array('js_library_driver' => 'jquery', 'autoload' => TRUE);\n\n\t\tforeach ($defaults as $key => $val)\n\t\t{\n\t\t\tif (isset($params[$key]) && $params[$key] !== '')\n\t\t\t{\n\t\t\t\t$defaults[$key] = $params[$key];\n\t\t\t}\n\t\t}\n\n\t\textract($defaults);\n\n\t\t$this->CI =& get_instance();\n\n\t\t// load the requested js library\n\t\t$this->CI->load->library('Javascript/'.$js_library_driver, array('autoload' => $autoload));\n\t\t// make js to refer to current library\n\t\t$this->js =& $this->CI->$js_library_driver;\n\n\t\tlog_message('info', 'Javascript Class Initialized and loaded. Driver used: '.$js_library_driver);\n\t}\n\n\t// --------------------------------------------------------------------\n\t// Event Code\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Blur\n\t *\n\t * Outputs a javascript library blur event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function blur($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_blur($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Change\n\t *\n\t * Outputs a javascript library change event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function change($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_change($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Click\n\t *\n\t * Outputs a javascript library click event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @param\tbool\twhether or not to return false\n\t * @return\tstring\n\t */\n\tpublic function click($element = 'this', $js = '', $ret_false = TRUE)\n\t{\n\t\treturn $this->js->_click($element, $js, $ret_false);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Double Click\n\t *\n\t * Outputs a javascript library dblclick event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function dblclick($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_dblclick($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Error\n\t *\n\t * Outputs a javascript library error event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function error($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_error($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Focus\n\t *\n\t * Outputs a javascript library focus event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function focus($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_focus($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Hover\n\t *\n\t * Outputs a javascript library hover event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- Javascript code for mouse over\n\t * @param\tstring\t- Javascript code for mouse out\n\t * @return\tstring\n\t */\n\tpublic function hover($element = 'this', $over = '', $out = '')\n\t{\n\t\treturn $this->js->_hover($element, $over, $out);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Keydown\n\t *\n\t * Outputs a javascript library keydown event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function keydown($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_keydown($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Keyup\n\t *\n\t * Outputs a javascript library keydown event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function keyup($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_keyup($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Load\n\t *\n\t * Outputs a javascript library load event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function load($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_load($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Mousedown\n\t *\n\t * Outputs a javascript library mousedown event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function mousedown($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_mousedown($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Mouse Out\n\t *\n\t * Outputs a javascript library mouseout event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function mouseout($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_mouseout($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Mouse Over\n\t *\n\t * Outputs a javascript library mouseover event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function mouseover($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_mouseover($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Mouseup\n\t *\n\t * Outputs a javascript library mouseup event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function mouseup($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_mouseup($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Output\n\t *\n\t * Outputs the called javascript to the screen\n\t *\n\t * @param\tstring\tThe code to output\n\t * @return\tstring\n\t */\n\tpublic function output($js)\n\t{\n\t\treturn $this->js->_output($js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Ready\n\t *\n\t * Outputs a javascript library mouseup event\n\t *\n\t * @param\tstring\t$js\tCode to execute\n\t * @return\tstring\n\t */\n\tpublic function ready($js)\n\t{\n\t\treturn $this->js->_document_ready($js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Resize\n\t *\n\t * Outputs a javascript library resize event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function resize($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_resize($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Scroll\n\t *\n\t * Outputs a javascript library scroll event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function scroll($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_scroll($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Unload\n\t *\n\t * Outputs a javascript library unload event\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tstring\tThe code to execute\n\t * @return\tstring\n\t */\n\tpublic function unload($element = 'this', $js = '')\n\t{\n\t\treturn $this->js->_unload($element, $js);\n\t}\n\n\t// --------------------------------------------------------------------\n\t// Effects\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add Class\n\t *\n\t * Outputs a javascript library addClass event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- Class to add\n\t * @return\tstring\n\t */\n\tpublic function addClass($element = 'this', $class = '')\n\t{\n\t\treturn $this->js->_addClass($element, $class);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Animate\n\t *\n\t * Outputs a javascript library animate event\n\t *\n\t * @param\tstring\t$element = 'this'\n\t * @param\tarray\t$params = array()\n\t * @param\tmixed\t$speed\t\t\t'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t$extra\n\t * @return\tstring\n\t */\n\tpublic function animate($element = 'this', $params = array(), $speed = '', $extra = '')\n\t{\n\t\treturn $this->js->_animate($element, $params, $speed, $extra);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fade In\n\t *\n\t * Outputs a javascript library hide event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tpublic function fadeIn($element = 'this', $speed = '', $callback = '')\n\t{\n\t\treturn $this->js->_fadeIn($element, $speed, $callback);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fade Out\n\t *\n\t * Outputs a javascript library hide event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tpublic function fadeOut($element = 'this', $speed = '', $callback = '')\n\t{\n\t\treturn $this->js->_fadeOut($element, $speed, $callback);\n\t}\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Slide Up\n\t *\n\t * Outputs a javascript library slideUp event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tpublic function slideUp($element = 'this', $speed = '', $callback = '')\n\t{\n\t\treturn $this->js->_slideUp($element, $speed, $callback);\n\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Remove Class\n\t *\n\t * Outputs a javascript library removeClass event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- Class to add\n\t * @return\tstring\n\t */\n\tpublic function removeClass($element = 'this', $class = '')\n\t{\n\t\treturn $this->js->_removeClass($element, $class);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Slide Down\n\t *\n\t * Outputs a javascript library slideDown event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tpublic function slideDown($element = 'this', $speed = '', $callback = '')\n\t{\n\t\treturn $this->js->_slideDown($element, $speed, $callback);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Slide Toggle\n\t *\n\t * Outputs a javascript library slideToggle event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tpublic function slideToggle($element = 'this', $speed = '', $callback = '')\n\t{\n\t\treturn $this->js->_slideToggle($element, $speed, $callback);\n\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Hide\n\t *\n\t * Outputs a javascript library hide action\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tpublic function hide($element = 'this', $speed = '', $callback = '')\n\t{\n\t\treturn $this->js->_hide($element, $speed, $callback);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Toggle\n\t *\n\t * Outputs a javascript library toggle event\n\t *\n\t * @param\tstring\t- element\n\t * @return\tstring\n\t */\n\tpublic function toggle($element = 'this')\n\t{\n\t\treturn $this->js->_toggle($element);\n\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Toggle Class\n\t *\n\t * Outputs a javascript library toggle class event\n\t *\n\t * @param\tstring\t$element = 'this'\n\t * @param\tstring\t$class = ''\n\t * @return\tstring\n\t */\n\tpublic function toggleClass($element = 'this', $class = '')\n\t{\n\t\treturn $this->js->_toggleClass($element, $class);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show\n\t *\n\t * Outputs a javascript library show event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tpublic function show($element = 'this', $speed = '', $callback = '')\n\t{\n\t\treturn $this->js->_show($element, $speed, $callback);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile\n\t *\n\t * gather together all script needing to be output\n\t *\n\t * @param\tstring\t$view_var\n\t * @param\tbool\t$script_tags\n\t * @return\tstring\n\t */\n\tpublic function compile($view_var = 'script_foot', $script_tags = TRUE)\n\t{\n\t\t$this->js->_compile($view_var, $script_tags);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Clear Compile\n\t *\n\t * Clears any previous javascript collected for output\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function clear_compile()\n\t{\n\t\t$this->js->_clear_compile();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * External\n\t *\n\t * Outputs a <script> tag with the source as an external js file\n\t *\n\t * @param\tstring\t$external_file\n\t * @param\tbool\t$relative\n\t * @return\tstring\n\t */\n\tpublic function external($external_file = '', $relative = FALSE)\n\t{\n\t\tif ($external_file !== '')\n\t\t{\n\t\t\t$this->_javascript_location = $external_file;\n\t\t}\n\t\telseif ($this->CI->config->item('javascript_location') !== '')\n\t\t{\n\t\t\t$this->_javascript_location = $this->CI->config->item('javascript_location');\n\t\t}\n\n\t\tif ($relative === TRUE OR strpos($external_file, 'http://') === 0 OR strpos($external_file, 'https://') === 0)\n\t\t{\n\t\t\t$str = $this->_open_script($external_file);\n\t\t}\n\t\telseif (strpos($this->_javascript_location, 'http://') !== FALSE)\n\t\t{\n\t\t\t$str = $this->_open_script($this->_javascript_location.$external_file);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$str = $this->_open_script($this->CI->config->slash_item('base_url').$this->_javascript_location.$external_file);\n\t\t}\n\n\t\treturn $str.$this->_close_script();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Inline\n\t *\n\t * Outputs a <script> tag\n\t *\n\t * @param\tstring\tThe element to attach the event to\n\t * @param\tbool\tIf a CDATA section should be added\n\t * @return\tstring\n\t */\n\tpublic function inline($script, $cdata = TRUE)\n\t{\n\t\treturn $this->_open_script()\n\t\t\t. ($cdata ? \"\\n// <![CDATA[\\n\".$script.\"\\n// ]]>\\n\" : \"\\n\".$script.\"\\n\")\n\t\t\t. $this->_close_script();\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Open Script\n\t *\n\t * Outputs an opening <script>\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _open_script($src = '')\n\t{\n\t\treturn '<script type=\"text/javascript\" charset=\"'.strtolower($this->CI->config->item('charset')).'\"'\n\t\t\t.($src === '' ? '>' : ' src=\"'.$src.'\">');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Close Script\n\t *\n\t * Outputs an closing </script>\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _close_script($extra = \"\\n\")\n\t{\n\t\treturn '</script>'.$extra;\n\t}\n\n\t// --------------------------------------------------------------------\n\t// AJAX-Y STUFF - still a testbed\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Update\n\t *\n\t * Outputs a javascript library slideDown event\n\t *\n\t * @param\tstring\t- element\n\t * @param\tstring\t- One of 'slow', 'normal', 'fast', or time in milliseconds\n\t * @param\tstring\t- Javascript callback function\n\t * @return\tstring\n\t */\n\tpublic function update($element = 'this', $speed = '', $callback = '')\n\t{\n\t\treturn $this->js->_updater($element, $speed, $callback);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Generate JSON\n\t *\n\t * Can be passed a database result or associative array and returns a JSON formatted string\n\t *\n\t * @param\tmixed\tresult set or array\n\t * @param\tbool\tmatch array types (defaults to objects)\n\t * @return\tstring\ta json formatted string\n\t */\n\tpublic function generate_json($result = NULL, $match_array_type = FALSE)\n\t{\n\t\t// JSON data can optionally be passed to this function\n\t\t// either as a database result object or an array, or a user supplied array\n\t\tif ($result !== NULL)\n\t\t{\n\t\t\tif (is_object($result))\n\t\t\t{\n\t\t\t\t$json_result = is_callable(array($result, 'result_array')) ? $result->result_array() : (array) $result;\n\t\t\t}\n\t\t\telseif (is_array($result))\n\t\t\t{\n\t\t\t\t$json_result = $result;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn $this->_prep_args($result);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn 'null';\n\t\t}\n\n\t\t$json = array();\n\t\t$_is_assoc = TRUE;\n\n\t\tif ( ! is_array($json_result) && empty($json_result))\n\t\t{\n\t\t\tshow_error('Generate JSON Failed - Illegal key, value pair.');\n\t\t}\n\t\telseif ($match_array_type)\n\t\t{\n\t\t\t$_is_assoc = $this->_is_associative_array($json_result);\n\t\t}\n\n\t\tforeach ($json_result as $k => $v)\n\t\t{\n\t\t\tif ($_is_assoc)\n\t\t\t{\n\t\t\t\t$json[] = $this->_prep_args($k, TRUE).':'.$this->generate_json($v, $match_array_type);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$json[] = $this->generate_json($v, $match_array_type);\n\t\t\t}\n\t\t}\n\n\t\t$json = implode(',', $json);\n\n\t\treturn $_is_assoc ? '{'.$json.'}' : '['.$json.']';\n\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is associative array\n\t *\n\t * Checks for an associative array\n\t *\n\t * @param\tarray\n\t * @return\tbool\n\t */\n\tprotected function _is_associative_array($arr)\n\t{\n\t\tforeach (array_keys($arr) as $key => $val)\n\t\t{\n\t\t\tif ($key !== $val)\n\t\t\t{\n\t\t\t\treturn TRUE;\n\t\t\t}\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prep Args\n\t *\n\t * Ensures a standard json value and escapes values\n\t *\n\t * @param\tmixed\t$result\n\t * @param\tbool\t$is_key = FALSE\n\t * @return\tstring\n\t */\n\tprotected function _prep_args($result, $is_key = FALSE)\n\t{\n\t\tif ($result === NULL)\n\t\t{\n\t\t\treturn 'null';\n\t\t}\n\t\telseif (is_bool($result))\n\t\t{\n\t\t\treturn ($result === TRUE) ? 'true' : 'false';\n\t\t}\n\t\telseif (is_string($result) OR $is_key)\n\t\t{\n\t\t\treturn '\"'.str_replace(array('\\\\', \"\\t\", \"\\n\", \"\\r\", '\"', '/'), array('\\\\\\\\', '\\\\t', '\\\\n', \"\\\\r\", '\\\"', '\\/'), $result).'\"';\n\t\t}\n\t\telseif (is_scalar($result))\n\t\t{\n\t\t\treturn $result;\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/Migration.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Migration Class\n *\n * All migrations should implement this, forces up() and down() and gives\n * access to the CI super-global.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tReactor Engineers\n * @link\n */\nclass CI_Migration {\n\n\t/**\n\t * Whether the library is enabled\n\t *\n\t * @var bool\n\t */\n\tprotected $_migration_enabled = FALSE;\n\n\t/**\n\t * Migration numbering type\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_migration_type = 'sequential';\n\n\t/**\n\t * Path to migration classes\n\t *\n\t * @var string\n\t */\n\tprotected $_migration_path = NULL;\n\n\t/**\n\t * Current migration version\n\t *\n\t * @var mixed\n\t */\n\tprotected $_migration_version = 0;\n\n\t/**\n\t * Database table with migration info\n\t *\n\t * @var string\n\t */\n\tprotected $_migration_table = 'migrations';\n\n\t/**\n\t * Whether to automatically run migrations\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_migration_auto_latest = FALSE;\n\n\t/**\n\t * Migration basename regex\n\t *\n\t * @var string\n\t */\n\tprotected $_migration_regex;\n\n\t/**\n\t * Error message\n\t *\n\t * @var string\n\t */\n\tprotected $_error_string = '';\n\n\t/**\n\t * Initialize Migration Class\n\t *\n\t * @param\tarray\t$config\n\t * @return\tvoid\n\t */\n\tpublic function __construct($config = array())\n\t{\n\t\t// Only run this constructor on main library load\n\t\tif ( ! in_array(get_class($this), array('CI_Migration', config_item('subclass_prefix').'Migration'), TRUE))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tforeach ($config as $key => $val)\n\t\t{\n\t\t\t$this->{'_'.$key} = $val;\n\t\t}\n\n\t\tlog_message('info', 'Migrations Class Initialized');\n\n\t\t// Are they trying to use migrations while it is disabled?\n\t\tif ($this->_migration_enabled !== TRUE)\n\t\t{\n\t\t\tshow_error('Migrations has been loaded but is disabled or set up incorrectly.');\n\t\t}\n\n\t\t// If not set, set it\n\t\t$this->_migration_path !== '' OR $this->_migration_path = APPPATH.'migrations/';\n\n\t\t// Add trailing slash if not set\n\t\t$this->_migration_path = rtrim($this->_migration_path, '/').'/';\n\n\t\t// Load migration language\n\t\t$this->lang->load('migration');\n\n\t\t// They'll probably be using dbforge\n\t\t$this->load->dbforge();\n\n\t\t// Make sure the migration table name was set.\n\t\tif (empty($this->_migration_table))\n\t\t{\n\t\t\tshow_error('Migrations configuration file (migration.php) must have \"migration_table\" set.');\n\t\t}\n\n\t\t// Migration basename regex\n\t\t$this->_migration_regex = ($this->_migration_type === 'timestamp')\n\t\t\t? '/^\\d{14}_(\\w+)$/'\n\t\t\t: '/^\\d{3}_(\\w+)$/';\n\n\t\t// Make sure a valid migration numbering type was set.\n\t\tif ( ! in_array($this->_migration_type, array('sequential', 'timestamp')))\n\t\t{\n\t\t\tshow_error('An invalid migration numbering type was specified: '.$this->_migration_type);\n\t\t}\n\n\t\t// If the migrations table is missing, make it\n\t\tif ( ! $this->db->table_exists($this->_migration_table))\n\t\t{\n\t\t\t$this->dbforge->add_field(array(\n\t\t\t\t'version' => array('type' => 'BIGINT', 'constraint' => 20),\n\t\t\t));\n\n\t\t\t$this->dbforge->create_table($this->_migration_table, TRUE);\n\n\t\t\t$this->db->insert($this->_migration_table, array('version' => 0));\n\t\t}\n\n\t\t// Do we auto migrate to the latest migration?\n\t\tif ($this->_migration_auto_latest === TRUE && ! $this->latest())\n\t\t{\n\t\t\tshow_error($this->error_string());\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Migrate to a schema version\n\t *\n\t * Calls each migration step required to get to the schema version of\n\t * choice\n\t *\n\t * @param\tstring\t$target_version\tTarget schema version\n\t * @return\tmixed\tTRUE if no migrations are found, current version string on success, FALSE on failure\n\t */\n\tpublic function version($target_version)\n\t{\n\t\t// Note: We use strings, so that timestamp versions work on 32-bit systems\n\t\t$current_version = $this->_get_version();\n\n\t\tif ($this->_migration_type === 'sequential')\n\t\t{\n\t\t\t$target_version = sprintf('%03d', $target_version);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$target_version = (string) $target_version;\n\t\t}\n\n\t\t$migrations = $this->find_migrations();\n\n\t\tif ($target_version > 0 && ! isset($migrations[$target_version]))\n\t\t{\n\t\t\t$this->_error_string = sprintf($this->lang->line('migration_not_found'), $target_version);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ($target_version > $current_version)\n\t\t{\n\t\t\t$method = 'up';\n\t\t}\n\t\telseif ($target_version < $current_version)\n\t\t{\n\t\t\t$method = 'down';\n\t\t\t// We need this so that migrations are applied in reverse order\n\t\t\tkrsort($migrations);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Well, there's nothing to migrate then ...\n\t\t\treturn TRUE;\n\t\t}\n\n\t\t// Validate all available migrations within our target range.\n\t\t//\n\t\t// Unfortunately, we'll have to use another loop to run them\n\t\t// in order to avoid leaving the procedure in a broken state.\n\t\t//\n\t\t// See https://github.com/bcit-ci/CodeIgniter/issues/4539\n\t\t$pending = array();\n\t\tforeach ($migrations as $number => $file)\n\t\t{\n\t\t\t// Ignore versions out of our range.\n\t\t\t//\n\t\t\t// Because we've previously sorted the $migrations array depending on the direction,\n\t\t\t// we can safely break the loop once we reach $target_version ...\n\t\t\tif ($method === 'up')\n\t\t\t{\n\t\t\t\tif ($number <= $current_version)\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telseif ($number > $target_version)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif ($number > $current_version)\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telseif ($number <= $target_version)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check for sequence gaps\n\t\t\tif ($this->_migration_type === 'sequential')\n\t\t\t{\n\t\t\t\tif (isset($previous) && abs($number - $previous) > 1)\n\t\t\t\t{\n\t\t\t\t\t$this->_error_string = sprintf($this->lang->line('migration_sequence_gap'), $number);\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\n\t\t\t\t$previous = $number;\n\t\t\t}\n\n\t\t\tinclude_once($file);\n\t\t\t$class = 'Migration_'.ucfirst(strtolower($this->_get_migration_name(basename($file, '.php'))));\n\n\t\t\t// Validate the migration file structure\n\t\t\tif ( ! class_exists($class, FALSE))\n\t\t\t{\n\t\t\t\t$this->_error_string = sprintf($this->lang->line('migration_class_doesnt_exist'), $class);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t\t// method_exists() returns true for non-public methods,\n\t\t\t// while is_callable() can't be used without instantiating.\n\t\t\t// Only get_class_methods() satisfies both conditions.\n\t\t\telseif ( ! in_array($method, array_map('strtolower', get_class_methods($class))))\n\t\t\t{\n\t\t\t\t$this->_error_string = sprintf($this->lang->line('migration_missing_'.$method.'_method'), $class);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$pending[$number] = array($class, $method);\n\t\t}\n\n\t\t// Now just run the necessary migrations\n\t\tforeach ($pending as $number => $migration)\n\t\t{\n\t\t\tlog_message('debug', 'Migrating '.$method.' from version '.$current_version.' to version '.$number);\n\n\t\t\t$migration[0] = new $migration[0];\n\t\t\tcall_user_func($migration);\n\t\t\t$current_version = $number;\n\t\t\t$this->_update_version($current_version);\n\t\t}\n\n\t\t// This is necessary when moving down, since the the last migration applied\n\t\t// will be the down() method for the next migration up from the target\n\t\tif ($current_version <> $target_version)\n\t\t{\n\t\t\t$current_version = $target_version;\n\t\t\t$this->_update_version($current_version);\n\t\t}\n\n\t\tlog_message('debug', 'Finished migrating to '.$current_version);\n\t\treturn $current_version;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Sets the schema to the latest migration\n\t *\n\t * @return\tmixed\tCurrent version string on success, FALSE on failure\n\t */\n\tpublic function latest()\n\t{\n\t\t$migrations = $this->find_migrations();\n\n\t\tif (empty($migrations))\n\t\t{\n\t\t\t$this->_error_string = $this->lang->line('migration_none_found');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$last_migration = basename(end($migrations));\n\n\t\t// Calculate the last migration step from existing migration\n\t\t// filenames and proceed to the standard version migration\n\t\treturn $this->version($this->_get_migration_number($last_migration));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Sets the schema to the migration version set in config\n\t *\n\t * @return\tmixed\tTRUE if no migrations are found, current version string on success, FALSE on failure\n\t */\n\tpublic function current()\n\t{\n\t\treturn $this->version($this->_migration_version);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Error string\n\t *\n\t * @return\tstring\tError message returned as a string\n\t */\n\tpublic function error_string()\n\t{\n\t\treturn $this->_error_string;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Retrieves list of available migration scripts\n\t *\n\t * @return\tarray\tlist of migration file paths sorted by version\n\t */\n\tpublic function find_migrations()\n\t{\n\t\t$migrations = array();\n\n\t\t// Load all *_*.php files in the migrations path\n\t\tforeach (glob($this->_migration_path.'*_*.php') as $file)\n\t\t{\n\t\t\t$name = basename($file, '.php');\n\n\t\t\t// Filter out non-migration files\n\t\t\tif (preg_match($this->_migration_regex, $name))\n\t\t\t{\n\t\t\t\t$number = $this->_get_migration_number($name);\n\n\t\t\t\t// There cannot be duplicate migration numbers\n\t\t\t\tif (isset($migrations[$number]))\n\t\t\t\t{\n\t\t\t\t\t$this->_error_string = sprintf($this->lang->line('migration_multiple_version'), $number);\n\t\t\t\t\tshow_error($this->_error_string);\n\t\t\t\t}\n\n\t\t\t\t$migrations[$number] = $file;\n\t\t\t}\n\t\t}\n\n\t\tksort($migrations);\n\t\treturn $migrations;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Extracts the migration number from a filename\n\t *\n\t * @param\tstring\t$migration\n\t * @return\tstring\tNumeric portion of a migration filename\n\t */\n\tprotected function _get_migration_number($migration)\n\t{\n\t\treturn sscanf($migration, '%[0-9]+', $number)\n\t\t\t? $number : '0';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Extracts the migration class name from a filename\n\t *\n\t * @param\tstring\t$migration\n\t * @return\tstring\ttext portion of a migration filename\n\t */\n\tprotected function _get_migration_name($migration)\n\t{\n\t\t$parts = explode('_', $migration);\n\t\tarray_shift($parts);\n\t\treturn implode('_', $parts);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Retrieves current schema version\n\t *\n\t * @return\tstring\tCurrent migration version\n\t */\n\tprotected function _get_version()\n\t{\n\t\t$row = $this->db->select('version')->get($this->_migration_table)->row();\n\t\treturn $row ? $row->version : '0';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Stores the current schema version\n\t *\n\t * @param\tstring\t$migration\tMigration reached\n\t * @return\tvoid\n\t */\n\tprotected function _update_version($migration)\n\t{\n\t\t$this->db->update($this->_migration_table, array(\n\t\t\t'version' => $migration\n\t\t));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Enable the use of CI super-global\n\t *\n\t * @param\tstring\t$var\n\t * @return\tmixed\n\t */\n\tpublic function __get($var)\n\t{\n\t\treturn get_instance()->$var;\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/Pagination.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Pagination Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tPagination\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/pagination.html\n */\nclass CI_Pagination {\n\n\t/**\n\t * Base URL\n\t *\n\t * The page that we're linking to\n\t *\n\t * @var\tstring\n\t */\n\tprotected $base_url\t\t= '';\n\n\t/**\n\t * Prefix\n\t *\n\t * @var\tstring\n\t */\n\tprotected $prefix = '';\n\n\t/**\n\t * Suffix\n\t *\n\t * @var\tstring\n\t */\n\tprotected $suffix = '';\n\n\t/**\n\t * Total number of items\n\t *\n\t * @var\tint\n\t */\n\tprotected $total_rows = 0;\n\n\t/**\n\t * Number of links to show\n\t *\n\t * Relates to \"digit\" type links shown before/after\n\t * the currently viewed page.\n\t *\n\t * @var\tint\n\t */\n\tprotected $num_links = 2;\n\n\t/**\n\t * Items per page\n\t *\n\t * @var\tint\n\t */\n\tpublic $per_page = 10;\n\n\t/**\n\t * Current page\n\t *\n\t * @var\tint\n\t */\n\tpublic $cur_page = 0;\n\n\t/**\n\t * Use page numbers flag\n\t *\n\t * Whether to use actual page numbers instead of an offset\n\t *\n\t * @var\tbool\n\t */\n\tprotected $use_page_numbers = FALSE;\n\n\t/**\n\t * First link\n\t *\n\t * @var\tstring\n\t */\n\tprotected $first_link = '&lsaquo; First';\n\n\t/**\n\t * Next link\n\t *\n\t * @var\tstring\n\t */\n\tprotected $next_link = '&gt;';\n\n\t/**\n\t * Previous link\n\t *\n\t * @var\tstring\n\t */\n\tprotected $prev_link = '&lt;';\n\n\t/**\n\t * Last link\n\t *\n\t * @var\tstring\n\t */\n\tprotected $last_link = 'Last &rsaquo;';\n\n\t/**\n\t * URI Segment\n\t *\n\t * @var\tint\n\t */\n\tprotected $uri_segment = 0;\n\n\t/**\n\t * Full tag open\n\t *\n\t * @var\tstring\n\t */\n\tprotected $full_tag_open = '';\n\n\t/**\n\t * Full tag close\n\t *\n\t * @var\tstring\n\t */\n\tprotected $full_tag_close = '';\n\n\t/**\n\t * First tag open\n\t *\n\t * @var\tstring\n\t */\n\tprotected $first_tag_open = '';\n\n\t/**\n\t * First tag close\n\t *\n\t * @var\tstring\n\t */\n\tprotected $first_tag_close = '';\n\n\t/**\n\t * Last tag open\n\t *\n\t * @var\tstring\n\t */\n\tprotected $last_tag_open = '';\n\n\t/**\n\t * Last tag close\n\t *\n\t * @var\tstring\n\t */\n\tprotected $last_tag_close = '';\n\n\t/**\n\t * First URL\n\t *\n\t * An alternative URL for the first page\n\t *\n\t * @var\tstring\n\t */\n\tprotected $first_url = '';\n\n\t/**\n\t * Current tag open\n\t *\n\t * @var\tstring\n\t */\n\tprotected $cur_tag_open = '<strong>';\n\n\t/**\n\t * Current tag close\n\t *\n\t * @var\tstring\n\t */\n\tprotected $cur_tag_close = '</strong>';\n\n\t/**\n\t * Next tag open\n\t *\n\t * @var\tstring\n\t */\n\tprotected $next_tag_open = '';\n\n\t/**\n\t * Next tag close\n\t *\n\t * @var\tstring\n\t */\n\tprotected $next_tag_close = '';\n\n\t/**\n\t * Previous tag open\n\t *\n\t * @var\tstring\n\t */\n\tprotected $prev_tag_open = '';\n\n\t/**\n\t * Previous tag close\n\t *\n\t * @var\tstring\n\t */\n\tprotected $prev_tag_close = '';\n\n\t/**\n\t * Number tag open\n\t *\n\t * @var\tstring\n\t */\n\tprotected $num_tag_open = '';\n\n\t/**\n\t * Number tag close\n\t *\n\t * @var\tstring\n\t */\n\tprotected $num_tag_close = '';\n\n\t/**\n\t * Page query string flag\n\t *\n\t * @var\tbool\n\t */\n\tprotected $page_query_string = FALSE;\n\n\t/**\n\t * Query string segment\n\t *\n\t * @var\tstring\n\t */\n\tprotected $query_string_segment = 'per_page';\n\n\t/**\n\t * Display pages flag\n\t *\n\t * @var\tbool\n\t */\n\tprotected $display_pages = TRUE;\n\n\t/**\n\t * Attributes\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_attributes = '';\n\n\t/**\n\t * Link types\n\t *\n\t * \"rel\" attribute\n\t *\n\t * @see\tCI_Pagination::_attr_rel()\n\t * @var\tarray\n\t */\n\tprotected $_link_types = array();\n\n\t/**\n\t * Reuse query string flag\n\t *\n\t * @var\tbool\n\t */\n\tprotected $reuse_query_string = FALSE;\n\n\t/**\n\t * Use global URL suffix flag\n\t *\n\t * @var\tbool\n\t */\n\tprotected $use_global_url_suffix = FALSE;\n\n\t/**\n\t * Data page attribute\n\t *\n\t * @var\tstring\n\t */\n\tprotected $data_page_attr = 'data-ci-pagination-page';\n\n\t/**\n\t * CI Singleton\n\t *\n\t * @var\tobject\n\t */\n\tprotected $CI;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @param\tarray\t$params\tInitialization parameters\n\t * @return\tvoid\n\t */\n\tpublic function __construct($params = array())\n\t{\n\t\t$this->CI =& get_instance();\n\t\t$this->CI->load->language('pagination');\n\t\tforeach (array('first_link', 'next_link', 'prev_link', 'last_link') as $key)\n\t\t{\n\t\t\tif (($val = $this->CI->lang->line('pagination_'.$key)) !== FALSE)\n\t\t\t{\n\t\t\t\t$this->$key = $val;\n\t\t\t}\n\t\t}\n\n\t\t$this->initialize($params);\n\t\tlog_message('info', 'Pagination Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize Preferences\n\t *\n\t * @param\tarray\t$params\tInitialization parameters\n\t * @return\tCI_Pagination\n\t */\n\tpublic function initialize(array $params = array())\n\t{\n\t\tisset($params['attributes']) OR $params['attributes'] = array();\n\t\tif (is_array($params['attributes']))\n\t\t{\n\t\t\t$this->_parse_attributes($params['attributes']);\n\t\t\tunset($params['attributes']);\n\t\t}\n\n\t\t// Deprecated legacy support for the anchor_class option\n\t\t// Should be removed in CI 3.1+\n\t\tif (isset($params['anchor_class']))\n\t\t{\n\t\t\tempty($params['anchor_class']) OR $attributes['class'] = $params['anchor_class'];\n\t\t\tunset($params['anchor_class']);\n\t\t}\n\n\t\tforeach ($params as $key => $val)\n\t\t{\n\t\t\tif (property_exists($this, $key))\n\t\t\t{\n\t\t\t\t$this->$key = $val;\n\t\t\t}\n\t\t}\n\n\t\tif ($this->CI->config->item('enable_query_strings') === TRUE)\n\t\t{\n\t\t\t$this->page_query_string = TRUE;\n\t\t}\n\n\t\tif ($this->use_global_url_suffix === TRUE)\n\t\t{\n\t\t\t$this->suffix = $this->CI->config->item('url_suffix');\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Generate the pagination links\n\t *\n\t * @return\tstring\n\t */\n\tpublic function create_links()\n\t{\n\t\t// If our item count or per-page total is zero there is no need to continue.\n\t\t// Note: DO NOT change the operator to === here!\n\t\tif ($this->total_rows == 0 OR $this->per_page == 0)\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\t// Calculate the total number of pages\n\t\t$num_pages = (int) ceil($this->total_rows / $this->per_page);\n\n\t\t// Is there only one page? Hm... nothing more to do here then.\n\t\tif ($num_pages === 1)\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\t// Check the user defined number of links.\n\t\t$this->num_links = (int) $this->num_links;\n\n\t\tif ($this->num_links < 0)\n\t\t{\n\t\t\tshow_error('Your number of links must be a non-negative number.');\n\t\t}\n\n\t\t// Keep any existing query string items.\n\t\t// Note: Has nothing to do with any other query string option.\n\t\tif ($this->reuse_query_string === TRUE)\n\t\t{\n\t\t\t$get = $this->CI->input->get();\n\n\t\t\t// Unset the controll, method, old-school routing options\n\t\t\tunset($get['c'], $get['m'], $get[$this->query_string_segment]);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$get = array();\n\t\t}\n\n\t\t// Put together our base and first URLs.\n\t\t// Note: DO NOT append to the properties as that would break successive calls\n\t\t$base_url = trim($this->base_url);\n\t\t$first_url = $this->first_url;\n\n\t\t$query_string = '';\n\t\t$query_string_sep = (strpos($base_url, '?') === FALSE) ? '?' : '&amp;';\n\n\t\t// Are we using query strings?\n\t\tif ($this->page_query_string === TRUE)\n\t\t{\n\t\t\t// If a custom first_url hasn't been specified, we'll create one from\n\t\t\t// the base_url, but without the page item.\n\t\t\tif ($first_url === '')\n\t\t\t{\n\t\t\t\t$first_url = $base_url;\n\n\t\t\t\t// If we saved any GET items earlier, make sure they're appended.\n\t\t\t\tif ( ! empty($get))\n\t\t\t\t{\n\t\t\t\t\t$first_url .= $query_string_sep.http_build_query($get);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add the page segment to the end of the query string, where the\n\t\t\t// page number will be appended.\n\t\t\t$base_url .= $query_string_sep.http_build_query(array_merge($get, array($this->query_string_segment => '')));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Standard segment mode.\n\t\t\t// Generate our saved query string to append later after the page number.\n\t\t\tif ( ! empty($get))\n\t\t\t{\n\t\t\t\t$query_string = $query_string_sep.http_build_query($get);\n\t\t\t\t$this->suffix .= $query_string;\n\t\t\t}\n\n\t\t\t// Does the base_url have the query string in it?\n\t\t\t// If we're supposed to save it, remove it so we can append it later.\n\t\t\tif ($this->reuse_query_string === TRUE && ($base_query_pos = strpos($base_url, '?')) !== FALSE)\n\t\t\t{\n\t\t\t\t$base_url = substr($base_url, 0, $base_query_pos);\n\t\t\t}\n\n\t\t\tif ($first_url === '')\n\t\t\t{\n\t\t\t\t$first_url = $base_url.$query_string;\n\t\t\t}\n\n\t\t\t$base_url = rtrim($base_url, '/').'/';\n\t\t}\n\n\t\t// Determine the current page number.\n\t\t$base_page = ($this->use_page_numbers) ? 1 : 0;\n\n\t\t// Are we using query strings?\n\t\tif ($this->page_query_string === TRUE)\n\t\t{\n\t\t\t$this->cur_page = $this->CI->input->get($this->query_string_segment);\n\t\t}\n\t\telseif (empty($this->cur_page))\n\t\t{\n\t\t\t// Default to the last segment number if one hasn't been defined.\n\t\t\tif ($this->uri_segment === 0)\n\t\t\t{\n\t\t\t\t$this->uri_segment = count($this->CI->uri->segment_array());\n\t\t\t}\n\n\t\t\t$this->cur_page = $this->CI->uri->segment($this->uri_segment);\n\n\t\t\t// Remove any specified prefix/suffix from the segment.\n\t\t\tif ($this->prefix !== '' OR $this->suffix !== '')\n\t\t\t{\n\t\t\t\t$this->cur_page = str_replace(array($this->prefix, $this->suffix), '', $this->cur_page);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->cur_page = (string) $this->cur_page;\n\t\t}\n\n\t\t// If something isn't quite right, back to the default base page.\n\t\tif ( ! ctype_digit($this->cur_page) OR ($this->use_page_numbers && (int) $this->cur_page === 0))\n\t\t{\n\t\t\t$this->cur_page = $base_page;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// Make sure we're using integers for comparisons later.\n\t\t\t$this->cur_page = (int) $this->cur_page;\n\t\t}\n\n\t\t// Is the page number beyond the result range?\n\t\t// If so, we show the last page.\n\t\tif ($this->use_page_numbers)\n\t\t{\n\t\t\tif ($this->cur_page > $num_pages)\n\t\t\t{\n\t\t\t\t$this->cur_page = $num_pages;\n\t\t\t}\n\t\t}\n\t\telseif ($this->cur_page > $this->total_rows)\n\t\t{\n\t\t\t$this->cur_page = ($num_pages - 1) * $this->per_page;\n\t\t}\n\n\t\t$uri_page_number = $this->cur_page;\n\n\t\t// If we're using offset instead of page numbers, convert it\n\t\t// to a page number, so we can generate the surrounding number links.\n\t\tif ( ! $this->use_page_numbers)\n\t\t{\n\t\t\t$this->cur_page = (int) floor(($this->cur_page/$this->per_page) + 1);\n\t\t}\n\n\t\t// Calculate the start and end numbers. These determine\n\t\t// which number to start and end the digit links with.\n\t\t$start\t= (($this->cur_page - $this->num_links) > 0) ? $this->cur_page - ($this->num_links - 1) : 1;\n\t\t$end\t= (($this->cur_page + $this->num_links) < $num_pages) ? $this->cur_page + $this->num_links : $num_pages;\n\n\t\t// And here we go...\n\t\t$output = '';\n\n\t\t// Render the \"First\" link.\n\t\tif ($this->first_link !== FALSE && $this->cur_page > ($this->num_links + 1 + ! $this->num_links))\n\t\t{\n\t\t\t// Take the general parameters, and squeeze this pagination-page attr in for JS frameworks.\n\t\t\t$attributes = sprintf('%s %s=\"%d\"', $this->_attributes, $this->data_page_attr, 1);\n\n\t\t\t$output .= $this->first_tag_open.'<a href=\"'.$first_url.'\"'.$attributes.$this->_attr_rel('start').'>'\n\t\t\t\t.$this->first_link.'</a>'.$this->first_tag_close;\n\t\t}\n\n\t\t// Render the \"Previous\" link.\n\t\tif ($this->prev_link !== FALSE && $this->cur_page !== 1)\n\t\t{\n\t\t\t$i = ($this->use_page_numbers) ? $uri_page_number - 1 : $uri_page_number - $this->per_page;\n\n\t\t\t$attributes = sprintf('%s %s=\"%d\"', $this->_attributes, $this->data_page_attr, ($this->cur_page - 1));\n\n\t\t\tif ($i === $base_page)\n\t\t\t{\n\t\t\t\t// First page\n\t\t\t\t$output .= $this->prev_tag_open.'<a href=\"'.$first_url.'\"'.$attributes.$this->_attr_rel('prev').'>'\n\t\t\t\t\t.$this->prev_link.'</a>'.$this->prev_tag_close;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$append = $this->prefix.$i.$this->suffix;\n\t\t\t\t$output .= $this->prev_tag_open.'<a href=\"'.$base_url.$append.'\"'.$attributes.$this->_attr_rel('prev').'>'\n\t\t\t\t\t.$this->prev_link.'</a>'.$this->prev_tag_close;\n\t\t\t}\n\n\t\t}\n\n\t\t// Render the pages\n\t\tif ($this->display_pages !== FALSE)\n\t\t{\n\t\t\t// Write the digit links\n\t\t\tfor ($loop = $start - 1; $loop <= $end; $loop++)\n\t\t\t{\n\t\t\t\t$i = ($this->use_page_numbers) ? $loop : ($loop * $this->per_page) - $this->per_page;\n\n\t\t\t\t$attributes = sprintf('%s %s=\"%d\"', $this->_attributes, $this->data_page_attr, $loop);\n\n\t\t\t\tif ($i >= $base_page)\n\t\t\t\t{\n\t\t\t\t\tif ($this->cur_page === $loop)\n\t\t\t\t\t{\n\t\t\t\t\t\t// Current page\n\t\t\t\t\t\t$output .= $this->cur_tag_open.$loop.$this->cur_tag_close;\n\t\t\t\t\t}\n\t\t\t\t\telseif ($i === $base_page)\n\t\t\t\t\t{\n\t\t\t\t\t\t// First page\n\t\t\t\t\t\t$output .= $this->num_tag_open.'<a href=\"'.$first_url.'\"'.$attributes.$this->_attr_rel('start').'>'\n\t\t\t\t\t\t\t.$loop.'</a>'.$this->num_tag_close;\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$append = $this->prefix.$i.$this->suffix;\n\t\t\t\t\t\t$output .= $this->num_tag_open.'<a href=\"'.$base_url.$append.'\"'.$attributes.'>'\n\t\t\t\t\t\t\t.$loop.'</a>'.$this->num_tag_close;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Render the \"next\" link\n\t\tif ($this->next_link !== FALSE && $this->cur_page < $num_pages)\n\t\t{\n\t\t\t$i = ($this->use_page_numbers) ? $this->cur_page + 1 : $this->cur_page * $this->per_page;\n\n\t\t\t$attributes = sprintf('%s %s=\"%d\"', $this->_attributes, $this->data_page_attr, $this->cur_page + 1);\n\n\t\t\t$output .= $this->next_tag_open.'<a href=\"'.$base_url.$this->prefix.$i.$this->suffix.'\"'.$attributes\n\t\t\t\t.$this->_attr_rel('next').'>'.$this->next_link.'</a>'.$this->next_tag_close;\n\t\t}\n\n\t\t// Render the \"Last\" link\n\t\tif ($this->last_link !== FALSE && ($this->cur_page + $this->num_links + ! $this->num_links) < $num_pages)\n\t\t{\n\t\t\t$i = ($this->use_page_numbers) ? $num_pages : ($num_pages * $this->per_page) - $this->per_page;\n\n\t\t\t$attributes = sprintf('%s %s=\"%d\"', $this->_attributes, $this->data_page_attr, $num_pages);\n\n\t\t\t$output .= $this->last_tag_open.'<a href=\"'.$base_url.$this->prefix.$i.$this->suffix.'\"'.$attributes.'>'\n\t\t\t\t.$this->last_link.'</a>'.$this->last_tag_close;\n\t\t}\n\n\t\t// Kill double slashes. Note: Sometimes we can end up with a double slash\n\t\t// in the penultimate link so we'll kill all double slashes.\n\t\t$output = preg_replace('#([^:\"])//+#', '\\\\1/', $output);\n\n\t\t// Add the wrapper HTML if exists\n\t\treturn $this->full_tag_open.$output.$this->full_tag_close;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse attributes\n\t *\n\t * @param\tarray\t$attributes\n\t * @return\tvoid\n\t */\n\tprotected function _parse_attributes($attributes)\n\t{\n\t\tisset($attributes['rel']) OR $attributes['rel'] = TRUE;\n\t\t$this->_link_types = ($attributes['rel'])\n\t\t\t? array('start' => 'start', 'prev' => 'prev', 'next' => 'next')\n\t\t\t: array();\n\t\tunset($attributes['rel']);\n\n\t\t$this->_attributes = '';\n\t\tforeach ($attributes as $key => $value)\n\t\t{\n\t\t\t$this->_attributes .= ' '.$key.'=\"'.$value.'\"';\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add \"rel\" attribute\n\t *\n\t * @link\thttp://www.w3.org/TR/html5/links.html#linkTypes\n\t * @param\tstring\t$type\n\t * @return\tstring\n\t */\n\tprotected function _attr_rel($type)\n\t{\n\t\tif (isset($this->_link_types[$type]))\n\t\t{\n\t\t\tunset($this->_link_types[$type]);\n\t\t\treturn ' rel=\"'.$type.'\"';\n\t\t}\n\n\t\treturn '';\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/Parser.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Parser Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tParser\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/parser.html\n */\nclass CI_Parser {\n\n\t/**\n\t * Left delimiter character for pseudo vars\n\t *\n\t * @var string\n\t */\n\tpublic $l_delim = '{';\n\n\t/**\n\t * Right delimiter character for pseudo vars\n\t *\n\t * @var string\n\t */\n\tpublic $r_delim = '}';\n\n\t/**\n\t * Reference to CodeIgniter instance\n\t *\n\t * @var object\n\t */\n\tprotected $CI;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\t$this->CI =& get_instance();\n\t\tlog_message('info', 'Parser Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse a template\n\t *\n\t * Parses pseudo-variables contained in the specified template view,\n\t * replacing them with the data in the second param\n\t *\n\t * @param\tstring\n\t * @param\tarray\n\t * @param\tbool\n\t * @return\tstring\n\t */\n\tpublic function parse($template, $data, $return = FALSE)\n\t{\n\t\t$template = $this->CI->load->view($template, $data, TRUE);\n\n\t\treturn $this->_parse($template, $data, $return);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse a String\n\t *\n\t * Parses pseudo-variables contained in the specified string,\n\t * replacing them with the data in the second param\n\t *\n\t * @param\tstring\n\t * @param\tarray\n\t * @param\tbool\n\t * @return\tstring\n\t */\n\tpublic function parse_string($template, $data, $return = FALSE)\n\t{\n\t\treturn $this->_parse($template, $data, $return);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse a template\n\t *\n\t * Parses pseudo-variables contained in the specified template,\n\t * replacing them with the data in the second param\n\t *\n\t * @param\tstring\n\t * @param\tarray\n\t * @param\tbool\n\t * @return\tstring\n\t */\n\tprotected function _parse($template, $data, $return = FALSE)\n\t{\n\t\tif ($template === '')\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$replace = array();\n\t\tforeach ($data as $key => $val)\n\t\t{\n\t\t\t$replace = array_merge(\n\t\t\t\t$replace,\n\t\t\t\tis_array($val)\n\t\t\t\t\t? $this->_parse_pair($key, $val, $template)\n\t\t\t\t\t: $this->_parse_single($key, (string) $val, $template)\n\t\t\t);\n\t\t}\n\n\t\tunset($data);\n\t\t$template = strtr($template, $replace);\n\n\t\tif ($return === FALSE)\n\t\t{\n\t\t\t$this->CI->output->append_output($template);\n\t\t}\n\n\t\treturn $template;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the left/right variable delimiters\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tvoid\n\t */\n\tpublic function set_delimiters($l = '{', $r = '}')\n\t{\n\t\t$this->l_delim = $l;\n\t\t$this->r_delim = $r;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse a single key/value\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _parse_single($key, $val, $string)\n\t{\n\t\treturn array($this->l_delim.$key.$this->r_delim => (string) $val);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse a tag pair\n\t *\n\t * Parses tag pairs: {some_tag} string... {/some_tag}\n\t *\n\t * @param\tstring\n\t * @param\tarray\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _parse_pair($variable, $data, $string)\n\t{\n\t\t$replace = array();\n\t\tpreg_match_all(\n\t\t\t'#'.preg_quote($this->l_delim.$variable.$this->r_delim).'(.+?)'.preg_quote($this->l_delim.'/'.$variable.$this->r_delim).'#s',\n\t\t\t$string,\n\t\t\t$matches,\n\t\t\tPREG_SET_ORDER\n\t\t);\n\n\t\tforeach ($matches as $match)\n\t\t{\n\t\t\t$str = '';\n\t\t\tforeach ($data as $row)\n\t\t\t{\n\t\t\t\t$temp = array();\n\t\t\t\tforeach ($row as $key => $val)\n\t\t\t\t{\n\t\t\t\t\tif (is_array($val))\n\t\t\t\t\t{\n\t\t\t\t\t\t$pair = $this->_parse_pair($key, $val, $match[1]);\n\t\t\t\t\t\tif ( ! empty($pair))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$temp = array_merge($temp, $pair);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\t$temp[$this->l_delim.$key.$this->r_delim] = $val;\n\t\t\t\t}\n\n\t\t\t\t$str .= strtr($match[1], $temp);\n\t\t\t}\n\n\t\t\t$replace[$match[0]] = $str;\n\t\t}\n\n\t\treturn $replace;\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/Profiler.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Profiler Class\n *\n * This class enables you to display benchmark, query, and other data\n * in order to help with debugging and optimization.\n *\n * Note: At some point it would be good to move all the HTML in this class\n * into a set of template files in order to allow customization.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tLibraries\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/general/profiling.html\n */\nclass CI_Profiler {\n\n\t/**\n\t * List of profiler sections available to show\n\t *\n\t * @var array\n\t */\n\tprotected $_available_sections = array(\n\t\t'benchmarks',\n\t\t'get',\n\t\t'memory_usage',\n\t\t'post',\n\t\t'uri_string',\n\t\t'controller_info',\n\t\t'queries',\n\t\t'http_headers',\n\t\t'session_data',\n\t\t'config'\n\t);\n\n\t/**\n\t * Number of queries to show before making the additional queries togglable\n\t *\n\t * @var int\n\t */\n\tprotected $_query_toggle_count = 25;\n\n\t/**\n\t * Reference to the CodeIgniter singleton\n\t *\n\t * @var object\n\t */\n\tprotected $CI;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * Initialize Profiler\n\t *\n\t * @param\tarray\t$config\tParameters\n\t */\n\tpublic function __construct($config = array())\n\t{\n\t\t$this->CI =& get_instance();\n\t\t$this->CI->load->language('profiler');\n\n\t\t// default all sections to display\n\t\tforeach ($this->_available_sections as $section)\n\t\t{\n\t\t\tif ( ! isset($config[$section]))\n\t\t\t{\n\t\t\t\t$this->_compile_{$section} = TRUE;\n\t\t\t}\n\t\t}\n\n\t\t$this->set_sections($config);\n\t\tlog_message('info', 'Profiler Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Sections\n\t *\n\t * Sets the private _compile_* properties to enable/disable Profiler sections\n\t *\n\t * @param\tmixed\t$config\n\t * @return\tvoid\n\t */\n\tpublic function set_sections($config)\n\t{\n\t\tif (isset($config['query_toggle_count']))\n\t\t{\n\t\t\t$this->_query_toggle_count = (int) $config['query_toggle_count'];\n\t\t\tunset($config['query_toggle_count']);\n\t\t}\n\n\t\tforeach ($config as $method => $enable)\n\t\t{\n\t\t\tif (in_array($method, $this->_available_sections))\n\t\t\t{\n\t\t\t\t$this->_compile_{$method} = ($enable !== FALSE);\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Auto Profiler\n\t *\n\t * This function cycles through the entire array of mark points and\n\t * matches any two points that are named identically (ending in \"_start\"\n\t * and \"_end\" respectively).  It then compiles the execution times for\n\t * all points and returns it as an array\n\t *\n\t * @return\tarray\n\t */\n\tprotected function _compile_benchmarks()\n\t{\n\t\t$profile = array();\n\t\tforeach ($this->CI->benchmark->marker as $key => $val)\n\t\t{\n\t\t\t// We match the \"end\" marker so that the list ends\n\t\t\t// up in the order that it was defined\n\t\t\tif (preg_match('/(.+?)_end$/i', $key, $match)\n\t\t\t\t&& isset($this->CI->benchmark->marker[$match[1].'_end'], $this->CI->benchmark->marker[$match[1].'_start']))\n\t\t\t{\n\t\t\t\t$profile[$match[1]] = $this->CI->benchmark->elapsed_time($match[1].'_start', $key);\n\t\t\t}\n\t\t}\n\n\t\t// Build a table containing the profile data.\n\t\t// Note: At some point we should turn this into a template that can\n\t\t// be modified. We also might want to make this data available to be logged\n\n\t\t$output = \"\\n\\n\"\n\t\t\t.'<fieldset id=\"ci_profiler_benchmarks\" style=\"border:1px solid #900;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;\">'\n\t\t\t.\"\\n\"\n\t\t\t.'<legend style=\"color:#900;\">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_benchmarks').\"&nbsp;&nbsp;</legend>\"\n\t\t\t.\"\\n\\n\\n<table style=\\\"width:100%;\\\">\\n\";\n\n\t\tforeach ($profile as $key => $val)\n\t\t{\n\t\t\t$key = ucwords(str_replace(array('_', '-'), ' ', $key));\n\t\t\t$output .= '<tr><td style=\"padding:5px;width:50%;color:#000;font-weight:bold;background-color:#ddd;\">'\n\t\t\t\t\t.$key.'&nbsp;&nbsp;</td><td style=\"padding:5px;width:50%;color:#900;font-weight:normal;background-color:#ddd;\">'\n\t\t\t\t\t.$val.\"</td></tr>\\n\";\n\t\t}\n\n\t\treturn $output.\"</table>\\n</fieldset>\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile Queries\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _compile_queries()\n\t{\n\t\t$dbs = array();\n\n\t\t// Let's determine which databases are currently connected to\n\t\tforeach (get_object_vars($this->CI) as $name => $cobject)\n\t\t{\n\t\t\tif (is_object($cobject))\n\t\t\t{\n\t\t\t\tif ($cobject instanceof CI_DB)\n\t\t\t\t{\n\t\t\t\t\t$dbs[get_class($this->CI).':$'.$name] = $cobject;\n\t\t\t\t}\n\t\t\t\telseif ($cobject instanceof CI_Model)\n\t\t\t\t{\n\t\t\t\t\tforeach (get_object_vars($cobject) as $mname => $mobject)\n\t\t\t\t\t{\n\t\t\t\t\t\tif ($mobject instanceof CI_DB)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$dbs[get_class($cobject).':$'.$mname] = $mobject;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (count($dbs) === 0)\n\t\t{\n\t\t\treturn \"\\n\\n\"\n\t\t\t\t.'<fieldset id=\"ci_profiler_queries\" style=\"border:1px solid #0000FF;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;\">'\n\t\t\t\t.\"\\n\"\n\t\t\t\t.'<legend style=\"color:#0000FF;\">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_queries').'&nbsp;&nbsp;</legend>'\n\t\t\t\t.\"\\n\\n\\n<table style=\\\"border:none; width:100%;\\\">\\n\"\n\t\t\t\t.'<tr><td style=\"width:100%;color:#0000FF;font-weight:normal;background-color:#eee;padding:5px;\">'\n\t\t\t\t.$this->CI->lang->line('profiler_no_db')\n\t\t\t\t.\"</td></tr>\\n</table>\\n</fieldset>\";\n\t\t}\n\n\t\t// Load the text helper so we can highlight the SQL\n\t\t$this->CI->load->helper('text');\n\n\t\t// Key words we want bolded\n\t\t$highlight = array('SELECT', 'DISTINCT', 'FROM', 'WHERE', 'AND', 'LEFT&nbsp;JOIN', 'ORDER&nbsp;BY', 'GROUP&nbsp;BY', 'LIMIT', 'INSERT', 'INTO', 'VALUES', 'UPDATE', 'OR&nbsp;', 'HAVING', 'OFFSET', 'NOT&nbsp;IN', 'IN', 'LIKE', 'NOT&nbsp;LIKE', 'COUNT', 'MAX', 'MIN', 'ON', 'AS', 'AVG', 'SUM', '(', ')');\n\n\t\t$output  = \"\\n\\n\";\n\t\t$count = 0;\n\n\t\tforeach ($dbs as $name => $db)\n\t\t{\n\t\t\t$hide_queries = (count($db->queries) > $this->_query_toggle_count) ? ' display:none' : '';\n\t\t\t$total_time = number_format(array_sum($db->query_times), 4).' '.$this->CI->lang->line('profiler_seconds');\n\n\t\t\t$show_hide_js = '(<span style=\"cursor: pointer;\" onclick=\"var s=document.getElementById(\\'ci_profiler_queries_db_'.$count.'\\').style;s.display=s.display==\\'none\\'?\\'\\':\\'none\\';this.innerHTML=this.innerHTML==\\''.$this->CI->lang->line('profiler_section_hide').'\\'?\\''.$this->CI->lang->line('profiler_section_show').'\\':\\''.$this->CI->lang->line('profiler_section_hide').'\\';\">'.$this->CI->lang->line('profiler_section_hide').'</span>)';\n\n\t\t\tif ($hide_queries !== '')\n\t\t\t{\n\t\t\t\t$show_hide_js = '(<span style=\"cursor: pointer;\" onclick=\"var s=document.getElementById(\\'ci_profiler_queries_db_'.$count.'\\').style;s.display=s.display==\\'none\\'?\\'\\':\\'none\\';this.innerHTML=this.innerHTML==\\''.$this->CI->lang->line('profiler_section_show').'\\'?\\''.$this->CI->lang->line('profiler_section_hide').'\\':\\''.$this->CI->lang->line('profiler_section_show').'\\';\">'.$this->CI->lang->line('profiler_section_show').'</span>)';\n\t\t\t}\n\n\t\t\t$output .= '<fieldset style=\"border:1px solid #0000FF;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;\">'\n\t\t\t\t.\"\\n\"\n\t\t\t\t.'<legend style=\"color:#0000FF;\">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_database')\n\t\t\t\t.':&nbsp; '.$db->database.' ('.$name.')&nbsp;&nbsp;&nbsp;'.$this->CI->lang->line('profiler_queries')\n\t\t\t\t.': '.count($db->queries).' ('.$total_time.')&nbsp;&nbsp;'.$show_hide_js.\"</legend>\\n\\n\\n\"\n\t\t\t\t.'<table style=\"width:100%;'.$hide_queries.'\" id=\"ci_profiler_queries_db_'.$count.\"\\\">\\n\";\n\n\t\t\tif (count($db->queries) === 0)\n\t\t\t{\n\t\t\t\t$output .= '<tr><td style=\"width:100%;color:#0000FF;font-weight:normal;background-color:#eee;padding:5px;\">'\n\t\t\t\t\t\t.$this->CI->lang->line('profiler_no_queries').\"</td></tr>\\n\";\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tforeach ($db->queries as $key => $val)\n\t\t\t\t{\n\t\t\t\t\t$time = number_format($db->query_times[$key], 4);\n\t\t\t\t\t$val = highlight_code($val);\n\n\t\t\t\t\tforeach ($highlight as $bold)\n\t\t\t\t\t{\n\t\t\t\t\t\t$val = str_replace($bold, '<strong>'.$bold.'</strong>', $val);\n\t\t\t\t\t}\n\n\t\t\t\t\t$output .= '<tr><td style=\"padding:5px;vertical-align:top;width:1%;color:#900;font-weight:normal;background-color:#ddd;\">'\n\t\t\t\t\t\t\t.$time.'&nbsp;&nbsp;</td><td style=\"padding:5px;color:#000;font-weight:normal;background-color:#ddd;\">'\n\t\t\t\t\t\t\t.$val.\"</td></tr>\\n\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$output .= \"</table>\\n</fieldset>\";\n\t\t\t$count++;\n\t\t}\n\n\t\treturn $output;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile $_GET Data\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _compile_get()\n\t{\n\t\t$output = \"\\n\\n\"\n\t\t\t.'<fieldset id=\"ci_profiler_get\" style=\"border:1px solid #cd6e00;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;\">'\n\t\t\t.\"\\n\"\n\t\t\t.'<legend style=\"color:#cd6e00;\">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_get_data').\"&nbsp;&nbsp;</legend>\\n\";\n\n\t\tif (count($_GET) === 0)\n\t\t{\n\t\t\t$output .= '<div style=\"color:#cd6e00;font-weight:normal;padding:4px 0 4px 0;\">'.$this->CI->lang->line('profiler_no_get').'</div>';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$output .= \"\\n\\n<table style=\\\"width:100%;border:none;\\\">\\n\";\n\n\t\t\tforeach ($_GET as $key => $val)\n\t\t\t{\n\t\t\t\tis_int($key) OR $key = \"'\".htmlspecialchars($key, ENT_QUOTES, config_item('charset')).\"'\";\n\t\t\t\t$val = (is_array($val) OR is_object($val))\n\t\t\t\t\t? '<pre>'.htmlspecialchars(print_r($val, TRUE), ENT_QUOTES, config_item('charset'))\n\t\t\t\t\t: htmlspecialchars($val, ENT_QUOTES, config_item('charset'));\n\n\t\t\t\t$output .= '<tr><td style=\"width:50%;color:#000;background-color:#ddd;padding:5px;\">&#36;_GET['\n\t\t\t\t\t.$key.']&nbsp;&nbsp; </td><td style=\"width:50%;padding:5px;color:#cd6e00;font-weight:normal;background-color:#ddd;\">'\n\t\t\t\t\t.$val.\"</td></tr>\\n\";\n\t\t\t}\n\n\t\t\t$output .= \"</table>\\n\";\n\t\t}\n\n\t\treturn $output.'</fieldset>';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile $_POST Data\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _compile_post()\n\t{\n\t\t$output = \"\\n\\n\"\n\t\t\t.'<fieldset id=\"ci_profiler_post\" style=\"border:1px solid #009900;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;\">'\n\t\t\t.\"\\n\"\n\t\t\t.'<legend style=\"color:#009900;\">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_post_data').\"&nbsp;&nbsp;</legend>\\n\";\n\n\t\tif (count($_POST) === 0 && count($_FILES) === 0)\n\t\t{\n\t\t\t$output .= '<div style=\"color:#009900;font-weight:normal;padding:4px 0 4px 0;\">'.$this->CI->lang->line('profiler_no_post').'</div>';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$output .= \"\\n\\n<table style=\\\"width:100%;\\\">\\n\";\n\n\t\t\tforeach ($_POST as $key => $val)\n\t\t\t{\n\t\t\t\tis_int($key) OR $key = \"'\".htmlspecialchars($key, ENT_QUOTES, config_item('charset')).\"'\";\n\t\t\t\t$val = (is_array($val) OR is_object($val))\n\t\t\t\t\t? '<pre>'.htmlspecialchars(print_r($val, TRUE), ENT_QUOTES, config_item('charset'))\n\t\t\t\t\t: htmlspecialchars($val, ENT_QUOTES, config_item('charset'));\n\n\t\t\t\t$output .= '<tr><td style=\"width:50%;padding:5px;color:#000;background-color:#ddd;\">&#36;_POST['\n\t\t\t\t\t.$key.']&nbsp;&nbsp; </td><td style=\"width:50%;padding:5px;color:#009900;font-weight:normal;background-color:#ddd;\">'\n\t\t\t\t\t.$val.\"</td></tr>\\n\";\n\t\t\t}\n\n\t\t\tforeach ($_FILES as $key => $val)\n\t\t\t{\n\t\t\t\tis_int($key) OR $key = \"'\".htmlspecialchars($key, ENT_QUOTES, config_item('charset')).\"'\";\n\t\t\t\t$val = (is_array($val) OR is_object($val))\n\t\t\t\t\t? '<pre>'.htmlspecialchars(print_r($val, TRUE), ENT_QUOTES, config_item('charset'))\n\t\t\t\t\t: htmlspecialchars($val, ENT_QUOTES, config_item('charset'));\n\n\t\t\t\t$output .= '<tr><td style=\"width:50%;padding:5px;color:#000;background-color:#ddd;\">&#36;_FILES['\n\t\t\t\t\t.$key.']&nbsp;&nbsp; </td><td style=\"width:50%;padding:5px;color:#009900;font-weight:normal;background-color:#ddd;\">'\n\t\t\t\t\t.$val.\"</td></tr>\\n\";\n\t\t\t}\n\n\t\t\t$output .= \"</table>\\n\";\n\t\t}\n\n\t\treturn $output.'</fieldset>';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show query string\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _compile_uri_string()\n\t{\n\t\treturn \"\\n\\n\"\n\t\t\t.'<fieldset id=\"ci_profiler_uri_string\" style=\"border:1px solid #000;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;\">'\n\t\t\t.\"\\n\"\n\t\t\t.'<legend style=\"color:#000;\">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_uri_string').\"&nbsp;&nbsp;</legend>\\n\"\n\t\t\t.'<div style=\"color:#000;font-weight:normal;padding:4px 0 4px 0;\">'\n\t\t\t.($this->CI->uri->uri_string === '' ? $this->CI->lang->line('profiler_no_uri') : $this->CI->uri->uri_string)\n\t\t\t.'</div></fieldset>';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show the controller and function that were called\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _compile_controller_info()\n\t{\n\t\treturn \"\\n\\n\"\n\t\t\t.'<fieldset id=\"ci_profiler_controller_info\" style=\"border:1px solid #995300;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;\">'\n\t\t\t.\"\\n\"\n\t\t\t.'<legend style=\"color:#995300;\">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_controller_info').\"&nbsp;&nbsp;</legend>\\n\"\n\t\t\t.'<div style=\"color:#995300;font-weight:normal;padding:4px 0 4px 0;\">'.$this->CI->router->class.'/'.$this->CI->router->method\n\t\t\t.'</div></fieldset>';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile memory usage\n\t *\n\t * Display total used memory\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _compile_memory_usage()\n\t{\n\t\treturn \"\\n\\n\"\n\t\t\t.'<fieldset id=\"ci_profiler_memory_usage\" style=\"border:1px solid #5a0099;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;\">'\n\t\t\t.\"\\n\"\n\t\t\t.'<legend style=\"color:#5a0099;\">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_memory_usage').\"&nbsp;&nbsp;</legend>\\n\"\n\t\t\t.'<div style=\"color:#5a0099;font-weight:normal;padding:4px 0 4px 0;\">'\n\t\t\t.(($usage = memory_get_usage()) != '' ? number_format($usage).' bytes' : $this->CI->lang->line('profiler_no_memory'))\n\t\t\t.'</div></fieldset>';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile header information\n\t *\n\t * Lists HTTP headers\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _compile_http_headers()\n\t{\n\t\t$output = \"\\n\\n\"\n\t\t\t.'<fieldset id=\"ci_profiler_http_headers\" style=\"border:1px solid #000;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;\">'\n\t\t\t.\"\\n\"\n\t\t\t.'<legend style=\"color:#000;\">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_headers')\n\t\t\t.'&nbsp;&nbsp;(<span style=\"cursor: pointer;\" onclick=\"var s=document.getElementById(\\'ci_profiler_httpheaders_table\\').style;s.display=s.display==\\'none\\'?\\'\\':\\'none\\';this.innerHTML=this.innerHTML==\\''.$this->CI->lang->line('profiler_section_show').'\\'?\\''.$this->CI->lang->line('profiler_section_hide').'\\':\\''.$this->CI->lang->line('profiler_section_show').'\\';\">'.$this->CI->lang->line('profiler_section_show').\"</span>)</legend>\\n\\n\\n\"\n\t\t\t.'<table style=\"width:100%;display:none;\" id=\"ci_profiler_httpheaders_table\">'.\"\\n\";\n\n\t\tforeach (array('HTTP_ACCEPT', 'HTTP_USER_AGENT', 'HTTP_CONNECTION', 'SERVER_PORT', 'SERVER_NAME', 'REMOTE_ADDR', 'SERVER_SOFTWARE', 'HTTP_ACCEPT_LANGUAGE', 'SCRIPT_NAME', 'REQUEST_METHOD',' HTTP_HOST', 'REMOTE_HOST', 'CONTENT_TYPE', 'SERVER_PROTOCOL', 'QUERY_STRING', 'HTTP_ACCEPT_ENCODING', 'HTTP_X_FORWARDED_FOR', 'HTTP_DNT') as $header)\n\t\t{\n\t\t\t$val = isset($_SERVER[$header]) ? htmlspecialchars($_SERVER[$header], ENT_QUOTES, config_item('charset')) : '';\n\t\t\t$output .= '<tr><td style=\"vertical-align:top;width:50%;padding:5px;color:#900;background-color:#ddd;\">'\n\t\t\t\t.$header.'&nbsp;&nbsp;</td><td style=\"width:50%;padding:5px;color:#000;background-color:#ddd;\">'.$val.\"</td></tr>\\n\";\n\t\t}\n\n\t\treturn $output.\"</table>\\n</fieldset>\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile config information\n\t *\n\t * Lists developer config variables\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _compile_config()\n\t{\n\t\t$output = \"\\n\\n\"\n\t\t\t.'<fieldset id=\"ci_profiler_config\" style=\"border:1px solid #000;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;\">'\n\t\t\t.\"\\n\"\n\t\t\t.'<legend style=\"color:#000;\">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_config').'&nbsp;&nbsp;(<span style=\"cursor: pointer;\" onclick=\"var s=document.getElementById(\\'ci_profiler_config_table\\').style;s.display=s.display==\\'none\\'?\\'\\':\\'none\\';this.innerHTML=this.innerHTML==\\''.$this->CI->lang->line('profiler_section_show').'\\'?\\''.$this->CI->lang->line('profiler_section_hide').'\\':\\''.$this->CI->lang->line('profiler_section_show').'\\';\">'.$this->CI->lang->line('profiler_section_show').\"</span>)</legend>\\n\\n\\n\"\n\t\t\t.'<table style=\"width:100%;display:none;\" id=\"ci_profiler_config_table\">'.\"\\n\";\n\n\t\tforeach ($this->CI->config->config as $config => $val)\n\t\t{\n\t\t\tif (is_array($val) OR is_object($val))\n\t\t\t{\n\t\t\t\t$val = print_r($val, TRUE);\n\t\t\t}\n\n\t\t\t$output .= '<tr><td style=\"padding:5px;vertical-align:top;color:#900;background-color:#ddd;\">'\n\t\t\t\t.$config.'&nbsp;&nbsp;</td><td style=\"padding:5px;color:#000;background-color:#ddd;\">'.htmlspecialchars($val).\"</td></tr>\\n\";\n\t\t}\n\n\t\treturn $output.\"</table>\\n</fieldset>\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile session userdata\n\t *\n\t * @return \tstring\n\t */\n\tprotected function _compile_session_data()\n\t{\n\t\tif ( ! isset($this->CI->session))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\t$output = '<fieldset id=\"ci_profiler_csession\" style=\"border:1px solid #000;padding:6px 10px 10px 10px;margin:20px 0 20px 0;background-color:#eee;\">'\n\t\t\t.'<legend style=\"color:#000;\">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_session_data').'&nbsp;&nbsp;(<span style=\"cursor: pointer;\" onclick=\"var s=document.getElementById(\\'ci_profiler_session_data\\').style;s.display=s.display==\\'none\\'?\\'\\':\\'none\\';this.innerHTML=this.innerHTML==\\''.$this->CI->lang->line('profiler_section_show').'\\'?\\''.$this->CI->lang->line('profiler_section_hide').'\\':\\''.$this->CI->lang->line('profiler_section_show').'\\';\">'.$this->CI->lang->line('profiler_section_show').'</span>)</legend>'\n\t\t\t.'<table style=\"width:100%;display:none;\" id=\"ci_profiler_session_data\">';\n\n\t\tforeach ($this->CI->session->userdata() as $key => $val)\n\t\t{\n\t\t\tif (is_array($val) OR is_object($val))\n\t\t\t{\n\t\t\t\t$val = print_r($val, TRUE);\n\t\t\t}\n\n\t\t\t$output .= '<tr><td style=\"padding:5px;vertical-align:top;color:#900;background-color:#ddd;\">'\n\t\t\t\t.$key.'&nbsp;&nbsp;</td><td style=\"padding:5px;color:#000;background-color:#ddd;\">'.htmlspecialchars($val).\"</td></tr>\\n\";\n\t\t}\n\n\t\treturn $output.\"</table>\\n</fieldset>\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Run the Profiler\n\t *\n\t * @return\tstring\n\t */\n\tpublic function run()\n\t{\n\t\t$output = '<div id=\"codeigniter_profiler\" style=\"clear:both;background-color:#fff;padding:10px;\">';\n\t\t$fields_displayed = 0;\n\n\t\tforeach ($this->_available_sections as $section)\n\t\t{\n\t\t\tif ($this->_compile_{$section} !== FALSE)\n\t\t\t{\n\t\t\t\t$func = '_compile_'.$section;\n\t\t\t\t$output .= $this->{$func}();\n\t\t\t\t$fields_displayed++;\n\t\t\t}\n\t\t}\n\n\t\tif ($fields_displayed === 0)\n\t\t{\n\t\t\t$output .= '<p style=\"border:1px solid #5a0099;padding:10px;margin:20px 0;background-color:#eee;\">'\n\t\t\t\t.$this->CI->lang->line('profiler_no_profiles').'</p>';\n\t\t}\n\n\t\treturn $output.'</div>';\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/Session/Session.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 2.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Session Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tSessions\n * @author\t\tAndrey Andreev\n * @link\t\thttps://codeigniter.com/user_guide/libraries/sessions.html\n */\nclass CI_Session {\n\n\t/**\n\t * Userdata array\n\t *\n\t * Just a reference to $_SESSION, for BC purposes.\n\t */\n\tpublic $userdata;\n\n\tprotected $_driver = 'files';\n\tprotected $_config;\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tarray\t$params\tConfiguration parameters\n\t * @return\tvoid\n\t */\n\tpublic function __construct(array $params = array())\n\t{\n\t\t// No sessions under CLI\n\t\tif (is_cli())\n\t\t{\n\t\t\tlog_message('debug', 'Session: Initialization under CLI aborted.');\n\t\t\treturn;\n\t\t}\n\t\telseif ((bool) ini_get('session.auto_start'))\n\t\t{\n\t\t\tlog_message('error', 'Session: session.auto_start is enabled in php.ini. Aborting.');\n\t\t\treturn;\n\t\t}\n\t\telseif ( ! empty($params['driver']))\n\t\t{\n\t\t\t$this->_driver = $params['driver'];\n\t\t\tunset($params['driver']);\n\t\t}\n\t\telseif ($driver = config_item('sess_driver'))\n\t\t{\n\t\t\t$this->_driver = $driver;\n\t\t}\n\t\t// Note: BC workaround\n\t\telseif (config_item('sess_use_database'))\n\t\t{\n\t\t\tlog_message('debug', 'Session: \"sess_driver\" is empty; using BC fallback to \"sess_use_database\".');\n\t\t\t$this->_driver = 'database';\n\t\t}\n\n\t\t$class = $this->_ci_load_classes($this->_driver);\n\n\t\t// Configuration ...\n\t\t$this->_configure($params);\n\n\t\t$class = new $class($this->_config);\n\t\tif ($class instanceof SessionHandlerInterface)\n\t\t{\n\t\t\tif (is_php('5.4'))\n\t\t\t{\n\t\t\t\tsession_set_save_handler($class, TRUE);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tsession_set_save_handler(\n\t\t\t\t\tarray($class, 'open'),\n\t\t\t\t\tarray($class, 'close'),\n\t\t\t\t\tarray($class, 'read'),\n\t\t\t\t\tarray($class, 'write'),\n\t\t\t\t\tarray($class, 'destroy'),\n\t\t\t\t\tarray($class, 'gc')\n\t\t\t\t);\n\n\t\t\t\tregister_shutdown_function('session_write_close');\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlog_message('error', \"Session: Driver '\".$this->_driver.\"' doesn't implement SessionHandlerInterface. Aborting.\");\n\t\t\treturn;\n\t\t}\n\n\t\t// Sanitize the cookie, because apparently PHP doesn't do that for userspace handlers\n\t\tif (isset($_COOKIE[$this->_config['cookie_name']])\n\t\t\t&& (\n\t\t\t\t! is_string($_COOKIE[$this->_config['cookie_name']])\n\t\t\t\tOR ! preg_match('/^[0-9a-f]{40}$/', $_COOKIE[$this->_config['cookie_name']])\n\t\t\t)\n\t\t)\n\t\t{\n\t\t\tunset($_COOKIE[$this->_config['cookie_name']]);\n\t\t}\n\n\t\tsession_start();\n\n\t\t// Is session ID auto-regeneration configured? (ignoring ajax requests)\n\t\tif ((empty($_SERVER['HTTP_X_REQUESTED_WITH']) OR strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) !== 'xmlhttprequest')\n\t\t\t&& ($regenerate_time = config_item('sess_time_to_update')) > 0\n\t\t)\n\t\t{\n\t\t\tif ( ! isset($_SESSION['__ci_last_regenerate']))\n\t\t\t{\n\t\t\t\t$_SESSION['__ci_last_regenerate'] = time();\n\t\t\t}\n\t\t\telseif ($_SESSION['__ci_last_regenerate'] < (time() - $regenerate_time))\n\t\t\t{\n\t\t\t\t$this->sess_regenerate((bool) config_item('sess_regenerate_destroy'));\n\t\t\t}\n\t\t}\n\t\t// Another work-around ... PHP doesn't seem to send the session cookie\n\t\t// unless it is being currently created or regenerated\n\t\telseif (isset($_COOKIE[$this->_config['cookie_name']]) && $_COOKIE[$this->_config['cookie_name']] === session_id())\n\t\t{\n\t\t\tsetcookie(\n\t\t\t\t$this->_config['cookie_name'],\n\t\t\t\tsession_id(),\n\t\t\t\t(empty($this->_config['cookie_lifetime']) ? 0 : time() + $this->_config['cookie_lifetime']),\n\t\t\t\t$this->_config['cookie_path'],\n\t\t\t\t$this->_config['cookie_domain'],\n\t\t\t\t$this->_config['cookie_secure'],\n\t\t\t\tTRUE\n\t\t\t);\n\t\t}\n\n\t\t$this->_ci_init_vars();\n\n\t\tlog_message('info', \"Session: Class initialized using '\".$this->_driver.\"' driver.\");\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * CI Load Classes\n\t *\n\t * An internal method to load all possible dependency and extension\n\t * classes. It kind of emulates the CI_Driver library, but is\n\t * self-sufficient.\n\t *\n\t * @param\tstring\t$driver\tDriver name\n\t * @return\tstring\tDriver class name\n\t */\n\tprotected function _ci_load_classes($driver)\n\t{\n\t\t// PHP 5.4 compatibility\n\t\tinterface_exists('SessionHandlerInterface', FALSE) OR require_once(BASEPATH.'libraries/Session/SessionHandlerInterface.php');\n\n\t\t$prefix = config_item('subclass_prefix');\n\n\t\tif ( ! class_exists('CI_Session_driver', FALSE))\n\t\t{\n\t\t\trequire_once(\n\t\t\t\tfile_exists(APPPATH.'libraries/Session/Session_driver.php')\n\t\t\t\t\t? APPPATH.'libraries/Session/Session_driver.php'\n\t\t\t\t\t: BASEPATH.'libraries/Session/Session_driver.php'\n\t\t\t);\n\n\t\t\tif (file_exists($file_path = APPPATH.'libraries/Session/'.$prefix.'Session_driver.php'))\n\t\t\t{\n\t\t\t\trequire_once($file_path);\n\t\t\t}\n\t\t}\n\n\t\t$class = 'Session_'.$driver.'_driver';\n\n\t\t// Allow custom drivers without the CI_ or MY_ prefix\n\t\tif ( ! class_exists($class, FALSE) && file_exists($file_path = APPPATH.'libraries/Session/drivers/'.$class.'.php'))\n\t\t{\n\t\t\trequire_once($file_path);\n\t\t\tif (class_exists($class, FALSE))\n\t\t\t{\n\t\t\t\treturn $class;\n\t\t\t}\n\t\t}\n\n\t\tif ( ! class_exists('CI_'.$class, FALSE))\n\t\t{\n\t\t\tif (file_exists($file_path = APPPATH.'libraries/Session/drivers/'.$class.'.php') OR file_exists($file_path = BASEPATH.'libraries/Session/drivers/'.$class.'.php'))\n\t\t\t{\n\t\t\t\trequire_once($file_path);\n\t\t\t}\n\n\t\t\tif ( ! class_exists('CI_'.$class, FALSE) && ! class_exists($class, FALSE))\n\t\t\t{\n\t\t\t\tthrow new UnexpectedValueException(\"Session: Configured driver '\".$driver.\"' was not found. Aborting.\");\n\t\t\t}\n\t\t}\n\n\t\tif ( ! class_exists($prefix.$class, FALSE) && file_exists($file_path = APPPATH.'libraries/Session/drivers/'.$prefix.$class.'.php'))\n\t\t{\n\t\t\trequire_once($file_path);\n\t\t\tif (class_exists($prefix.$class, FALSE))\n\t\t\t{\n\t\t\t\treturn $prefix.$class;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tlog_message('debug', 'Session: '.$prefix.$class.\".php found but it doesn't declare class \".$prefix.$class.'.');\n\t\t\t}\n\t\t}\n\n\t\treturn 'CI_'.$class;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Configuration\n\t *\n\t * Handle input parameters and configuration defaults\n\t *\n\t * @param\tarray\t&$params\tInput parameters\n\t * @return\tvoid\n\t */\n\tprotected function _configure(&$params)\n\t{\n\t\t$expiration = config_item('sess_expiration');\n\n\t\tif (isset($params['cookie_lifetime']))\n\t\t{\n\t\t\t$params['cookie_lifetime'] = (int) $params['cookie_lifetime'];\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$params['cookie_lifetime'] = ( ! isset($expiration) && config_item('sess_expire_on_close'))\n\t\t\t\t? 0 : (int) $expiration;\n\t\t}\n\n\t\tisset($params['cookie_name']) OR $params['cookie_name'] = config_item('sess_cookie_name');\n\t\tif (empty($params['cookie_name']))\n\t\t{\n\t\t\t$params['cookie_name'] = ini_get('session.name');\n\t\t}\n\t\telse\n\t\t{\n\t\t\tini_set('session.name', $params['cookie_name']);\n\t\t}\n\n\t\tisset($params['cookie_path']) OR $params['cookie_path'] = config_item('cookie_path');\n\t\tisset($params['cookie_domain']) OR $params['cookie_domain'] = config_item('cookie_domain');\n\t\tisset($params['cookie_secure']) OR $params['cookie_secure'] = (bool) config_item('cookie_secure');\n\n\t\tsession_set_cookie_params(\n\t\t\t$params['cookie_lifetime'],\n\t\t\t$params['cookie_path'],\n\t\t\t$params['cookie_domain'],\n\t\t\t$params['cookie_secure'],\n\t\t\tTRUE // HttpOnly; Yes, this is intentional and not configurable for security reasons\n\t\t);\n\n\t\tif (empty($expiration))\n\t\t{\n\t\t\t$params['expiration'] = (int) ini_get('session.gc_maxlifetime');\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$params['expiration'] = (int) $expiration;\n\t\t\tini_set('session.gc_maxlifetime', $expiration);\n\t\t}\n\n\t\t$params['match_ip'] = (bool) (isset($params['match_ip']) ? $params['match_ip'] : config_item('sess_match_ip'));\n\n\t\tisset($params['save_path']) OR $params['save_path'] = config_item('sess_save_path');\n\n\t\t$this->_config = $params;\n\n\t\t// Security is king\n\t\tini_set('session.use_trans_sid', 0);\n\t\tini_set('session.use_strict_mode', 1);\n\t\tini_set('session.use_cookies', 1);\n\t\tini_set('session.use_only_cookies', 1);\n\t\tini_set('session.hash_function', 1);\n\t\tini_set('session.hash_bits_per_character', 4);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Handle temporary variables\n\t *\n\t * Clears old \"flash\" data, marks the new one for deletion and handles\n\t * \"temp\" data deletion.\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _ci_init_vars()\n\t{\n\t\tif ( ! empty($_SESSION['__ci_vars']))\n\t\t{\n\t\t\t$current_time = time();\n\n\t\t\tforeach ($_SESSION['__ci_vars'] as $key => &$value)\n\t\t\t{\n\t\t\t\tif ($value === 'new')\n\t\t\t\t{\n\t\t\t\t\t$_SESSION['__ci_vars'][$key] = 'old';\n\t\t\t\t}\n\t\t\t\t// Hacky, but 'old' will (implicitly) always be less than time() ;)\n\t\t\t\t// DO NOT move this above the 'new' check!\n\t\t\t\telseif ($value < $current_time)\n\t\t\t\t{\n\t\t\t\t\tunset($_SESSION[$key], $_SESSION['__ci_vars'][$key]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (empty($_SESSION['__ci_vars']))\n\t\t\t{\n\t\t\t\tunset($_SESSION['__ci_vars']);\n\t\t\t}\n\t\t}\n\n\t\t$this->userdata =& $_SESSION;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Mark as flash\n\t *\n\t * @param\tmixed\t$key\tSession data key(s)\n\t * @return\tbool\n\t */\n\tpublic function mark_as_flash($key)\n\t{\n\t\tif (is_array($key))\n\t\t{\n\t\t\tfor ($i = 0, $c = count($key); $i < $c; $i++)\n\t\t\t{\n\t\t\t\tif ( ! isset($_SESSION[$key[$i]]))\n\t\t\t\t{\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$new = array_fill_keys($key, 'new');\n\n\t\t\t$_SESSION['__ci_vars'] = isset($_SESSION['__ci_vars'])\n\t\t\t\t? array_merge($_SESSION['__ci_vars'], $new)\n\t\t\t\t: $new;\n\n\t\t\treturn TRUE;\n\t\t}\n\n\t\tif ( ! isset($_SESSION[$key]))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$_SESSION['__ci_vars'][$key] = 'new';\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get flash keys\n\t *\n\t * @return\tarray\n\t */\n\tpublic function get_flash_keys()\n\t{\n\t\tif ( ! isset($_SESSION['__ci_vars']))\n\t\t{\n\t\t\treturn array();\n\t\t}\n\n\t\t$keys = array();\n\t\tforeach (array_keys($_SESSION['__ci_vars']) as $key)\n\t\t{\n\t\t\tis_int($_SESSION['__ci_vars'][$key]) OR $keys[] = $key;\n\t\t}\n\n\t\treturn $keys;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Unmark flash\n\t *\n\t * @param\tmixed\t$key\tSession data key(s)\n\t * @return\tvoid\n\t */\n\tpublic function unmark_flash($key)\n\t{\n\t\tif (empty($_SESSION['__ci_vars']))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tis_array($key) OR $key = array($key);\n\n\t\tforeach ($key as $k)\n\t\t{\n\t\t\tif (isset($_SESSION['__ci_vars'][$k]) && ! is_int($_SESSION['__ci_vars'][$k]))\n\t\t\t{\n\t\t\t\tunset($_SESSION['__ci_vars'][$k]);\n\t\t\t}\n\t\t}\n\n\t\tif (empty($_SESSION['__ci_vars']))\n\t\t{\n\t\t\tunset($_SESSION['__ci_vars']);\n\t\t}\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Mark as temp\n\t *\n\t * @param\tmixed\t$key\tSession data key(s)\n\t * @param\tint\t$ttl\tTime-to-live in seconds\n\t * @return\tbool\n\t */\n\tpublic function mark_as_temp($key, $ttl = 300)\n\t{\n\t\t$ttl += time();\n\n\t\tif (is_array($key))\n\t\t{\n\t\t\t$temp = array();\n\n\t\t\tforeach ($key as $k => $v)\n\t\t\t{\n\t\t\t\t// Do we have a key => ttl pair, or just a key?\n\t\t\t\tif (is_int($k))\n\t\t\t\t{\n\t\t\t\t\t$k = $v;\n\t\t\t\t\t$v = $ttl;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$v += time();\n\t\t\t\t}\n\n\t\t\t\tif ( ! isset($_SESSION[$k]))\n\t\t\t\t{\n\t\t\t\t\treturn FALSE;\n\t\t\t\t}\n\n\t\t\t\t$temp[$k] = $v;\n\t\t\t}\n\n\t\t\t$_SESSION['__ci_vars'] = isset($_SESSION['__ci_vars'])\n\t\t\t\t? array_merge($_SESSION['__ci_vars'], $temp)\n\t\t\t\t: $temp;\n\n\t\t\treturn TRUE;\n\t\t}\n\n\t\tif ( ! isset($_SESSION[$key]))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$_SESSION['__ci_vars'][$key] = $ttl;\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get temp keys\n\t *\n\t * @return\tarray\n\t */\n\tpublic function get_temp_keys()\n\t{\n\t\tif ( ! isset($_SESSION['__ci_vars']))\n\t\t{\n\t\t\treturn array();\n\t\t}\n\n\t\t$keys = array();\n\t\tforeach (array_keys($_SESSION['__ci_vars']) as $key)\n\t\t{\n\t\t\tis_int($_SESSION['__ci_vars'][$key]) && $keys[] = $key;\n\t\t}\n\n\t\treturn $keys;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Unmark flash\n\t *\n\t * @param\tmixed\t$key\tSession data key(s)\n\t * @return\tvoid\n\t */\n\tpublic function unmark_temp($key)\n\t{\n\t\tif (empty($_SESSION['__ci_vars']))\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tis_array($key) OR $key = array($key);\n\n\t\tforeach ($key as $k)\n\t\t{\n\t\t\tif (isset($_SESSION['__ci_vars'][$k]) && is_int($_SESSION['__ci_vars'][$k]))\n\t\t\t{\n\t\t\t\tunset($_SESSION['__ci_vars'][$k]);\n\t\t\t}\n\t\t}\n\n\t\tif (empty($_SESSION['__ci_vars']))\n\t\t{\n\t\t\tunset($_SESSION['__ci_vars']);\n\t\t}\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * __get()\n\t *\n\t * @param\tstring\t$key\t'session_id' or a session data key\n\t * @return\tmixed\n\t */\n\tpublic function __get($key)\n\t{\n\t\t// Note: Keep this order the same, just in case somebody wants to\n\t\t//       use 'session_id' as a session data key, for whatever reason\n\t\tif (isset($_SESSION[$key]))\n\t\t{\n\t\t\treturn $_SESSION[$key];\n\t\t}\n\t\telseif ($key === 'session_id')\n\t\t{\n\t\t\treturn session_id();\n\t\t}\n\n\t\treturn NULL;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * __isset()\n\t *\n\t * @param\tstring\t$key\t'session_id' or a session data key\n\t * @return\tbool\n\t */\n\tpublic function __isset($key)\n\t{\n\t\tif ($key === 'session_id')\n\t\t{\n\t\t\treturn (session_status() === PHP_SESSION_ACTIVE);\n\t\t}\n\n\t\treturn isset($_SESSION[$key]);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * __set()\n\t *\n\t * @param\tstring\t$key\tSession data key\n\t * @param\tmixed\t$value\tSession data value\n\t * @return\tvoid\n\t */\n\tpublic function __set($key, $value)\n\t{\n\t\t$_SESSION[$key] = $value;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Session destroy\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function sess_destroy()\n\t{\n\t\tsession_destroy();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Session regenerate\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @param\tbool\t$destroy\tDestroy old session data flag\n\t * @return\tvoid\n\t */\n\tpublic function sess_regenerate($destroy = FALSE)\n\t{\n\t\t$_SESSION['__ci_last_regenerate'] = time();\n\t\tsession_regenerate_id($destroy);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get userdata reference\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @returns\tarray\n\t */\n\tpublic function &get_userdata()\n\t{\n\t\treturn $_SESSION;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Userdata (fetch)\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @param\tstring\t$key\tSession data key\n\t * @return\tmixed\tSession data value or NULL if not found\n\t */\n\tpublic function userdata($key = NULL)\n\t{\n\t\tif (isset($key))\n\t\t{\n\t\t\treturn isset($_SESSION[$key]) ? $_SESSION[$key] : NULL;\n\t\t}\n\t\telseif (empty($_SESSION))\n\t\t{\n\t\t\treturn array();\n\t\t}\n\n\t\t$userdata = array();\n\t\t$_exclude = array_merge(\n\t\t\tarray('__ci_vars'),\n\t\t\t$this->get_flash_keys(),\n\t\t\t$this->get_temp_keys()\n\t\t);\n\n\t\tforeach (array_keys($_SESSION) as $key)\n\t\t{\n\t\t\tif ( ! in_array($key, $_exclude, TRUE))\n\t\t\t{\n\t\t\t\t$userdata[$key] = $_SESSION[$key];\n\t\t\t}\n\t\t}\n\n\t\treturn $userdata;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Set userdata\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @param\tmixed\t$data\tSession data key or an associative array\n\t * @param\tmixed\t$value\tValue to store\n\t * @return\tvoid\n\t */\n\tpublic function set_userdata($data, $value = NULL)\n\t{\n\t\tif (is_array($data))\n\t\t{\n\t\t\tforeach ($data as $key => &$value)\n\t\t\t{\n\t\t\t\t$_SESSION[$key] = $value;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t$_SESSION[$data] = $value;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Unset userdata\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @param\tmixed\t$key\tSession data key(s)\n\t * @return\tvoid\n\t */\n\tpublic function unset_userdata($key)\n\t{\n\t\tif (is_array($key))\n\t\t{\n\t\t\tforeach ($key as $k)\n\t\t\t{\n\t\t\t\tunset($_SESSION[$k]);\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tunset($_SESSION[$key]);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * All userdata (fetch)\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @return\tarray\t$_SESSION, excluding flash data items\n\t */\n\tpublic function all_userdata()\n\t{\n\t\treturn $this->userdata();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Has userdata\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @param\tstring\t$key\tSession data key\n\t * @return\tbool\n\t */\n\tpublic function has_userdata($key)\n\t{\n\t\treturn isset($_SESSION[$key]);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Flashdata (fetch)\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @param\tstring\t$key\tSession data key\n\t * @return\tmixed\tSession data value or NULL if not found\n\t */\n\tpublic function flashdata($key = NULL)\n\t{\n\t\tif (isset($key))\n\t\t{\n\t\t\treturn (isset($_SESSION['__ci_vars'], $_SESSION['__ci_vars'][$key], $_SESSION[$key]) && ! is_int($_SESSION['__ci_vars'][$key]))\n\t\t\t\t? $_SESSION[$key]\n\t\t\t\t: NULL;\n\t\t}\n\n\t\t$flashdata = array();\n\n\t\tif ( ! empty($_SESSION['__ci_vars']))\n\t\t{\n\t\t\tforeach ($_SESSION['__ci_vars'] as $key => &$value)\n\t\t\t{\n\t\t\t\tis_int($value) OR $flashdata[$key] = $_SESSION[$key];\n\t\t\t}\n\t\t}\n\n\t\treturn $flashdata;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Set flashdata\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @param\tmixed\t$data\tSession data key or an associative array\n\t * @param\tmixed\t$value\tValue to store\n\t * @return\tvoid\n\t */\n\tpublic function set_flashdata($data, $value = NULL)\n\t{\n\t\t$this->set_userdata($data, $value);\n\t\t$this->mark_as_flash(is_array($data) ? array_keys($data) : $data);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Keep flashdata\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @param\tmixed\t$key\tSession data key(s)\n\t * @return\tvoid\n\t */\n\tpublic function keep_flashdata($key)\n\t{\n\t\t$this->mark_as_flash($key);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Temp data (fetch)\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @param\tstring\t$key\tSession data key\n\t * @return\tmixed\tSession data value or NULL if not found\n\t */\n\tpublic function tempdata($key = NULL)\n\t{\n\t\tif (isset($key))\n\t\t{\n\t\t\treturn (isset($_SESSION['__ci_vars'], $_SESSION['__ci_vars'][$key], $_SESSION[$key]) && is_int($_SESSION['__ci_vars'][$key]))\n\t\t\t\t? $_SESSION[$key]\n\t\t\t\t: NULL;\n\t\t}\n\n\t\t$tempdata = array();\n\n\t\tif ( ! empty($_SESSION['__ci_vars']))\n\t\t{\n\t\t\tforeach ($_SESSION['__ci_vars'] as $key => &$value)\n\t\t\t{\n\t\t\t\tis_int($value) && $tempdata[$key] = $_SESSION[$key];\n\t\t\t}\n\t\t}\n\n\t\treturn $tempdata;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Set tempdata\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @param\tmixed\t$data\tSession data key or an associative array of items\n\t * @param\tmixed\t$value\tValue to store\n\t * @param\tint\t$ttl\tTime-to-live in seconds\n\t * @return\tvoid\n\t */\n\tpublic function set_tempdata($data, $value = NULL, $ttl = 300)\n\t{\n\t\t$this->set_userdata($data, $value);\n\t\t$this->mark_as_temp(is_array($data) ? array_keys($data) : $data, $ttl);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Unset tempdata\n\t *\n\t * Legacy CI_Session compatibility method\n\t *\n\t * @param\tmixed\t$data\tSession data key(s)\n\t * @return\tvoid\n\t */\n\tpublic function unset_tempdata($key)\n\t{\n\t\t$this->unmark_temp($key);\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/Session/SessionHandlerInterface.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * SessionHandlerInterface\n *\n * PHP 5.4 compatibility interface\n *\n * @package\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tSessions\n * @author\tAndrey Andreev\n * @link\thttps://codeigniter.com/user_guide/libraries/sessions.html\n */\ninterface SessionHandlerInterface {\n\n\tpublic function open($save_path, $name);\n\tpublic function close();\n\tpublic function read($session_id);\n\tpublic function write($session_id, $session_data);\n\tpublic function destroy($session_id);\n\tpublic function gc($maxlifetime);\n}\n"
  },
  {
    "path": "system/libraries/Session/Session_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Session Driver Class\n *\n * @package\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tSessions\n * @author\tAndrey Andreev\n * @link\thttps://codeigniter.com/user_guide/libraries/sessions.html\n */\nabstract class CI_Session_driver implements SessionHandlerInterface {\n\n\tprotected $_config;\n\n\t/**\n\t * Data fingerprint\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_fingerprint;\n\n\t/**\n\t * Lock placeholder\n\t *\n\t * @var\tmixed\n\t */\n\tprotected $_lock = FALSE;\n\n\t/**\n\t * Read session ID\n\t *\n\t * Used to detect session_regenerate_id() calls because PHP only calls\n\t * write() after regenerating the ID.\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_session_id;\n\n\t/**\n\t * Success and failure return values\n\t *\n\t * Necessary due to a bug in all PHP 5 versions where return values\n\t * from userspace handlers are not handled properly. PHP 7 fixes the\n\t * bug, so we need to return different values depending on the version.\n\t *\n\t * @see\thttps://wiki.php.net/rfc/session.user.return-value\n\t * @var\tmixed\n\t */\n\tprotected $_success, $_failure;\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tarray\t$params\tConfiguration parameters\n\t * @return\tvoid\n\t */\n\tpublic function __construct(&$params)\n\t{\n\t\t$this->_config =& $params;\n\n\t\tif (is_php('7'))\n\t\t{\n\t\t\t$this->_success = TRUE;\n\t\t\t$this->_failure = FALSE;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->_success = 0;\n\t\t\t$this->_failure = -1;\n\t\t}\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Cookie destroy\n\t *\n\t * Internal method to force removal of a cookie by the client\n\t * when session_destroy() is called.\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _cookie_destroy()\n\t{\n\t\treturn setcookie(\n\t\t\t$this->_config['cookie_name'],\n\t\t\tNULL,\n\t\t\t1,\n\t\t\t$this->_config['cookie_path'],\n\t\t\t$this->_config['cookie_domain'],\n\t\t\t$this->_config['cookie_secure'],\n\t\t\tTRUE\n\t\t);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get lock\n\t *\n\t * A dummy method allowing drivers with no locking functionality\n\t * (databases other than PostgreSQL and MySQL) to act as if they\n\t * do acquire a lock.\n\t *\n\t * @param\tstring\t$session_id\n\t * @return\tbool\n\t */\n\tprotected function _get_lock($session_id)\n\t{\n\t\t$this->_lock = TRUE;\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Release lock\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _release_lock()\n\t{\n\t\tif ($this->_lock)\n\t\t{\n\t\t\t$this->_lock = FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Fail\n\t *\n\t * Drivers other than the 'files' one don't (need to) use the\n\t * session.save_path INI setting, but that leads to confusing\n\t * error messages emitted by PHP when open() or write() fail,\n\t * as the message contains session.save_path ...\n\t * To work around the problem, the drivers will call this method\n\t * so that the INI is set just in time for the error message to\n\t * be properly generated.\n\t *\n\t * @return\tmixed\n\t */\n\tprotected function _fail()\n\t{\n\t\tini_set('session.save_path', config_item('sess_save_path'));\n\t\treturn $this->_failure;\n\t}\n}\n"
  },
  {
    "path": "system/libraries/Session/drivers/Session_database_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Session Database Driver\n *\n * @package\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tSessions\n * @author\tAndrey Andreev\n * @link\thttps://codeigniter.com/user_guide/libraries/sessions.html\n */\nclass CI_Session_database_driver extends CI_Session_driver implements SessionHandlerInterface {\n\n\t/**\n\t * DB object\n\t *\n\t * @var\tobject\n\t */\n\tprotected $_db;\n\n\t/**\n\t * Row exists flag\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_row_exists = FALSE;\n\n\t/**\n\t * Lock \"driver\" flag\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_platform;\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tarray\t$params\tConfiguration parameters\n\t * @return\tvoid\n\t */\n\tpublic function __construct(&$params)\n\t{\n\t\tparent::__construct($params);\n\n\t\t$CI =& get_instance();\n\t\tisset($CI->db) OR $CI->load->database();\n\t\t$this->_db = $CI->db;\n\n\t\tif ( ! $this->_db instanceof CI_DB_query_builder)\n\t\t{\n\t\t\tthrow new Exception('Query Builder not enabled for the configured database. Aborting.');\n\t\t}\n\t\telseif ($this->_db->pconnect)\n\t\t{\n\t\t\tthrow new Exception('Configured database connection is persistent. Aborting.');\n\t\t}\n\t\telseif ($this->_db->cache_on)\n\t\t{\n\t\t\tthrow new Exception('Configured database connection has cache enabled. Aborting.');\n\t\t}\n\n\t\t$db_driver = $this->_db->dbdriver.(empty($this->_db->subdriver) ? '' : '_'.$this->_db->subdriver);\n\t\tif (strpos($db_driver, 'mysql') !== FALSE)\n\t\t{\n\t\t\t$this->_platform = 'mysql';\n\t\t}\n\t\telseif (in_array($db_driver, array('postgre', 'pdo_pgsql'), TRUE))\n\t\t{\n\t\t\t$this->_platform = 'postgre';\n\t\t}\n\n\t\t// Note: BC work-around for the old 'sess_table_name' setting, should be removed in the future.\n\t\tif ( ! isset($this->_config['save_path']) && ($this->_config['save_path'] = config_item('sess_table_name')))\n\t\t{\n\t\t\tlog_message('debug', 'Session: \"sess_save_path\" is empty; using BC fallback to \"sess_table_name\".');\n\t\t}\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Open\n\t *\n\t * Initializes the database connection\n\t *\n\t * @param\tstring\t$save_path\tTable name\n\t * @param\tstring\t$name\t\tSession cookie name, unused\n\t * @return\tbool\n\t */\n\tpublic function open($save_path, $name)\n\t{\n\t\tif (empty($this->_db->conn_id) && ! $this->_db->db_connect())\n\t\t{\n\t\t\treturn $this->_fail();\n\t\t}\n\n\t\treturn $this->_success;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Read\n\t *\n\t * Reads session data and acquires a lock\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @return\tstring\tSerialized session data\n\t */\n\tpublic function read($session_id)\n\t{\n\t\tif ($this->_get_lock($session_id) !== FALSE)\n\t\t{\n\t\t\t// Prevent previous QB calls from messing with our queries\n\t\t\t$this->_db->reset_query();\n\n\t\t\t// Needed by write() to detect session_regenerate_id() calls\n\t\t\t$this->_session_id = $session_id;\n\n\t\t\t$this->_db\n\t\t\t\t->select('data')\n\t\t\t\t->from($this->_config['save_path'])\n\t\t\t\t->where('id', $session_id);\n\n\t\t\tif ($this->_config['match_ip'])\n\t\t\t{\n\t\t\t\t$this->_db->where('ip_address', $_SERVER['REMOTE_ADDR']);\n\t\t\t}\n\n\t\t\tif ( ! ($result = $this->_db->get()) OR ($result = $result->row()) === NULL)\n\t\t\t{\n\t\t\t\t// PHP7 will reuse the same SessionHandler object after\n\t\t\t\t// ID regeneration, so we need to explicitly set this to\n\t\t\t\t// FALSE instead of relying on the default ...\n\t\t\t\t$this->_row_exists = FALSE;\n\t\t\t\t$this->_fingerprint = md5('');\n\t\t\t\treturn '';\n\t\t\t}\n\n\t\t\t// PostgreSQL's variant of a BLOB datatype is Bytea, which is a\n\t\t\t// PITA to work with, so we use base64-encoded data in a TEXT\n\t\t\t// field instead.\n\t\t\t$result = ($this->_platform === 'postgre')\n\t\t\t\t? base64_decode(rtrim($result->data))\n\t\t\t\t: $result->data;\n\n\t\t\t$this->_fingerprint = md5($result);\n\t\t\t$this->_row_exists = TRUE;\n\t\t\treturn $result;\n\t\t}\n\n\t\t$this->_fingerprint = md5('');\n\t\treturn '';\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Write\n\t *\n\t * Writes (create / update) session data\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @param\tstring\t$session_data\tSerialized session data\n\t * @return\tbool\n\t */\n\tpublic function write($session_id, $session_data)\n\t{\n\t\t// Prevent previous QB calls from messing with our queries\n\t\t$this->_db->reset_query();\n\n\t\t// Was the ID regenerated?\n\t\tif ($session_id !== $this->_session_id)\n\t\t{\n\t\t\tif ( ! $this->_release_lock() OR ! $this->_get_lock($session_id))\n\t\t\t{\n\t\t\t\treturn $this->_fail();\n\t\t\t}\n\n\t\t\t$this->_row_exists = FALSE;\n\t\t\t$this->_session_id = $session_id;\n\t\t}\n\t\telseif ($this->_lock === FALSE)\n\t\t{\n\t\t\treturn $this->_fail();\n\t\t}\n\n\t\tif ($this->_row_exists === FALSE)\n\t\t{\n\t\t\t$insert_data = array(\n\t\t\t\t'id' => $session_id,\n\t\t\t\t'ip_address' => $_SERVER['REMOTE_ADDR'],\n\t\t\t\t'timestamp' => time(),\n\t\t\t\t'data' => ($this->_platform === 'postgre' ? base64_encode($session_data) : $session_data)\n\t\t\t);\n\n\t\t\tif ($this->_db->insert($this->_config['save_path'], $insert_data))\n\t\t\t{\n\t\t\t\t$this->_fingerprint = md5($session_data);\n\t\t\t\t$this->_row_exists = TRUE;\n\t\t\t\treturn $this->_success;\n\t\t\t}\n\n\t\t\treturn $this->_fail();\n\t\t}\n\n\t\t$this->_db->where('id', $session_id);\n\t\tif ($this->_config['match_ip'])\n\t\t{\n\t\t\t$this->_db->where('ip_address', $_SERVER['REMOTE_ADDR']);\n\t\t}\n\n\t\t$update_data = array('timestamp' => time());\n\t\tif ($this->_fingerprint !== md5($session_data))\n\t\t{\n\t\t\t$update_data['data'] = ($this->_platform === 'postgre')\n\t\t\t\t? base64_encode($session_data)\n\t\t\t\t: $session_data;\n\t\t}\n\n\t\tif ($this->_db->update($this->_config['save_path'], $update_data))\n\t\t{\n\t\t\t$this->_fingerprint = md5($session_data);\n\t\t\treturn $this->_success;\n\t\t}\n\n\t\treturn $this->_fail();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Close\n\t *\n\t * Releases locks\n\t *\n\t * @return\tbool\n\t */\n\tpublic function close()\n\t{\n\t\treturn ($this->_lock && ! $this->_release_lock())\n\t\t\t? $this->_fail()\n\t\t\t: $this->_success;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Destroy\n\t *\n\t * Destroys the current session.\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @return\tbool\n\t */\n\tpublic function destroy($session_id)\n\t{\n\t\tif ($this->_lock)\n\t\t{\n\t\t\t// Prevent previous QB calls from messing with our queries\n\t\t\t$this->_db->reset_query();\n\n\t\t\t$this->_db->where('id', $session_id);\n\t\t\tif ($this->_config['match_ip'])\n\t\t\t{\n\t\t\t\t$this->_db->where('ip_address', $_SERVER['REMOTE_ADDR']);\n\t\t\t}\n\n\t\t\tif ( ! $this->_db->delete($this->_config['save_path']))\n\t\t\t{\n\t\t\t\treturn $this->_fail();\n\t\t\t}\n\t\t}\n\n\t\tif ($this->close() === $this->_success)\n\t\t{\n\t\t\t$this->_cookie_destroy();\n\t\t\treturn $this->_success;\n\t\t}\n\n\t\treturn $this->_fail();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Garbage Collector\n\t *\n\t * Deletes expired sessions\n\t *\n\t * @param\tint \t$maxlifetime\tMaximum lifetime of sessions\n\t * @return\tbool\n\t */\n\tpublic function gc($maxlifetime)\n\t{\n\t\t// Prevent previous QB calls from messing with our queries\n\t\t$this->_db->reset_query();\n\n\t\treturn ($this->_db->delete($this->_config['save_path'], 'timestamp < '.(time() - $maxlifetime)))\n\t\t\t? $this->_success\n\t\t\t: $this->_fail();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get lock\n\t *\n\t * Acquires a lock, depending on the underlying platform.\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @return\tbool\n\t */\n\tprotected function _get_lock($session_id)\n\t{\n\t\tif ($this->_platform === 'mysql')\n\t\t{\n\t\t\t$arg = $session_id.($this->_config['match_ip'] ? '_'.$_SERVER['REMOTE_ADDR'] : '');\n\t\t\tif ($this->_db->query(\"SELECT GET_LOCK('\".$arg.\"', 300) AS ci_session_lock\")->row()->ci_session_lock)\n\t\t\t{\n\t\t\t\t$this->_lock = $arg;\n\t\t\t\treturn TRUE;\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\t\telseif ($this->_platform === 'postgre')\n\t\t{\n\t\t\t$arg = \"hashtext('\".$session_id.\"')\".($this->_config['match_ip'] ? \", hashtext('\".$_SERVER['REMOTE_ADDR'].\"')\" : '');\n\t\t\tif ($this->_db->simple_query('SELECT pg_advisory_lock('.$arg.')'))\n\t\t\t{\n\t\t\t\t$this->_lock = $arg;\n\t\t\t\treturn TRUE;\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn parent::_get_lock($session_id);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Release lock\n\t *\n\t * Releases a previously acquired lock\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _release_lock()\n\t{\n\t\tif ( ! $this->_lock)\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\tif ($this->_platform === 'mysql')\n\t\t{\n\t\t\tif ($this->_db->query(\"SELECT RELEASE_LOCK('\".$this->_lock.\"') AS ci_session_lock\")->row()->ci_session_lock)\n\t\t\t{\n\t\t\t\t$this->_lock = FALSE;\n\t\t\t\treturn TRUE;\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\t\telseif ($this->_platform === 'postgre')\n\t\t{\n\t\t\tif ($this->_db->simple_query('SELECT pg_advisory_unlock('.$this->_lock.')'))\n\t\t\t{\n\t\t\t\t$this->_lock = FALSE;\n\t\t\t\treturn TRUE;\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn parent::_release_lock();\n\t}\n}"
  },
  {
    "path": "system/libraries/Session/drivers/Session_files_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n*/\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Session Files Driver\n *\n * @package\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tSessions\n * @author\tAndrey Andreev\n * @link\thttps://codeigniter.com/user_guide/libraries/sessions.html\n */\nclass CI_Session_files_driver extends CI_Session_driver implements SessionHandlerInterface {\n\n\t/**\n\t * Save path\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_save_path;\n\n\t/**\n\t * File handle\n\t *\n\t * @var\tresource\n\t */\n\tprotected $_file_handle;\n\n\t/**\n\t * File name\n\t *\n\t * @var\tresource\n\t */\n\tprotected $_file_path;\n\n\t/**\n\t * File new flag\n\t *\n\t * @var\tbool\n\t */\n\tprotected $_file_new;\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tarray\t$params\tConfiguration parameters\n\t * @return\tvoid\n\t */\n\tpublic function __construct(&$params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif (isset($this->_config['save_path']))\n\t\t{\n\t\t\t$this->_config['save_path'] = rtrim($this->_config['save_path'], '/\\\\');\n\t\t\tini_set('session.save_path', $this->_config['save_path']);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlog_message('debug', 'Session: \"sess_save_path\" is empty; using \"session.save_path\" value from php.ini.');\n\t\t\t$this->_config['save_path'] = rtrim(ini_get('session.save_path'), '/\\\\');\n\t\t}\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Open\n\t *\n\t * Sanitizes the save_path directory.\n\t *\n\t * @param\tstring\t$save_path\tPath to session files' directory\n\t * @param\tstring\t$name\t\tSession cookie name\n\t * @return\tbool\n\t */\n\tpublic function open($save_path, $name)\n\t{\n\t\tif ( ! is_dir($save_path))\n\t\t{\n\t\t\tif ( ! mkdir($save_path, 0700, TRUE))\n\t\t\t{\n\t\t\t\tthrow new Exception(\"Session: Configured save path '\".$this->_config['save_path'].\"' is not a directory, doesn't exist or cannot be created.\");\n\t\t\t}\n\t\t}\n\t\telseif ( ! is_writable($save_path))\n\t\t{\n\t\t\tthrow new Exception(\"Session: Configured save path '\".$this->_config['save_path'].\"' is not writable by the PHP process.\");\n\t\t}\n\n\t\t$this->_config['save_path'] = $save_path;\n\t\t$this->_file_path = $this->_config['save_path'].DIRECTORY_SEPARATOR\n\t\t\t.$name // we'll use the session cookie name as a prefix to avoid collisions\n\t\t\t.($this->_config['match_ip'] ? md5($_SERVER['REMOTE_ADDR']) : '');\n\n\t\treturn $this->_success;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Read\n\t *\n\t * Reads session data and acquires a lock\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @return\tstring\tSerialized session data\n\t */\n\tpublic function read($session_id)\n\t{\n\t\t// This might seem weird, but PHP 5.6 introduces session_reset(),\n\t\t// which re-reads session data\n\t\tif ($this->_file_handle === NULL)\n\t\t{\n\t\t\t// Just using fopen() with 'c+b' mode would be perfect, but it is only\n\t\t\t// available since PHP 5.2.6 and we have to set permissions for new files,\n\t\t\t// so we'd have to hack around this ...\n\t\t\tif (($this->_file_new = ! file_exists($this->_file_path.$session_id)) === TRUE)\n\t\t\t{\n\t\t\t\tif (($this->_file_handle = fopen($this->_file_path.$session_id, 'w+b')) === FALSE)\n\t\t\t\t{\n\t\t\t\t\tlog_message('error', \"Session: File '\".$this->_file_path.$session_id.\"' doesn't exist and cannot be created.\");\n\t\t\t\t\treturn $this->_failure;\n\t\t\t\t}\n\t\t\t}\n\t\t\telseif (($this->_file_handle = fopen($this->_file_path.$session_id, 'r+b')) === FALSE)\n\t\t\t{\n\t\t\t\tlog_message('error', \"Session: Unable to open file '\".$this->_file_path.$session_id.\"'.\");\n\t\t\t\treturn $this->_failure;\n\t\t\t}\n\n\t\t\tif (flock($this->_file_handle, LOCK_EX) === FALSE)\n\t\t\t{\n\t\t\t\tlog_message('error', \"Session: Unable to obtain lock for file '\".$this->_file_path.$session_id.\"'.\");\n\t\t\t\tfclose($this->_file_handle);\n\t\t\t\t$this->_file_handle = NULL;\n\t\t\t\treturn $this->_failure;\n\t\t\t}\n\n\t\t\t// Needed by write() to detect session_regenerate_id() calls\n\t\t\t$this->_session_id = $session_id;\n\n\t\t\tif ($this->_file_new)\n\t\t\t{\n\t\t\t\tchmod($this->_file_path.$session_id, 0600);\n\t\t\t\t$this->_fingerprint = md5('');\n\t\t\t\treturn '';\n\t\t\t}\n\t\t}\n\t\t// We shouldn't need this, but apparently we do ...\n\t\t// See https://github.com/bcit-ci/CodeIgniter/issues/4039\n\t\telseif ($this->_file_handle === FALSE)\n\t\t{\n\t\t\treturn $this->_failure;\n\t\t}\n\t\telse\n\t\t{\n\t\t\trewind($this->_file_handle);\n\t\t}\n\n\t\t$session_data = '';\n\t\tfor ($read = 0, $length = filesize($this->_file_path.$session_id); $read < $length; $read += strlen($buffer))\n\t\t{\n\t\t\tif (($buffer = fread($this->_file_handle, $length - $read)) === FALSE)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t$session_data .= $buffer;\n\t\t}\n\n\t\t$this->_fingerprint = md5($session_data);\n\t\treturn $session_data;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Write\n\t *\n\t * Writes (create / update) session data\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @param\tstring\t$session_data\tSerialized session data\n\t * @return\tbool\n\t */\n\tpublic function write($session_id, $session_data)\n\t{\n\t\t// If the two IDs don't match, we have a session_regenerate_id() call\n\t\t// and we need to close the old handle and open a new one\n\t\tif ($session_id !== $this->_session_id && ($this->close() === $this->_failure OR $this->read($session_id) === $this->_failure))\n\t\t{\n\t\t\treturn $this->_failure;\n\t\t}\n\n\t\tif ( ! is_resource($this->_file_handle))\n\t\t{\n\t\t\treturn $this->_failure;\n\t\t}\n\t\telseif ($this->_fingerprint === md5($session_data))\n\t\t{\n\t\t\treturn ( ! $this->_file_new && ! touch($this->_file_path.$session_id))\n\t\t\t\t? $this->_failure\n\t\t\t\t: $this->_success;\n\t\t}\n\n\t\tif ( ! $this->_file_new)\n\t\t{\n\t\t\tftruncate($this->_file_handle, 0);\n\t\t\trewind($this->_file_handle);\n\t\t}\n\n\t\tif (($length = strlen($session_data)) > 0)\n\t\t{\n\t\t\tfor ($written = 0; $written < $length; $written += $result)\n\t\t\t{\n\t\t\t\tif (($result = fwrite($this->_file_handle, substr($session_data, $written))) === FALSE)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( ! is_int($result))\n\t\t\t{\n\t\t\t\t$this->_fingerprint = md5(substr($session_data, 0, $written));\n\t\t\t\tlog_message('error', 'Session: Unable to write data.');\n\t\t\t\treturn $this->_failure;\n\t\t\t}\n\t\t}\n\n\t\t$this->_fingerprint = md5($session_data);\n\t\treturn $this->_success;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Close\n\t *\n\t * Releases locks and closes file descriptor.\n\t *\n\t * @return\tbool\n\t */\n\tpublic function close()\n\t{\n\t\tif (is_resource($this->_file_handle))\n\t\t{\n\t\t\tflock($this->_file_handle, LOCK_UN);\n\t\t\tfclose($this->_file_handle);\n\n\t\t\t$this->_file_handle = $this->_file_new = $this->_session_id = NULL;\n\t\t}\n\n\t\treturn $this->_success;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Destroy\n\t *\n\t * Destroys the current session.\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @return\tbool\n\t */\n\tpublic function destroy($session_id)\n\t{\n\t\tif ($this->close() === $this->_success)\n\t\t{\n\t\t\tif (file_exists($this->_file_path.$session_id))\n\t\t\t{\n\t\t\t\t$this->_cookie_destroy();\n\t\t\t\treturn unlink($this->_file_path.$session_id)\n\t\t\t\t\t? $this->_success\n\t\t\t\t\t: $this->_failure;\n\t\t\t}\n\n\t\t\treturn $this->_success;\n\t\t}\n\t\telseif ($this->_file_path !== NULL)\n\t\t{\n\t\t\tclearstatcache();\n\t\t\tif (file_exists($this->_file_path.$session_id))\n\t\t\t{\n\t\t\t\t$this->_cookie_destroy();\n\t\t\t\treturn unlink($this->_file_path.$session_id)\n\t\t\t\t\t? $this->_success\n\t\t\t\t\t: $this->_failure;\n\t\t\t}\n\n\t\t\treturn $this->_success;\n\t\t}\n\n\t\treturn $this->_failure;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Garbage Collector\n\t *\n\t * Deletes expired sessions\n\t *\n\t * @param\tint \t$maxlifetime\tMaximum lifetime of sessions\n\t * @return\tbool\n\t */\n\tpublic function gc($maxlifetime)\n\t{\n\t\tif ( ! is_dir($this->_config['save_path']) OR ($directory = opendir($this->_config['save_path'])) === FALSE)\n\t\t{\n\t\t\tlog_message('debug', \"Session: Garbage collector couldn't list files under directory '\".$this->_config['save_path'].\"'.\");\n\t\t\treturn $this->_failure;\n\t\t}\n\n\t\t$ts = time() - $maxlifetime;\n\n\t\t$pattern = sprintf(\n\t\t\t'/^%s[0-9a-f]{%d}$/',\n\t\t\tpreg_quote($this->_config['cookie_name'], '/'),\n\t\t\t($this->_config['match_ip'] === TRUE ? 72 : 40)\n\t\t);\n\n\t\twhile (($file = readdir($directory)) !== FALSE)\n\t\t{\n\t\t\t// If the filename doesn't match this pattern, it's either not a session file or is not ours\n\t\t\tif ( ! preg_match($pattern, $file)\n\t\t\t\tOR ! is_file($this->_config['save_path'].DIRECTORY_SEPARATOR.$file)\n\t\t\t\tOR ($mtime = filemtime($this->_config['save_path'].DIRECTORY_SEPARATOR.$file)) === FALSE\n\t\t\t\tOR $mtime > $ts)\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tunlink($this->_config['save_path'].DIRECTORY_SEPARATOR.$file);\n\t\t}\n\n\t\tclosedir($directory);\n\n\t\treturn $this->_success;\n\t}\n\n}"
  },
  {
    "path": "system/libraries/Session/drivers/Session_memcached_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Session Memcached Driver\n *\n * @package\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tSessions\n * @author\tAndrey Andreev\n * @link\thttps://codeigniter.com/user_guide/libraries/sessions.html\n */\nclass CI_Session_memcached_driver extends CI_Session_driver implements SessionHandlerInterface {\n\n\t/**\n\t * Memcached instance\n\t *\n\t * @var\tMemcached\n\t */\n\tprotected $_memcached;\n\n\t/**\n\t * Key prefix\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_key_prefix = 'ci_session:';\n\n\t/**\n\t * Lock key\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_lock_key;\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tarray\t$params\tConfiguration parameters\n\t * @return\tvoid\n\t */\n\tpublic function __construct(&$params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif (empty($this->_config['save_path']))\n\t\t{\n\t\t\tlog_message('error', 'Session: No Memcached save path configured.');\n\t\t}\n\n\t\tif ($this->_config['match_ip'] === TRUE)\n\t\t{\n\t\t\t$this->_key_prefix .= $_SERVER['REMOTE_ADDR'].':';\n\t\t}\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Open\n\t *\n\t * Sanitizes save_path and initializes connections.\n\t *\n\t * @param\tstring\t$save_path\tServer path(s)\n\t * @param\tstring\t$name\t\tSession cookie name, unused\n\t * @return\tbool\n\t */\n\tpublic function open($save_path, $name)\n\t{\n\t\t$this->_memcached = new Memcached();\n\t\t$this->_memcached->setOption(Memcached::OPT_BINARY_PROTOCOL, TRUE); // required for touch() usage\n\t\t$server_list = array();\n\t\tforeach ($this->_memcached->getServerList() as $server)\n\t\t{\n\t\t\t$server_list[] = $server['host'].':'.$server['port'];\n\t\t}\n\n\t\tif ( ! preg_match_all('#,?([^,:]+)\\:(\\d{1,5})(?:\\:(\\d+))?#', $this->_config['save_path'], $matches, PREG_SET_ORDER))\n\t\t{\n\t\t\t$this->_memcached = NULL;\n\t\t\tlog_message('error', 'Session: Invalid Memcached save path format: '.$this->_config['save_path']);\n\t\t\treturn $this->_fail();\n\t\t}\n\n\t\tforeach ($matches as $match)\n\t\t{\n\t\t\t// If Memcached already has this server (or if the port is invalid), skip it\n\t\t\tif (in_array($match[1].':'.$match[2], $server_list, TRUE))\n\t\t\t{\n\t\t\t\tlog_message('debug', 'Session: Memcached server pool already has '.$match[1].':'.$match[2]);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( ! $this->_memcached->addServer($match[1], $match[2], isset($match[3]) ? $match[3] : 0))\n\t\t\t{\n\t\t\t\tlog_message('error', 'Could not add '.$match[1].':'.$match[2].' to Memcached server pool.');\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$server_list[] = $match[1].':'.$match[2];\n\t\t\t}\n\t\t}\n\n\t\tif (empty($server_list))\n\t\t{\n\t\t\tlog_message('error', 'Session: Memcached server pool is empty.');\n\t\t\treturn $this->_fail();\n\t\t}\n\n\t\treturn $this->_success;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Read\n\t *\n\t * Reads session data and acquires a lock\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @return\tstring\tSerialized session data\n\t */\n\tpublic function read($session_id)\n\t{\n\t\tif (isset($this->_memcached) && $this->_get_lock($session_id))\n\t\t{\n\t\t\t// Needed by write() to detect session_regenerate_id() calls\n\t\t\t$this->_session_id = $session_id;\n\n\t\t\t$session_data = (string) $this->_memcached->get($this->_key_prefix.$session_id);\n\t\t\t$this->_fingerprint = md5($session_data);\n\t\t\treturn $session_data;\n\t\t}\n\n\t\treturn $this->_fail();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Write\n\t *\n\t * Writes (create / update) session data\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @param\tstring\t$session_data\tSerialized session data\n\t * @return\tbool\n\t */\n\tpublic function write($session_id, $session_data)\n\t{\n\t\tif ( ! isset($this->_memcached))\n\t\t{\n\t\t\treturn $this->_fail();\n\t\t}\n\t\t// Was the ID regenerated?\n\t\telseif ($session_id !== $this->_session_id)\n\t\t{\n\t\t\tif ( ! $this->_release_lock() OR ! $this->_get_lock($session_id))\n\t\t\t{\n\t\t\t\treturn $this->_fail();\n\t\t\t}\n\n\t\t\t$this->_fingerprint = md5('');\n\t\t\t$this->_session_id = $session_id;\n\t\t}\n\n\t\tif (isset($this->_lock_key))\n\t\t{\n\t\t\t$key = $this->_key_prefix.$session_id;\n\n\t\t\t$this->_memcached->replace($this->_lock_key, time(), 300);\n\t\t\tif ($this->_fingerprint !== ($fingerprint = md5($session_data)))\n\t\t\t{\n\t\t\t\tif (\n\t\t\t\t\t$this->_memcached->replace($key, $session_data, $this->_config['expiration'])\n\t\t\t\t\tOR ($this->_memcached->getResultCode() === Memcached::RES_NOTFOUND && $this->_memcached->set($key, $session_data, $this->_config['expiration']))\n\t\t\t\t)\n\t\t\t\t{\n\t\t\t\t\t$this->_fingerprint = $fingerprint;\n\t\t\t\t\treturn $this->_success;\n\t\t\t\t}\n\n\t\t\t\treturn $this->_fail();\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\t$this->_memcached->touch($key, $this->_config['expiration'])\n\t\t\t\tOR ($this->_memcached->getResultCode() === Memcached::RES_NOTFOUND && $this->_memcached->set($key, $session_data, $this->_config['expiration']))\n\t\t\t)\n\t\t\t{\n\t\t\t\treturn $this->_success;\n\t\t\t}\n\t\t}\n\n\t\treturn $this->_fail();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Close\n\t *\n\t * Releases locks and closes connection.\n\t *\n\t * @return\tbool\n\t */\n\tpublic function close()\n\t{\n\t\tif (isset($this->_memcached))\n\t\t{\n\t\t\t$this->_release_lock();\n\t\t\tif ( ! $this->_memcached->quit())\n\t\t\t{\n\t\t\t\treturn $this->_fail();\n\t\t\t}\n\n\t\t\t$this->_memcached = NULL;\n\t\t\treturn $this->_success;\n\t\t}\n\n\t\treturn $this->_fail();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Destroy\n\t *\n\t * Destroys the current session.\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @return\tbool\n\t */\n\tpublic function destroy($session_id)\n\t{\n\t\tif (isset($this->_memcached, $this->_lock_key))\n\t\t{\n\t\t\t$this->_memcached->delete($this->_key_prefix.$session_id);\n\t\t\t$this->_cookie_destroy();\n\t\t\treturn $this->_success;\n\t\t}\n\n\t\treturn $this->_fail();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Garbage Collector\n\t *\n\t * Deletes expired sessions\n\t *\n\t * @param\tint \t$maxlifetime\tMaximum lifetime of sessions\n\t * @return\tbool\n\t */\n\tpublic function gc($maxlifetime)\n\t{\n\t\t// Not necessary, Memcached takes care of that.\n\t\treturn $this->_success;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get lock\n\t *\n\t * Acquires an (emulated) lock.\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @return\tbool\n\t */\n\tprotected function _get_lock($session_id)\n\t{\n\t\t// PHP 7 reuses the SessionHandler object on regeneration,\n\t\t// so we need to check here if the lock key is for the\n\t\t// correct session ID.\n\t\tif ($this->_lock_key === $this->_key_prefix.$session_id.':lock')\n\t\t{\n\t\t\tif ( ! $this->_memcached->replace($this->_lock_key, time(), 300))\n\t\t\t{\n\t\t\t\treturn ($this->_memcached->getResultCode() === Memcached::RES_NOTFOUND)\n\t\t\t\t\t? $this->_memcached->set($this->_lock_key, time(), 300)\n\t\t\t\t\t: FALSE;\n\t\t\t}\n\t\t}\n\n\t\t// 30 attempts to obtain a lock, in case another request already has it\n\t\t$lock_key = $this->_key_prefix.$session_id.':lock';\n\t\t$attempt = 0;\n\t\tdo\n\t\t{\n\t\t\tif ($this->_memcached->get($lock_key))\n\t\t\t{\n\t\t\t\tsleep(1);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( ! $this->_memcached->set($lock_key, time(), 300))\n\t\t\t{\n\t\t\t\tlog_message('error', 'Session: Error while trying to obtain lock for '.$this->_key_prefix.$session_id);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$this->_lock_key = $lock_key;\n\t\t\tbreak;\n\t\t}\n\t\twhile (++$attempt < 30);\n\n\t\tif ($attempt === 30)\n\t\t{\n\t\t\tlog_message('error', 'Session: Unable to obtain lock for '.$this->_key_prefix.$session_id.' after 30 attempts, aborting.');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->_lock = TRUE;\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Release lock\n\t *\n\t * Releases a previously acquired lock\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _release_lock()\n\t{\n\t\tif (isset($this->_memcached, $this->_lock_key) && $this->_lock)\n\t\t{\n\t\t\tif ( ! $this->_memcached->delete($this->_lock_key) && $this->_memcached->getResultCode() !== Memcached::RES_NOTFOUND)\n\t\t\t{\n\t\t\t\tlog_message('error', 'Session: Error while trying to free lock for '.$this->_lock_key);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$this->_lock_key = NULL;\n\t\t\t$this->_lock = FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n}"
  },
  {
    "path": "system/libraries/Session/drivers/Session_redis_driver.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 3.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * CodeIgniter Session Redis Driver\n *\n * @package\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tSessions\n * @author\tAndrey Andreev\n * @link\thttps://codeigniter.com/user_guide/libraries/sessions.html\n */\nclass CI_Session_redis_driver extends CI_Session_driver implements SessionHandlerInterface {\n\n\t/**\n\t * phpRedis instance\n\t *\n\t * @var\tresource\n\t */\n\tprotected $_redis;\n\n\t/**\n\t * Key prefix\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_key_prefix = 'ci_session:';\n\n\t/**\n\t * Lock key\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_lock_key;\n\n\t/**\n\t * Key exists flag\n\t *\n\t * @var bool\n\t */\n\tprotected $_key_exists = FALSE;\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Class constructor\n\t *\n\t * @param\tarray\t$params\tConfiguration parameters\n\t * @return\tvoid\n\t */\n\tpublic function __construct(&$params)\n\t{\n\t\tparent::__construct($params);\n\n\t\tif (empty($this->_config['save_path']))\n\t\t{\n\t\t\tlog_message('error', 'Session: No Redis save path configured.');\n\t\t}\n\t\telseif (preg_match('#(?:tcp://)?([^:?]+)(?:\\:(\\d+))?(\\?.+)?#', $this->_config['save_path'], $matches))\n\t\t{\n\t\t\tisset($matches[3]) OR $matches[3] = ''; // Just to avoid undefined index notices below\n\t\t\t$this->_config['save_path'] = array(\n\t\t\t\t'host' => $matches[1],\n\t\t\t\t'port' => empty($matches[2]) ? NULL : $matches[2],\n\t\t\t\t'password' => preg_match('#auth=([^\\s&]+)#', $matches[3], $match) ? $match[1] : NULL,\n\t\t\t\t'database' => preg_match('#database=(\\d+)#', $matches[3], $match) ? (int) $match[1] : NULL,\n\t\t\t\t'timeout' => preg_match('#timeout=(\\d+\\.\\d+)#', $matches[3], $match) ? (float) $match[1] : NULL\n\t\t\t);\n\n\t\t\tpreg_match('#prefix=([^\\s&]+)#', $matches[3], $match) && $this->_key_prefix = $match[1];\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlog_message('error', 'Session: Invalid Redis save path format: '.$this->_config['save_path']);\n\t\t}\n\n\t\tif ($this->_config['match_ip'] === TRUE)\n\t\t{\n\t\t\t$this->_key_prefix .= $_SERVER['REMOTE_ADDR'].':';\n\t\t}\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Open\n\t *\n\t * Sanitizes save_path and initializes connection.\n\t *\n\t * @param\tstring\t$save_path\tServer path\n\t * @param\tstring\t$name\t\tSession cookie name, unused\n\t * @return\tbool\n\t */\n\tpublic function open($save_path, $name)\n\t{\n\t\tif (empty($this->_config['save_path']))\n\t\t{\n\t\t\treturn $this->_fail();\n\t\t}\n\n\t\t$redis = new Redis();\n\t\tif ( ! $redis->connect($this->_config['save_path']['host'], $this->_config['save_path']['port'], $this->_config['save_path']['timeout']))\n\t\t{\n\t\t\tlog_message('error', 'Session: Unable to connect to Redis with the configured settings.');\n\t\t}\n\t\telseif (isset($this->_config['save_path']['password']) && ! $redis->auth($this->_config['save_path']['password']))\n\t\t{\n\t\t\tlog_message('error', 'Session: Unable to authenticate to Redis instance.');\n\t\t}\n\t\telseif (isset($this->_config['save_path']['database']) && ! $redis->select($this->_config['save_path']['database']))\n\t\t{\n\t\t\tlog_message('error', 'Session: Unable to select Redis database with index '.$this->_config['save_path']['database']);\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->_redis = $redis;\n\t\t\treturn $this->_success;\n\t\t}\n\n\t\treturn $this->_fail();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Read\n\t *\n\t * Reads session data and acquires a lock\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @return\tstring\tSerialized session data\n\t */\n\tpublic function read($session_id)\n\t{\n\t\tif (isset($this->_redis) && $this->_get_lock($session_id))\n\t\t{\n\t\t\t// Needed by write() to detect session_regenerate_id() calls\n\t\t\t$this->_session_id = $session_id;\n\n\t\t\t$session_data = $this->_redis->get($this->_key_prefix.$session_id);\n\n\t\t\tis_string($session_data)\n\t\t\t\t? $this->_key_exists = TRUE\n\t\t\t\t: $session_data = '';\n\n\t\t\t$this->_fingerprint = md5($session_data);\n\t\t\treturn $session_data;\n\t\t}\n\n\t\treturn $this->_fail();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Write\n\t *\n\t * Writes (create / update) session data\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @param\tstring\t$session_data\tSerialized session data\n\t * @return\tbool\n\t */\n\tpublic function write($session_id, $session_data)\n\t{\n\t\tif ( ! isset($this->_redis))\n\t\t{\n\t\t\treturn $this->_fail();\n\t\t}\n\t\t// Was the ID regenerated?\n\t\telseif ($session_id !== $this->_session_id)\n\t\t{\n\t\t\tif ( ! $this->_release_lock() OR ! $this->_get_lock($session_id))\n\t\t\t{\n\t\t\t\treturn $this->_fail();\n\t\t\t}\n\n\t\t\t$this->_key_exists = FALSE;\n\t\t\t$this->_session_id = $session_id;\n\t\t}\n\n\t\tif (isset($this->_lock_key))\n\t\t{\n\t\t\t$this->_redis->setTimeout($this->_lock_key, 300);\n\t\t\tif ($this->_fingerprint !== ($fingerprint = md5($session_data)) OR $this->_key_exists === FALSE)\n\t\t\t{\n\t\t\t\tif ($this->_redis->set($this->_key_prefix.$session_id, $session_data, $this->_config['expiration']))\n\t\t\t\t{\n\t\t\t\t\t$this->_fingerprint = $fingerprint;\n\t\t\t\t\t$this->_key_exists = TRUE;\n\t\t\t\t\treturn $this->_success;\n\t\t\t\t}\n\n\t\t\t\treturn $this->_fail();\n\t\t\t}\n\n\t\t\treturn ($this->_redis->setTimeout($this->_key_prefix.$session_id, $this->_config['expiration']))\n\t\t\t\t? $this->_success\n\t\t\t\t: $this->_fail();\n\t\t}\n\n\t\treturn $this->_fail();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Close\n\t *\n\t * Releases locks and closes connection.\n\t *\n\t * @return\tbool\n\t */\n\tpublic function close()\n\t{\n\t\tif (isset($this->_redis))\n\t\t{\n\t\t\ttry {\n\t\t\t\tif ($this->_redis->ping() === '+PONG')\n\t\t\t\t{\n\t\t\t\t\t$this->_release_lock();\n\t\t\t\t\tif ($this->_redis->close() === FALSE)\n\t\t\t\t\t{\n\t\t\t\t\t\treturn $this->_fail();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (RedisException $e)\n\t\t\t{\n\t\t\t\tlog_message('error', 'Session: Got RedisException on close(): '.$e->getMessage());\n\t\t\t}\n\n\t\t\t$this->_redis = NULL;\n\t\t\treturn $this->_success;\n\t\t}\n\n\t\treturn $this->_success;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Destroy\n\t *\n\t * Destroys the current session.\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @return\tbool\n\t */\n\tpublic function destroy($session_id)\n\t{\n\t\tif (isset($this->_redis, $this->_lock_key))\n\t\t{\n\t\t\tif (($result = $this->_redis->delete($this->_key_prefix.$session_id)) !== 1)\n\t\t\t{\n\t\t\t\tlog_message('debug', 'Session: Redis::delete() expected to return 1, got '.var_export($result, TRUE).' instead.');\n\t\t\t}\n\n\t\t\t$this->_cookie_destroy();\n\t\t\treturn $this->_success;\n\t\t}\n\n\t\treturn $this->_fail();\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Garbage Collector\n\t *\n\t * Deletes expired sessions\n\t *\n\t * @param\tint \t$maxlifetime\tMaximum lifetime of sessions\n\t * @return\tbool\n\t */\n\tpublic function gc($maxlifetime)\n\t{\n\t\t// Not necessary, Redis takes care of that.\n\t\treturn $this->_success;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Get lock\n\t *\n\t * Acquires an (emulated) lock.\n\t *\n\t * @param\tstring\t$session_id\tSession ID\n\t * @return\tbool\n\t */\n\tprotected function _get_lock($session_id)\n\t{\n\t\t// PHP 7 reuses the SessionHandler object on regeneration,\n\t\t// so we need to check here if the lock key is for the\n\t\t// correct session ID.\n\t\tif ($this->_lock_key === $this->_key_prefix.$session_id.':lock')\n\t\t{\n\t\t\treturn $this->_redis->setTimeout($this->_lock_key, 300);\n\t\t}\n\n\t\t// 30 attempts to obtain a lock, in case another request already has it\n\t\t$lock_key = $this->_key_prefix.$session_id.':lock';\n\t\t$attempt = 0;\n\t\tdo\n\t\t{\n\t\t\tif (($ttl = $this->_redis->ttl($lock_key)) > 0)\n\t\t\t{\n\t\t\t\tsleep(1);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ( ! $this->_redis->setex($lock_key, 300, time()))\n\t\t\t{\n\t\t\t\tlog_message('error', 'Session: Error while trying to obtain lock for '.$this->_key_prefix.$session_id);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$this->_lock_key = $lock_key;\n\t\t\tbreak;\n\t\t}\n\t\twhile (++$attempt < 30);\n\n\t\tif ($attempt === 30)\n\t\t{\n\t\t\tlog_message('error', 'Session: Unable to obtain lock for '.$this->_key_prefix.$session_id.' after 30 attempts, aborting.');\n\t\t\treturn FALSE;\n\t\t}\n\t\telseif ($ttl === -1)\n\t\t{\n\t\t\tlog_message('debug', 'Session: Lock for '.$this->_key_prefix.$session_id.' had no TTL, overriding.');\n\t\t}\n\n\t\t$this->_lock = TRUE;\n\t\treturn TRUE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Release lock\n\t *\n\t * Releases a previously acquired lock\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _release_lock()\n\t{\n\t\tif (isset($this->_redis, $this->_lock_key) && $this->_lock)\n\t\t{\n\t\t\tif ( ! $this->_redis->delete($this->_lock_key))\n\t\t\t{\n\t\t\t\tlog_message('error', 'Session: Error while trying to free lock for '.$this->_lock_key);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$this->_lock_key = NULL;\n\t\t\t$this->_lock = FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/Session/drivers/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/libraries/Session/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  },
  {
    "path": "system/libraries/Table.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.3.1\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * HTML Table Generating Class\n *\n * Lets you create tables manually or from database result objects, or arrays.\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tHTML Tables\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/table.html\n */\nclass CI_Table {\n\n\t/**\n\t * Data for table rows\n\t *\n\t * @var array\n\t */\n\tpublic $rows\t\t= array();\n\n\t/**\n\t * Data for table heading\n\t *\n\t * @var array\n\t */\n\tpublic $heading\t\t= array();\n\n\t/**\n\t * Whether or not to automatically create the table header\n\t *\n\t * @var bool\n\t */\n\tpublic $auto_heading\t= TRUE;\n\n\t/**\n\t * Table caption\n\t *\n\t * @var string\n\t */\n\tpublic $caption\t\t= NULL;\n\n\t/**\n\t * Table layout template\n\t *\n\t * @var array\n\t */\n\tpublic $template\t= NULL;\n\n\t/**\n\t * Newline setting\n\t *\n\t * @var string\n\t */\n\tpublic $newline\t\t= \"\\n\";\n\n\t/**\n\t * Contents of empty cells\n\t *\n\t * @var string\n\t */\n\tpublic $empty_cells\t= '';\n\n\t/**\n\t * Callback for custom table layout\n\t *\n\t * @var function\n\t */\n\tpublic $function\t= NULL;\n\n\t/**\n\t * Set the template from the table config file if it exists\n\t *\n\t * @param\tarray\t$config\t(default: array())\n\t * @return\tvoid\n\t */\n\tpublic function __construct($config = array())\n\t{\n\t\t// initialize config\n\t\tforeach ($config as $key => $val)\n\t\t{\n\t\t\t$this->template[$key] = $val;\n\t\t}\n\n\t\tlog_message('info', 'Table Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the template\n\t *\n\t * @param\tarray\t$template\n\t * @return\tbool\n\t */\n\tpublic function set_template($template)\n\t{\n\t\tif ( ! is_array($template))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->template = $template;\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the table heading\n\t *\n\t * Can be passed as an array or discreet params\n\t *\n\t * @param\tmixed\n\t * @return\tCI_Table\n\t */\n\tpublic function set_heading($args = array())\n\t{\n\t\t$this->heading = $this->_prep_args(func_get_args());\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set columns. Takes a one-dimensional array as input and creates\n\t * a multi-dimensional array with a depth equal to the number of\n\t * columns. This allows a single array with many elements to be\n\t * displayed in a table that has a fixed column count.\n\t *\n\t * @param\tarray\t$array\n\t * @param\tint\t$col_limit\n\t * @return\tarray\n\t */\n\tpublic function make_columns($array = array(), $col_limit = 0)\n\t{\n\t\tif ( ! is_array($array) OR count($array) === 0 OR ! is_int($col_limit))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Turn off the auto-heading feature since it's doubtful we\n\t\t// will want headings from a one-dimensional array\n\t\t$this->auto_heading = FALSE;\n\n\t\tif ($col_limit === 0)\n\t\t{\n\t\t\treturn $array;\n\t\t}\n\n\t\t$new = array();\n\t\tdo\n\t\t{\n\t\t\t$temp = array_splice($array, 0, $col_limit);\n\n\t\t\tif (count($temp) < $col_limit)\n\t\t\t{\n\t\t\t\tfor ($i = count($temp); $i < $col_limit; $i++)\n\t\t\t\t{\n\t\t\t\t\t$temp[] = '&nbsp;';\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$new[] = $temp;\n\t\t}\n\t\twhile (count($array) > 0);\n\n\t\treturn $new;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set \"empty\" cells\n\t *\n\t * Can be passed as an array or discreet params\n\t *\n\t * @param\tmixed\t$value\n\t * @return\tCI_Table\n\t */\n\tpublic function set_empty($value)\n\t{\n\t\t$this->empty_cells = $value;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add a table row\n\t *\n\t * Can be passed as an array or discreet params\n\t *\n\t * @param\tmixed\n\t * @return\tCI_Table\n\t */\n\tpublic function add_row($args = array())\n\t{\n\t\t$this->rows[] = $this->_prep_args(func_get_args());\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prep Args\n\t *\n\t * Ensures a standard associative array format for all cell data\n\t *\n\t * @param\tarray\n\t * @return\tarray\n\t */\n\tprotected function _prep_args($args)\n\t{\n\t\t// If there is no $args[0], skip this and treat as an associative array\n\t\t// This can happen if there is only a single key, for example this is passed to table->generate\n\t\t// array(array('foo'=>'bar'))\n\t\tif (isset($args[0]) && count($args) === 1 && is_array($args[0]) && ! isset($args[0]['data']))\n\t\t{\n\t\t\t$args = $args[0];\n\t\t}\n\n\t\tforeach ($args as $key => $val)\n\t\t{\n\t\t\tis_array($val) OR $args[$key] = array('data' => $val);\n\t\t}\n\n\t\treturn $args;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add a table caption\n\t *\n\t * @param\tstring\t$caption\n\t * @return\tCI_Table\n\t */\n\tpublic function set_caption($caption)\n\t{\n\t\t$this->caption = $caption;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Generate the table\n\t *\n\t * @param\tmixed\t$table_data\n\t * @return\tstring\n\t */\n\tpublic function generate($table_data = NULL)\n\t{\n\t\t// The table data can optionally be passed to this function\n\t\t// either as a database result object or an array\n\t\tif ( ! empty($table_data))\n\t\t{\n\t\t\tif ($table_data instanceof CI_DB_result)\n\t\t\t{\n\t\t\t\t$this->_set_from_db_result($table_data);\n\t\t\t}\n\t\t\telseif (is_array($table_data))\n\t\t\t{\n\t\t\t\t$this->_set_from_array($table_data);\n\t\t\t}\n\t\t}\n\n\t\t// Is there anything to display? No? Smite them!\n\t\tif (empty($this->heading) && empty($this->rows))\n\t\t{\n\t\t\treturn 'Undefined table data';\n\t\t}\n\n\t\t// Compile and validate the template date\n\t\t$this->_compile_template();\n\n\t\t// Validate a possibly existing custom cell manipulation function\n\t\tif (isset($this->function) && ! is_callable($this->function))\n\t\t{\n\t\t\t$this->function = NULL;\n\t\t}\n\n\t\t// Build the table!\n\n\t\t$out = $this->template['table_open'].$this->newline;\n\n\t\t// Add any caption here\n\t\tif ($this->caption)\n\t\t{\n\t\t\t$out .= '<caption>'.$this->caption.'</caption>'.$this->newline;\n\t\t}\n\n\t\t// Is there a table heading to display?\n\t\tif ( ! empty($this->heading))\n\t\t{\n\t\t\t$out .= $this->template['thead_open'].$this->newline.$this->template['heading_row_start'].$this->newline;\n\n\t\t\tforeach ($this->heading as $heading)\n\t\t\t{\n\t\t\t\t$temp = $this->template['heading_cell_start'];\n\n\t\t\t\tforeach ($heading as $key => $val)\n\t\t\t\t{\n\t\t\t\t\tif ($key !== 'data')\n\t\t\t\t\t{\n\t\t\t\t\t\t$temp = str_replace('<th', '<th '.$key.'=\"'.$val.'\"', $temp);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t$out .= $temp.(isset($heading['data']) ? $heading['data'] : '').$this->template['heading_cell_end'];\n\t\t\t}\n\n\t\t\t$out .= $this->template['heading_row_end'].$this->newline.$this->template['thead_close'].$this->newline;\n\t\t}\n\n\t\t// Build the table rows\n\t\tif ( ! empty($this->rows))\n\t\t{\n\t\t\t$out .= $this->template['tbody_open'].$this->newline;\n\n\t\t\t$i = 1;\n\t\t\tforeach ($this->rows as $row)\n\t\t\t{\n\t\t\t\tif ( ! is_array($row))\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t// We use modulus to alternate the row colors\n\t\t\t\t$name = fmod($i++, 2) ? '' : 'alt_';\n\n\t\t\t\t$out .= $this->template['row_'.$name.'start'].$this->newline;\n\n\t\t\t\tforeach ($row as $cell)\n\t\t\t\t{\n\t\t\t\t\t$temp = $this->template['cell_'.$name.'start'];\n\n\t\t\t\t\tforeach ($cell as $key => $val)\n\t\t\t\t\t{\n\t\t\t\t\t\tif ($key !== 'data')\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$temp = str_replace('<td', '<td '.$key.'=\"'.$val.'\"', $temp);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t$cell = isset($cell['data']) ? $cell['data'] : '';\n\t\t\t\t\t$out .= $temp;\n\n\t\t\t\t\tif ($cell === '' OR $cell === NULL)\n\t\t\t\t\t{\n\t\t\t\t\t\t$out .= $this->empty_cells;\n\t\t\t\t\t}\n\t\t\t\t\telseif (isset($this->function))\n\t\t\t\t\t{\n\t\t\t\t\t\t$out .= call_user_func($this->function, $cell);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$out .= $cell;\n\t\t\t\t\t}\n\n\t\t\t\t\t$out .= $this->template['cell_'.$name.'end'];\n\t\t\t\t}\n\n\t\t\t\t$out .= $this->template['row_'.$name.'end'].$this->newline;\n\t\t\t}\n\n\t\t\t$out .= $this->template['tbody_close'].$this->newline;\n\t\t}\n\n\t\t$out .= $this->template['table_close'];\n\n\t\t// Clear table class properties before generating the table\n\t\t$this->clear();\n\n\t\treturn $out;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Clears the table arrays.  Useful if multiple tables are being generated\n\t *\n\t * @return\tCI_Table\n\t */\n\tpublic function clear()\n\t{\n\t\t$this->rows = array();\n\t\t$this->heading = array();\n\t\t$this->auto_heading = TRUE;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set table data from a database result object\n\t *\n\t * @param\tCI_DB_result\t$db_result\tDatabase result object\n\t * @return\tvoid\n\t */\n\tprotected function _set_from_db_result($object)\n\t{\n\t\t// First generate the headings from the table column names\n\t\tif ($this->auto_heading === TRUE && empty($this->heading))\n\t\t{\n\t\t\t$this->heading = $this->_prep_args($object->list_fields());\n\t\t}\n\n\t\tforeach ($object->result_array() as $row)\n\t\t{\n\t\t\t$this->rows[] = $this->_prep_args($row);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set table data from an array\n\t *\n\t * @param\tarray\t$data\n\t * @return\tvoid\n\t */\n\tprotected function _set_from_array($data)\n\t{\n\t\tif ($this->auto_heading === TRUE && empty($this->heading))\n\t\t{\n\t\t\t$this->heading = $this->_prep_args(array_shift($data));\n\t\t}\n\n\t\tforeach ($data as &$row)\n\t\t{\n\t\t\t$this->rows[] = $this->_prep_args($row);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile Template\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _compile_template()\n\t{\n\t\tif ($this->template === NULL)\n\t\t{\n\t\t\t$this->template = $this->_default_template();\n\t\t\treturn;\n\t\t}\n\n\t\t$this->temp = $this->_default_template();\n\t\tforeach (array('table_open', 'thead_open', 'thead_close', 'heading_row_start', 'heading_row_end', 'heading_cell_start', 'heading_cell_end', 'tbody_open', 'tbody_close', 'row_start', 'row_end', 'cell_start', 'cell_end', 'row_alt_start', 'row_alt_end', 'cell_alt_start', 'cell_alt_end', 'table_close') as $val)\n\t\t{\n\t\t\tif ( ! isset($this->template[$val]))\n\t\t\t{\n\t\t\t\t$this->template[$val] = $this->temp[$val];\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Default Template\n\t *\n\t * @return\tarray\n\t */\n\tprotected function _default_template()\n\t{\n\t\treturn array(\n\t\t\t'table_open'\t\t=> '<table border=\"0\" cellpadding=\"4\" cellspacing=\"0\">',\n\n\t\t\t'thead_open'\t\t=> '<thead>',\n\t\t\t'thead_close'\t\t=> '</thead>',\n\n\t\t\t'heading_row_start'\t=> '<tr>',\n\t\t\t'heading_row_end'\t=> '</tr>',\n\t\t\t'heading_cell_start'\t=> '<th>',\n\t\t\t'heading_cell_end'\t=> '</th>',\n\n\t\t\t'tbody_open'\t\t=> '<tbody>',\n\t\t\t'tbody_close'\t\t=> '</tbody>',\n\n\t\t\t'row_start'\t\t=> '<tr>',\n\t\t\t'row_end'\t\t=> '</tr>',\n\t\t\t'cell_start'\t\t=> '<td>',\n\t\t\t'cell_end'\t\t=> '</td>',\n\n\t\t\t'row_alt_start'\t\t=> '<tr>',\n\t\t\t'row_alt_end'\t\t=> '</tr>',\n\t\t\t'cell_alt_start'\t=> '<td>',\n\t\t\t'cell_alt_end'\t\t=> '</td>',\n\n\t\t\t'table_close'\t\t=> '</table>'\n\t\t);\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/Trackback.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Trackback Class\n *\n * Trackback Sending/Receiving Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tTrackbacks\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/trackback.html\n */\nclass CI_Trackback {\n\n\t/**\n\t * Character set\n\t *\n\t * @var\tstring\n\t */\n\tpublic $charset = 'UTF-8';\n\n\t/**\n\t * Trackback data\n\t *\n\t * @var\tarray\n\t */\n\tpublic $data = array(\n\t\t'url' => '',\n\t\t'title' => '',\n\t\t'excerpt' => '',\n\t\t'blog_name' => '',\n\t\t'charset' => ''\n\t);\n\n\t/**\n\t * Convert ASCII flag\n\t *\n\t * Whether to convert high-ASCII and MS Word\n\t * characters to HTML entities.\n\t *\n\t * @var\tbool\n\t */\n\tpublic $convert_ascii = TRUE;\n\n\t/**\n\t * Response\n\t *\n\t * @var\tstring\n\t */\n\tpublic $response = '';\n\n\t/**\n\t * Error messages list\n\t *\n\t * @var\tstring[]\n\t */\n\tpublic $error_msg = array();\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\tlog_message('info', 'Trackback Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send Trackback\n\t *\n\t * @param\tarray\n\t * @return\tbool\n\t */\n\tpublic function send($tb_data)\n\t{\n\t\tif ( ! is_array($tb_data))\n\t\t{\n\t\t\t$this->set_error('The send() method must be passed an array');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Pre-process the Trackback Data\n\t\tforeach (array('url', 'title', 'excerpt', 'blog_name', 'ping_url') as $item)\n\t\t{\n\t\t\tif ( ! isset($tb_data[$item]))\n\t\t\t{\n\t\t\t\t$this->set_error('Required item missing: '.$item);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tswitch ($item)\n\t\t\t{\n\t\t\t\tcase 'ping_url':\n\t\t\t\t\t$$item = $this->extract_urls($tb_data[$item]);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'excerpt':\n\t\t\t\t\t$$item = $this->limit_characters($this->convert_xml(strip_tags(stripslashes($tb_data[$item]))));\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'url':\n\t\t\t\t\t$$item = str_replace('&#45;', '-', $this->convert_xml(strip_tags(stripslashes($tb_data[$item]))));\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\t$$item = $this->convert_xml(strip_tags(stripslashes($tb_data[$item])));\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// Convert High ASCII Characters\n\t\t\tif ($this->convert_ascii === TRUE && in_array($item, array('excerpt', 'title', 'blog_name'), TRUE))\n\t\t\t{\n\t\t\t\t$$item = $this->convert_ascii($$item);\n\t\t\t}\n\t\t}\n\n\t\t// Build the Trackback data string\n\t\t$charset = isset($tb_data['charset']) ? $tb_data['charset'] : $this->charset;\n\n\t\t$data = 'url='.rawurlencode($url).'&title='.rawurlencode($title).'&blog_name='.rawurlencode($blog_name)\n\t\t\t.'&excerpt='.rawurlencode($excerpt).'&charset='.rawurlencode($charset);\n\n\t\t// Send Trackback(s)\n\t\t$return = TRUE;\n\t\tif (count($ping_url) > 0)\n\t\t{\n\t\t\tforeach ($ping_url as $url)\n\t\t\t{\n\t\t\t\tif ($this->process($url, $data) === FALSE)\n\t\t\t\t{\n\t\t\t\t\t$return = FALSE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn $return;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Receive Trackback  Data\n\t *\n\t * This function simply validates the incoming TB data.\n\t * It returns FALSE on failure and TRUE on success.\n\t * If the data is valid it is set to the $this->data array\n\t * so that it can be inserted into a database.\n\t *\n\t * @return\tbool\n\t */\n\tpublic function receive()\n\t{\n\t\tforeach (array('url', 'title', 'blog_name', 'excerpt') as $val)\n\t\t{\n\t\t\tif (empty($_POST[$val]))\n\t\t\t{\n\t\t\t\t$this->set_error('The following required POST variable is missing: '.$val);\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\t$this->data['charset'] = isset($_POST['charset']) ? strtoupper(trim($_POST['charset'])) : 'auto';\n\n\t\t\tif ($val !== 'url' && MB_ENABLED === TRUE)\n\t\t\t{\n\t\t\t\tif (MB_ENABLED === TRUE)\n\t\t\t\t{\n\t\t\t\t\t$_POST[$val] = mb_convert_encoding($_POST[$val], $this->charset, $this->data['charset']);\n\t\t\t\t}\n\t\t\t\telseif (ICONV_ENABLED === TRUE)\n\t\t\t\t{\n\t\t\t\t\t$_POST[$val] = @iconv($this->data['charset'], $this->charset.'//IGNORE', $_POST[$val]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$_POST[$val] = ($val !== 'url') ? $this->convert_xml(strip_tags($_POST[$val])) : strip_tags($_POST[$val]);\n\n\t\t\tif ($val === 'excerpt')\n\t\t\t{\n\t\t\t\t$_POST['excerpt'] = $this->limit_characters($_POST['excerpt']);\n\t\t\t}\n\n\t\t\t$this->data[$val] = $_POST[$val];\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send Trackback Error Message\n\t *\n\t * Allows custom errors to be set. By default it\n\t * sends the \"incomplete information\" error, as that's\n\t * the most common one.\n\t *\n\t * @param\tstring\n\t * @return\tvoid\n\t */\n\tpublic function send_error($message = 'Incomplete Information')\n\t{\n\t\texit('<?xml version=\"1.0\" encoding=\"utf-8\"?'.\">\\n<response>\\n<error>1</error>\\n<message>\".$message.\"</message>\\n</response>\");\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send Trackback Success Message\n\t *\n\t * This should be called when a trackback has been\n\t * successfully received and inserted.\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function send_success()\n\t{\n\t\texit('<?xml version=\"1.0\" encoding=\"utf-8\"?'.\">\\n<response>\\n<error>0</error>\\n</response>\");\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fetch a particular item\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function data($item)\n\t{\n\t\treturn isset($this->data[$item]) ? $this->data[$item] : '';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Process Trackback\n\t *\n\t * Opens a socket connection and passes the data to\n\t * the server. Returns TRUE on success, FALSE on failure\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tbool\n\t */\n\tpublic function process($url, $data)\n\t{\n\t\t$target = parse_url($url);\n\n\t\t// Open the socket\n\t\tif ( ! $fp = @fsockopen($target['host'], 80))\n\t\t{\n\t\t\t$this->set_error('Invalid Connection: '.$url);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Build the path\n\t\t$path = isset($target['path']) ? $target['path'] : $url;\n\t\tempty($target['query']) OR $path .= '?'.$target['query'];\n\n\t\t// Add the Trackback ID to the data string\n\t\tif ($id = $this->get_id($url))\n\t\t{\n\t\t\t$data = 'tb_id='.$id.'&'.$data;\n\t\t}\n\n\t\t// Transfer the data\n\t\tfputs($fp, 'POST '.$path.\" HTTP/1.0\\r\\n\");\n\t\tfputs($fp, 'Host: '.$target['host'].\"\\r\\n\");\n\t\tfputs($fp, \"Content-type: application/x-www-form-urlencoded\\r\\n\");\n\t\tfputs($fp, 'Content-length: '.strlen($data).\"\\r\\n\");\n\t\tfputs($fp, \"Connection: close\\r\\n\\r\\n\");\n\t\tfputs($fp, $data);\n\n\t\t// Was it successful?\n\n\t\t$this->response = '';\n\t\twhile ( ! feof($fp))\n\t\t{\n\t\t\t$this->response .= fgets($fp, 128);\n\t\t}\n\t\t@fclose($fp);\n\n\t\tif (stripos($this->response, '<error>0</error>') === FALSE)\n\t\t{\n\t\t\t$message = preg_match('/<message>(.*?)<\\/message>/is', $this->response, $match)\n\t\t\t\t? trim($match[1])\n\t\t\t\t: 'An unknown error was encountered';\n\t\t\t$this->set_error($message);\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Extract Trackback URLs\n\t *\n\t * This function lets multiple trackbacks be sent.\n\t * It takes a string of URLs (separated by comma or\n\t * space) and puts each URL into an array\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function extract_urls($urls)\n\t{\n\t\t// Remove the pesky white space and replace with a comma, then replace doubles.\n\t\t$urls = str_replace(',,', ',', preg_replace('/\\s*(\\S+)\\s*/', '\\\\1,', $urls));\n\n\t\t// Break into an array via commas and remove duplicates\n\t\t$urls = array_unique(preg_split('/[,]/', rtrim($urls, ',')));\n\n\t\tarray_walk($urls, array($this, 'validate_url'));\n\t\treturn $urls;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Validate URL\n\t *\n\t * Simply adds \"http://\" if missing\n\t *\n\t * @param\tstring\n\t * @return\tvoid\n\t */\n\tpublic function validate_url(&$url)\n\t{\n\t\t$url = trim($url);\n\n\t\tif (strpos($url, 'http') !== 0)\n\t\t{\n\t\t\t$url = 'http://'.$url;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Find the Trackback URL's ID\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function get_id($url)\n\t{\n\t\t$tb_id = '';\n\n\t\tif (strpos($url, '?') !== FALSE)\n\t\t{\n\t\t\t$tb_array = explode('/', $url);\n\t\t\t$tb_end   = $tb_array[count($tb_array)-1];\n\n\t\t\tif ( ! is_numeric($tb_end))\n\t\t\t{\n\t\t\t\t$tb_end  = $tb_array[count($tb_array)-2];\n\t\t\t}\n\n\t\t\t$tb_array = explode('=', $tb_end);\n\t\t\t$tb_id\t= $tb_array[count($tb_array)-1];\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$url = rtrim($url, '/');\n\n\t\t\t$tb_array = explode('/', $url);\n\t\t\t$tb_id\t= $tb_array[count($tb_array)-1];\n\n\t\t\tif ( ! is_numeric($tb_id))\n\t\t\t{\n\t\t\t\t$tb_id = $tb_array[count($tb_array)-2];\n\t\t\t}\n\t\t}\n\n\t\treturn ctype_digit((string) $tb_id) ? $tb_id : FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Convert Reserved XML characters to Entities\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function convert_xml($str)\n\t{\n\t\t$temp = '__TEMP_AMPERSANDS__';\n\n\t\t$str = preg_replace(array('/&#(\\d+);/', '/&(\\w+);/'), $temp.'\\\\1;', $str);\n\n\t\t$str = str_replace(array('&', '<', '>', '\"', \"'\", '-'),\n\t\t\t\t\tarray('&amp;', '&lt;', '&gt;', '&quot;', '&#39;', '&#45;'),\n\t\t\t\t\t$str);\n\n\t\treturn preg_replace(array('/'.$temp.'(\\d+);/', '/'.$temp.'(\\w+);/'), array('&#\\\\1;', '&\\\\1;'), $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Character limiter\n\t *\n\t * Limits the string based on the character count. Will preserve complete words.\n\t *\n\t * @param\tstring\n\t * @param\tint\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function limit_characters($str, $n = 500, $end_char = '&#8230;')\n\t{\n\t\tif (strlen($str) < $n)\n\t\t{\n\t\t\treturn $str;\n\t\t}\n\n\t\t$str = preg_replace('/\\s+/', ' ', str_replace(array(\"\\r\\n\", \"\\r\", \"\\n\"), ' ', $str));\n\n\t\tif (strlen($str) <= $n)\n\t\t{\n\t\t\treturn $str;\n\t\t}\n\n\t\t$out = '';\n\t\tforeach (explode(' ', trim($str)) as $val)\n\t\t{\n\t\t\t$out .= $val.' ';\n\t\t\tif (strlen($out) >= $n)\n\t\t\t{\n\t\t\t\treturn rtrim($out).$end_char;\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * High ASCII to Entities\n\t *\n\t * Converts Hight ascii text and MS Word special chars\n\t * to character entities\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function convert_ascii($str)\n\t{\n\t\t$count\t= 1;\n\t\t$out\t= '';\n\t\t$temp\t= array();\n\n\t\tfor ($i = 0, $s = strlen($str); $i < $s; $i++)\n\t\t{\n\t\t\t$ordinal = ord($str[$i]);\n\n\t\t\tif ($ordinal < 128)\n\t\t\t{\n\t\t\t\t$out .= $str[$i];\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (count($temp) === 0)\n\t\t\t\t{\n\t\t\t\t\t$count = ($ordinal < 224) ? 2 : 3;\n\t\t\t\t}\n\n\t\t\t\t$temp[] = $ordinal;\n\n\t\t\t\tif (count($temp) === $count)\n\t\t\t\t{\n\t\t\t\t\t$number = ($count === 3)\n\t\t\t\t\t\t? (($temp[0] % 16) * 4096) + (($temp[1] % 64) * 64) + ($temp[2] % 64)\n\t\t\t\t\t\t: (($temp[0] % 32) * 64) + ($temp[1] % 64);\n\n\t\t\t\t\t$out .= '&#'.$number.';';\n\t\t\t\t\t$count = 1;\n\t\t\t\t\t$temp = array();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn $out;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set error message\n\t *\n\t * @param\tstring\n\t * @return\tvoid\n\t */\n\tpublic function set_error($msg)\n\t{\n\t\tlog_message('error', $msg);\n\t\t$this->error_msg[] = $msg;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Show error messages\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function display_errors($open = '<p>', $close = '</p>')\n\t{\n\t\treturn (count($this->error_msg) > 0) ? $open.implode($close.$open, $this->error_msg).$close : '';\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/Typography.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Typography Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tHelpers\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/typography.html\n */\nclass CI_Typography {\n\n\t/**\n\t * Block level elements that should not be wrapped inside <p> tags\n\t *\n\t * @var string\n\t */\n\tpublic $block_elements = 'address|blockquote|div|dl|fieldset|form|h\\d|hr|noscript|object|ol|p|pre|script|table|ul';\n\n\t/**\n\t * Elements that should not have <p> and <br /> tags within them.\n\t *\n\t * @var string\n\t */\n\tpublic $skip_elements\t= 'p|pre|ol|ul|dl|object|table|h\\d';\n\n\t/**\n\t * Tags we want the parser to completely ignore when splitting the string.\n\t *\n\t * @var string\n\t */\n\tpublic $inline_elements = 'a|abbr|acronym|b|bdo|big|br|button|cite|code|del|dfn|em|i|img|ins|input|label|map|kbd|q|samp|select|small|span|strong|sub|sup|textarea|tt|var';\n\n\t/**\n\t * array of block level elements that require inner content to be within another block level element\n\t *\n\t * @var array\n\t */\n\tpublic $inner_block_required = array('blockquote');\n\n\t/**\n\t * the last block element parsed\n\t *\n\t * @var string\n\t */\n\tpublic $last_block_element = '';\n\n\t/**\n\t * whether or not to protect quotes within { curly braces }\n\t *\n\t * @var bool\n\t */\n\tpublic $protect_braced_quotes = FALSE;\n\n\t/**\n\t * Auto Typography\n\t *\n\t * This function converts text, making it typographically correct:\n\t *\t- Converts double spaces into paragraphs.\n\t *\t- Converts single line breaks into <br /> tags\n\t *\t- Converts single and double quotes into correctly facing curly quote entities.\n\t *\t- Converts three dots into ellipsis.\n\t *\t- Converts double dashes into em-dashes.\n\t *  - Converts two spaces into entities\n\t *\n\t * @param\tstring\n\t * @param\tbool\twhether to reduce more then two consecutive newlines to two\n\t * @return\tstring\n\t */\n\tpublic function auto_typography($str, $reduce_linebreaks = FALSE)\n\t{\n\t\tif ($str === '')\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\t// Standardize Newlines to make matching easier\n\t\tif (strpos($str, \"\\r\") !== FALSE)\n\t\t{\n\t\t\t$str = str_replace(array(\"\\r\\n\", \"\\r\"), \"\\n\", $str);\n\t\t}\n\n\t\t// Reduce line breaks.  If there are more than two consecutive linebreaks\n\t\t// we'll compress them down to a maximum of two since there's no benefit to more.\n\t\tif ($reduce_linebreaks === TRUE)\n\t\t{\n\t\t\t$str = preg_replace(\"/\\n\\n+/\", \"\\n\\n\", $str);\n\t\t}\n\n\t\t// HTML comment tags don't conform to patterns of normal tags, so pull them out separately, only if needed\n\t\t$html_comments = array();\n\t\tif (strpos($str, '<!--') !== FALSE && preg_match_all('#(<!\\-\\-.*?\\-\\->)#s', $str, $matches))\n\t\t{\n\t\t\tfor ($i = 0, $total = count($matches[0]); $i < $total; $i++)\n\t\t\t{\n\t\t\t\t$html_comments[] = $matches[0][$i];\n\t\t\t\t$str = str_replace($matches[0][$i], '{@HC'.$i.'}', $str);\n\t\t\t}\n\t\t}\n\n\t\t// match and yank <pre> tags if they exist.  It's cheaper to do this separately since most content will\n\t\t// not contain <pre> tags, and it keeps the PCRE patterns below simpler and faster\n\t\tif (strpos($str, '<pre') !== FALSE)\n\t\t{\n\t\t\t$str = preg_replace_callback('#<pre.*?>.*?</pre>#si', array($this, '_protect_characters'), $str);\n\t\t}\n\n\t\t// Convert quotes within tags to temporary markers.\n\t\t$str = preg_replace_callback('#<.+?>#si', array($this, '_protect_characters'), $str);\n\n\t\t// Do the same with braces if necessary\n\t\tif ($this->protect_braced_quotes === TRUE)\n\t\t{\n\t\t\t$str = preg_replace_callback('#\\{.+?\\}#si', array($this, '_protect_characters'), $str);\n\t\t}\n\n\t\t// Convert \"ignore\" tags to temporary marker.  The parser splits out the string at every tag\n\t\t// it encounters.  Certain inline tags, like image tags, links, span tags, etc. will be\n\t\t// adversely affected if they are split out so we'll convert the opening bracket < temporarily to: {@TAG}\n\t\t$str = preg_replace('#<(/*)('.$this->inline_elements.')([ >])#i', '{@TAG}\\\\1\\\\2\\\\3', $str);\n\n\t\t/* Split the string at every tag. This expression creates an array with this prototype:\n\t\t *\n\t\t *\t[array]\n\t\t *\t{\n\t\t *\t\t[0] = <opening tag>\n\t\t *\t\t[1] = Content...\n\t\t *\t\t[2] = <closing tag>\n\t\t *\t\tEtc...\n\t\t *\t}\n\t\t */\n\t\t$chunks = preg_split('/(<(?:[^<>]+(?:\"[^\"]*\"|\\'[^\\']*\\')?)+>)/', $str, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);\n\n\t\t// Build our finalized string.  We cycle through the array, skipping tags, and processing the contained text\n\t\t$str = '';\n\t\t$process = TRUE;\n\n\t\tfor ($i = 0, $c = count($chunks) - 1; $i <= $c; $i++)\n\t\t{\n\t\t\t// Are we dealing with a tag? If so, we'll skip the processing for this cycle.\n\t\t\t// Well also set the \"process\" flag which allows us to skip <pre> tags and a few other things.\n\t\t\tif (preg_match('#<(/*)('.$this->block_elements.').*?>#', $chunks[$i], $match))\n\t\t\t{\n\t\t\t\tif (preg_match('#'.$this->skip_elements.'#', $match[2]))\n\t\t\t\t{\n\t\t\t\t\t$process = ($match[1] === '/');\n\t\t\t\t}\n\n\t\t\t\tif ($match[1] === '')\n\t\t\t\t{\n\t\t\t\t\t$this->last_block_element = $match[2];\n\t\t\t\t}\n\n\t\t\t\t$str .= $chunks[$i];\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif ($process === FALSE)\n\t\t\t{\n\t\t\t\t$str .= $chunks[$i];\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t//  Force a newline to make sure end tags get processed by _format_newlines()\n\t\t\tif ($i === $c)\n\t\t\t{\n\t\t\t\t$chunks[$i] .= \"\\n\";\n\t\t\t}\n\n\t\t\t//  Convert Newlines into <p> and <br /> tags\n\t\t\t$str .= $this->_format_newlines($chunks[$i]);\n\t\t}\n\n\t\t// No opening block level tag? Add it if needed.\n\t\tif ( ! preg_match('/^\\s*<(?:'.$this->block_elements.')/i', $str))\n\t\t{\n\t\t\t$str = preg_replace('/^(.*?)<('.$this->block_elements.')/i', '<p>$1</p><$2', $str);\n\t\t}\n\n\t\t// Convert quotes, elipsis, em-dashes, non-breaking spaces, and ampersands\n\t\t$str = $this->format_characters($str);\n\n\t\t// restore HTML comments\n\t\tfor ($i = 0, $total = count($html_comments); $i < $total; $i++)\n\t\t{\n\t\t\t// remove surrounding paragraph tags, but only if there's an opening paragraph tag\n\t\t\t// otherwise HTML comments at the ends of paragraphs will have the closing tag removed\n\t\t\t// if '<p>{@HC1}' then replace <p>{@HC1}</p> with the comment, else replace only {@HC1} with the comment\n\t\t\t$str = preg_replace('#(?(?=<p>\\{@HC'.$i.'\\})<p>\\{@HC'.$i.'\\}(\\s*</p>)|\\{@HC'.$i.'\\})#s', $html_comments[$i], $str);\n\t\t}\n\n\t\t// Final clean up\n\t\t$table = array(\n\n\t\t\t\t\t\t// If the user submitted their own paragraph tags within the text\n\t\t\t\t\t\t// we will retain them instead of using our tags.\n\t\t\t\t\t\t'/(<p[^>*?]>)<p>/'\t=> '$1', // <?php BBEdit syntax coloring bug fix\n\n\t\t\t\t\t\t// Reduce multiple instances of opening/closing paragraph tags to a single one\n\t\t\t\t\t\t'#(</p>)+#'\t\t\t=> '</p>',\n\t\t\t\t\t\t'/(<p>\\W*<p>)+/'\t=> '<p>',\n\n\t\t\t\t\t\t// Clean up stray paragraph tags that appear before block level elements\n\t\t\t\t\t\t'#<p></p><('.$this->block_elements.')#'\t=> '<$1',\n\n\t\t\t\t\t\t// Clean up stray non-breaking spaces preceeding block elements\n\t\t\t\t\t\t'#(&nbsp;\\s*)+<('.$this->block_elements.')#'\t=> '  <$2',\n\n\t\t\t\t\t\t// Replace the temporary markers we added earlier\n\t\t\t\t\t\t'/\\{@TAG\\}/'\t\t=> '<',\n\t\t\t\t\t\t'/\\{@DQ\\}/'\t\t\t=> '\"',\n\t\t\t\t\t\t'/\\{@SQ\\}/'\t\t\t=> \"'\",\n\t\t\t\t\t\t'/\\{@DD\\}/'\t\t\t=> '--',\n\t\t\t\t\t\t'/\\{@NBS\\}/'\t\t=> '  ',\n\n\t\t\t\t\t\t// An unintended consequence of the _format_newlines function is that\n\t\t\t\t\t\t// some of the newlines get truncated, resulting in <p> tags\n\t\t\t\t\t\t// starting immediately after <block> tags on the same line.\n\t\t\t\t\t\t// This forces a newline after such occurrences, which looks much nicer.\n\t\t\t\t\t\t\"/><p>\\n/\"\t\t\t=> \">\\n<p>\",\n\n\t\t\t\t\t\t// Similarly, there might be cases where a closing </block> will follow\n\t\t\t\t\t\t// a closing </p> tag, so we'll correct it by adding a newline in between\n\t\t\t\t\t\t'#</p></#'\t\t\t=> \"</p>\\n</\"\n\t\t\t\t\t\t);\n\n\t\t// Do we need to reduce empty lines?\n\t\tif ($reduce_linebreaks === TRUE)\n\t\t{\n\t\t\t$table['#<p>\\n*</p>#'] = '';\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// If we have empty paragraph tags we add a non-breaking space\n\t\t\t// otherwise most browsers won't treat them as true paragraphs\n\t\t\t$table['#<p></p>#'] = '<p>&nbsp;</p>';\n\t\t}\n\n\t\treturn preg_replace(array_keys($table), $table, $str);\n\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Format Characters\n\t *\n\t * This function mainly converts double and single quotes\n\t * to curly entities, but it also converts em-dashes,\n\t * double spaces, and ampersands\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function format_characters($str)\n\t{\n\t\tstatic $table;\n\n\t\tif ( ! isset($table))\n\t\t{\n\t\t\t$table = array(\n\t\t\t\t\t\t\t// nested smart quotes, opening and closing\n\t\t\t\t\t\t\t// note that rules for grammar (English) allow only for two levels deep\n\t\t\t\t\t\t\t// and that single quotes are _supposed_ to always be on the outside\n\t\t\t\t\t\t\t// but we'll accommodate both\n\t\t\t\t\t\t\t// Note that in all cases, whitespace is the primary determining factor\n\t\t\t\t\t\t\t// on which direction to curl, with non-word characters like punctuation\n\t\t\t\t\t\t\t// being a secondary factor only after whitespace is addressed.\n\t\t\t\t\t\t\t'/\\'\"(\\s|$)/'\t\t\t\t\t=> '&#8217;&#8221;$1',\n\t\t\t\t\t\t\t'/(^|\\s|<p>)\\'\"/'\t\t\t\t=> '$1&#8216;&#8220;',\n\t\t\t\t\t\t\t'/\\'\"(\\W)/'\t\t\t\t\t\t=> '&#8217;&#8221;$1',\n\t\t\t\t\t\t\t'/(\\W)\\'\"/'\t\t\t\t\t\t=> '$1&#8216;&#8220;',\n\t\t\t\t\t\t\t'/\"\\'(\\s|$)/'\t\t\t\t\t=> '&#8221;&#8217;$1',\n\t\t\t\t\t\t\t'/(^|\\s|<p>)\"\\'/'\t\t\t\t=> '$1&#8220;&#8216;',\n\t\t\t\t\t\t\t'/\"\\'(\\W)/'\t\t\t\t\t\t=> '&#8221;&#8217;$1',\n\t\t\t\t\t\t\t'/(\\W)\"\\'/'\t\t\t\t\t\t=> '$1&#8220;&#8216;',\n\n\t\t\t\t\t\t\t// single quote smart quotes\n\t\t\t\t\t\t\t'/\\'(\\s|$)/'\t\t\t\t\t=> '&#8217;$1',\n\t\t\t\t\t\t\t'/(^|\\s|<p>)\\'/'\t\t\t\t=> '$1&#8216;',\n\t\t\t\t\t\t\t'/\\'(\\W)/'\t\t\t\t\t\t=> '&#8217;$1',\n\t\t\t\t\t\t\t'/(\\W)\\'/'\t\t\t\t\t\t=> '$1&#8216;',\n\n\t\t\t\t\t\t\t// double quote smart quotes\n\t\t\t\t\t\t\t'/\"(\\s|$)/'\t\t\t\t\t\t=> '&#8221;$1',\n\t\t\t\t\t\t\t'/(^|\\s|<p>)\"/'\t\t\t\t\t=> '$1&#8220;',\n\t\t\t\t\t\t\t'/\"(\\W)/'\t\t\t\t\t\t=> '&#8221;$1',\n\t\t\t\t\t\t\t'/(\\W)\"/'\t\t\t\t\t\t=> '$1&#8220;',\n\n\t\t\t\t\t\t\t// apostrophes\n\t\t\t\t\t\t\t\"/(\\w)'(\\w)/\"\t\t\t\t\t=> '$1&#8217;$2',\n\n\t\t\t\t\t\t\t// Em dash and ellipses dots\n\t\t\t\t\t\t\t'/\\s?\\-\\-\\s?/'\t\t\t\t\t=> '&#8212;',\n\t\t\t\t\t\t\t'/(\\w)\\.{3}/'\t\t\t\t\t=> '$1&#8230;',\n\n\t\t\t\t\t\t\t// double space after sentences\n\t\t\t\t\t\t\t'/(\\W)  /'\t\t\t\t\t\t=> '$1&nbsp; ',\n\n\t\t\t\t\t\t\t// ampersands, if not a character entity\n\t\t\t\t\t\t\t'/&(?!#?[a-zA-Z0-9]{2,};)/'\t\t=> '&amp;'\n\t\t\t\t\t\t);\n\t\t}\n\n\t\treturn preg_replace(array_keys($table), $table, $str);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Format Newlines\n\t *\n\t * Converts newline characters into either <p> tags or <br />\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tprotected function _format_newlines($str)\n\t{\n\t\tif ($str === '' OR (strpos($str, \"\\n\") === FALSE && ! in_array($this->last_block_element, $this->inner_block_required)))\n\t\t{\n\t\t\treturn $str;\n\t\t}\n\n\t\t// Convert two consecutive newlines to paragraphs\n\t\t$str = str_replace(\"\\n\\n\", \"</p>\\n\\n<p>\", $str);\n\n\t\t// Convert single spaces to <br /> tags\n\t\t$str = preg_replace(\"/([^\\n])(\\n)([^\\n])/\", '\\\\1<br />\\\\2\\\\3', $str);\n\n\t\t// Wrap the whole enchilada in enclosing paragraphs\n\t\tif ($str !== \"\\n\")\n\t\t{\n\t\t\t// We trim off the right-side new line so that the closing </p> tag\n\t\t\t// will be positioned immediately following the string, matching\n\t\t\t// the behavior of the opening <p> tag\n\t\t\t$str =  '<p>'.rtrim($str).'</p>';\n\t\t}\n\n\t\t// Remove empty paragraphs if they are on the first line, as this\n\t\t// is a potential unintended consequence of the previous code\n\t\treturn preg_replace('/<p><\\/p>(.*)/', '\\\\1', $str, 1);\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Protect Characters\n\t *\n\t * Protects special characters from being formatted later\n\t * We don't want quotes converted within tags so we'll temporarily convert them to {@DQ} and {@SQ}\n\t * and we don't want double dashes converted to emdash entities, so they are marked with {@DD}\n\t * likewise double spaces are converted to {@NBS} to prevent entity conversion\n\t *\n\t * @param\tarray\n\t * @return\tstring\n\t */\n\tprotected function _protect_characters($match)\n\t{\n\t\treturn str_replace(array(\"'\",'\"','--','  '), array('{@SQ}', '{@DQ}', '{@DD}', '{@NBS}'), $match[0]);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Convert newlines to HTML line breaks except within PRE tags\n\t *\n\t * @param\tstring\n\t * @return\tstring\n\t */\n\tpublic function nl2br_except_pre($str)\n\t{\n\t\t$newstr = '';\n\t\tfor ($ex = explode('pre>', $str), $ct = count($ex), $i = 0; $i < $ct; $i++)\n\t\t{\n\t\t\t$newstr .= (($i % 2) === 0) ? nl2br($ex[$i]) : $ex[$i];\n\t\t\tif ($ct - 1 !== $i)\n\t\t\t{\n\t\t\t\t$newstr .= 'pre>';\n\t\t\t}\n\t\t}\n\n\t\treturn $newstr;\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/Unit_test.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.3.1\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Unit Testing Class\n *\n * Simple testing class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tUnitTesting\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/unit_testing.html\n */\nclass CI_Unit_test {\n\n\t/**\n\t * Active flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $active = TRUE;\n\n\t/**\n\t * Test results\n\t *\n\t * @var\tarray\n\t */\n\tpublic $results = array();\n\n\t/**\n\t * Strict comparison flag\n\t *\n\t * Whether to use === or == when comparing\n\t *\n\t * @var\tbool\n\t */\n\tpublic $strict = FALSE;\n\n\t/**\n\t * Template\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_template = NULL;\n\n\t/**\n\t * Template rows\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_template_rows = NULL;\n\n\t/**\n\t * List of visible test items\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_test_items_visible\t= array(\n\t\t'test_name',\n\t\t'test_datatype',\n\t\t'res_datatype',\n\t\t'result',\n\t\t'file',\n\t\t'line',\n\t\t'notes'\n\t);\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\tlog_message('info', 'Unit Testing Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Run the tests\n\t *\n\t * Runs the supplied tests\n\t *\n\t * @param\tarray\t$items\n\t * @return\tvoid\n\t */\n\tpublic function set_test_items($items)\n\t{\n\t\tif ( ! empty($items) && is_array($items))\n\t\t{\n\t\t\t$this->_test_items_visible = $items;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Run the tests\n\t *\n\t * Runs the supplied tests\n\t *\n\t * @param\tmixed\t$test\n\t * @param\tmixed\t$expected\n\t * @param\tstring\t$test_name\n\t * @param\tstring\t$notes\n\t * @return\tstring\n\t */\n\tpublic function run($test, $expected = TRUE, $test_name = 'undefined', $notes = '')\n\t{\n\t\tif ($this->active === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (in_array($expected, array('is_object', 'is_string', 'is_bool', 'is_true', 'is_false', 'is_int', 'is_numeric', 'is_float', 'is_double', 'is_array', 'is_null', 'is_resource'), TRUE))\n\t\t{\n\t\t\t$expected = str_replace('is_double', 'is_float', $expected);\n\t\t\t$result = $expected($test);\n\t\t\t$extype = str_replace(array('true', 'false'), 'bool', str_replace('is_', '', $expected));\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$result = ($this->strict === TRUE) ? ($test === $expected) : ($test == $expected);\n\t\t\t$extype = gettype($expected);\n\t\t}\n\n\t\t$back = $this->_backtrace();\n\n\t\t$report = array (\n\t\t\t'test_name'     => $test_name,\n\t\t\t'test_datatype' => gettype($test),\n\t\t\t'res_datatype'  => $extype,\n\t\t\t'result'        => ($result === TRUE) ? 'passed' : 'failed',\n\t\t\t'file'          => $back['file'],\n\t\t\t'line'          => $back['line'],\n\t\t\t'notes'         => $notes\n\t\t);\n\n\t\t$this->results[] = $report;\n\n\t\treturn $this->report($this->result(array($report)));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Generate a report\n\t *\n\t * Displays a table with the test data\n\t *\n\t * @param\tarray\t $result\n\t * @return\tstring\n\t */\n\tpublic function report($result = array())\n\t{\n\t\tif (count($result) === 0)\n\t\t{\n\t\t\t$result = $this->result();\n\t\t}\n\n\t\t$CI =& get_instance();\n\t\t$CI->load->language('unit_test');\n\n\t\t$this->_parse_template();\n\n\t\t$r = '';\n\t\tforeach ($result as $res)\n\t\t{\n\t\t\t$table = '';\n\n\t\t\tforeach ($res as $key => $val)\n\t\t\t{\n\t\t\t\tif ($key === $CI->lang->line('ut_result'))\n\t\t\t\t{\n\t\t\t\t\tif ($val === $CI->lang->line('ut_passed'))\n\t\t\t\t\t{\n\t\t\t\t\t\t$val = '<span style=\"color: #0C0;\">'.$val.'</span>';\n\t\t\t\t\t}\n\t\t\t\t\telseif ($val === $CI->lang->line('ut_failed'))\n\t\t\t\t\t{\n\t\t\t\t\t\t$val = '<span style=\"color: #C00;\">'.$val.'</span>';\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t$table .= str_replace(array('{item}', '{result}'), array($key, $val), $this->_template_rows);\n\t\t\t}\n\n\t\t\t$r .= str_replace('{rows}', $table, $this->_template);\n\t\t}\n\n\t\treturn $r;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Use strict comparison\n\t *\n\t * Causes the evaluation to use === rather than ==\n\t *\n\t * @param\tbool\t$state\n\t * @return\tvoid\n\t */\n\tpublic function use_strict($state = TRUE)\n\t{\n\t\t$this->strict = (bool) $state;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Make Unit testing active\n\t *\n\t * Enables/disables unit testing\n\t *\n\t * @param\tbool\n\t * @return\tvoid\n\t */\n\tpublic function active($state = TRUE)\n\t{\n\t\t$this->active = (bool) $state;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Result Array\n\t *\n\t * Returns the raw result data\n\t *\n\t * @param\tarray\t$results\n\t * @return\tarray\n\t */\n\tpublic function result($results = array())\n\t{\n\t\t$CI =& get_instance();\n\t\t$CI->load->language('unit_test');\n\n\t\tif (count($results) === 0)\n\t\t{\n\t\t\t$results = $this->results;\n\t\t}\n\n\t\t$retval = array();\n\t\tforeach ($results as $result)\n\t\t{\n\t\t\t$temp = array();\n\t\t\tforeach ($result as $key => $val)\n\t\t\t{\n\t\t\t\tif ( ! in_array($key, $this->_test_items_visible))\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\telseif (in_array($key, array('test_name', 'test_datatype', 'test_res_datatype', 'result'), TRUE))\n\t\t\t\t{\n\t\t\t\t\tif (FALSE !== ($line = $CI->lang->line(strtolower('ut_'.$val), FALSE)))\n\t\t\t\t\t{\n\t\t\t\t\t\t$val = $line;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t$temp[$CI->lang->line('ut_'.$key, FALSE)] = $val;\n\t\t\t}\n\n\t\t\t$retval[] = $temp;\n\t\t}\n\n\t\treturn $retval;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the template\n\t *\n\t * This lets us set the template to be used to display results\n\t *\n\t * @param\tstring\n\t * @return\tvoid\n\t */\n\tpublic function set_template($template)\n\t{\n\t\t$this->_template = $template;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Generate a backtrace\n\t *\n\t * This lets us show file names and line numbers\n\t *\n\t * @return\tarray\n\t */\n\tprotected function _backtrace()\n\t{\n\t\t$back = debug_backtrace();\n\t\treturn array(\n\t\t\t'file' => (isset($back[1]['file']) ? $back[1]['file'] : ''),\n\t\t\t'line' => (isset($back[1]['line']) ? $back[1]['line'] : '')\n\t\t);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Default Template\n\t *\n\t * @return\tstring\n\t */\n\tprotected function _default_template()\n\t{\n\t\t$this->_template = \"\\n\".'<table style=\"width:100%; font-size:small; margin:10px 0; border-collapse:collapse; border:1px solid #CCC;\">{rows}'.\"\\n</table>\";\n\n\t\t$this->_template_rows = \"\\n\\t<tr>\\n\\t\\t\".'<th style=\"text-align: left; border-bottom:1px solid #CCC;\">{item}</th>'\n\t\t\t\t\t.\"\\n\\t\\t\".'<td style=\"border-bottom:1px solid #CCC;\">{result}</td>'.\"\\n\\t</tr>\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse Template\n\t *\n\t * Harvests the data within the template {pseudo-variables}\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _parse_template()\n\t{\n\t\tif ($this->_template_rows !== NULL)\n\t\t{\n\t\t\treturn;\n\t\t}\n\n\t\tif ($this->_template === NULL OR ! preg_match('/\\{rows\\}(.*?)\\{\\/rows\\}/si', $this->_template, $match))\n\t\t{\n\t\t\t$this->_default_template();\n\t\t\treturn;\n\t\t}\n\n\t\t$this->_template_rows = $match[1];\n\t\t$this->_template = str_replace($match[0], '{rows}', $this->_template);\n\t}\n\n}\n\n/**\n * Helper function to test boolean TRUE\n *\n * @param\tmixed\t$test\n * @return\tbool\n */\nfunction is_true($test)\n{\n\treturn ($test === TRUE);\n}\n\n/**\n * Helper function to test boolean FALSE\n *\n * @param\tmixed\t$test\n * @return\tbool\n */\nfunction is_false($test)\n{\n\treturn ($test === FALSE);\n}\n"
  },
  {
    "path": "system/libraries/Upload.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * File Uploading Class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tUploads\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/file_uploading.html\n */\nclass CI_Upload {\n\n\t/**\n\t * Maximum file size\n\t *\n\t * @var\tint\n\t */\n\tpublic $max_size = 0;\n\n\t/**\n\t * Maximum image width\n\t *\n\t * @var\tint\n\t */\n\tpublic $max_width = 0;\n\n\t/**\n\t * Maximum image height\n\t *\n\t * @var\tint\n\t */\n\tpublic $max_height = 0;\n\n\t/**\n\t * Minimum image width\n\t *\n\t * @var\tint\n\t */\n\tpublic $min_width = 0;\n\n\t/**\n\t * Minimum image height\n\t *\n\t * @var\tint\n\t */\n\tpublic $min_height = 0;\n\n\t/**\n\t * Maximum filename length\n\t *\n\t * @var\tint\n\t */\n\tpublic $max_filename = 0;\n\n\t/**\n\t * Maximum duplicate filename increment ID\n\t *\n\t * @var\tint\n\t */\n\tpublic $max_filename_increment = 100;\n\n\t/**\n\t * Allowed file types\n\t *\n\t * @var\tstring\n\t */\n\tpublic $allowed_types = '';\n\n\t/**\n\t * Temporary filename\n\t *\n\t * @var\tstring\n\t */\n\tpublic $file_temp = '';\n\n\t/**\n\t * Filename\n\t *\n\t * @var\tstring\n\t */\n\tpublic $file_name = '';\n\n\t/**\n\t * Original filename\n\t *\n\t * @var\tstring\n\t */\n\tpublic $orig_name = '';\n\n\t/**\n\t * File type\n\t *\n\t * @var\tstring\n\t */\n\tpublic $file_type = '';\n\n\t/**\n\t * File size\n\t *\n\t * @var\tint\n\t */\n\tpublic $file_size = NULL;\n\n\t/**\n\t * Filename extension\n\t *\n\t * @var\tstring\n\t */\n\tpublic $file_ext = '';\n\n\t/**\n\t * Force filename extension to lowercase\n\t *\n\t * @var\tstring\n\t */\n\tpublic $file_ext_tolower = FALSE;\n\n\t/**\n\t * Upload path\n\t *\n\t * @var\tstring\n\t */\n\tpublic $upload_path = '';\n\n\t/**\n\t * Overwrite flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $overwrite = FALSE;\n\n\t/**\n\t * Obfuscate filename flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $encrypt_name = FALSE;\n\n\t/**\n\t * Is image flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $is_image = FALSE;\n\n\t/**\n\t * Image width\n\t *\n\t * @var\tint\n\t */\n\tpublic $image_width = NULL;\n\n\t/**\n\t * Image height\n\t *\n\t * @var\tint\n\t */\n\tpublic $image_height = NULL;\n\n\t/**\n\t * Image type\n\t *\n\t * @var\tstring\n\t */\n\tpublic $image_type = '';\n\n\t/**\n\t * Image size string\n\t *\n\t * @var\tstring\n\t */\n\tpublic $image_size_str = '';\n\n\t/**\n\t * Error messages list\n\t *\n\t * @var\tarray\n\t */\n\tpublic $error_msg = array();\n\n\t/**\n\t * Remove spaces flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $remove_spaces = TRUE;\n\n\t/**\n\t * MIME detection flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $detect_mime = TRUE;\n\n\t/**\n\t * XSS filter flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $xss_clean = FALSE;\n\n\t/**\n\t * Apache mod_mime fix flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $mod_mime_fix = TRUE;\n\n\t/**\n\t * Temporary filename prefix\n\t *\n\t * @var\tstring\n\t */\n\tpublic $temp_prefix = 'temp_file_';\n\n\t/**\n\t * Filename sent by the client\n\t *\n\t * @var\tbool\n\t */\n\tpublic $client_name = '';\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Filename override\n\t *\n\t * @var\tstring\n\t */\n\tprotected $_file_name_override = '';\n\n\t/**\n\t * MIME types list\n\t *\n\t * @var\tarray\n\t */\n\tprotected $_mimes = array();\n\n\t/**\n\t * CI Singleton\n\t *\n\t * @var\tobject\n\t */\n\tprotected $_CI;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @param\tarray\t$config\n\t * @return\tvoid\n\t */\n\tpublic function __construct($config = array())\n\t{\n\t\tempty($config) OR $this->initialize($config, FALSE);\n\n\t\t$this->_mimes =& get_mimes();\n\t\t$this->_CI =& get_instance();\n\n\t\tlog_message('info', 'Upload Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize preferences\n\t *\n\t * @param\tarray\t$config\n\t * @param\tbool\t$reset\n\t * @return\tCI_Upload\n\t */\n\tpublic function initialize(array $config = array(), $reset = TRUE)\n\t{\n\t\t$reflection = new ReflectionClass($this);\n\n\t\tif ($reset === TRUE)\n\t\t{\n\t\t\t$defaults = $reflection->getDefaultProperties();\n\t\t\tforeach (array_keys($defaults) as $key)\n\t\t\t{\n\t\t\t\tif ($key[0] === '_')\n\t\t\t\t{\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (isset($config[$key]))\n\t\t\t\t{\n\t\t\t\t\tif ($reflection->hasMethod('set_'.$key))\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->{'set_'.$key}($config[$key]);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->$key = $config[$key];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t$this->$key = $defaults[$key];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tforeach ($config as $key => &$value)\n\t\t\t{\n\t\t\t\tif ($key[0] !== '_' && $reflection->hasProperty($key))\n\t\t\t\t{\n\t\t\t\t\tif ($reflection->hasMethod('set_'.$key))\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->{'set_'.$key}($value);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->$key = $value;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// if a file_name was provided in the config, use it instead of the user input\n\t\t// supplied file name for all uploads until initialized again\n\t\t$this->_file_name_override = $this->file_name;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Perform the file upload\n\t *\n\t * @param\tstring\t$field\n\t * @return\tbool\n\t */\n\tpublic function do_upload($field = 'userfile')\n\t{\n\t\t// Is $_FILES[$field] set? If not, no reason to continue.\n\t\tif (isset($_FILES[$field]))\n\t\t{\n\t\t\t$_file = $_FILES[$field];\n\t\t}\n\t\t// Does the field name contain array notation?\n\t\telseif (($c = preg_match_all('/(?:^[^\\[]+)|\\[[^]]*\\]/', $field, $matches)) > 1)\n\t\t{\n\t\t\t$_file = $_FILES;\n\t\t\tfor ($i = 0; $i < $c; $i++)\n\t\t\t{\n\t\t\t\t// We can't track numeric iterations, only full field names are accepted\n\t\t\t\tif (($field = trim($matches[0][$i], '[]')) === '' OR ! isset($_file[$field]))\n\t\t\t\t{\n\t\t\t\t\t$_file = NULL;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\t$_file = $_file[$field];\n\t\t\t}\n\t\t}\n\n\t\tif ( ! isset($_file))\n\t\t{\n\t\t\t$this->set_error('upload_no_file_selected', 'debug');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Is the upload path valid?\n\t\tif ( ! $this->validate_upload_path())\n\t\t{\n\t\t\t// errors will already be set by validate_upload_path() so just return FALSE\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Was the file able to be uploaded? If not, determine the reason why.\n\t\tif ( ! is_uploaded_file($_file['tmp_name']))\n\t\t{\n\t\t\t$error = isset($_file['error']) ? $_file['error'] : 4;\n\n\t\t\tswitch ($error)\n\t\t\t{\n\t\t\t\tcase UPLOAD_ERR_INI_SIZE:\n\t\t\t\t\t$this->set_error('upload_file_exceeds_limit', 'info');\n\t\t\t\t\tbreak;\n\t\t\t\tcase UPLOAD_ERR_FORM_SIZE:\n\t\t\t\t\t$this->set_error('upload_file_exceeds_form_limit', 'info');\n\t\t\t\t\tbreak;\n\t\t\t\tcase UPLOAD_ERR_PARTIAL:\n\t\t\t\t\t$this->set_error('upload_file_partial', 'debug');\n\t\t\t\t\tbreak;\n\t\t\t\tcase UPLOAD_ERR_NO_FILE:\n\t\t\t\t\t$this->set_error('upload_no_file_selected', 'debug');\n\t\t\t\t\tbreak;\n\t\t\t\tcase UPLOAD_ERR_NO_TMP_DIR:\n\t\t\t\t\t$this->set_error('upload_no_temp_directory', 'error');\n\t\t\t\t\tbreak;\n\t\t\t\tcase UPLOAD_ERR_CANT_WRITE:\n\t\t\t\t\t$this->set_error('upload_unable_to_write_file', 'error');\n\t\t\t\t\tbreak;\n\t\t\t\tcase UPLOAD_ERR_EXTENSION:\n\t\t\t\t\t$this->set_error('upload_stopped_by_extension', 'debug');\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\t$this->set_error('upload_no_file_selected', 'debug');\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Set the uploaded data as class variables\n\t\t$this->file_temp = $_file['tmp_name'];\n\t\t$this->file_size = $_file['size'];\n\n\t\t// Skip MIME type detection?\n\t\tif ($this->detect_mime !== FALSE)\n\t\t{\n\t\t\t$this->_file_mime_type($_file);\n\t\t}\n\n\t\t$this->file_type = preg_replace('/^(.+?);.*$/', '\\\\1', $this->file_type);\n\t\t$this->file_type = strtolower(trim(stripslashes($this->file_type), '\"'));\n\t\t$this->file_name = $this->_prep_filename($_file['name']);\n\t\t$this->file_ext\t = $this->get_extension($this->file_name);\n\t\t$this->client_name = $this->file_name;\n\n\t\t// Is the file type allowed to be uploaded?\n\t\tif ( ! $this->is_allowed_filetype())\n\t\t{\n\t\t\t$this->set_error('upload_invalid_filetype', 'debug');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// if we're overriding, let's now make sure the new name and type is allowed\n\t\tif ($this->_file_name_override !== '')\n\t\t{\n\t\t\t$this->file_name = $this->_prep_filename($this->_file_name_override);\n\n\t\t\t// If no extension was provided in the file_name config item, use the uploaded one\n\t\t\tif (strpos($this->_file_name_override, '.') === FALSE)\n\t\t\t{\n\t\t\t\t$this->file_name .= $this->file_ext;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t// An extension was provided, let's have it!\n\t\t\t\t$this->file_ext\t= $this->get_extension($this->_file_name_override);\n\t\t\t}\n\n\t\t\tif ( ! $this->is_allowed_filetype(TRUE))\n\t\t\t{\n\t\t\t\t$this->set_error('upload_invalid_filetype', 'debug');\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\t// Convert the file size to kilobytes\n\t\tif ($this->file_size > 0)\n\t\t{\n\t\t\t$this->file_size = round($this->file_size/1024, 2);\n\t\t}\n\n\t\t// Is the file size within the allowed maximum?\n\t\tif ( ! $this->is_allowed_filesize())\n\t\t{\n\t\t\t$this->set_error('upload_invalid_filesize', 'info');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Are the image dimensions within the allowed size?\n\t\t// Note: This can fail if the server has an open_basedir restriction.\n\t\tif ( ! $this->is_allowed_dimensions())\n\t\t{\n\t\t\t$this->set_error('upload_invalid_dimensions', 'info');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Sanitize the file name for security\n\t\t$this->file_name = $this->_CI->security->sanitize_filename($this->file_name);\n\n\t\t// Truncate the file name if it's too long\n\t\tif ($this->max_filename > 0)\n\t\t{\n\t\t\t$this->file_name = $this->limit_filename_length($this->file_name, $this->max_filename);\n\t\t}\n\n\t\t// Remove white spaces in the name\n\t\tif ($this->remove_spaces === TRUE)\n\t\t{\n\t\t\t$this->file_name = preg_replace('/\\s+/', '_', $this->file_name);\n\t\t}\n\n\t\tif ($this->file_ext_tolower && ($ext_length = strlen($this->file_ext)))\n\t\t{\n\t\t\t// file_ext was previously lower-cased by a get_extension() call\n\t\t\t$this->file_name = substr($this->file_name, 0, -$ext_length).$this->file_ext;\n\t\t}\n\n\t\t/*\n\t\t * Validate the file name\n\t\t * This function appends an number onto the end of\n\t\t * the file if one with the same name already exists.\n\t\t * If it returns false there was a problem.\n\t\t */\n\t\t$this->orig_name = $this->file_name;\n\t\tif (FALSE === ($this->file_name = $this->set_filename($this->upload_path, $this->file_name)))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t/*\n\t\t * Run the file through the XSS hacking filter\n\t\t * This helps prevent malicious code from being\n\t\t * embedded within a file. Scripts can easily\n\t\t * be disguised as images or other file types.\n\t\t */\n\t\tif ($this->xss_clean && $this->do_xss_clean() === FALSE)\n\t\t{\n\t\t\t$this->set_error('upload_unable_to_write_file', 'error');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t/*\n\t\t * Move the file to the final destination\n\t\t * To deal with different server configurations\n\t\t * we'll attempt to use copy() first. If that fails\n\t\t * we'll use move_uploaded_file(). One of the two should\n\t\t * reliably work in most environments\n\t\t */\n\t\tif ( ! @copy($this->file_temp, $this->upload_path.$this->file_name))\n\t\t{\n\t\t\tif ( ! @move_uploaded_file($this->file_temp, $this->upload_path.$this->file_name))\n\t\t\t{\n\t\t\t\t$this->set_error('upload_destination_error', 'error');\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\t/*\n\t\t * Set the finalized image dimensions\n\t\t * This sets the image width/height (assuming the\n\t\t * file was an image). We use this information\n\t\t * in the \"data\" function.\n\t\t */\n\t\t$this->set_image_properties($this->upload_path.$this->file_name);\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Finalized Data Array\n\t *\n\t * Returns an associative array containing all of the information\n\t * related to the upload, allowing the developer easy access in one array.\n\t *\n\t * @param\tstring\t$index\n\t * @return\tmixed\n\t */\n\tpublic function data($index = NULL)\n\t{\n\t\t$data = array(\n\t\t\t\t'file_name'\t\t=> $this->file_name,\n\t\t\t\t'file_type'\t\t=> $this->file_type,\n\t\t\t\t'file_path'\t\t=> $this->upload_path,\n\t\t\t\t'full_path'\t\t=> $this->upload_path.$this->file_name,\n\t\t\t\t'raw_name'\t\t=> substr($this->file_name, 0, -strlen($this->file_ext)),\n\t\t\t\t'orig_name'\t\t=> $this->orig_name,\n\t\t\t\t'client_name'\t\t=> $this->client_name,\n\t\t\t\t'file_ext'\t\t=> $this->file_ext,\n\t\t\t\t'file_size'\t\t=> $this->file_size,\n\t\t\t\t'is_image'\t\t=> $this->is_image(),\n\t\t\t\t'image_width'\t\t=> $this->image_width,\n\t\t\t\t'image_height'\t\t=> $this->image_height,\n\t\t\t\t'image_type'\t\t=> $this->image_type,\n\t\t\t\t'image_size_str'\t=> $this->image_size_str,\n\t\t\t);\n\n\t\tif ( ! empty($index))\n\t\t{\n\t\t\treturn isset($data[$index]) ? $data[$index] : NULL;\n\t\t}\n\n\t\treturn $data;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Upload Path\n\t *\n\t * @param\tstring\t$path\n\t * @return\tCI_Upload\n\t */\n\tpublic function set_upload_path($path)\n\t{\n\t\t// Make sure it has a trailing slash\n\t\t$this->upload_path = rtrim($path, '/').'/';\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the file name\n\t *\n\t * This function takes a filename/path as input and looks for the\n\t * existence of a file with the same name. If found, it will append a\n\t * number to the end of the filename to avoid overwriting a pre-existing file.\n\t *\n\t * @param\tstring\t$path\n\t * @param\tstring\t$filename\n\t * @return\tstring\n\t */\n\tpublic function set_filename($path, $filename)\n\t{\n\t\tif ($this->encrypt_name === TRUE)\n\t\t{\n\t\t\t$filename = md5(uniqid(mt_rand())).$this->file_ext;\n\t\t}\n\n\t\tif ($this->overwrite === TRUE OR ! file_exists($path.$filename))\n\t\t{\n\t\t\treturn $filename;\n\t\t}\n\n\t\t$filename = str_replace($this->file_ext, '', $filename);\n\n\t\t$new_filename = '';\n\t\tfor ($i = 1; $i < $this->max_filename_increment; $i++)\n\t\t{\n\t\t\tif ( ! file_exists($path.$filename.$i.$this->file_ext))\n\t\t\t{\n\t\t\t\t$new_filename = $filename.$i.$this->file_ext;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif ($new_filename === '')\n\t\t{\n\t\t\t$this->set_error('upload_bad_filename', 'debug');\n\t\t\treturn FALSE;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn $new_filename;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Maximum File Size\n\t *\n\t * @param\tint\t$n\n\t * @return\tCI_Upload\n\t */\n\tpublic function set_max_filesize($n)\n\t{\n\t\t$this->max_size = ($n < 0) ? 0 : (int) $n;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Maximum File Size\n\t *\n\t * An internal alias to set_max_filesize() to help with configuration\n\t * as initialize() will look for a set_<property_name>() method ...\n\t *\n\t * @param\tint\t$n\n\t * @return\tCI_Upload\n\t */\n\tprotected function set_max_size($n)\n\t{\n\t\treturn $this->set_max_filesize($n);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Maximum File Name Length\n\t *\n\t * @param\tint\t$n\n\t * @return\tCI_Upload\n\t */\n\tpublic function set_max_filename($n)\n\t{\n\t\t$this->max_filename = ($n < 0) ? 0 : (int) $n;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Maximum Image Width\n\t *\n\t * @param\tint\t$n\n\t * @return\tCI_Upload\n\t */\n\tpublic function set_max_width($n)\n\t{\n\t\t$this->max_width = ($n < 0) ? 0 : (int) $n;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Maximum Image Height\n\t *\n\t * @param\tint\t$n\n\t * @return\tCI_Upload\n\t */\n\tpublic function set_max_height($n)\n\t{\n\t\t$this->max_height = ($n < 0) ? 0 : (int) $n;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set minimum image width\n\t *\n\t * @param\tint\t$n\n\t * @return\tCI_Upload\n\t */\n\tpublic function set_min_width($n)\n\t{\n\t\t$this->min_width = ($n < 0) ? 0 : (int) $n;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set minimum image height\n\t *\n\t * @param\tint\t$n\n\t * @return\tCI_Upload\n\t */\n\tpublic function set_min_height($n)\n\t{\n\t\t$this->min_height = ($n < 0) ? 0 : (int) $n;\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Allowed File Types\n\t *\n\t * @param\tmixed\t$types\n\t * @return\tCI_Upload\n\t */\n\tpublic function set_allowed_types($types)\n\t{\n\t\t$this->allowed_types = (is_array($types) OR $types === '*')\n\t\t\t? $types\n\t\t\t: explode('|', $types);\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Image Properties\n\t *\n\t * Uses GD to determine the width/height/type of image\n\t *\n\t * @param\tstring\t$path\n\t * @return\tCI_Upload\n\t */\n\tpublic function set_image_properties($path = '')\n\t{\n\t\tif ($this->is_image() && function_exists('getimagesize'))\n\t\t{\n\t\t\tif (FALSE !== ($D = @getimagesize($path)))\n\t\t\t{\n\t\t\t\t$types = array(1 => 'gif', 2 => 'jpeg', 3 => 'png');\n\n\t\t\t\t$this->image_width\t= $D[0];\n\t\t\t\t$this->image_height\t= $D[1];\n\t\t\t\t$this->image_type\t= isset($types[$D[2]]) ? $types[$D[2]] : 'unknown';\n\t\t\t\t$this->image_size_str\t= $D[3]; // string containing height and width\n\t\t\t}\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set XSS Clean\n\t *\n\t * Enables the XSS flag so that the file that was uploaded\n\t * will be run through the XSS filter.\n\t *\n\t * @param\tbool\t$flag\n\t * @return\tCI_Upload\n\t */\n\tpublic function set_xss_clean($flag = FALSE)\n\t{\n\t\t$this->xss_clean = ($flag === TRUE);\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Validate the image\n\t *\n\t * @return\tbool\n\t */\n\tpublic function is_image()\n\t{\n\t\t// IE will sometimes return odd mime-types during upload, so here we just standardize all\n\t\t// jpegs or pngs to the same file type.\n\n\t\t$png_mimes  = array('image/x-png');\n\t\t$jpeg_mimes = array('image/jpg', 'image/jpe', 'image/jpeg', 'image/pjpeg');\n\n\t\tif (in_array($this->file_type, $png_mimes))\n\t\t{\n\t\t\t$this->file_type = 'image/png';\n\t\t}\n\t\telseif (in_array($this->file_type, $jpeg_mimes))\n\t\t{\n\t\t\t$this->file_type = 'image/jpeg';\n\t\t}\n\n\t\t$img_mimes = array('image/gif',\t'image/jpeg', 'image/png');\n\n\t\treturn in_array($this->file_type, $img_mimes, TRUE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Verify that the filetype is allowed\n\t *\n\t * @param\tbool\t$ignore_mime\n\t * @return\tbool\n\t */\n\tpublic function is_allowed_filetype($ignore_mime = FALSE)\n\t{\n\t\tif ($this->allowed_types === '*')\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\tif (empty($this->allowed_types) OR ! is_array($this->allowed_types))\n\t\t{\n\t\t\t$this->set_error('upload_no_file_types', 'debug');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$ext = strtolower(ltrim($this->file_ext, '.'));\n\n\t\tif ( ! in_array($ext, $this->allowed_types, TRUE))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Images get some additional checks\n\t\tif (in_array($ext, array('gif', 'jpg', 'jpeg', 'jpe', 'png'), TRUE) && @getimagesize($this->file_temp) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ($ignore_mime === TRUE)\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\tif (isset($this->_mimes[$ext]))\n\t\t{\n\t\t\treturn is_array($this->_mimes[$ext])\n\t\t\t\t? in_array($this->file_type, $this->_mimes[$ext], TRUE)\n\t\t\t\t: ($this->_mimes[$ext] === $this->file_type);\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Verify that the file is within the allowed size\n\t *\n\t * @return\tbool\n\t */\n\tpublic function is_allowed_filesize()\n\t{\n\t\treturn ($this->max_size === 0 OR $this->max_size > $this->file_size);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Verify that the image is within the allowed width/height\n\t *\n\t * @return\tbool\n\t */\n\tpublic function is_allowed_dimensions()\n\t{\n\t\tif ( ! $this->is_image())\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\tif (function_exists('getimagesize'))\n\t\t{\n\t\t\t$D = @getimagesize($this->file_temp);\n\n\t\t\tif ($this->max_width > 0 && $D[0] > $this->max_width)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tif ($this->max_height > 0 && $D[1] > $this->max_height)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tif ($this->min_width > 0 && $D[0] < $this->min_width)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\n\t\t\tif ($this->min_height > 0 && $D[1] < $this->min_height)\n\t\t\t{\n\t\t\t\treturn FALSE;\n\t\t\t}\n\t\t}\n\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Validate Upload Path\n\t *\n\t * Verifies that it is a valid upload path with proper permissions.\n\t *\n\t * @return\tbool\n\t */\n\tpublic function validate_upload_path()\n\t{\n\t\tif ($this->upload_path === '')\n\t\t{\n\t\t\t$this->set_error('upload_no_filepath', 'error');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (realpath($this->upload_path) !== FALSE)\n\t\t{\n\t\t\t$this->upload_path = str_replace('\\\\', '/', realpath($this->upload_path));\n\t\t}\n\n\t\tif ( ! is_dir($this->upload_path))\n\t\t{\n\t\t\t$this->set_error('upload_no_filepath', 'error');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif ( ! is_really_writable($this->upload_path))\n\t\t{\n\t\t\t$this->set_error('upload_not_writable', 'error');\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->upload_path = preg_replace('/(.+?)\\/*$/', '\\\\1/',  $this->upload_path);\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Extract the file extension\n\t *\n\t * @param\tstring\t$filename\n\t * @return\tstring\n\t */\n\tpublic function get_extension($filename)\n\t{\n\t\t$x = explode('.', $filename);\n\n\t\tif (count($x) === 1)\n\t\t{\n\t\t\treturn '';\n\t\t}\n\n\t\t$ext = ($this->file_ext_tolower) ? strtolower(end($x)) : end($x);\n\t\treturn '.'.$ext;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Limit the File Name Length\n\t *\n\t * @param\tstring\t$filename\n\t * @param\tint\t$length\n\t * @return\tstring\n\t */\n\tpublic function limit_filename_length($filename, $length)\n\t{\n\t\tif (strlen($filename) < $length)\n\t\t{\n\t\t\treturn $filename;\n\t\t}\n\n\t\t$ext = '';\n\t\tif (strpos($filename, '.') !== FALSE)\n\t\t{\n\t\t\t$parts\t\t= explode('.', $filename);\n\t\t\t$ext\t\t= '.'.array_pop($parts);\n\t\t\t$filename\t= implode('.', $parts);\n\t\t}\n\n\t\treturn substr($filename, 0, ($length - strlen($ext))).$ext;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Runs the file through the XSS clean function\n\t *\n\t * This prevents people from embedding malicious code in their files.\n\t * I'm not sure that it won't negatively affect certain files in unexpected ways,\n\t * but so far I haven't found that it causes trouble.\n\t *\n\t * @return\tstring\n\t */\n\tpublic function do_xss_clean()\n\t{\n\t\t$file = $this->file_temp;\n\n\t\tif (filesize($file) == 0)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tif (memory_get_usage() && ($memory_limit = ini_get('memory_limit')))\n\t\t{\n\t\t\t$memory_limit *= 1024 * 1024;\n\n\t\t\t// There was a bug/behavioural change in PHP 5.2, where numbers over one million get output\n\t\t\t// into scientific notation. number_format() ensures this number is an integer\n\t\t\t// http://bugs.php.net/bug.php?id=43053\n\n\t\t\t$memory_limit = number_format(ceil(filesize($file) + $memory_limit), 0, '.', '');\n\n\t\t\tini_set('memory_limit', $memory_limit); // When an integer is used, the value is measured in bytes. - PHP.net\n\t\t}\n\n\t\t// If the file being uploaded is an image, then we should have no problem with XSS attacks (in theory), but\n\t\t// IE can be fooled into mime-type detecting a malformed image as an html file, thus executing an XSS attack on anyone\n\t\t// using IE who looks at the image. It does this by inspecting the first 255 bytes of an image. To get around this\n\t\t// CI will itself look at the first 255 bytes of an image to determine its relative safety. This can save a lot of\n\t\t// processor power and time if it is actually a clean image, as it will be in nearly all instances _except_ an\n\t\t// attempted XSS attack.\n\n\t\tif (function_exists('getimagesize') && @getimagesize($file) !== FALSE)\n\t\t{\n\t\t\tif (($file = @fopen($file, 'rb')) === FALSE) // \"b\" to force binary\n\t\t\t{\n\t\t\t\treturn FALSE; // Couldn't open the file, return FALSE\n\t\t\t}\n\n\t\t\t$opening_bytes = fread($file, 256);\n\t\t\tfclose($file);\n\n\t\t\t// These are known to throw IE into mime-type detection chaos\n\t\t\t// <a, <body, <head, <html, <img, <plaintext, <pre, <script, <table, <title\n\t\t\t// title is basically just in SVG, but we filter it anyhow\n\n\t\t\t// if it's an image or no \"triggers\" detected in the first 256 bytes - we're good\n\t\t\treturn ! preg_match('/<(a|body|head|html|img|plaintext|pre|script|table|title)[\\s>]/i', $opening_bytes);\n\t\t}\n\n\t\tif (($data = @file_get_contents($file)) === FALSE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn $this->_CI->security->xss_clean($data, TRUE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set an error message\n\t *\n\t * @param\tstring\t$msg\n\t * @return\tCI_Upload\n\t */\n\tpublic function set_error($msg, $log_level = 'error')\n\t{\n\t\t$this->_CI->lang->load('upload');\n\n\t\tis_array($msg) OR $msg = array($msg);\n\t\tforeach ($msg as $val)\n\t\t{\n\t\t\t$msg = ($this->_CI->lang->line($val) === FALSE) ? $val : $this->_CI->lang->line($val);\n\t\t\t$this->error_msg[] = $msg;\n\t\t\tlog_message($log_level, $msg);\n\t\t}\n\n\t\treturn $this;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Display the error message\n\t *\n\t * @param\tstring\t$open\n\t * @param\tstring\t$close\n\t * @return\tstring\n\t */\n\tpublic function display_errors($open = '<p>', $close = '</p>')\n\t{\n\t\treturn (count($this->error_msg) > 0) ? $open.implode($close.$open, $this->error_msg).$close : '';\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prep Filename\n\t *\n\t * Prevents possible script execution from Apache's handling\n\t * of files' multiple extensions.\n\t *\n\t * @link\thttp://httpd.apache.org/docs/1.3/mod/mod_mime.html#multipleext\n\t *\n\t * @param\tstring\t$filename\n\t * @return\tstring\n\t */\n\tprotected function _prep_filename($filename)\n\t{\n\t\tif ($this->mod_mime_fix === FALSE OR $this->allowed_types === '*' OR ($ext_pos = strrpos($filename, '.')) === FALSE)\n\t\t{\n\t\t\treturn $filename;\n\t\t}\n\n\t\t$ext = substr($filename, $ext_pos);\n\t\t$filename = substr($filename, 0, $ext_pos);\n\t\treturn str_replace('.', '_', $filename).$ext;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * File MIME type\n\t *\n\t * Detects the (actual) MIME type of the uploaded file, if possible.\n\t * The input array is expected to be $_FILES[$field]\n\t *\n\t * @param\tarray\t$file\n\t * @return\tvoid\n\t */\n\tprotected function _file_mime_type($file)\n\t{\n\t\t// We'll need this to validate the MIME info string (e.g. text/plain; charset=us-ascii)\n\t\t$regexp = '/^([a-z\\-]+\\/[a-z0-9\\-\\.\\+]+)(;\\s.+)?$/';\n\n\t\t/* Fileinfo extension - most reliable method\n\t\t *\n\t\t * Unfortunately, prior to PHP 5.3 - it's only available as a PECL extension and the\n\t\t * more convenient FILEINFO_MIME_TYPE flag doesn't exist.\n\t\t */\n\t\tif (function_exists('finfo_file'))\n\t\t{\n\t\t\t$finfo = @finfo_open(FILEINFO_MIME);\n\t\t\tif (is_resource($finfo)) // It is possible that a FALSE value is returned, if there is no magic MIME database file found on the system\n\t\t\t{\n\t\t\t\t$mime = @finfo_file($finfo, $file['tmp_name']);\n\t\t\t\tfinfo_close($finfo);\n\n\t\t\t\t/* According to the comments section of the PHP manual page,\n\t\t\t\t * it is possible that this function returns an empty string\n\t\t\t\t * for some files (e.g. if they don't exist in the magic MIME database)\n\t\t\t\t */\n\t\t\t\tif (is_string($mime) && preg_match($regexp, $mime, $matches))\n\t\t\t\t{\n\t\t\t\t\t$this->file_type = $matches[1];\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/* This is an ugly hack, but UNIX-type systems provide a \"native\" way to detect the file type,\n\t\t * which is still more secure than depending on the value of $_FILES[$field]['type'], and as it\n\t\t * was reported in issue #750 (https://github.com/EllisLab/CodeIgniter/issues/750) - it's better\n\t\t * than mime_content_type() as well, hence the attempts to try calling the command line with\n\t\t * three different functions.\n\t\t *\n\t\t * Notes:\n\t\t *\t- the DIRECTORY_SEPARATOR comparison ensures that we're not on a Windows system\n\t\t *\t- many system admins would disable the exec(), shell_exec(), popen() and similar functions\n\t\t *\t  due to security concerns, hence the function_usable() checks\n\t\t */\n\t\tif (DIRECTORY_SEPARATOR !== '\\\\')\n\t\t{\n\t\t\t$cmd = function_exists('escapeshellarg')\n\t\t\t\t? 'file --brief --mime '.escapeshellarg($file['tmp_name']).' 2>&1'\n\t\t\t\t: 'file --brief --mime '.$file['tmp_name'].' 2>&1';\n\n\t\t\tif (function_usable('exec'))\n\t\t\t{\n\t\t\t\t/* This might look confusing, as $mime is being populated with all of the output when set in the second parameter.\n\t\t\t\t * However, we only need the last line, which is the actual return value of exec(), and as such - it overwrites\n\t\t\t\t * anything that could already be set for $mime previously. This effectively makes the second parameter a dummy\n\t\t\t\t * value, which is only put to allow us to get the return status code.\n\t\t\t\t */\n\t\t\t\t$mime = @exec($cmd, $mime, $return_status);\n\t\t\t\tif ($return_status === 0 && is_string($mime) && preg_match($regexp, $mime, $matches))\n\t\t\t\t{\n\t\t\t\t\t$this->file_type = $matches[1];\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( ! ini_get('safe_mode') && function_usable('shell_exec'))\n\t\t\t{\n\t\t\t\t$mime = @shell_exec($cmd);\n\t\t\t\tif (strlen($mime) > 0)\n\t\t\t\t{\n\t\t\t\t\t$mime = explode(\"\\n\", trim($mime));\n\t\t\t\t\tif (preg_match($regexp, $mime[(count($mime) - 1)], $matches))\n\t\t\t\t\t{\n\t\t\t\t\t\t$this->file_type = $matches[1];\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (function_usable('popen'))\n\t\t\t{\n\t\t\t\t$proc = @popen($cmd, 'r');\n\t\t\t\tif (is_resource($proc))\n\t\t\t\t{\n\t\t\t\t\t$mime = @fread($proc, 512);\n\t\t\t\t\t@pclose($proc);\n\t\t\t\t\tif ($mime !== FALSE)\n\t\t\t\t\t{\n\t\t\t\t\t\t$mime = explode(\"\\n\", trim($mime));\n\t\t\t\t\t\tif (preg_match($regexp, $mime[(count($mime) - 1)], $matches))\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$this->file_type = $matches[1];\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Fall back to the deprecated mime_content_type(), if available (still better than $_FILES[$field]['type'])\n\t\tif (function_exists('mime_content_type'))\n\t\t{\n\t\t\t$this->file_type = @mime_content_type($file['tmp_name']);\n\t\t\tif (strlen($this->file_type) > 0) // It's possible that mime_content_type() returns FALSE or an empty string\n\t\t\t{\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t$this->file_type = $file['type'];\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/User_agent.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * User Agent Class\n *\n * Identifies the platform, browser, robot, or mobile device of the browsing agent\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tUser Agent\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/user_agent.html\n */\nclass CI_User_agent {\n\n\t/**\n\t * Current user-agent\n\t *\n\t * @var string\n\t */\n\tpublic $agent = NULL;\n\n\t/**\n\t * Flag for if the user-agent belongs to a browser\n\t *\n\t * @var bool\n\t */\n\tpublic $is_browser = FALSE;\n\n\t/**\n\t * Flag for if the user-agent is a robot\n\t *\n\t * @var bool\n\t */\n\tpublic $is_robot = FALSE;\n\n\t/**\n\t * Flag for if the user-agent is a mobile browser\n\t *\n\t * @var bool\n\t */\n\tpublic $is_mobile = FALSE;\n\n\t/**\n\t * Languages accepted by the current user agent\n\t *\n\t * @var array\n\t */\n\tpublic $languages = array();\n\n\t/**\n\t * Character sets accepted by the current user agent\n\t *\n\t * @var array\n\t */\n\tpublic $charsets = array();\n\n\t/**\n\t * List of platforms to compare against current user agent\n\t *\n\t * @var array\n\t */\n\tpublic $platforms = array();\n\n\t/**\n\t * List of browsers to compare against current user agent\n\t *\n\t * @var array\n\t */\n\tpublic $browsers = array();\n\n\t/**\n\t * List of mobile browsers to compare against current user agent\n\t *\n\t * @var array\n\t */\n\tpublic $mobiles = array();\n\n\t/**\n\t * List of robots to compare against current user agent\n\t *\n\t * @var array\n\t */\n\tpublic $robots = array();\n\n\t/**\n\t * Current user-agent platform\n\t *\n\t * @var string\n\t */\n\tpublic $platform = '';\n\n\t/**\n\t * Current user-agent browser\n\t *\n\t * @var string\n\t */\n\tpublic $browser = '';\n\n\t/**\n\t * Current user-agent version\n\t *\n\t * @var string\n\t */\n\tpublic $version = '';\n\n\t/**\n\t * Current user-agent mobile name\n\t *\n\t * @var string\n\t */\n\tpublic $mobile = '';\n\n\t/**\n\t * Current user-agent robot name\n\t *\n\t * @var string\n\t */\n\tpublic $robot = '';\n\n\t/**\n\t * HTTP Referer\n\t *\n\t * @var\tmixed\n\t */\n\tpublic $referer;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * Sets the User Agent and runs the compilation routine\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\t$this->_load_agent_file();\n\n\t\tif (isset($_SERVER['HTTP_USER_AGENT']))\n\t\t{\n\t\t\t$this->agent = trim($_SERVER['HTTP_USER_AGENT']);\n\t\t\t$this->_compile_data();\n\t\t}\n\n\t\tlog_message('info', 'User Agent Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile the User Agent Data\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _load_agent_file()\n\t{\n\t\tif (($found = file_exists(APPPATH.'config/user_agents.php')))\n\t\t{\n\t\t\tinclude(APPPATH.'config/user_agents.php');\n\t\t}\n\n\t\tif (file_exists(APPPATH.'config/'.ENVIRONMENT.'/user_agents.php'))\n\t\t{\n\t\t\tinclude(APPPATH.'config/'.ENVIRONMENT.'/user_agents.php');\n\t\t\t$found = TRUE;\n\t\t}\n\n\t\tif ($found !== TRUE)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$return = FALSE;\n\n\t\tif (isset($platforms))\n\t\t{\n\t\t\t$this->platforms = $platforms;\n\t\t\tunset($platforms);\n\t\t\t$return = TRUE;\n\t\t}\n\n\t\tif (isset($browsers))\n\t\t{\n\t\t\t$this->browsers = $browsers;\n\t\t\tunset($browsers);\n\t\t\t$return = TRUE;\n\t\t}\n\n\t\tif (isset($mobiles))\n\t\t{\n\t\t\t$this->mobiles = $mobiles;\n\t\t\tunset($mobiles);\n\t\t\t$return = TRUE;\n\t\t}\n\n\t\tif (isset($robots))\n\t\t{\n\t\t\t$this->robots = $robots;\n\t\t\tunset($robots);\n\t\t\t$return = TRUE;\n\t\t}\n\n\t\treturn $return;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Compile the User Agent Data\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _compile_data()\n\t{\n\t\t$this->_set_platform();\n\n\t\tforeach (array('_set_robot', '_set_browser', '_set_mobile') as $function)\n\t\t{\n\t\t\tif ($this->$function() === TRUE)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the Platform\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _set_platform()\n\t{\n\t\tif (is_array($this->platforms) && count($this->platforms) > 0)\n\t\t{\n\t\t\tforeach ($this->platforms as $key => $val)\n\t\t\t{\n\t\t\t\tif (preg_match('|'.preg_quote($key).'|i', $this->agent))\n\t\t\t\t{\n\t\t\t\t\t$this->platform = $val;\n\t\t\t\t\treturn TRUE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$this->platform = 'Unknown Platform';\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the Browser\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _set_browser()\n\t{\n\t\tif (is_array($this->browsers) && count($this->browsers) > 0)\n\t\t{\n\t\t\tforeach ($this->browsers as $key => $val)\n\t\t\t{\n\t\t\t\tif (preg_match('|'.$key.'.*?([0-9\\.]+)|i', $this->agent, $match))\n\t\t\t\t{\n\t\t\t\t\t$this->is_browser = TRUE;\n\t\t\t\t\t$this->version = $match[1];\n\t\t\t\t\t$this->browser = $val;\n\t\t\t\t\t$this->_set_mobile();\n\t\t\t\t\treturn TRUE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the Robot\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _set_robot()\n\t{\n\t\tif (is_array($this->robots) && count($this->robots) > 0)\n\t\t{\n\t\t\tforeach ($this->robots as $key => $val)\n\t\t\t{\n\t\t\t\tif (preg_match('|'.preg_quote($key).'|i', $this->agent))\n\t\t\t\t{\n\t\t\t\t\t$this->is_robot = TRUE;\n\t\t\t\t\t$this->robot = $val;\n\t\t\t\t\t$this->_set_mobile();\n\t\t\t\t\treturn TRUE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the Mobile Device\n\t *\n\t * @return\tbool\n\t */\n\tprotected function _set_mobile()\n\t{\n\t\tif (is_array($this->mobiles) && count($this->mobiles) > 0)\n\t\t{\n\t\t\tforeach ($this->mobiles as $key => $val)\n\t\t\t{\n\t\t\t\tif (FALSE !== (stripos($this->agent, $key)))\n\t\t\t\t{\n\t\t\t\t\t$this->is_mobile = TRUE;\n\t\t\t\t\t$this->mobile = $val;\n\t\t\t\t\treturn TRUE;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the accepted languages\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _set_languages()\n\t{\n\t\tif ((count($this->languages) === 0) && ! empty($_SERVER['HTTP_ACCEPT_LANGUAGE']))\n\t\t{\n\t\t\t$this->languages = explode(',', preg_replace('/(;\\s?q=[0-9\\.]+)|\\s/i', '', strtolower(trim($_SERVER['HTTP_ACCEPT_LANGUAGE']))));\n\t\t}\n\n\t\tif (count($this->languages) === 0)\n\t\t{\n\t\t\t$this->languages = array('Undefined');\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set the accepted character sets\n\t *\n\t * @return\tvoid\n\t */\n\tprotected function _set_charsets()\n\t{\n\t\tif ((count($this->charsets) === 0) && ! empty($_SERVER['HTTP_ACCEPT_CHARSET']))\n\t\t{\n\t\t\t$this->charsets = explode(',', preg_replace('/(;\\s?q=.+)|\\s/i', '', strtolower(trim($_SERVER['HTTP_ACCEPT_CHARSET']))));\n\t\t}\n\n\t\tif (count($this->charsets) === 0)\n\t\t{\n\t\t\t$this->charsets = array('Undefined');\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is Browser\n\t *\n\t * @param\tstring\t$key\n\t * @return\tbool\n\t */\n\tpublic function is_browser($key = NULL)\n\t{\n\t\tif ( ! $this->is_browser)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// No need to be specific, it's a browser\n\t\tif ($key === NULL)\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\t// Check for a specific browser\n\t\treturn (isset($this->browsers[$key]) && $this->browser === $this->browsers[$key]);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is Robot\n\t *\n\t * @param\tstring\t$key\n\t * @return\tbool\n\t */\n\tpublic function is_robot($key = NULL)\n\t{\n\t\tif ( ! $this->is_robot)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// No need to be specific, it's a robot\n\t\tif ($key === NULL)\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\t// Check for a specific robot\n\t\treturn (isset($this->robots[$key]) && $this->robot === $this->robots[$key]);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is Mobile\n\t *\n\t * @param\tstring\t$key\n\t * @return\tbool\n\t */\n\tpublic function is_mobile($key = NULL)\n\t{\n\t\tif ( ! $this->is_mobile)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// No need to be specific, it's a mobile\n\t\tif ($key === NULL)\n\t\t{\n\t\t\treturn TRUE;\n\t\t}\n\n\t\t// Check for a specific robot\n\t\treturn (isset($this->mobiles[$key]) && $this->mobile === $this->mobiles[$key]);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Is this a referral from another site?\n\t *\n\t * @return\tbool\n\t */\n\tpublic function is_referral()\n\t{\n\t\tif ( ! isset($this->referer))\n\t\t{\n\t\t\tif (empty($_SERVER['HTTP_REFERER']))\n\t\t\t{\n\t\t\t\t$this->referer = FALSE;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$referer_host = @parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST);\n\t\t\t\t$own_host = parse_url(config_item('base_url'), PHP_URL_HOST);\n\n\t\t\t\t$this->referer = ($referer_host && $referer_host !== $own_host);\n\t\t\t}\n\t\t}\n\n\t\treturn $this->referer;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Agent String\n\t *\n\t * @return\tstring\n\t */\n\tpublic function agent_string()\n\t{\n\t\treturn $this->agent;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Platform\n\t *\n\t * @return\tstring\n\t */\n\tpublic function platform()\n\t{\n\t\treturn $this->platform;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get Browser Name\n\t *\n\t * @return\tstring\n\t */\n\tpublic function browser()\n\t{\n\t\treturn $this->browser;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get the Browser Version\n\t *\n\t * @return\tstring\n\t */\n\tpublic function version()\n\t{\n\t\treturn $this->version;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get The Robot Name\n\t *\n\t * @return\tstring\n\t */\n\tpublic function robot()\n\t{\n\t\treturn $this->robot;\n\t}\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get the Mobile Device\n\t *\n\t * @return\tstring\n\t */\n\tpublic function mobile()\n\t{\n\t\treturn $this->mobile;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get the referrer\n\t *\n\t * @return\tbool\n\t */\n\tpublic function referrer()\n\t{\n\t\treturn empty($_SERVER['HTTP_REFERER']) ? '' : trim($_SERVER['HTTP_REFERER']);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get the accepted languages\n\t *\n\t * @return\tarray\n\t */\n\tpublic function languages()\n\t{\n\t\tif (count($this->languages) === 0)\n\t\t{\n\t\t\t$this->_set_languages();\n\t\t}\n\n\t\treturn $this->languages;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get the accepted Character Sets\n\t *\n\t * @return\tarray\n\t */\n\tpublic function charsets()\n\t{\n\t\tif (count($this->charsets) === 0)\n\t\t{\n\t\t\t$this->_set_charsets();\n\t\t}\n\n\t\treturn $this->charsets;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Test for a particular language\n\t *\n\t * @param\tstring\t$lang\n\t * @return\tbool\n\t */\n\tpublic function accept_lang($lang = 'en')\n\t{\n\t\treturn in_array(strtolower($lang), $this->languages(), TRUE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Test for a particular character set\n\t *\n\t * @param\tstring\t$charset\n\t * @return\tbool\n\t */\n\tpublic function accept_charset($charset = 'utf-8')\n\t{\n\t\treturn in_array(strtolower($charset), $this->charsets(), TRUE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse a custom user-agent string\n\t *\n\t * @param\tstring\t$string\n\t * @return\tvoid\n\t */\n\tpublic function parse($string)\n\t{\n\t\t// Reset values\n\t\t$this->is_browser = FALSE;\n\t\t$this->is_robot = FALSE;\n\t\t$this->is_mobile = FALSE;\n\t\t$this->browser = '';\n\t\t$this->version = '';\n\t\t$this->mobile = '';\n\t\t$this->robot = '';\n\n\t\t// Set the new user-agent string and parse it, unless empty\n\t\t$this->agent = $string;\n\n\t\tif ( ! empty($string))\n\t\t{\n\t\t\t$this->_compile_data();\n\t\t}\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/Xmlrpc.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\nif ( ! function_exists('xml_parser_create'))\n{\n\tshow_error('Your PHP installation does not support XML');\n}\n\n// ------------------------------------------------------------------------\n\n/**\n * XML-RPC request handler class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tXML-RPC\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/xmlrpc.html\n */\nclass CI_Xmlrpc {\n\n\t/**\n\t * Debug flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $debug\t\t= FALSE;\n\n\t/**\n\t * I4 data type\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpcI4\t= 'i4';\n\n\t/**\n\t * Integer data type\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpcInt\t= 'int';\n\n\t/**\n\t * Boolean data type\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpcBoolean\t= 'boolean';\n\n\t/**\n\t * Double data type\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpcDouble\t= 'double';\n\n\t/**\n\t * String data type\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpcString\t= 'string';\n\n\t/**\n\t * DateTime format\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpcDateTime\t= 'dateTime.iso8601';\n\n\t/**\n\t * Base64 data type\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpcBase64\t= 'base64';\n\n\t/**\n\t * Array data type\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpcArray\t= 'array';\n\n\t/**\n\t * Struct data type\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpcStruct\t= 'struct';\n\n\t/**\n\t * Data types list\n\t *\n\t * @var\tarray\n\t */\n\tpublic $xmlrpcTypes\t= array();\n\n\t/**\n\t * Valid parents list\n\t *\n\t * @var\tarray\n\t */\n\tpublic $valid_parents\t= array();\n\n\t/**\n\t * Response error numbers list\n\t *\n\t * @var\tarray\n\t */\n\tpublic $xmlrpcerr\t\t= array();\n\n\t/**\n\t * Response error messages list\n\t *\n\t * @var\tstring[]\n\t */\n\tpublic $xmlrpcstr\t\t= array();\n\n\t/**\n\t * Encoding charset\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpc_defencoding\t= 'UTF-8';\n\n\t/**\n\t * XML-RPC client name\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpcName\t\t= 'XML-RPC for CodeIgniter';\n\n\t/**\n\t * XML-RPC version\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpcVersion\t\t= '1.1';\n\n\t/**\n\t * Start of user errors\n\t *\n\t * @var\tint\n\t */\n\tpublic $xmlrpcerruser\t\t= 800;\n\n\t/**\n\t * Start of XML parse errors\n\t *\n\t * @var\tint\n\t */\n\tpublic $xmlrpcerrxml\t\t= 100;\n\n\t/**\n\t * Backslash replacement value\n\t *\n\t * @var\tstring\n\t */\n\tpublic $xmlrpc_backslash\t= '';\n\n\t/**\n\t * XML-RPC Client object\n\t *\n\t * @var\tobject\n\t */\n\tpublic $client;\n\n\t/**\n\t * XML-RPC Method name\n\t *\n\t * @var\tstring\n\t */\n\tpublic $method;\n\n\t/**\n\t * XML-RPC Data\n\t *\n\t * @var\tarray\n\t */\n\tpublic $data;\n\n\t/**\n\t * XML-RPC Message\n\t *\n\t * @var\tstring\n\t */\n\tpublic $message\t\t\t= '';\n\n\t/**\n\t * Request error message\n\t *\n\t * @var\tstring\n\t */\n\tpublic $error\t\t\t= '';\n\n\t/**\n\t * XML-RPC result object\n\t *\n\t * @var\tobject\n\t */\n\tpublic $result;\n\n\t/**\n\t * XML-RPC Reponse\n\t *\n\t * @var\tarray\n\t */\n\tpublic $response\t\t= array(); // Response from remote server\n\n\t/**\n\t * XSS Filter flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $xss_clean\t\t= TRUE;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * Initializes property default values\n\t *\n\t * @param\tarray\t$config\n\t * @return\tvoid\n\t */\n\tpublic function __construct($config = array())\n\t{\n\t\t$this->xmlrpc_backslash = chr(92).chr(92);\n\n\t\t// Types for info sent back and forth\n\t\t$this->xmlrpcTypes = array(\n\t\t\t$this->xmlrpcI4\t \t\t=> '1',\n\t\t\t$this->xmlrpcInt\t\t=> '1',\n\t\t\t$this->xmlrpcBoolean\t=> '1',\n\t\t\t$this->xmlrpcString\t\t=> '1',\n\t\t\t$this->xmlrpcDouble\t\t=> '1',\n\t\t\t$this->xmlrpcDateTime\t=> '1',\n\t\t\t$this->xmlrpcBase64\t\t=> '1',\n\t\t\t$this->xmlrpcArray\t\t=> '2',\n\t\t\t$this->xmlrpcStruct\t\t=> '3'\n\t\t);\n\n\t\t// Array of Valid Parents for Various XML-RPC elements\n\t\t$this->valid_parents = array('BOOLEAN' => array('VALUE'),\n\t\t\t'I4'\t\t\t\t=> array('VALUE'),\n\t\t\t'INT'\t\t\t\t=> array('VALUE'),\n\t\t\t'STRING'\t\t\t=> array('VALUE'),\n\t\t\t'DOUBLE'\t\t\t=> array('VALUE'),\n\t\t\t'DATETIME.ISO8601'\t=> array('VALUE'),\n\t\t\t'BASE64'\t\t\t=> array('VALUE'),\n\t\t\t'ARRAY'\t\t\t=> array('VALUE'),\n\t\t\t'STRUCT'\t\t\t=> array('VALUE'),\n\t\t\t'PARAM'\t\t\t=> array('PARAMS'),\n\t\t\t'METHODNAME'\t\t=> array('METHODCALL'),\n\t\t\t'PARAMS'\t\t\t=> array('METHODCALL', 'METHODRESPONSE'),\n\t\t\t'MEMBER'\t\t\t=> array('STRUCT'),\n\t\t\t'NAME'\t\t\t\t=> array('MEMBER'),\n\t\t\t'DATA'\t\t\t\t=> array('ARRAY'),\n\t\t\t'FAULT'\t\t\t=> array('METHODRESPONSE'),\n\t\t\t'VALUE'\t\t\t=> array('MEMBER', 'DATA', 'PARAM', 'FAULT')\n\t\t);\n\n\t\t// XML-RPC Responses\n\t\t$this->xmlrpcerr['unknown_method'] = '1';\n\t\t$this->xmlrpcstr['unknown_method'] = 'This is not a known method for this XML-RPC Server';\n\t\t$this->xmlrpcerr['invalid_return'] = '2';\n\t\t$this->xmlrpcstr['invalid_return'] = 'The XML data received was either invalid or not in the correct form for XML-RPC. Turn on debugging to examine the XML data further.';\n\t\t$this->xmlrpcerr['incorrect_params'] = '3';\n\t\t$this->xmlrpcstr['incorrect_params'] = 'Incorrect parameters were passed to method';\n\t\t$this->xmlrpcerr['introspect_unknown'] = '4';\n\t\t$this->xmlrpcstr['introspect_unknown'] = 'Cannot inspect signature for request: method unknown';\n\t\t$this->xmlrpcerr['http_error'] = '5';\n\t\t$this->xmlrpcstr['http_error'] = \"Did not receive a '200 OK' response from remote server.\";\n\t\t$this->xmlrpcerr['no_data'] = '6';\n\t\t$this->xmlrpcstr['no_data'] = 'No data received from server.';\n\n\t\t$this->initialize($config);\n\n\t\tlog_message('info', 'XML-RPC Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize\n\t *\n\t * @param\tarray\t$config\n\t * @return\tvoid\n\t */\n\tpublic function initialize($config = array())\n\t{\n\t\tif (count($config) > 0)\n\t\t{\n\t\t\tforeach ($config as $key => $val)\n\t\t\t{\n\t\t\t\tif (isset($this->$key))\n\t\t\t\t{\n\t\t\t\t\t$this->$key = $val;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse server URL\n\t *\n\t * @param\tstring\t$url\n\t * @param\tint\t$port\n\t * @param\tstring\t$proxy\n\t * @param\tint\t$proxy_port\n\t * @return\tvoid\n\t */\n\tpublic function server($url, $port = 80, $proxy = FALSE, $proxy_port = 8080)\n\t{\n\t\tif (strpos($url, 'http') !== 0)\n\t\t{\n\t\t\t$url = 'http://'.$url;\n\t\t}\n\n\t\t$parts = parse_url($url);\n\n\t\tif (isset($parts['user'], $parts['pass']))\n\t\t{\n\t\t\t$parts['host'] = $parts['user'].':'.$parts['pass'].'@'.$parts['host'];\n\t\t}\n\n\t\t$path = isset($parts['path']) ? $parts['path'] : '/';\n\n\t\tif ( ! empty($parts['query']))\n\t\t{\n\t\t\t$path .= '?'.$parts['query'];\n\t\t}\n\n\t\t$this->client = new XML_RPC_Client($path, $parts['host'], $port, $proxy, $proxy_port);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Timeout\n\t *\n\t * @param\tint\t$seconds\n\t * @return\tvoid\n\t */\n\tpublic function timeout($seconds = 5)\n\t{\n\t\tif ($this->client !== NULL && is_int($seconds))\n\t\t{\n\t\t\t$this->client->timeout = $seconds;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Methods\n\t *\n\t * @param\tstring\t$function\tMethod name\n\t * @return\tvoid\n\t */\n\tpublic function method($function)\n\t{\n\t\t$this->method = $function;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Take Array of Data and Create Objects\n\t *\n\t * @param\tarray\t$incoming\n\t * @return\tvoid\n\t */\n\tpublic function request($incoming)\n\t{\n\t\tif ( ! is_array($incoming))\n\t\t{\n\t\t\t// Send Error\n\t\t\treturn;\n\t\t}\n\n\t\t$this->data = array();\n\n\t\tforeach ($incoming as $key => $value)\n\t\t{\n\t\t\t$this->data[$key] = $this->values_parsing($value);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Set Debug\n\t *\n\t * @param\tbool\t$flag\n\t * @return\tvoid\n\t */\n\tpublic function set_debug($flag = TRUE)\n\t{\n\t\t$this->debug = ($flag === TRUE);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Values Parsing\n\t *\n\t * @param\tmixed\t$value\n\t * @return\tobject\n\t */\n\tpublic function values_parsing($value)\n\t{\n\t\tif (is_array($value) && array_key_exists(0, $value))\n\t\t{\n\t\t\tif ( ! isset($value[1], $this->xmlrpcTypes[$value[1]]))\n\t\t\t{\n\t\t\t\t$temp = new XML_RPC_Values($value[0], (is_array($value[0]) ? 'array' : 'string'));\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (is_array($value[0]) && ($value[1] === 'struct' OR $value[1] === 'array'))\n\t\t\t\t{\n\t\t\t\t\twhile (list($k) = each($value[0]))\n\t\t\t\t\t{\n\t\t\t\t\t\t$value[0][$k] = $this->values_parsing($value[0][$k]);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t$temp = new XML_RPC_Values($value[0], $value[1]);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$temp = new XML_RPC_Values($value, 'string');\n\t\t}\n\n\t\treturn $temp;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Sends XML-RPC Request\n\t *\n\t * @return\tbool\n\t */\n\tpublic function send_request()\n\t{\n\t\t$this->message = new XML_RPC_Message($this->method, $this->data);\n\t\t$this->message->debug = $this->debug;\n\n\t\tif ( ! $this->result = $this->client->send($this->message) OR ! is_object($this->result->val))\n\t\t{\n\t\t\t$this->error = $this->result->errstr;\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t$this->response = $this->result->decode();\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns Error\n\t *\n\t * @return\tstring\n\t */\n\tpublic function display_error()\n\t{\n\t\treturn $this->error;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Returns Remote Server Response\n\t *\n\t * @return\tstring\n\t */\n\tpublic function display_response()\n\t{\n\t\treturn $this->response;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Sends an Error Message for Server Request\n\t *\n\t * @param\tint\t$number\n\t * @param\tstring\t$message\n\t * @return\tobject\n\t */\n\tpublic function send_error_message($number, $message)\n\t{\n\t\treturn new XML_RPC_Response(0, $number, $message);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send Response for Server Request\n\t *\n\t * @param\tarray\t$response\n\t * @return\tobject\n\t */\n\tpublic function send_response($response)\n\t{\n\t\t// $response should be array of values, which will be parsed\n\t\t// based on their data and type into a valid group of XML-RPC values\n\t\treturn new XML_RPC_Response($this->values_parsing($response));\n\t}\n\n} // END XML_RPC Class\n\n/**\n * XML-RPC Client class\n *\n * @category\tXML-RPC\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/xmlrpc.html\n */\nclass XML_RPC_Client extends CI_Xmlrpc\n{\n\t/**\n\t * Path\n\t *\n\t * @var\tstring\n\t */\n\tpublic $path\t\t\t= '';\n\n\t/**\n\t * Server hostname\n\t *\n\t * @var\tstring\n\t */\n\tpublic $server\t\t\t= '';\n\n\t/**\n\t * Server port\n\t *\n\t * @var\tint\n\t */\n\tpublic $port\t\t\t= 80;\n\n\t/**\n\t *\n\t * Server username\n\t *\n\t * @var\tstring\n\t */\n\tpublic $username;\n\n\t/**\n\t * Server password\n\t *\n\t * @var\tstring\n\t */\n\tpublic $password;\n\n\t/**\n\t * Proxy hostname\n\t *\n\t * @var\tstring\n\t */\n\tpublic $proxy\t\t\t= FALSE;\n\n\t/**\n\t * Proxy port\n\t *\n\t * @var\tint\n\t */\n\tpublic $proxy_port\t\t= 8080;\n\n\t/**\n\t * Error number\n\t *\n\t * @var\tstring\n\t */\n\tpublic $errno\t\t\t= '';\n\n\t/**\n\t * Error message\n\t *\n\t * @var\tstring\n\t */\n\tpublic $errstring\t\t= '';\n\n\t/**\n\t * Timeout in seconds\n\t *\n\t * @var\tint\n\t */\n\tpublic $timeout\t\t= 5;\n\n\t/**\n\t * No Multicall flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $no_multicall\t= FALSE;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @param\tstring\t$path\n\t * @param\tobject\t$server\n\t * @param\tint\t$port\n\t * @param\tstring\t$proxy\n\t * @param\tint\t$proxy_port\n\t * @return\tvoid\n\t */\n\tpublic function __construct($path, $server, $port = 80, $proxy = FALSE, $proxy_port = 8080)\n\t{\n\t\tparent::__construct();\n\n\t\t$url = parse_url('http://'.$server);\n\n\t\tif (isset($url['user'], $url['pass']))\n\t\t{\n\t\t\t$this->username = $url['user'];\n\t\t\t$this->password = $url['pass'];\n\t\t}\n\n\t\t$this->port = $port;\n\t\t$this->server = $url['host'];\n\t\t$this->path = $path;\n\t\t$this->proxy = $proxy;\n\t\t$this->proxy_port = $proxy_port;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send message\n\t *\n\t * @param\tmixed\t$msg\n\t * @return\tobject\n\t */\n\tpublic function send($msg)\n\t{\n\t\tif (is_array($msg))\n\t\t{\n\t\t\t// Multi-call disabled\n\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['multicall_recursion'], $this->xmlrpcstr['multicall_recursion']);\n\t\t}\n\n\t\treturn $this->sendPayload($msg);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Send payload\n\t *\n\t * @param\tobject\t$msg\n\t * @return\tobject\n\t */\n\tpublic function sendPayload($msg)\n\t{\n\t\tif ($this->proxy === FALSE)\n\t\t{\n\t\t\t$server = $this->server;\n\t\t\t$port = $this->port;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$server = $this->proxy;\n\t\t\t$port = $this->proxy_port;\n\t\t}\n\n\t\t$fp = @fsockopen($server, $port, $this->errno, $this->errstring, $this->timeout);\n\n\t\tif ( ! is_resource($fp))\n\t\t{\n\t\t\terror_log($this->xmlrpcstr['http_error']);\n\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);\n\t\t}\n\n\t\tif (empty($msg->payload))\n\t\t{\n\t\t\t// $msg = XML_RPC_Messages\n\t\t\t$msg->createPayload();\n\t\t}\n\n\t\t$r = \"\\r\\n\";\n\t\t$op = 'POST '.$this->path.' HTTP/1.0'.$r\n\t\t\t.'Host: '.$this->server.$r\n\t\t\t.'Content-Type: text/xml'.$r\n\t\t\t.(isset($this->username, $this->password) ? 'Authorization: Basic '.base64_encode($this->username.':'.$this->password).$r : '')\n\t\t\t.'User-Agent: '.$this->xmlrpcName.$r\n\t\t\t.'Content-Length: '.strlen($msg->payload).$r.$r\n\t\t\t.$msg->payload;\n\n\t\tfor ($written = $timestamp = 0, $length = strlen($op); $written < $length; $written += $result)\n\t\t{\n\t\t\tif (($result = fwrite($fp, substr($op, $written))) === FALSE)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// See https://bugs.php.net/bug.php?id=39598 and http://php.net/manual/en/function.fwrite.php#96951\n\t\t\telseif ($result === 0)\n\t\t\t{\n\t\t\t\tif ($timestamp === 0)\n\t\t\t\t{\n\t\t\t\t\t$timestamp = time();\n\t\t\t\t}\n\t\t\t\telseif ($timestamp < (time() - $this->timeout))\n\t\t\t\t{\n\t\t\t\t\t$result = FALSE;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tusleep(250000);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$timestamp = 0;\n\t\t\t}\n\t\t}\n\n\t\tif ($result === FALSE)\n\t\t{\n\t\t\terror_log($this->xmlrpcstr['http_error']);\n\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);\n\t\t}\n\n\t\t$resp = $msg->parseResponse($fp);\n\t\tfclose($fp);\n\t\treturn $resp;\n\t}\n\n} // END XML_RPC_Client Class\n\n/**\n * XML-RPC Response class\n *\n * @category\tXML-RPC\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/xmlrpc.html\n */\nclass XML_RPC_Response\n{\n\n\t/**\n\t * Value\n\t *\n\t * @var\tmixed\n\t */\n\tpublic $val\t\t= 0;\n\n\t/**\n\t * Error number\n\t *\n\t * @var\tint\n\t */\n\tpublic $errno\t\t= 0;\n\n\t/**\n\t * Error message\n\t *\n\t * @var\tstring\n\t */\n\tpublic $errstr\t\t= '';\n\n\t/**\n\t * Headers list\n\t *\n\t * @var\tarray\n\t */\n\tpublic $headers\t\t= array();\n\n\t/**\n\t * XSS Filter flag\n\t *\n\t * @var\tbool\n\t */\n\tpublic $xss_clean\t= TRUE;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @param\tmixed\t$val\n\t * @param\tint\t$code\n\t * @param\tstring\t$fstr\n\t * @return\tvoid\n\t */\n\tpublic function __construct($val, $code = 0, $fstr = '')\n\t{\n\t\tif ($code !== 0)\n\t\t{\n\t\t\t// error\n\t\t\t$this->errno = $code;\n\t\t\t$this->errstr = htmlspecialchars($fstr,\n\t\t\t\t\t\t\t(is_php('5.4') ? ENT_XML1 | ENT_NOQUOTES : ENT_NOQUOTES),\n\t\t\t\t\t\t\t'UTF-8');\n\t\t}\n\t\telseif ( ! is_object($val))\n\t\t{\n\t\t\t// programmer error, not an object\n\t\t\terror_log(\"Invalid type '\".gettype($val).\"' (value: \".$val.') passed to XML_RPC_Response. Defaulting to empty value.');\n\t\t\t$this->val = new XML_RPC_Values();\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$this->val = $val;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fault code\n\t *\n\t * @return\tint\n\t */\n\tpublic function faultCode()\n\t{\n\t\treturn $this->errno;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Fault string\n\t *\n\t * @return\tstring\n\t */\n\tpublic function faultString()\n\t{\n\t\treturn $this->errstr;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Value\n\t *\n\t * @return\tmixed\n\t */\n\tpublic function value()\n\t{\n\t\treturn $this->val;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Prepare response\n\t *\n\t * @return\tstring\txml\n\t */\n\tpublic function prepare_response()\n\t{\n\t\treturn \"<methodResponse>\\n\"\n\t\t\t.($this->errno\n\t\t\t\t? '<fault>\n\t<value>\n\t\t<struct>\n\t\t\t<member>\n\t\t\t\t<name>faultCode</name>\n\t\t\t\t<value><int>'.$this->errno.'</int></value>\n\t\t\t</member>\n\t\t\t<member>\n\t\t\t\t<name>faultString</name>\n\t\t\t\t<value><string>'.$this->errstr.'</string></value>\n\t\t\t</member>\n\t\t</struct>\n\t</value>\n</fault>'\n\t\t\t\t: \"<params>\\n<param>\\n\".$this->val->serialize_class().\"</param>\\n</params>\")\n\t\t\t.\"\\n</methodResponse>\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Decode\n\t *\n\t * @param\tmixed\t$array\n\t * @return\tarray\n\t */\n\tpublic function decode($array = NULL)\n\t{\n\t\t$CI =& get_instance();\n\n\t\tif (is_array($array))\n\t\t{\n\t\t\twhile (list($key) = each($array))\n\t\t\t{\n\t\t\t\tif (is_array($array[$key]))\n\t\t\t\t{\n\t\t\t\t\t$array[$key] = $this->decode($array[$key]);\n\t\t\t\t}\n\t\t\t\telseif ($this->xss_clean)\n\t\t\t\t{\n\t\t\t\t\t$array[$key] = $CI->security->xss_clean($array[$key]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn $array;\n\t\t}\n\n\t\t$result = $this->xmlrpc_decoder($this->val);\n\n\t\tif (is_array($result))\n\t\t{\n\t\t\t$result = $this->decode($result);\n\t\t}\n\t\telseif ($this->xss_clean)\n\t\t{\n\t\t\t$result = $CI->security->xss_clean($result);\n\t\t}\n\n\t\treturn $result;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * XML-RPC Object to PHP Types\n\t *\n\t * @param\tobject\n\t * @return\tarray\n\t */\n\tpublic function xmlrpc_decoder($xmlrpc_val)\n\t{\n\t\t$kind = $xmlrpc_val->kindOf();\n\n\t\tif ($kind === 'scalar')\n\t\t{\n\t\t\treturn $xmlrpc_val->scalarval();\n\t\t}\n\t\telseif ($kind === 'array')\n\t\t{\n\t\t\treset($xmlrpc_val->me);\n\t\t\t$b = current($xmlrpc_val->me);\n\t\t\t$arr = array();\n\n\t\t\tfor ($i = 0, $size = count($b); $i < $size; $i++)\n\t\t\t{\n\t\t\t\t$arr[] = $this->xmlrpc_decoder($xmlrpc_val->me['array'][$i]);\n\t\t\t}\n\t\t\treturn $arr;\n\t\t}\n\t\telseif ($kind === 'struct')\n\t\t{\n\t\t\treset($xmlrpc_val->me['struct']);\n\t\t\t$arr = array();\n\n\t\t\twhile (list($key,$value) = each($xmlrpc_val->me['struct']))\n\t\t\t{\n\t\t\t\t$arr[$key] = $this->xmlrpc_decoder($value);\n\t\t\t}\n\t\t\treturn $arr;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * ISO-8601 time to server or UTC time\n\t *\n\t * @param\tstring\n\t * @param\tbool\n\t * @return\tint\tunix timestamp\n\t */\n\tpublic function iso8601_decode($time, $utc = FALSE)\n\t{\n\t\t// Return a time in the localtime, or UTC\n\t\t$t = 0;\n\t\tif (preg_match('/([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/', $time, $regs))\n\t\t{\n\t\t\t$fnc = ($utc === TRUE) ? 'gmmktime' : 'mktime';\n\t\t\t$t = $fnc($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);\n\t\t}\n\t\treturn $t;\n\t}\n\n} // END XML_RPC_Response Class\n\n/**\n * XML-RPC Message class\n *\n * @category\tXML-RPC\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/xmlrpc.html\n */\nclass XML_RPC_Message extends CI_Xmlrpc\n{\n\n\t/**\n\t * Payload\n\t *\n\t * @var\tstring\n\t */\n\tpublic $payload;\n\n\t/**\n\t * Method name\n\t *\n\t * @var\tstring\n\t */\n\tpublic $method_name;\n\n\t/**\n\t * Parameter list\n\t *\n\t * @var\tarray\n\t */\n\tpublic $params\t\t= array();\n\n\t/**\n\t * XH?\n\t *\n\t * @var\tarray\n\t */\n\tpublic $xh\t\t= array();\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @param\tstring\t$method\n\t * @param\tarray\t$pars\n\t * @return\tvoid\n\t */\n\tpublic function __construct($method, $pars = FALSE)\n\t{\n\t\tparent::__construct();\n\n\t\t$this->method_name = $method;\n\t\tif (is_array($pars) && count($pars) > 0)\n\t\t{\n\t\t\tfor ($i = 0, $c = count($pars); $i < $c; $i++)\n\t\t\t{\n\t\t\t\t// $pars[$i] = XML_RPC_Values\n\t\t\t\t$this->params[] = $pars[$i];\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Create Payload to Send\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function createPayload()\n\t{\n\t\t$this->payload = '<?xml version=\"1.0\"?'.\">\\r\\n<methodCall>\\r\\n\"\n\t\t\t\t.'<methodName>'.$this->method_name.\"</methodName>\\r\\n\"\n\t\t\t\t.\"<params>\\r\\n\";\n\n\t\tfor ($i = 0, $c = count($this->params); $i < $c; $i++)\n\t\t{\n\t\t\t// $p = XML_RPC_Values\n\t\t\t$p = $this->params[$i];\n\t\t\t$this->payload .= \"<param>\\r\\n\".$p->serialize_class().\"</param>\\r\\n\";\n\t\t}\n\n\t\t$this->payload .= \"</params>\\r\\n</methodCall>\\r\\n\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse External XML-RPC Server's Response\n\t *\n\t * @param\tresource\n\t * @return\tobject\n\t */\n\tpublic function parseResponse($fp)\n\t{\n\t\t$data = '';\n\n\t\twhile ($datum = fread($fp, 4096))\n\t\t{\n\t\t\t$data .= $datum;\n\t\t}\n\n\t\t// Display HTTP content for debugging\n\t\tif ($this->debug === TRUE)\n\t\t{\n\t\t\techo \"<pre>---DATA---\\n\".htmlspecialchars($data).\"\\n---END DATA---\\n\\n</pre>\";\n\t\t}\n\n\t\t// Check for data\n\t\tif ($data === '')\n\t\t{\n\t\t\terror_log($this->xmlrpcstr['no_data']);\n\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['no_data'], $this->xmlrpcstr['no_data']);\n\t\t}\n\n\t\t// Check for HTTP 200 Response\n\t\tif (strpos($data, 'HTTP') === 0 && ! preg_match('/^HTTP\\/[0-9\\.]+ 200 /', $data))\n\t\t{\n\t\t\t$errstr = substr($data, 0, strpos($data, \"\\n\")-1);\n\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error'].' ('.$errstr.')');\n\t\t}\n\n\t\t//-------------------------------------\n\t\t// Create and Set Up XML Parser\n\t\t//-------------------------------------\n\n\t\t$parser = xml_parser_create($this->xmlrpc_defencoding);\n\t\t$pname = (string) $parser;\n\t\t$this->xh[$pname] = array(\n\t\t\t'isf'\t\t=> 0,\n\t\t\t'ac'\t\t=> '',\n\t\t\t'headers'\t=> array(),\n\t\t\t'stack'\t\t=> array(),\n\t\t\t'valuestack'\t=> array(),\n\t\t\t'isf_reason'\t=> 0\n\t\t);\n\n\t\txml_set_object($parser, $this);\n\t\txml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, TRUE);\n\t\txml_set_element_handler($parser, 'open_tag', 'closing_tag');\n\t\txml_set_character_data_handler($parser, 'character_data');\n\t\t//xml_set_default_handler($parser, 'default_handler');\n\n\t\t// Get headers\n\t\t$lines = explode(\"\\r\\n\", $data);\n\t\twhile (($line = array_shift($lines)))\n\t\t{\n\t\t\tif (strlen($line) < 1)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t$this->xh[$pname]['headers'][] = $line;\n\t\t}\n\t\t$data = implode(\"\\r\\n\", $lines);\n\n\t\t// Parse XML data\n\t\tif ( ! xml_parse($parser, $data, count($data)))\n\t\t{\n\t\t\t$errstr = sprintf('XML error: %s at line %d',\n\t\t\t\t\t\txml_error_string(xml_get_error_code($parser)),\n\t\t\t\t\t\txml_get_current_line_number($parser));\n\n\t\t\t$r = new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);\n\t\t\txml_parser_free($parser);\n\t\t\treturn $r;\n\t\t}\n\t\txml_parser_free($parser);\n\n\t\t// Got ourselves some badness, it seems\n\t\tif ($this->xh[$pname]['isf'] > 1)\n\t\t{\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\techo \"---Invalid Return---\\n\".$this->xh[$pname]['isf_reason'].\"---Invalid Return---\\n\\n\";\n\t\t\t}\n\n\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$pname]['isf_reason']);\n\t\t}\n\t\telseif ( ! is_object($this->xh[$pname]['value']))\n\t\t{\n\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$pname]['isf_reason']);\n\t\t}\n\n\t\t// Display XML content for debugging\n\t\tif ($this->debug === TRUE)\n\t\t{\n\t\t\techo '<pre>';\n\n\t\t\tif (count($this->xh[$pname]['headers'] > 0))\n\t\t\t{\n\t\t\t\techo \"---HEADERS---\\n\";\n\t\t\t\tforeach ($this->xh[$pname]['headers'] as $header)\n\t\t\t\t{\n\t\t\t\t\techo $header.\"\\n\";\n\t\t\t\t}\n\t\t\t\techo \"---END HEADERS---\\n\\n\";\n\t\t\t}\n\n\t\t\techo \"---DATA---\\n\".htmlspecialchars($data).\"\\n---END DATA---\\n\\n---PARSED---\\n\";\n\t\t\tvar_dump($this->xh[$pname]['value']);\n\t\t\techo \"\\n---END PARSED---</pre>\";\n\t\t}\n\n\t\t// Send response\n\t\t$v = $this->xh[$pname]['value'];\n\t\tif ($this->xh[$pname]['isf'])\n\t\t{\n\t\t\t$errno_v = $v->me['struct']['faultCode'];\n\t\t\t$errstr_v = $v->me['struct']['faultString'];\n\t\t\t$errno = $errno_v->scalarval();\n\n\t\t\tif ($errno === 0)\n\t\t\t{\n\t\t\t\t// FAULT returned, errno needs to reflect that\n\t\t\t\t$errno = -1;\n\t\t\t}\n\n\t\t\t$r = new XML_RPC_Response($v, $errno, $errstr_v->scalarval());\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$r = new XML_RPC_Response($v);\n\t\t}\n\n\t\t$r->headers = $this->xh[$pname]['headers'];\n\t\treturn $r;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t// ------------------------------------\n\t//  Begin Return Message Parsing section\n\t// ------------------------------------\n\n\t// quick explanation of components:\n\t//   ac - used to accumulate values\n\t//   isf - used to indicate a fault\n\t//   lv - used to indicate \"looking for a value\": implements\n\t//\t\tthe logic to allow values with no types to be strings\n\t//   params - used to store parameters in method calls\n\t//   method - used to store method name\n\t//\t stack - array with parent tree of the xml element,\n\t//\t\t\t used to validate the nesting of elements\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Start Element Handler\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tvoid\n\t */\n\tpublic function open_tag($the_parser, $name)\n\t{\n\t\t$the_parser = (string) $the_parser;\n\n\t\t// If invalid nesting, then return\n\t\tif ($this->xh[$the_parser]['isf'] > 1) return;\n\n\t\t// Evaluate and check for correct nesting of XML elements\n\t\tif (count($this->xh[$the_parser]['stack']) === 0)\n\t\t{\n\t\t\tif ($name !== 'METHODRESPONSE' && $name !== 'METHODCALL')\n\t\t\t{\n\t\t\t\t$this->xh[$the_parser]['isf'] = 2;\n\t\t\t\t$this->xh[$the_parser]['isf_reason'] = 'Top level XML-RPC element is missing';\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t// not top level element: see if parent is OK\n\t\telseif ( ! in_array($this->xh[$the_parser]['stack'][0], $this->valid_parents[$name], TRUE))\n\t\t{\n\t\t\t$this->xh[$the_parser]['isf'] = 2;\n\t\t\t$this->xh[$the_parser]['isf_reason'] = 'XML-RPC element '.$name.' cannot be child of '.$this->xh[$the_parser]['stack'][0];\n\t\t\treturn;\n\t\t}\n\n\t\tswitch ($name)\n\t\t{\n\t\t\tcase 'STRUCT':\n\t\t\tcase 'ARRAY':\n\t\t\t\t// Creates array for child elements\n\t\t\t\t$cur_val = array('value' => array(), 'type' => $name);\n\t\t\t\tarray_unshift($this->xh[$the_parser]['valuestack'], $cur_val);\n\t\t\t\tbreak;\n\t\t\tcase 'METHODNAME':\n\t\t\tcase 'NAME':\n\t\t\t\t$this->xh[$the_parser]['ac'] = '';\n\t\t\t\tbreak;\n\t\t\tcase 'FAULT':\n\t\t\t\t$this->xh[$the_parser]['isf'] = 1;\n\t\t\t\tbreak;\n\t\t\tcase 'PARAM':\n\t\t\t\t$this->xh[$the_parser]['value'] = NULL;\n\t\t\t\tbreak;\n\t\t\tcase 'VALUE':\n\t\t\t\t$this->xh[$the_parser]['vt'] = 'value';\n\t\t\t\t$this->xh[$the_parser]['ac'] = '';\n\t\t\t\t$this->xh[$the_parser]['lv'] = 1;\n\t\t\t\tbreak;\n\t\t\tcase 'I4':\n\t\t\tcase 'INT':\n\t\t\tcase 'STRING':\n\t\t\tcase 'BOOLEAN':\n\t\t\tcase 'DOUBLE':\n\t\t\tcase 'DATETIME.ISO8601':\n\t\t\tcase 'BASE64':\n\t\t\t\tif ($this->xh[$the_parser]['vt'] !== 'value')\n\t\t\t\t{\n\t\t\t\t\t//two data elements inside a value: an error occurred!\n\t\t\t\t\t$this->xh[$the_parser]['isf'] = 2;\n\t\t\t\t\t$this->xh[$the_parser]['isf_reason'] = 'There is a '.$name.' element following a '\n\t\t\t\t\t\t\t\t\t\t.$this->xh[$the_parser]['vt'].' element inside a single value';\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t$this->xh[$the_parser]['ac'] = '';\n\t\t\t\tbreak;\n\t\t\tcase 'MEMBER':\n\t\t\t\t// Set name of <member> to nothing to prevent errors later if no <name> is found\n\t\t\t\t$this->xh[$the_parser]['valuestack'][0]['name'] = '';\n\n\t\t\t\t// Set NULL value to check to see if value passed for this param/member\n\t\t\t\t$this->xh[$the_parser]['value'] = NULL;\n\t\t\t\tbreak;\n\t\t\tcase 'DATA':\n\t\t\tcase 'METHODCALL':\n\t\t\tcase 'METHODRESPONSE':\n\t\t\tcase 'PARAMS':\n\t\t\t\t// valid elements that add little to processing\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t/// An Invalid Element is Found, so we have trouble\n\t\t\t\t$this->xh[$the_parser]['isf'] = 2;\n\t\t\t\t$this->xh[$the_parser]['isf_reason'] = 'Invalid XML-RPC element found: '.$name;\n\t\t\t\tbreak;\n\t\t}\n\n\t\t// Add current element name to stack, to allow validation of nesting\n\t\tarray_unshift($this->xh[$the_parser]['stack'], $name);\n\n\t\t$name === 'VALUE' OR $this->xh[$the_parser]['lv'] = 0;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * End Element Handler\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tvoid\n\t */\n\tpublic function closing_tag($the_parser, $name)\n\t{\n\t\t$the_parser = (string) $the_parser;\n\n\t\tif ($this->xh[$the_parser]['isf'] > 1) return;\n\n\t\t// Remove current element from stack and set variable\n\t\t// NOTE: If the XML validates, then we do not have to worry about\n\t\t// the opening and closing of elements. Nesting is checked on the opening\n\t\t// tag so we be safe there as well.\n\n\t\t$curr_elem = array_shift($this->xh[$the_parser]['stack']);\n\n\t\tswitch ($name)\n\t\t{\n\t\t\tcase 'STRUCT':\n\t\t\tcase 'ARRAY':\n\t\t\t\t$cur_val = array_shift($this->xh[$the_parser]['valuestack']);\n\t\t\t\t$this->xh[$the_parser]['value'] = isset($cur_val['values']) ? $cur_val['values'] : array();\n\t\t\t\t$this->xh[$the_parser]['vt']\t= strtolower($name);\n\t\t\t\tbreak;\n\t\t\tcase 'NAME':\n\t\t\t\t$this->xh[$the_parser]['valuestack'][0]['name'] = $this->xh[$the_parser]['ac'];\n\t\t\t\tbreak;\n\t\t\tcase 'BOOLEAN':\n\t\t\tcase 'I4':\n\t\t\tcase 'INT':\n\t\t\tcase 'STRING':\n\t\t\tcase 'DOUBLE':\n\t\t\tcase 'DATETIME.ISO8601':\n\t\t\tcase 'BASE64':\n\t\t\t\t$this->xh[$the_parser]['vt'] = strtolower($name);\n\n\t\t\t\tif ($name === 'STRING')\n\t\t\t\t{\n\t\t\t\t\t$this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];\n\t\t\t\t}\n\t\t\t\telseif ($name === 'DATETIME.ISO8601')\n\t\t\t\t{\n\t\t\t\t\t$this->xh[$the_parser]['vt']\t= $this->xmlrpcDateTime;\n\t\t\t\t\t$this->xh[$the_parser]['value'] = $this->xh[$the_parser]['ac'];\n\t\t\t\t}\n\t\t\t\telseif ($name === 'BASE64')\n\t\t\t\t{\n\t\t\t\t\t$this->xh[$the_parser]['value'] = base64_decode($this->xh[$the_parser]['ac']);\n\t\t\t\t}\n\t\t\t\telseif ($name === 'BOOLEAN')\n\t\t\t\t{\n\t\t\t\t\t// Translated BOOLEAN values to TRUE AND FALSE\n\t\t\t\t\t$this->xh[$the_parser]['value'] = (bool) $this->xh[$the_parser]['ac'];\n\t\t\t\t}\n\t\t\t\telseif ($name=='DOUBLE')\n\t\t\t\t{\n\t\t\t\t\t// we have a DOUBLE\n\t\t\t\t\t// we must check that only 0123456789-.<space> are characters here\n\t\t\t\t\t$this->xh[$the_parser]['value'] = preg_match('/^[+-]?[eE0-9\\t \\.]+$/', $this->xh[$the_parser]['ac'])\n\t\t\t\t\t\t\t\t\t\t? (float) $this->xh[$the_parser]['ac']\n\t\t\t\t\t\t\t\t\t\t: 'ERROR_NON_NUMERIC_FOUND';\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// we have an I4/INT\n\t\t\t\t\t// we must check that only 0123456789-<space> are characters here\n\t\t\t\t\t$this->xh[$the_parser]['value'] = preg_match('/^[+-]?[0-9\\t ]+$/', $this->xh[$the_parser]['ac'])\n\t\t\t\t\t\t\t\t\t\t? (int) $this->xh[$the_parser]['ac']\n\t\t\t\t\t\t\t\t\t\t: 'ERROR_NON_NUMERIC_FOUND';\n\t\t\t\t}\n\t\t\t\t$this->xh[$the_parser]['ac'] = '';\n\t\t\t\t$this->xh[$the_parser]['lv'] = 3; // indicate we've found a value\n\t\t\t\tbreak;\n\t\t\tcase 'VALUE':\n\t\t\t\t// This if() detects if no scalar was inside <VALUE></VALUE>\n\t\t\t\tif ($this->xh[$the_parser]['vt'] == 'value')\n\t\t\t\t{\n\t\t\t\t\t$this->xh[$the_parser]['value']\t= $this->xh[$the_parser]['ac'];\n\t\t\t\t\t$this->xh[$the_parser]['vt']\t= $this->xmlrpcString;\n\t\t\t\t}\n\n\t\t\t\t// build the XML-RPC value out of the data received, and substitute it\n\t\t\t\t$temp = new XML_RPC_Values($this->xh[$the_parser]['value'], $this->xh[$the_parser]['vt']);\n\n\t\t\t\tif (count($this->xh[$the_parser]['valuestack']) && $this->xh[$the_parser]['valuestack'][0]['type'] === 'ARRAY')\n\t\t\t\t{\n\t\t\t\t\t// Array\n\t\t\t\t\t$this->xh[$the_parser]['valuestack'][0]['values'][] = $temp;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\t// Struct\n\t\t\t\t\t$this->xh[$the_parser]['value'] = $temp;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'MEMBER':\n\t\t\t\t$this->xh[$the_parser]['ac'] = '';\n\n\t\t\t\t// If value add to array in the stack for the last element built\n\t\t\t\tif ($this->xh[$the_parser]['value'])\n\t\t\t\t{\n\t\t\t\t\t$this->xh[$the_parser]['valuestack'][0]['values'][$this->xh[$the_parser]['valuestack'][0]['name']] = $this->xh[$the_parser]['value'];\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'DATA':\n\t\t\t\t$this->xh[$the_parser]['ac'] = '';\n\t\t\t\tbreak;\n\t\t\tcase 'PARAM':\n\t\t\t\tif ($this->xh[$the_parser]['value'])\n\t\t\t\t{\n\t\t\t\t\t$this->xh[$the_parser]['params'][] = $this->xh[$the_parser]['value'];\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'METHODNAME':\n\t\t\t\t$this->xh[$the_parser]['method'] = ltrim($this->xh[$the_parser]['ac']);\n\t\t\t\tbreak;\n\t\t\tcase 'PARAMS':\n\t\t\tcase 'FAULT':\n\t\t\tcase 'METHODCALL':\n\t\t\tcase 'METHORESPONSE':\n\t\t\t\t// We're all good kids with nuthin' to do\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\t// End of an Invalid Element. Taken care of during the opening tag though\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse character data\n\t *\n\t * @param\tstring\n\t * @param\tstring\n\t * @return\tvoid\n\t */\n\tpublic function character_data($the_parser, $data)\n\t{\n\t\t$the_parser = (string) $the_parser;\n\n\t\tif ($this->xh[$the_parser]['isf'] > 1) return; // XML Fault found already\n\n\t\t// If a value has not been found\n\t\tif ($this->xh[$the_parser]['lv'] !== 3)\n\t\t{\n\t\t\tif ($this->xh[$the_parser]['lv'] === 1)\n\t\t\t{\n\t\t\t\t$this->xh[$the_parser]['lv'] = 2; // Found a value\n\t\t\t}\n\n\t\t\tif ( ! isset($this->xh[$the_parser]['ac']))\n\t\t\t{\n\t\t\t\t$this->xh[$the_parser]['ac'] = '';\n\t\t\t}\n\n\t\t\t$this->xh[$the_parser]['ac'] .= $data;\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add parameter\n\t *\n\t * @param\tmixed\n\t * @return\tvoid\n\t */\n\tpublic function addParam($par)\n\t{\n\t\t$this->params[] = $par;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Output parameters\n\t *\n\t * @param\tarray\t$array\n\t * @return\tarray\n\t */\n\tpublic function output_parameters(array $array = array())\n\t{\n\t\t$CI =& get_instance();\n\n\t\tif ( ! empty($array))\n\t\t{\n\t\t\twhile (list($key) = each($array))\n\t\t\t{\n\t\t\t\tif (is_array($array[$key]))\n\t\t\t\t{\n\t\t\t\t\t$array[$key] = $this->output_parameters($array[$key]);\n\t\t\t\t}\n\t\t\t\telseif ($key !== 'bits' && $this->xss_clean)\n\t\t\t\t{\n\t\t\t\t\t// 'bits' is for the MetaWeblog API image bits\n\t\t\t\t\t// @todo - this needs to be made more general purpose\n\t\t\t\t\t$array[$key] = $CI->security->xss_clean($array[$key]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn $array;\n\t\t}\n\n\t\t$parameters = array();\n\n\t\tfor ($i = 0, $c = count($this->params); $i < $c; $i++)\n\t\t{\n\t\t\t$a_param = $this->decode_message($this->params[$i]);\n\n\t\t\tif (is_array($a_param))\n\t\t\t{\n\t\t\t\t$parameters[] = $this->output_parameters($a_param);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$parameters[] = ($this->xss_clean) ? $CI->security->xss_clean($a_param) : $a_param;\n\t\t\t}\n\t\t}\n\n\t\treturn $parameters;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Decode message\n\t *\n\t * @param\tobject\n\t * @return\tmixed\n\t */\n\tpublic function decode_message($param)\n\t{\n\t\t$kind = $param->kindOf();\n\n\t\tif ($kind === 'scalar')\n\t\t{\n\t\t\treturn $param->scalarval();\n\t\t}\n\t\telseif ($kind === 'array')\n\t\t{\n\t\t\treset($param->me);\n\t\t\t$b = current($param->me);\n\t\t\t$arr = array();\n\n\t\t\tfor ($i = 0, $c = count($b); $i < $c; $i++)\n\t\t\t{\n\t\t\t\t$arr[] = $this->decode_message($param->me['array'][$i]);\n\t\t\t}\n\n\t\t\treturn $arr;\n\t\t}\n\t\telseif ($kind === 'struct')\n\t\t{\n\t\t\treset($param->me['struct']);\n\t\t\t$arr = array();\n\n\t\t\twhile (list($key,$value) = each($param->me['struct']))\n\t\t\t{\n\t\t\t\t$arr[$key] = $this->decode_message($value);\n\t\t\t}\n\n\t\t\treturn $arr;\n\t\t}\n\t}\n\n} // END XML_RPC_Message Class\n\n/**\n * XML-RPC Values class\n *\n * @category\tXML-RPC\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/xmlrpc.html\n */\nclass XML_RPC_Values extends CI_Xmlrpc\n{\n\t/**\n\t * Value data\n\t *\n\t * @var\tarray\n\t */\n\tpublic $me\t= array();\n\n\t/**\n\t * Value type\n\t *\n\t * @var\tint\n\t */\n\tpublic $mytype\t= 0;\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Constructor\n\t *\n\t * @param\tmixed\t$val\n\t * @param\tstring\t$type\n\t * @return\tvoid\n\t */\n\tpublic function __construct($val = -1, $type = '')\n\t{\n\t\tparent::__construct();\n\n\t\tif ($val !== -1 OR $type !== '')\n\t\t{\n\t\t\t$type = $type === '' ? 'string' : $type;\n\n\t\t\tif ($this->xmlrpcTypes[$type] == 1)\n\t\t\t{\n\t\t\t\t$this->addScalar($val, $type);\n\t\t\t}\n\t\t\telseif ($this->xmlrpcTypes[$type] == 2)\n\t\t\t{\n\t\t\t\t$this->addArray($val);\n\t\t\t}\n\t\t\telseif ($this->xmlrpcTypes[$type] == 3)\n\t\t\t{\n\t\t\t\t$this->addStruct($val);\n\t\t\t}\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add scalar value\n\t *\n\t * @param\tscalar\n\t * @param\tstring\n\t * @return\tint\n\t */\n\tpublic function addScalar($val, $type = 'string')\n\t{\n\t\t$typeof = $this->xmlrpcTypes[$type];\n\n\t\tif ($this->mytype === 1)\n\t\t{\n\t\t\techo '<strong>XML_RPC_Values</strong>: scalar can have only one value<br />';\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ($typeof != 1)\n\t\t{\n\t\t\techo '<strong>XML_RPC_Values</strong>: not a scalar type (${typeof})<br />';\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ($type === $this->xmlrpcBoolean)\n\t\t{\n\t\t\t$val = (int) (strcasecmp($val, 'true') === 0 OR $val === 1 OR ($val === TRUE && strcasecmp($val, 'false')));\n\t\t}\n\n\t\tif ($this->mytype === 2)\n\t\t{\n\t\t\t// adding to an array here\n\t\t\t$ar = $this->me['array'];\n\t\t\t$ar[] = new XML_RPC_Values($val, $type);\n\t\t\t$this->me['array'] = $ar;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t// a scalar, so set the value and remember we're scalar\n\t\t\t$this->me[$type] = $val;\n\t\t\t$this->mytype = $typeof;\n\t\t}\n\n\t\treturn 1;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add array value\n\t *\n\t * @param\tarray\n\t * @return\tint\n\t */\n\tpublic function addArray($vals)\n\t{\n\t\tif ($this->mytype !== 0)\n\t\t{\n\t\t\techo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';\n\t\t\treturn 0;\n\t\t}\n\n\t\t$this->mytype = $this->xmlrpcTypes['array'];\n\t\t$this->me['array'] = $vals;\n\t\treturn 1;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add struct value\n\t *\n\t * @param\tobject\n\t * @return\tint\n\t */\n\tpublic function addStruct($vals)\n\t{\n\t\tif ($this->mytype !== 0)\n\t\t{\n\t\t\techo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';\n\t\t\treturn 0;\n\t\t}\n\t\t$this->mytype = $this->xmlrpcTypes['struct'];\n\t\t$this->me['struct'] = $vals;\n\t\treturn 1;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get value type\n\t *\n\t * @return\tstring\n\t */\n\tpublic function kindOf()\n\t{\n\t\tswitch ($this->mytype)\n\t\t{\n\t\t\tcase 3: return 'struct';\n\t\t\tcase 2: return 'array';\n\t\t\tcase 1: return 'scalar';\n\t\t\tdefault: return 'undef';\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Serialize data\n\t *\n\t * @param\tstring\n\t * @param\tmixed\n\t * @return\tstring\n\t */\n\tpublic function serializedata($typ, $val)\n\t{\n\t\t$rs = '';\n\n\t\tswitch ($this->xmlrpcTypes[$typ])\n\t\t{\n\t\t\tcase 3:\n\t\t\t\t// struct\n\t\t\t\t$rs .= \"<struct>\\n\";\n\t\t\t\treset($val);\n\t\t\t\twhile (list($key2, $val2) = each($val))\n\t\t\t\t{\n\t\t\t\t\t$rs .= \"<member>\\n<name>{$key2}</name>\\n\".$this->serializeval($val2).\"</member>\\n\";\n\t\t\t\t}\n\t\t\t\t$rs .= '</struct>';\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\t// array\n\t\t\t\t$rs .= \"<array>\\n<data>\\n\";\n\t\t\t\tfor ($i = 0, $c = count($val); $i < $c; $i++)\n\t\t\t\t{\n\t\t\t\t\t$rs .= $this->serializeval($val[$i]);\n\t\t\t\t}\n\t\t\t\t$rs .= \"</data>\\n</array>\\n\";\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\t// others\n\t\t\t\tswitch ($typ)\n\t\t\t\t{\n\t\t\t\t\tcase $this->xmlrpcBase64:\n\t\t\t\t\t\t$rs .= '<'.$typ.'>'.base64_encode( (string) $val).'</'.$typ.\">\\n\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase $this->xmlrpcBoolean:\n\t\t\t\t\t\t$rs .= '<'.$typ.'>'.( (bool) $val ? '1' : '0').'</'.$typ.\">\\n\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase $this->xmlrpcString:\n\t\t\t\t\t\t$rs .= '<'.$typ.'>'.htmlspecialchars( (string) $val).'</'.$typ.\">\\n\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t$rs .= '<'.$typ.'>'.$val.'</'.$typ.\">\\n\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn $rs;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Serialize class\n\t *\n\t * @return\tstring\n\t */\n\tpublic function serialize_class()\n\t{\n\t\treturn $this->serializeval($this);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Serialize value\n\t *\n\t * @param\tobject\n\t * @return\tstring\n\t */\n\tpublic function serializeval($o)\n\t{\n\t\t$ar = $o->me;\n\t\treset($ar);\n\n\t\tlist($typ, $val) = each($ar);\n\t\treturn \"<value>\\n\".$this->serializedata($typ, $val).\"</value>\\n\";\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Scalar value\n\t *\n\t * @return\tmixed\n\t */\n\tpublic function scalarval()\n\t{\n\t\treset($this->me);\n\t\treturn current($this->me);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Encode time in ISO-8601 form.\n\t * Useful for sending time in XML-RPC\n\t *\n\t * @param\tint\tunix timestamp\n\t * @param\tbool\n\t * @return\tstring\n\t*/\n\tpublic function iso8601_encode($time, $utc = FALSE)\n\t{\n\t\treturn ($utc) ? strftime('%Y%m%dT%H:%i:%s', $time) : gmstrftime('%Y%m%dT%H:%i:%s', $time);\n\t}\n\n} // END XML_RPC_Values Class\n"
  },
  {
    "path": "system/libraries/Xmlrpcs.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\nif ( ! function_exists('xml_parser_create'))\n{\n\tshow_error('Your PHP installation does not support XML');\n}\n\nif ( ! class_exists('CI_Xmlrpc', FALSE))\n{\n\tshow_error('You must load the Xmlrpc class before loading the Xmlrpcs class in order to create a server.');\n}\n\n// ------------------------------------------------------------------------\n\n/**\n * XML-RPC server class\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tXML-RPC\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/xmlrpc.html\n */\nclass CI_Xmlrpcs extends CI_Xmlrpc {\n\n\t/**\n\t * Array of methods mapped to function names and signatures\n\t *\n\t * @var array\n\t */\n\tpublic $methods = array();\n\n\t/**\n\t * Debug Message\n\t *\n\t * @var string\n\t */\n\tpublic $debug_msg = '';\n\n\t/**\n\t * XML RPC Server methods\n\t *\n\t * @var array\n\t */\n\tpublic $system_methods\t= array();\n\n\t/**\n\t * Configuration object\n\t *\n\t * @var object\n\t */\n\tpublic $object = FALSE;\n\n\t/**\n\t * Initialize XMLRPC class\n\t *\n\t * @param\tarray\t$config\n\t * @return\tvoid\n\t */\n\tpublic function __construct($config = array())\n\t{\n\t\tparent::__construct();\n\t\t$this->set_system_methods();\n\n\t\tif (isset($config['functions']) && is_array($config['functions']))\n\t\t{\n\t\t\t$this->methods = array_merge($this->methods, $config['functions']);\n\t\t}\n\n\t\tlog_message('info', 'XML-RPC Server Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize Prefs and Serve\n\t *\n\t * @param\tmixed\n\t * @return\tvoid\n\t */\n\tpublic function initialize($config = array())\n\t{\n\t\tif (isset($config['functions']) && is_array($config['functions']))\n\t\t{\n\t\t\t$this->methods = array_merge($this->methods, $config['functions']);\n\t\t}\n\n\t\tif (isset($config['debug']))\n\t\t{\n\t\t\t$this->debug = $config['debug'];\n\t\t}\n\n\t\tif (isset($config['object']) && is_object($config['object']))\n\t\t{\n\t\t\t$this->object = $config['object'];\n\t\t}\n\n\t\tif (isset($config['xss_clean']))\n\t\t{\n\t\t\t$this->xss_clean = $config['xss_clean'];\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Setting of System Methods\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function set_system_methods()\n\t{\n\t\t$this->methods = array(\n\t\t\t\t\t'system.listMethods'\t => array(\n\t\t\t\t\t\t\t\t\t\t'function' => 'this.listMethods',\n\t\t\t\t\t\t\t\t\t\t'signature' => array(array($this->xmlrpcArray, $this->xmlrpcString), array($this->xmlrpcArray)),\n\t\t\t\t\t\t\t\t\t\t'docstring' => 'Returns an array of available methods on this server'),\n\t\t\t\t\t'system.methodHelp'\t => array(\n\t\t\t\t\t\t\t\t\t\t'function' => 'this.methodHelp',\n\t\t\t\t\t\t\t\t\t\t'signature' => array(array($this->xmlrpcString, $this->xmlrpcString)),\n\t\t\t\t\t\t\t\t\t\t'docstring' => 'Returns a documentation string for the specified method'),\n\t\t\t\t\t'system.methodSignature' => array(\n\t\t\t\t\t\t\t\t\t\t'function' => 'this.methodSignature',\n\t\t\t\t\t\t\t\t\t\t'signature' => array(array($this->xmlrpcArray, $this->xmlrpcString)),\n\t\t\t\t\t\t\t\t\t\t'docstring' => 'Returns an array describing the return type and required parameters of a method'),\n\t\t\t\t\t'system.multicall'\t => array(\n\t\t\t\t\t\t\t\t\t\t'function' => 'this.multicall',\n\t\t\t\t\t\t\t\t\t\t'signature' => array(array($this->xmlrpcArray, $this->xmlrpcArray)),\n\t\t\t\t\t\t\t\t\t\t'docstring' => 'Combine multiple RPC calls in one request. See http://www.xmlrpc.com/discuss/msgReader$1208 for details')\n\t\t\t\t);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Main Server Function\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function serve()\n\t{\n\t\t$r = $this->parseRequest();\n\t\t$payload = '<?xml version=\"1.0\" encoding=\"'.$this->xmlrpc_defencoding.'\"?'.'>'.\"\\n\".$this->debug_msg.$r->prepare_response();\n\n\t\theader('Content-Type: text/xml');\n\t\theader('Content-Length: '.strlen($payload));\n\t\texit($payload);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add Method to Class\n\t *\n\t * @param\tstring\tmethod name\n\t * @param\tstring\tfunction\n\t * @param\tstring\tsignature\n\t * @param\tstring\tdocstring\n\t * @return\tvoid\n\t */\n\tpublic function add_to_map($methodname, $function, $sig, $doc)\n\t{\n\t\t$this->methods[$methodname] = array(\n\t\t\t'function'\t=> $function,\n\t\t\t'signature'\t=> $sig,\n\t\t\t'docstring'\t=> $doc\n\t\t);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Parse Server Request\n\t *\n\t * @param\tstring\tdata\n\t * @return\tobject\txmlrpc response\n\t */\n\tpublic function parseRequest($data = '')\n\t{\n\t\t//-------------------------------------\n\t\t//  Get Data\n\t\t//-------------------------------------\n\n\t\tif ($data === '')\n\t\t{\n\t\t\t$CI =& get_instance();\n\t\t\tif ($CI->input->method() === 'post')\n\t\t\t{\n\t\t\t\t$data = $CI->input->raw_input_stream;\n\t\t\t}\n\t\t}\n\n\t\t//-------------------------------------\n\t\t//  Set up XML Parser\n\t\t//-------------------------------------\n\n\t\t$parser = xml_parser_create($this->xmlrpc_defencoding);\n\t\t$parser_object = new XML_RPC_Message('filler');\n\t\t$pname = (string) $parser;\n\n\t\t$parser_object->xh[$pname] = array(\n\t\t\t'isf' => 0,\n\t\t\t'isf_reason' => '',\n\t\t\t'params' => array(),\n\t\t\t'stack' => array(),\n\t\t\t'valuestack' => array(),\n\t\t\t'method' => ''\n\t\t);\n\n\t\txml_set_object($parser, $parser_object);\n\t\txml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, TRUE);\n\t\txml_set_element_handler($parser, 'open_tag', 'closing_tag');\n\t\txml_set_character_data_handler($parser, 'character_data');\n\t\t//xml_set_default_handler($parser, 'default_handler');\n\n\t\t//-------------------------------------\n\t\t// PARSE + PROCESS XML DATA\n\t\t//-------------------------------------\n\n\t\tif ( ! xml_parse($parser, $data, 1))\n\t\t{\n\t\t\t// Return XML error as a faultCode\n\t\t\t$r = new XML_RPC_Response(0,\n\t\t\t\t$this->xmlrpcerrxml + xml_get_error_code($parser),\n\t\t\t\tsprintf('XML error: %s at line %d',\n\t\t\t\txml_error_string(xml_get_error_code($parser)),\n\t\t\t\txml_get_current_line_number($parser)));\n\t\t\txml_parser_free($parser);\n\t\t}\n\t\telseif ($parser_object->xh[$pname]['isf'])\n\t\t{\n\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return']);\n\t\t}\n\t\telse\n\t\t{\n\t\t\txml_parser_free($parser);\n\n\t\t\t$m = new XML_RPC_Message($parser_object->xh[$pname]['method']);\n\t\t\t$plist = '';\n\n\t\t\tfor ($i = 0, $c = count($parser_object->xh[$pname]['params']); $i < $c; $i++)\n\t\t\t{\n\t\t\t\tif ($this->debug === TRUE)\n\t\t\t\t{\n\t\t\t\t\t$plist .= $i.' - '.print_r(get_object_vars($parser_object->xh[$pname]['params'][$i]), TRUE).\";\\n\";\n\t\t\t\t}\n\n\t\t\t\t$m->addParam($parser_object->xh[$pname]['params'][$i]);\n\t\t\t}\n\n\t\t\tif ($this->debug === TRUE)\n\t\t\t{\n\t\t\t\techo \"<pre>---PLIST---\\n\".$plist.\"\\n---PLIST END---\\n\\n</pre>\";\n\t\t\t}\n\n\t\t\t$r = $this->_execute($m);\n\t\t}\n\n\t\t//-------------------------------------\n\t\t// SET DEBUGGING MESSAGE\n\t\t//-------------------------------------\n\n\t\tif ($this->debug === TRUE)\n\t\t{\n\t\t\t$this->debug_msg = \"<!-- DEBUG INFO:\\n\\n\".$plist.\"\\n END DEBUG-->\\n\";\n\t\t}\n\n\t\treturn $r;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Executes the Method\n\t *\n\t * @param\tobject\n\t * @return\tmixed\n\t */\n\tprotected function _execute($m)\n\t{\n\t\t$methName = $m->method_name;\n\n\t\t// Check to see if it is a system call\n\t\t$system_call = (strpos($methName, 'system') === 0);\n\n\t\tif ($this->xss_clean === FALSE)\n\t\t{\n\t\t\t$m->xss_clean = FALSE;\n\t\t}\n\n\t\t//-------------------------------------\n\t\t// Valid Method\n\t\t//-------------------------------------\n\n\t\tif ( ! isset($this->methods[$methName]['function']))\n\t\t{\n\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['unknown_method'], $this->xmlrpcstr['unknown_method']);\n\t\t}\n\n\t\t//-------------------------------------\n\t\t// Check for Method (and Object)\n\t\t//-------------------------------------\n\n\t\t$method_parts = explode('.', $this->methods[$methName]['function']);\n\t\t$objectCall = (isset($method_parts[1]) && $method_parts[1] !== '');\n\n\t\tif ($system_call === TRUE)\n\t\t{\n\t\t\tif ( ! is_callable(array($this,$method_parts[1])))\n\t\t\t{\n\t\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['unknown_method'], $this->xmlrpcstr['unknown_method']);\n\t\t\t}\n\t\t}\n\t\telseif (($objectCall && ! is_callable(array($method_parts[0], $method_parts[1])))\n\t\t\tOR ( ! $objectCall && ! is_callable($this->methods[$methName]['function']))\n\t\t)\n\t\t{\n\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['unknown_method'], $this->xmlrpcstr['unknown_method']);\n\t\t}\n\n\t\t//-------------------------------------\n\t\t// Checking Methods Signature\n\t\t//-------------------------------------\n\n\t\tif (isset($this->methods[$methName]['signature']))\n\t\t{\n\t\t\t$sig = $this->methods[$methName]['signature'];\n\t\t\tfor ($i = 0, $c = count($sig); $i < $c; $i++)\n\t\t\t{\n\t\t\t\t$current_sig = $sig[$i];\n\n\t\t\t\tif (count($current_sig) === count($m->params)+1)\n\t\t\t\t{\n\t\t\t\t\tfor ($n = 0, $mc = count($m->params); $n < $mc; $n++)\n\t\t\t\t\t{\n\t\t\t\t\t\t$p = $m->params[$n];\n\t\t\t\t\t\t$pt = ($p->kindOf() === 'scalar') ? $p->scalarval() : $p->kindOf();\n\n\t\t\t\t\t\tif ($pt !== $current_sig[$n+1])\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t$pno = $n+1;\n\t\t\t\t\t\t\t$wanted = $current_sig[$n+1];\n\n\t\t\t\t\t\t\treturn new XML_RPC_Response(0,\n\t\t\t\t\t\t\t\t$this->xmlrpcerr['incorrect_params'],\n\t\t\t\t\t\t\t\t$this->xmlrpcstr['incorrect_params'] .\n\t\t\t\t\t\t\t\t': Wanted '.$wanted.', got '.$pt.' at param '.$pno.')');\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t//-------------------------------------\n\t\t// Calls the Function\n\t\t//-------------------------------------\n\n\t\tif ($objectCall === TRUE)\n\t\t{\n\t\t\tif ($method_parts[0] === 'this' && $system_call === TRUE)\n\t\t\t{\n\t\t\t\treturn call_user_func(array($this, $method_parts[1]), $m);\n\t\t\t}\n\t\t\telseif ($this->object === FALSE)\n\t\t\t{\n\t\t\t\treturn get_instance()->$method_parts[1]($m);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\treturn $this->object->$method_parts[1]($m);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn call_user_func($this->methods[$methName]['function'], $m);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Server Function: List Methods\n\t *\n\t * @param\tmixed\n\t * @return\tobject\n\t */\n\tpublic function listMethods($m)\n\t{\n\t\t$v = new XML_RPC_Values();\n\t\t$output = array();\n\n\t\tforeach ($this->methods as $key => $value)\n\t\t{\n\t\t\t$output[] = new XML_RPC_Values($key, 'string');\n\t\t}\n\n\t\tforeach ($this->system_methods as $key => $value)\n\t\t{\n\t\t\t$output[] = new XML_RPC_Values($key, 'string');\n\t\t}\n\n\t\t$v->addArray($output);\n\t\treturn new XML_RPC_Response($v);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Server Function: Return Signature for Method\n\t *\n\t * @param\tmixed\n\t * @return\tobject\n\t */\n\tpublic function methodSignature($m)\n\t{\n\t\t$parameters = $m->output_parameters();\n\t\t$method_name = $parameters[0];\n\n\t\tif (isset($this->methods[$method_name]))\n\t\t{\n\t\t\tif ($this->methods[$method_name]['signature'])\n\t\t\t{\n\t\t\t\t$sigs = array();\n\t\t\t\t$signature = $this->methods[$method_name]['signature'];\n\n\t\t\t\tfor ($i = 0, $c = count($signature); $i < $c; $i++)\n\t\t\t\t{\n\t\t\t\t\t$cursig = array();\n\t\t\t\t\t$inSig = $signature[$i];\n\t\t\t\t\tfor ($j = 0, $jc = count($inSig); $j < $jc; $j++)\n\t\t\t\t\t{\n\t\t\t\t\t\t$cursig[]= new XML_RPC_Values($inSig[$j], 'string');\n\t\t\t\t\t}\n\t\t\t\t\t$sigs[] = new XML_RPC_Values($cursig, 'array');\n\t\t\t\t}\n\n\t\t\t\treturn new XML_RPC_Response(new XML_RPC_Values($sigs, 'array'));\n\t\t\t}\n\n\t\t\treturn new XML_RPC_Response(new XML_RPC_Values('undef', 'string'));\n\t\t}\n\n\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['introspect_unknown'], $this->xmlrpcstr['introspect_unknown']);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Server Function: Doc String for Method\n\t *\n\t * @param\tmixed\n\t * @return\tobject\n\t */\n\tpublic function methodHelp($m)\n\t{\n\t\t$parameters = $m->output_parameters();\n\t\t$method_name = $parameters[0];\n\n\t\tif (isset($this->methods[$method_name]))\n\t\t{\n\t\t\t$docstring = isset($this->methods[$method_name]['docstring']) ? $this->methods[$method_name]['docstring'] : '';\n\n\t\t\treturn new XML_RPC_Response(new XML_RPC_Values($docstring, 'string'));\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['introspect_unknown'], $this->xmlrpcstr['introspect_unknown']);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Server Function: Multi-call\n\t *\n\t * @param\tmixed\n\t * @return\tobject\n\t */\n\tpublic function multicall($m)\n\t{\n\t\t// Disabled\n\t\treturn new XML_RPC_Response(0, $this->xmlrpcerr['unknown_method'], $this->xmlrpcstr['unknown_method']);\n\n\t\t$parameters = $m->output_parameters();\n\t\t$calls = $parameters[0];\n\n\t\t$result = array();\n\n\t\tforeach ($calls as $value)\n\t\t{\n\t\t\t$m = new XML_RPC_Message($value[0]);\n\t\t\t$plist = '';\n\n\t\t\tfor ($i = 0, $c = count($value[1]); $i < $c; $i++)\n\t\t\t{\n\t\t\t\t$m->addParam(new XML_RPC_Values($value[1][$i], 'string'));\n\t\t\t}\n\n\t\t\t$attempt = $this->_execute($m);\n\n\t\t\tif ($attempt->faultCode() !== 0)\n\t\t\t{\n\t\t\t\treturn $attempt;\n\t\t\t}\n\n\t\t\t$result[] = new XML_RPC_Values(array($attempt->value()), 'array');\n\t\t}\n\n\t\treturn new XML_RPC_Response(new XML_RPC_Values($result, 'array'));\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Multi-call Function: Error Handling\n\t *\n\t * @param\tmixed\n\t * @return\tobject\n\t */\n\tpublic function multicall_error($err)\n\t{\n\t\t$str = is_string($err) ? $this->xmlrpcstr[\"multicall_${err}\"] : $err->faultString();\n\t\t$code = is_string($err) ? $this->xmlrpcerr[\"multicall_${err}\"] : $err->faultCode();\n\n\t\t$struct['faultCode'] = new XML_RPC_Values($code, 'int');\n\t\t$struct['faultString'] = new XML_RPC_Values($str, 'string');\n\n\t\treturn new XML_RPC_Values($struct, 'struct');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Multi-call Function: Processes method\n\t *\n\t * @param\tmixed\n\t * @return\tobject\n\t */\n\tpublic function do_multicall($call)\n\t{\n\t\tif ($call->kindOf() !== 'struct')\n\t\t{\n\t\t\treturn $this->multicall_error('notstruct');\n\t\t}\n\t\telseif ( ! $methName = $call->me['struct']['methodName'])\n\t\t{\n\t\t\treturn $this->multicall_error('nomethod');\n\t\t}\n\n\t\tlist($scalar_type, $scalar_value) = each($methName->me);\n\t\t$scalar_type = $scalar_type === $this->xmlrpcI4 ? $this->xmlrpcInt : $scalar_type;\n\n\t\tif ($methName->kindOf() !== 'scalar' OR $scalar_type !== 'string')\n\t\t{\n\t\t\treturn $this->multicall_error('notstring');\n\t\t}\n\t\telseif ($scalar_value === 'system.multicall')\n\t\t{\n\t\t\treturn $this->multicall_error('recursion');\n\t\t}\n\t\telseif ( ! $params = $call->me['struct']['params'])\n\t\t{\n\t\t\treturn $this->multicall_error('noparams');\n\t\t}\n\t\telseif ($params->kindOf() !== 'array')\n\t\t{\n\t\t\treturn $this->multicall_error('notarray');\n\t\t}\n\n\t\tlist($a, $b) = each($params->me);\n\n\t\t$msg = new XML_RPC_Message($scalar_value);\n\t\tfor ($i = 0, $numParams = count($b); $i < $numParams; $i++)\n\t\t{\n\t\t\t$msg->params[] = $params->me['array'][$i];\n\t\t}\n\n\t\t$result = $this->_execute($msg);\n\n\t\tif ($result->faultCode() !== 0)\n\t\t{\n\t\t\treturn $this->multicall_error($result);\n\t\t}\n\n\t\treturn new XML_RPC_Values(array($result->value()), 'array');\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/Zip.php",
    "content": "<?php\n/**\n * CodeIgniter\n *\n * An open source application development framework for PHP\n *\n * This content is released under the MIT License (MIT)\n *\n * Copyright (c) 2014 - 2016, British Columbia Institute of Technology\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n * @package\tCodeIgniter\n * @author\tEllisLab Dev Team\n * @copyright\tCopyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)\n * @copyright\tCopyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)\n * @license\thttp://opensource.org/licenses/MIT\tMIT License\n * @link\thttps://codeigniter.com\n * @since\tVersion 1.0.0\n * @filesource\n */\ndefined('BASEPATH') OR exit('No direct script access allowed');\n\n/**\n * Zip Compression Class\n *\n * This class is based on a library I found at Zend:\n * http://www.zend.com/codex.php?id=696&single=1\n *\n * The original library is a little rough around the edges so I\n * refactored it and added several additional methods -- Rick Ellis\n *\n * @package\t\tCodeIgniter\n * @subpackage\tLibraries\n * @category\tEncryption\n * @author\t\tEllisLab Dev Team\n * @link\t\thttps://codeigniter.com/user_guide/libraries/zip.html\n */\nclass CI_Zip {\n\n\t/**\n\t * Zip data in string form\n\t *\n\t * @var string\n\t */\n\tpublic $zipdata = '';\n\n\t/**\n\t * Zip data for a directory in string form\n\t *\n\t * @var string\n\t */\n\tpublic $directory = '';\n\n\t/**\n\t * Number of files/folder in zip file\n\t *\n\t * @var int\n\t */\n\tpublic $entries = 0;\n\n\t/**\n\t * Number of files in zip\n\t *\n\t * @var int\n\t */\n\tpublic $file_num = 0;\n\n\t/**\n\t * relative offset of local header\n\t *\n\t * @var int\n\t */\n\tpublic $offset = 0;\n\n\t/**\n\t * Reference to time at init\n\t *\n\t * @var int\n\t */\n\tpublic $now;\n\n\t/**\n\t * The level of compression\n\t *\n\t * Ranges from 0 to 9, with 9 being the highest level.\n\t *\n\t * @var\tint\n\t */\n\tpublic $compression_level = 2;\n\n\t/**\n\t * Initialize zip compression class\n\t *\n\t * @return\tvoid\n\t */\n\tpublic function __construct()\n\t{\n\t\t$this->now = time();\n\t\tlog_message('info', 'Zip Compression Class Initialized');\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add Directory\n\t *\n\t * Lets you add a virtual directory into which you can place files.\n\t *\n\t * @param\tmixed\t$directory\tthe directory name. Can be string or array\n\t * @return\tvoid\n\t */\n\tpublic function add_dir($directory)\n\t{\n\t\tforeach ((array) $directory as $dir)\n\t\t{\n\t\t\tif ( ! preg_match('|.+/$|', $dir))\n\t\t\t{\n\t\t\t\t$dir .= '/';\n\t\t\t}\n\n\t\t\t$dir_time = $this->_get_mod_time($dir);\n\t\t\t$this->_add_dir($dir, $dir_time['file_mtime'], $dir_time['file_mdate']);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get file/directory modification time\n\t *\n\t * If this is a newly created file/dir, we will set the time to 'now'\n\t *\n\t * @param\tstring\t$dir\tpath to file\n\t * @return\tarray\tfilemtime/filemdate\n\t */\n\tprotected function _get_mod_time($dir)\n\t{\n\t\t// filemtime() may return false, but raises an error for non-existing files\n\t\t$date = file_exists($dir) ? getdate(filemtime($dir)) : getdate($this->now);\n\n\t\treturn array(\n\t\t\t'file_mtime' => ($date['hours'] << 11) + ($date['minutes'] << 5) + $date['seconds'] / 2,\n\t\t\t'file_mdate' => (($date['year'] - 1980) << 9) + ($date['mon'] << 5) + $date['mday']\n\t\t);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add Directory\n\t *\n\t * @param\tstring\t$dir\tthe directory name\n\t * @param\tint\t$file_mtime\n\t * @param\tint\t$file_mdate\n\t * @return\tvoid\n\t */\n\tprotected function _add_dir($dir, $file_mtime, $file_mdate)\n\t{\n\t\t$dir = str_replace('\\\\', '/', $dir);\n\n\t\t$this->zipdata .=\n\t\t\t\"\\x50\\x4b\\x03\\x04\\x0a\\x00\\x00\\x00\\x00\\x00\"\n\t\t\t.pack('v', $file_mtime)\n\t\t\t.pack('v', $file_mdate)\n\t\t\t.pack('V', 0) // crc32\n\t\t\t.pack('V', 0) // compressed filesize\n\t\t\t.pack('V', 0) // uncompressed filesize\n\t\t\t.pack('v', strlen($dir)) // length of pathname\n\t\t\t.pack('v', 0) // extra field length\n\t\t\t.$dir\n\t\t\t// below is \"data descriptor\" segment\n\t\t\t.pack('V', 0) // crc32\n\t\t\t.pack('V', 0) // compressed filesize\n\t\t\t.pack('V', 0); // uncompressed filesize\n\n\t\t$this->directory .=\n\t\t\t\"\\x50\\x4b\\x01\\x02\\x00\\x00\\x0a\\x00\\x00\\x00\\x00\\x00\"\n\t\t\t.pack('v', $file_mtime)\n\t\t\t.pack('v', $file_mdate)\n\t\t\t.pack('V',0) // crc32\n\t\t\t.pack('V',0) // compressed filesize\n\t\t\t.pack('V',0) // uncompressed filesize\n\t\t\t.pack('v', strlen($dir)) // length of pathname\n\t\t\t.pack('v', 0) // extra field length\n\t\t\t.pack('v', 0) // file comment length\n\t\t\t.pack('v', 0) // disk number start\n\t\t\t.pack('v', 0) // internal file attributes\n\t\t\t.pack('V', 16) // external file attributes - 'directory' bit set\n\t\t\t.pack('V', $this->offset) // relative offset of local header\n\t\t\t.$dir;\n\n\t\t$this->offset = strlen($this->zipdata);\n\t\t$this->entries++;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add Data to Zip\n\t *\n\t * Lets you add files to the archive. If the path is included\n\t * in the filename it will be placed within a directory. Make\n\t * sure you use add_dir() first to create the folder.\n\t *\n\t * @param\tmixed\t$filepath\tA single filepath or an array of file => data pairs\n\t * @param\tstring\t$data\t\tSingle file contents\n\t * @return\tvoid\n\t */\n\tpublic function add_data($filepath, $data = NULL)\n\t{\n\t\tif (is_array($filepath))\n\t\t{\n\t\t\tforeach ($filepath as $path => $data)\n\t\t\t{\n\t\t\t\t$file_data = $this->_get_mod_time($path);\n\t\t\t\t$this->_add_data($path, $data, $file_data['file_mtime'], $file_data['file_mdate']);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t$file_data = $this->_get_mod_time($filepath);\n\t\t\t$this->_add_data($filepath, $data, $file_data['file_mtime'], $file_data['file_mdate']);\n\t\t}\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Add Data to Zip\n\t *\n\t * @param\tstring\t$filepath\tthe file name/path\n\t * @param\tstring\t$data\tthe data to be encoded\n\t * @param\tint\t$file_mtime\n\t * @param\tint\t$file_mdate\n\t * @return\tvoid\n\t */\n\tprotected function _add_data($filepath, $data, $file_mtime, $file_mdate)\n\t{\n\t\t$filepath = str_replace('\\\\', '/', $filepath);\n\n\t\t$uncompressed_size = strlen($data);\n\t\t$crc32  = crc32($data);\n\t\t$gzdata = substr(gzcompress($data, $this->compression_level), 2, -4);\n\t\t$compressed_size = strlen($gzdata);\n\n\t\t$this->zipdata .=\n\t\t\t\"\\x50\\x4b\\x03\\x04\\x14\\x00\\x00\\x00\\x08\\x00\"\n\t\t\t.pack('v', $file_mtime)\n\t\t\t.pack('v', $file_mdate)\n\t\t\t.pack('V', $crc32)\n\t\t\t.pack('V', $compressed_size)\n\t\t\t.pack('V', $uncompressed_size)\n\t\t\t.pack('v', strlen($filepath)) // length of filename\n\t\t\t.pack('v', 0) // extra field length\n\t\t\t.$filepath\n\t\t\t.$gzdata; // \"file data\" segment\n\n\t\t$this->directory .=\n\t\t\t\"\\x50\\x4b\\x01\\x02\\x00\\x00\\x14\\x00\\x00\\x00\\x08\\x00\"\n\t\t\t.pack('v', $file_mtime)\n\t\t\t.pack('v', $file_mdate)\n\t\t\t.pack('V', $crc32)\n\t\t\t.pack('V', $compressed_size)\n\t\t\t.pack('V', $uncompressed_size)\n\t\t\t.pack('v', strlen($filepath)) // length of filename\n\t\t\t.pack('v', 0) // extra field length\n\t\t\t.pack('v', 0) // file comment length\n\t\t\t.pack('v', 0) // disk number start\n\t\t\t.pack('v', 0) // internal file attributes\n\t\t\t.pack('V', 32) // external file attributes - 'archive' bit set\n\t\t\t.pack('V', $this->offset) // relative offset of local header\n\t\t\t.$filepath;\n\n\t\t$this->offset = strlen($this->zipdata);\n\t\t$this->entries++;\n\t\t$this->file_num++;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Read the contents of a file and add it to the zip\n\t *\n\t * @param\tstring\t$path\n\t * @param\tbool\t$archive_filepath\n\t * @return\tbool\n\t */\n\tpublic function read_file($path, $archive_filepath = FALSE)\n\t{\n\t\tif (file_exists($path) && FALSE !== ($data = file_get_contents($path)))\n\t\t{\n\t\t\tif (is_string($archive_filepath))\n\t\t\t{\n\t\t\t\t$name = str_replace('\\\\', '/', $archive_filepath);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t$name = str_replace('\\\\', '/', $path);\n\n\t\t\t\tif ($archive_filepath === FALSE)\n\t\t\t\t{\n\t\t\t\t\t$name = preg_replace('|.*/(.+)|', '\\\\1', $name);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$this->add_data($name, $data);\n\t\t\treturn TRUE;\n\t\t}\n\n\t\treturn FALSE;\n\t}\n\n\t// ------------------------------------------------------------------------\n\n\t/**\n\t * Read a directory and add it to the zip.\n\t *\n\t * This function recursively reads a folder and everything it contains (including\n\t * sub-folders) and creates a zip based on it. Whatever directory structure\n\t * is in the original file path will be recreated in the zip file.\n\t *\n\t * @param\tstring\t$path\tpath to source directory\n\t * @param\tbool\t$preserve_filepath\n\t * @param\tstring\t$root_path\n\t * @return\tbool\n\t */\n\tpublic function read_dir($path, $preserve_filepath = TRUE, $root_path = NULL)\n\t{\n\t\t$path = rtrim($path, '/\\\\').DIRECTORY_SEPARATOR;\n\t\tif ( ! $fp = @opendir($path))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\t// Set the original directory root for child dir's to use as relative\n\t\tif ($root_path === NULL)\n\t\t{\n\t\t\t$root_path = str_replace(array('\\\\', '/'), DIRECTORY_SEPARATOR, dirname($path)).DIRECTORY_SEPARATOR;\n\t\t}\n\n\t\twhile (FALSE !== ($file = readdir($fp)))\n\t\t{\n\t\t\tif ($file[0] === '.')\n\t\t\t{\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (is_dir($path.$file))\n\t\t\t{\n\t\t\t\t$this->read_dir($path.$file.DIRECTORY_SEPARATOR, $preserve_filepath, $root_path);\n\t\t\t}\n\t\t\telseif (FALSE !== ($data = file_get_contents($path.$file)))\n\t\t\t{\n\t\t\t\t$name = str_replace(array('\\\\', '/'), DIRECTORY_SEPARATOR, $path);\n\t\t\t\tif ($preserve_filepath === FALSE)\n\t\t\t\t{\n\t\t\t\t\t$name = str_replace($root_path, '', $name);\n\t\t\t\t}\n\n\t\t\t\t$this->add_data($name.$file, $data);\n\t\t\t}\n\t\t}\n\n\t\tclosedir($fp);\n\t\treturn TRUE;\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Get the Zip file\n\t *\n\t * @return\tstring\t(binary encoded)\n\t */\n\tpublic function get_zip()\n\t{\n\t\t// Is there any data to return?\n\t\tif ($this->entries === 0)\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\treturn $this->zipdata\n\t\t\t.$this->directory.\"\\x50\\x4b\\x05\\x06\\x00\\x00\\x00\\x00\"\n\t\t\t.pack('v', $this->entries) // total # of entries \"on this disk\"\n\t\t\t.pack('v', $this->entries) // total # of entries overall\n\t\t\t.pack('V', strlen($this->directory)) // size of central dir\n\t\t\t.pack('V', strlen($this->zipdata)) // offset to start of central dir\n\t\t\t.\"\\x00\\x00\"; // .zip file comment length\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Write File to the specified directory\n\t *\n\t * Lets you write a file\n\t *\n\t * @param\tstring\t$filepath\tthe file name\n\t * @return\tbool\n\t */\n\tpublic function archive($filepath)\n\t{\n\t\tif ( ! ($fp = @fopen($filepath, 'w+b')))\n\t\t{\n\t\t\treturn FALSE;\n\t\t}\n\n\t\tflock($fp, LOCK_EX);\n\n\t\tfor ($result = $written = 0, $data = $this->get_zip(), $length = strlen($data); $written < $length; $written += $result)\n\t\t{\n\t\t\tif (($result = fwrite($fp, substr($data, $written))) === FALSE)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tflock($fp, LOCK_UN);\n\t\tfclose($fp);\n\n\t\treturn is_int($result);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Download\n\t *\n\t * @param\tstring\t$filename\tthe file name\n\t * @return\tvoid\n\t */\n\tpublic function download($filename = 'backup.zip')\n\t{\n\t\tif ( ! preg_match('|.+?\\.zip$|', $filename))\n\t\t{\n\t\t\t$filename .= '.zip';\n\t\t}\n\n\t\tget_instance()->load->helper('download');\n\t\t$get_zip = $this->get_zip();\n\t\t$zip_content =& $get_zip;\n\n\t\tforce_download($filename, $zip_content);\n\t}\n\n\t// --------------------------------------------------------------------\n\n\t/**\n\t * Initialize Data\n\t *\n\t * Lets you clear current zip data. Useful if you need to create\n\t * multiple zips with different data.\n\t *\n\t * @return\tCI_Zip\n\t */\n\tpublic function clear_data()\n\t{\n\t\t$this->zipdata = '';\n\t\t$this->directory = '';\n\t\t$this->entries = 0;\n\t\t$this->file_num = 0;\n\t\t$this->offset = 0;\n\t\treturn $this;\n\t}\n\n}\n"
  },
  {
    "path": "system/libraries/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<title>403 Forbidden</title>\n</head>\n<body>\n\n<p>Directory access is forbidden.</p>\n\n</body>\n</html>\n"
  }
]