diff --git a/README.md b/README.md
index e09bfd8b..7b3d77bd 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,58 @@
-# appstarter
-CodeIgniter 4 app starter
+# CodeIgniter 4 Application Starter
+
+## What is CodeIgniter?
+CodeIgniter is a PHP full-stack web framework that is light, fast, flexible, and secure.
+More information can be found at the [official site](http://codeigniter.com).
+
+This repository holds a composer-installable app starter.
+It has been built from the
+[development repository](https://github.com/codeigniter4/CodeIgniter4).
+
+**This is pre-release code and should not be used in production sites.**
+
+---
+
+**CAUTION: This app starter is EXPERIMENTAL, and likely to change before
+the framework release. We are looking for feedback and suggestions!**
+
+---
+
+More information about the plans for version 4 can be found in [the announcement](http://forum.codeigniter.com/thread-62615.html) on the forums.
+
+The user guide corresponding to this version of the framework can be found
+[here](https://codeigniter4.github.io/userguide/).
+
+##Installation & updates
+
+`composer create-project codeigniter4/appstarter` then `composer update` whenever
+there is a new release of the framework.
+
+##Setup
+
+Copy `env` to `.env` and tailor for your app, specifically the baseURL
+and any database settings.
+
+## Important Change with index.php
+
+`index.php` is no longer in the root of the project! It has been moved inside the *public* folder,
+for better security and separation of components.
+
+This means that you should configure your web server to "point" to your project's *public* folder, and
+not to the project root. A better practice would be to configure a virtual host to point there. A poor practice would be to point your web server to the project root and expect to enter *public/...*, as the rest of your logic and the
+framework are exposed.
+
+**Please** read the user guide for a better explanation of how CI4 works!
+The user guide updating and deployment is a bit awkward at the moment, but we are working on it!
+
+## Server Requirements
+PHP version 7.1 or higher is required, with the following extensions installed:
+
+- [intl](http://php.net/manual/en/intl.requirements.php)
+- [libcurl](http://php.net/manual/en/curl.requirements.php) if you plan to use the HTTP\CURLRequest library
+
+Additionally, make sure that the following extensions are enabled in your PHP:
+
+- json (enabled by default - don't turn it off)
+- [mbstring](http://php.net/manual/en/mbstring.installation.php)
+- [mysqlnd](http://php.net/manual/en/mysqlnd.install.php)
+- xml (enabled by default - don't turn it off)
diff --git a/application/.htaccess b/application/.htaccess
new file mode 100644
index 00000000..f24db0ac
--- /dev/null
+++ b/application/.htaccess
@@ -0,0 +1,6 @@
+
+ Require all denied
+
+
+ Deny from all
+
diff --git a/application/Config/App.php b/application/Config/App.php
new file mode 100644
index 00000000..ef0ebee9
--- /dev/null
+++ b/application/Config/App.php
@@ -0,0 +1,306 @@
+ SYSPATH
+ * `];
+ */
+ $psr4 = [
+ 'Config' => APPPATH . 'Config',
+ APP_NAMESPACE => APPPATH, // For custom namespace
+ 'App' => APPPATH, // To ensure filters, etc still found,
+ ];
+
+ /**
+ * -------------------------------------------------------------------
+ * Class Map
+ * -------------------------------------------------------------------
+ * The class map provides a map of class names and their exact
+ * location on the drive. Classes loaded in this manner will have
+ * slightly faster performance because they will not have to be
+ * searched for within one or more directories as they would if they
+ * were being autoloaded through a namespace.
+ *
+ * Prototype:
+ *
+ * $Config['classmap'] = [
+ * 'MyClass' => '/path/to/class/file.php'
+ * ];
+ */
+ $classmap = [];
+
+ //--------------------------------------------------------------------
+ // Do Not Edit Below This Line
+ //--------------------------------------------------------------------
+
+ $this->psr4 = array_merge($this->psr4, $psr4);
+ $this->classmap = array_merge($this->classmap, $classmap);
+
+ unset($psr4, $classmap);
+ }
+
+ //--------------------------------------------------------------------
+
+}
diff --git a/application/Config/Boot/development.php b/application/Config/Boot/development.php
new file mode 100644
index 00000000..61707a9b
--- /dev/null
+++ b/application/Config/Boot/development.php
@@ -0,0 +1,32 @@
+ '127.0.0.1',
+ 'port' => 11211,
+ 'weight' => 1,
+ 'raw' => false,
+ ];
+
+ /*
+ | -------------------------------------------------------------------------
+ | Redis settings
+ | -------------------------------------------------------------------------
+ | Your Redis server can be specified below, if you are using
+ | the Redis or Predis drivers.
+ |
+ */
+ public $redis = [
+ 'host' => '127.0.0.1',
+ 'password' => null,
+ 'port' => 6379,
+ 'timeout' => 0,
+ ];
+
+ /*
+ |--------------------------------------------------------------------------
+ | Available Cache Handlers
+ |--------------------------------------------------------------------------
+ |
+ | This is an array of cache engine alias' and class names. Only engines
+ | that are listed here are allowed to be used.
+ |
+ */
+ public $validHandlers = [
+ 'dummy' => \CodeIgniter\Cache\Handlers\DummyHandler::class,
+ 'file' => \CodeIgniter\Cache\Handlers\FileHandler::class,
+ 'memcached' => \CodeIgniter\Cache\Handlers\MemcachedHandler::class,
+ 'predis' => \CodeIgniter\Cache\Handlers\PredisHandler::class,
+ 'redis' => \CodeIgniter\Cache\Handlers\RedisHandler::class,
+ 'wincache' => \CodeIgniter\Cache\Handlers\WincacheHandler::class,
+ ];
+}
diff --git a/application/Config/Constants.php b/application/Config/Constants.php
new file mode 100644
index 00000000..3f7cef1b
--- /dev/null
+++ b/application/Config/Constants.php
@@ -0,0 +1,77 @@
+ '',
+ 'hostname' => 'localhost',
+ 'username' => '',
+ 'password' => '',
+ 'database' => '',
+ 'DBDriver' => 'MySQLi',
+ 'DBPrefix' => '',
+ 'pConnect' => false,
+ 'DBDebug' => (ENVIRONMENT !== 'production'),
+ 'cacheOn' => false,
+ 'cacheDir' => '',
+ 'charset' => 'utf8',
+ 'DBCollat' => 'utf8_general_ci',
+ 'swapPre' => '',
+ 'encrypt' => false,
+ 'compress' => false,
+ 'strictOn' => false,
+ 'failover' => [],
+ 'port' => 3306,
+ ];
+
+ /**
+ * This database connection is used when
+ * running PHPUnit database tests.
+ *
+ * @var array
+ */
+ public $tests = [
+ 'DSN' => '',
+ 'hostname' => '127.0.0.1',
+ 'username' => '',
+ 'password' => '',
+ 'database' => '',
+ 'DBDriver' => '',
+ 'DBPrefix' => 'db_', // Needed to ensure we're working correctly with prefixes live. DO NOT REMOVE.
+ 'pConnect' => false,
+ 'DBDebug' => (ENVIRONMENT !== 'production'),
+ 'cacheOn' => false,
+ 'cacheDir' => '',
+ 'charset' => 'utf8',
+ 'DBCollat' => 'utf8_general_ci',
+ 'swapPre' => '',
+ 'encrypt' => false,
+ 'compress' => false,
+ 'strictOn' => false,
+ 'failover' => [],
+ 'port' => 3306,
+ ];
+
+ //--------------------------------------------------------------------
+
+ public function __construct()
+ {
+ parent::__construct();
+
+ // Ensure that we always set the database group to 'tests' if
+ // we are currently running an automated test suite, so that
+ // we don't overwrite live data on accident.
+ if (ENVIRONMENT === 'testing')
+ {
+ $this->defaultGroup = 'tests';
+
+ // Under Travis-CI, we can set an ENV var named 'DB_GROUP'
+ // so that we can test against multiple databases.
+ if ($group = getenv('DB'))
+ {
+ if (is_file(TESTPATH . 'travis/Database.php'))
+ {
+ require TESTPATH . 'travis/Database.php';
+
+ if (! empty($dbconfig) && array_key_exists($group, $dbconfig))
+ {
+ $this->tests = $dbconfig[$group];
+ }
+ }
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+
+}
diff --git a/application/Config/DocTypes.php b/application/Config/DocTypes.php
new file mode 100755
index 00000000..67d5dd20
--- /dev/null
+++ b/application/Config/DocTypes.php
@@ -0,0 +1,33 @@
+ '',
+ 'xhtml1-strict' => '',
+ 'xhtml1-trans' => '',
+ 'xhtml1-frame' => '',
+ 'xhtml-basic11' => '',
+ 'html5' => '',
+ 'html4-strict' => '',
+ 'html4-trans' => '',
+ 'html4-frame' => '',
+ 'mathml1' => '',
+ 'mathml2' => '',
+ 'svg10' => '',
+ 'svg11' => '',
+ 'svg11-basic' => '',
+ 'svg11-tiny' => '',
+ 'xhtml-math-svg-xh' => '',
+ 'xhtml-math-svg-sh' => '',
+ 'xhtml-rdfa-1' => '',
+ 'xhtml-rdfa-2' => '',
+ ];
+}
diff --git a/application/Config/Email.php b/application/Config/Email.php
new file mode 100644
index 00000000..45661240
--- /dev/null
+++ b/application/Config/Email.php
@@ -0,0 +1,161 @@
+ \App\Filters\CSRF::class,
+ 'toolbar' => \App\Filters\DebugToolbar::class,
+ 'honeypot' => \App\Filters\Honeypot::class,
+ ];
+
+ // Always applied before every request
+ public $globals = [
+ 'before' => [
+ //'honeypot'
+ // 'csrf',
+ ],
+ 'after' => [
+ 'toolbar',
+ //'honeypot'
+ ],
+ ];
+
+ // Works on all of a particular HTTP method
+ // (GET, POST, etc) as BEFORE filters only
+ // like: 'post' => ['CSRF', 'throttle'],
+ public $methods = [];
+
+ // List filter aliases and any before/after uri patterns
+ // that they should run on, like:
+ // 'isLoggedIn' => ['before' => ['account/*', 'profiles/*']],
+ public $filters = [];
+}
diff --git a/application/Config/ForeignCharacters.php b/application/Config/ForeignCharacters.php
new file mode 100644
index 00000000..8ee6f113
--- /dev/null
+++ b/application/Config/ForeignCharacters.php
@@ -0,0 +1,6 @@
+ \CodeIgniter\Format\JSONFormatter::class,
+ 'application/xml' => \CodeIgniter\Format\XMLFormatter::class,
+ 'text/xml' => \CodeIgniter\Format\XMLFormatter::class,
+ ];
+
+ //--------------------------------------------------------------------
+
+ /**
+ * A Factory method to return the appropriate formatter for the given mime type.
+ *
+ * @param string $mime
+ *
+ * @return \CodeIgniter\Format\FormatterInterface
+ */
+ public function getFormatter(string $mime)
+ {
+ if (! array_key_exists($mime, $this->formatters))
+ {
+ throw new \InvalidArgumentException('No Formatter defined for mime type: ' . $mime);
+ }
+
+ $class = $this->formatters[$mime];
+
+ if (! class_exists($class))
+ {
+ throw new \BadMethodCallException($class . ' is not a valid Formatter.');
+ }
+
+ return new $class();
+ }
+
+ //--------------------------------------------------------------------
+
+}
diff --git a/application/Config/Honeypot.php b/application/Config/Honeypot.php
new file mode 100644
index 00000000..f4444a5d
--- /dev/null
+++ b/application/Config/Honeypot.php
@@ -0,0 +1,34 @@
+{label}';
+}
diff --git a/application/Config/Images.php b/application/Config/Images.php
new file mode 100644
index 00000000..730ddee7
--- /dev/null
+++ b/application/Config/Images.php
@@ -0,0 +1,31 @@
+ \CodeIgniter\Images\Handlers\GDHandler::class,
+ 'imagick' => \CodeIgniter\Images\Handlers\ImageMagickHandler::class,
+ ];
+}
diff --git a/application/Config/Logger.php b/application/Config/Logger.php
new file mode 100644
index 00000000..d32e195f
--- /dev/null
+++ b/application/Config/Logger.php
@@ -0,0 +1,140 @@
+ [
+
+ /*
+ * The log levels that this handler will handle.
+ */
+ 'handles' => [
+ 'critical',
+ 'alert',
+ 'emergency',
+ 'debug',
+ 'error',
+ 'info',
+ 'notice',
+ 'warning',
+ ],
+
+ /*
+ * Leave this BLANK unless you would like to set something other than the default
+ * writeable/logs/ directory. Use a full getServer path with trailing slash.
+ */
+ 'path' => WRITEPATH . 'logs/',
+
+ /*
+ * The default filename extension for log files. The default 'php' allows for
+ * protecting the log files via basic scripting, when they are to be stored
+ * under a publicly accessible directory.
+ *
+ * Note: Leaving it blank will default to 'php'.
+ */
+ 'fileExtension' => 'php',
+
+ /*
+ * The file system permissions to be applied on newly created log files.
+ *
+ * IMPORTANT: This MUST be an integer (no quotes) and you MUST use octal
+ * integer notation (i.e. 0700, 0644, etc.)
+ */
+ 'filePermissions' => 0644,
+ ],
+
+ /**
+ * The ChromeLoggerHandler requires the use of the Chrome web browser
+ * and the ChromeLogger extension. Uncomment this block to use it.
+ */
+ // 'CodeIgniter\Log\Handlers\ChromeLoggerHandler' => [
+ // /*
+ // * The log levels that this handler will handle.
+ // */
+ // 'handles' => ['critical', 'alert', 'emergency', 'debug',
+ // 'error', 'info', 'notice', 'warning'],
+ // ]
+ ];
+}
diff --git a/application/Config/Migrations.php b/application/Config/Migrations.php
new file mode 100644
index 00000000..c746a22c
--- /dev/null
+++ b/application/Config/Migrations.php
@@ -0,0 +1,63 @@
+migration->current() this is the version that schema will
+ | be upgraded / downgraded to.
+ |
+ */
+ public $currentVersion = 0;
+
+}
diff --git a/application/Config/Mimes.php b/application/Config/Mimes.php
new file mode 100644
index 00000000..a570ef54
--- /dev/null
+++ b/application/Config/Mimes.php
@@ -0,0 +1,534 @@
+ [
+ 'application/mac-binhex40',
+ 'application/mac-binhex',
+ 'application/x-binhex40',
+ 'application/x-mac-binhex40',
+ ],
+ 'cpt' => 'application/mac-compactpro',
+ 'csv' => [
+ 'text/csv',
+ 'text/x-comma-separated-values',
+ 'text/comma-separated-values',
+ 'application/octet-stream',
+ 'application/vnd.ms-excel',
+ 'application/x-csv',
+ 'text/x-csv',
+ 'application/csv',
+ 'application/excel',
+ 'application/vnd.msexcel',
+ 'text/plain',
+ ],
+ 'bin' => [
+ 'application/macbinary',
+ 'application/mac-binary',
+ 'application/octet-stream',
+ 'application/x-binary',
+ 'application/x-macbinary',
+ ],
+ 'dms' => 'application/octet-stream',
+ 'lha' => 'application/octet-stream',
+ 'lzh' => 'application/octet-stream',
+ 'exe' => [
+ 'application/octet-stream',
+ 'application/x-msdownload',
+ ],
+ 'class' => 'application/octet-stream',
+ 'psd' => [
+ 'application/x-photoshop',
+ 'image/vnd.adobe.photoshop',
+ ],
+ 'so' => 'application/octet-stream',
+ 'sea' => 'application/octet-stream',
+ 'dll' => 'application/octet-stream',
+ 'oda' => 'application/oda',
+ 'pdf' => [
+ 'application/pdf',
+ 'application/force-download',
+ 'application/x-download',
+ 'binary/octet-stream',
+ ],
+ 'ai' => [
+ 'application/pdf',
+ 'application/postscript',
+ ],
+ 'eps' => 'application/postscript',
+ 'ps' => 'application/postscript',
+ 'smi' => 'application/smil',
+ 'smil' => 'application/smil',
+ 'mif' => 'application/vnd.mif',
+ 'xls' => [
+ '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',
+ ],
+ 'ppt' => [
+ 'application/vnd.ms-powerpoint',
+ 'application/powerpoint',
+ 'application/vnd.ms-office',
+ 'application/msword',
+ ],
+ 'pptx' => [
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+ 'application/x-zip',
+ 'application/zip',
+ ],
+ 'wbxml' => 'application/wbxml',
+ 'wmlc' => 'application/wmlc',
+ 'dcr' => 'application/x-director',
+ 'dir' => 'application/x-director',
+ 'dxr' => 'application/x-director',
+ 'dvi' => 'application/x-dvi',
+ 'gtar' => 'application/x-gtar',
+ 'gz' => 'application/x-gzip',
+ 'gzip' => 'application/x-gzip',
+ 'php' => [
+ 'application/x-php',
+ 'application/x-httpd-php',
+ 'application/php',
+ 'text/php',
+ 'text/x-php',
+ 'application/x-httpd-php-source',
+ ],
+ 'php4' => 'application/x-httpd-php',
+ 'php3' => 'application/x-httpd-php',
+ 'phtml' => 'application/x-httpd-php',
+ 'phps' => 'application/x-httpd-php-source',
+ 'js' => [
+ 'application/x-javascript',
+ 'text/plain',
+ ],
+ 'swf' => 'application/x-shockwave-flash',
+ 'sit' => 'application/x-stuffit',
+ 'tar' => 'application/x-tar',
+ 'tgz' => [
+ 'application/x-tar',
+ 'application/x-gzip-compressed',
+ ],
+ 'z' => 'application/x-compress',
+ 'xhtml' => 'application/xhtml+xml',
+ 'xht' => 'application/xhtml+xml',
+ 'zip' => [
+ 'application/x-zip',
+ 'application/zip',
+ 'application/x-zip-compressed',
+ 'application/s-compressed',
+ 'multipart/x-zip',
+ ],
+ 'rar' => [
+ 'application/x-rar',
+ 'application/rar',
+ 'application/x-rar-compressed',
+ ],
+ 'mid' => 'audio/midi',
+ 'midi' => 'audio/midi',
+ 'mpga' => 'audio/mpeg',
+ 'mp2' => 'audio/mpeg',
+ 'mp3' => [
+ 'audio/mpeg',
+ 'audio/mpg',
+ 'audio/mpeg3',
+ 'audio/mp3',
+ ],
+ 'aif' => [
+ 'audio/x-aiff',
+ 'audio/aiff',
+ ],
+ 'aiff' => [
+ 'audio/x-aiff',
+ 'audio/aiff',
+ ],
+ 'aifc' => 'audio/x-aiff',
+ 'ram' => 'audio/x-pn-realaudio',
+ 'rm' => 'audio/x-pn-realaudio',
+ 'rpm' => 'audio/x-pn-realaudio-plugin',
+ 'ra' => 'audio/x-realaudio',
+ 'rv' => 'video/vnd.rn-realvideo',
+ 'wav' => [
+ 'audio/x-wav',
+ 'audio/wave',
+ 'audio/wav',
+ ],
+ 'bmp' => [
+ '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',
+ ],
+ 'gif' => 'image/gif',
+ 'jpg' => [
+ 'image/jpeg',
+ 'image/pjpeg',
+ ],
+ 'jpeg' => [
+ 'image/jpeg',
+ 'image/pjpeg',
+ ],
+ 'jpe' => [
+ 'image/jpeg',
+ 'image/pjpeg',
+ ],
+ 'jp2' => [
+ 'image/jp2',
+ 'video/mj2',
+ 'image/jpx',
+ 'image/jpm',
+ ],
+ 'j2k' => [
+ 'image/jp2',
+ 'video/mj2',
+ 'image/jpx',
+ 'image/jpm',
+ ],
+ 'jpf' => [
+ 'image/jp2',
+ 'video/mj2',
+ 'image/jpx',
+ 'image/jpm',
+ ],
+ 'jpg2' => [
+ 'image/jp2',
+ 'video/mj2',
+ 'image/jpx',
+ 'image/jpm',
+ ],
+ 'jpx' => [
+ 'image/jp2',
+ 'video/mj2',
+ 'image/jpx',
+ 'image/jpm',
+ ],
+ 'jpm' => [
+ 'image/jp2',
+ 'video/mj2',
+ 'image/jpx',
+ 'image/jpm',
+ ],
+ 'mj2' => [
+ 'image/jp2',
+ 'video/mj2',
+ 'image/jpx',
+ 'image/jpm',
+ ],
+ 'mjp2' => [
+ 'image/jp2',
+ 'video/mj2',
+ 'image/jpx',
+ 'image/jpm',
+ ],
+ 'png' => [
+ 'image/png',
+ 'image/x-png',
+ ],
+ 'tif' => 'image/tiff',
+ 'tiff' => 'image/tiff',
+ 'css' => [
+ 'text/css',
+ 'text/plain',
+ ],
+ 'html' => [
+ 'text/html',
+ 'text/plain',
+ ],
+ 'htm' => [
+ 'text/html',
+ 'text/plain',
+ ],
+ 'shtml' => [
+ 'text/html',
+ 'text/plain',
+ ],
+ 'txt' => 'text/plain',
+ 'text' => 'text/plain',
+ 'log' => [
+ 'text/plain',
+ 'text/x-log',
+ ],
+ 'rtx' => 'text/richtext',
+ 'rtf' => 'text/rtf',
+ 'xml' => [
+ 'application/xml',
+ 'text/xml',
+ 'text/plain',
+ ],
+ 'xsl' => [
+ 'application/xml',
+ 'text/xsl',
+ 'text/xml',
+ ],
+ 'mpeg' => 'video/mpeg',
+ 'mpg' => 'video/mpeg',
+ 'mpe' => 'video/mpeg',
+ 'qt' => 'video/quicktime',
+ 'mov' => 'video/quicktime',
+ 'avi' => [
+ 'video/x-msvideo',
+ 'video/msvideo',
+ 'video/avi',
+ 'application/x-troff-msvideo',
+ ],
+ 'movie' => 'video/x-sgi-movie',
+ 'doc' => [
+ 'application/msword',
+ 'application/vnd.ms-office',
+ ],
+ 'docx' => [
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ 'application/zip',
+ 'application/msword',
+ 'application/x-zip',
+ ],
+ 'dot' => [
+ 'application/msword',
+ 'application/vnd.ms-office',
+ ],
+ 'dotx' => [
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ 'application/zip',
+ 'application/msword',
+ ],
+ 'xlsx' => [
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+ 'application/zip',
+ 'application/vnd.ms-excel',
+ 'application/msword',
+ 'application/x-zip',
+ ],
+ 'word' => [
+ 'application/msword',
+ 'application/octet-stream',
+ ],
+ 'xl' => 'application/excel',
+ 'eml' => 'message/rfc822',
+ 'json' => [
+ 'application/json',
+ 'text/json',
+ ],
+ 'pem' => [
+ 'application/x-x509-user-cert',
+ 'application/x-pem-file',
+ 'application/octet-stream',
+ ],
+ 'p10' => [
+ 'application/x-pkcs10',
+ 'application/pkcs10',
+ ],
+ 'p12' => 'application/x-pkcs12',
+ 'p7a' => 'application/x-pkcs7-signature',
+ 'p7c' => [
+ 'application/pkcs7-mime',
+ 'application/x-pkcs7-mime',
+ ],
+ 'p7m' => [
+ 'application/pkcs7-mime',
+ 'application/x-pkcs7-mime',
+ ],
+ 'p7r' => 'application/x-pkcs7-certreqresp',
+ 'p7s' => 'application/pkcs7-signature',
+ 'crt' => [
+ 'application/x-x509-ca-cert',
+ 'application/x-x509-user-cert',
+ 'application/pkix-cert',
+ ],
+ 'crl' => [
+ 'application/pkix-crl',
+ 'application/pkcs-crl',
+ ],
+ 'der' => 'application/x-x509-ca-cert',
+ 'kdb' => 'application/octet-stream',
+ 'pgp' => 'application/pgp',
+ 'gpg' => 'application/gpg-keys',
+ 'sst' => 'application/octet-stream',
+ 'csr' => 'application/octet-stream',
+ 'rsa' => 'application/x-pkcs7',
+ 'cer' => [
+ 'application/pkix-cert',
+ 'application/x-x509-ca-cert',
+ ],
+ '3g2' => 'video/3gpp2',
+ '3gp' => [
+ 'video/3gp',
+ 'video/3gpp',
+ ],
+ 'mp4' => 'video/mp4',
+ 'm4a' => 'audio/x-m4a',
+ 'f4v' => [
+ 'video/mp4',
+ 'video/x-f4v',
+ ],
+ 'flv' => 'video/x-flv',
+ 'webm' => 'video/webm',
+ 'aac' => 'audio/x-acc',
+ 'm4u' => 'application/vnd.mpegurl',
+ 'm3u' => 'text/plain',
+ 'xspf' => 'application/xspf+xml',
+ 'vlc' => 'application/videolan',
+ 'wmv' => [
+ 'video/x-ms-wmv',
+ 'video/x-ms-asf',
+ ],
+ 'au' => 'audio/x-au',
+ 'ac3' => 'audio/ac3',
+ 'flac' => 'audio/x-flac',
+ 'ogg' => [
+ 'audio/ogg',
+ 'video/ogg',
+ 'application/ogg',
+ ],
+ 'kmz' => [
+ 'application/vnd.google-earth.kmz',
+ 'application/zip',
+ 'application/x-zip',
+ ],
+ 'kml' => [
+ 'application/vnd.google-earth.kml+xml',
+ 'application/xml',
+ 'text/xml',
+ ],
+ 'ics' => 'text/calendar',
+ 'ical' => 'text/calendar',
+ 'zsh' => 'text/x-scriptzsh',
+ '7zip' => [
+ 'application/x-compressed',
+ 'application/x-zip-compressed',
+ 'application/zip',
+ 'multipart/x-zip',
+ ],
+ 'cdr' => [
+ 'application/cdr',
+ 'application/coreldraw',
+ 'application/x-cdr',
+ 'application/x-coreldraw',
+ 'image/cdr',
+ 'image/x-cdr',
+ 'zz-application/zz-winassoc-cdr',
+ ],
+ 'wma' => [
+ 'audio/x-ms-wma',
+ 'video/x-ms-asf',
+ ],
+ 'jar' => [
+ 'application/java-archive',
+ 'application/x-java-application',
+ 'application/x-jar',
+ 'application/x-compressed',
+ ],
+ 'svg' => [
+ 'image/svg+xml',
+ 'application/xml',
+ 'text/xml',
+ ],
+ 'vcf' => 'text/x-vcard',
+ 'srt' => [
+ 'text/srt',
+ 'text/plain',
+ ],
+ 'vtt' => [
+ 'text/vtt',
+ 'text/plain',
+ ],
+ 'ico' => [
+ 'image/x-icon',
+ 'image/x-ico',
+ 'image/vnd.microsoft.icon',
+ ],
+ ];
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Attempts to determine the best mime type for the given file extension.
+ *
+ * @param string $extension
+ *
+ * @return string|null The mime type found, or none if unable to determine.
+ */
+ public static function guessTypeFromExtension(string $extension)
+ {
+ $extension = trim(strtolower($extension), '. ');
+
+ if (! array_key_exists($extension, static::$mimes))
+ {
+ return null;
+ }
+
+ return is_array(static::$mimes[$extension]) ? static::$mimes[$extension][0] : static::$mimes[$extension];
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Attempts to determine the best file extension for a given mime type.
+ *
+ * @param string $type
+ * @param string $proposed_extension - default extension (in case there is more than one with the same mime type)
+ *
+ * @return string|null The extension determined, or null if unable to match.
+ */
+ public static function guessExtensionFromType(string $type, ?string $proposed_extension = null)
+ {
+ $type = trim(strtolower($type), '. ');
+
+ $proposed_extension = trim(strtolower($proposed_extension));
+
+ if (! is_null($proposed_extension) && array_key_exists($proposed_extension, static::$mimes) && in_array($type, is_string(static::$mimes[$proposed_extension]) ? [static::$mimes[$proposed_extension]] : static::$mimes[$proposed_extension]))
+ {
+ return $proposed_extension;
+ }
+
+ foreach (static::$mimes as $ext => $types)
+ {
+ if (is_string($types) && $types === $type)
+ {
+ return $ext;
+ }
+ else if (is_array($types) && in_array($type, $types))
+ {
+ return $ext;
+ }
+ }
+
+ return null;
+ }
+
+ //--------------------------------------------------------------------
+
+}
diff --git a/application/Config/Modules.php b/application/Config/Modules.php
new file mode 100644
index 00000000..2dcd22be
--- /dev/null
+++ b/application/Config/Modules.php
@@ -0,0 +1,57 @@
+enabled)
+ {
+ return false;
+ }
+
+ $alias = strtolower($alias);
+
+ return in_array($alias, $this->activeExplorers);
+ }
+}
diff --git a/application/Config/Pager.php b/application/Config/Pager.php
new file mode 100644
index 00000000..9b6ed83c
--- /dev/null
+++ b/application/Config/Pager.php
@@ -0,0 +1,35 @@
+ 'CodeIgniter\Pager\Views\default_full',
+ 'default_simple' => 'CodeIgniter\Pager\Views\default_simple',
+ 'default_head' => 'CodeIgniter\Pager\Views\default_head',
+ ];
+
+ /*
+ |--------------------------------------------------------------------------
+ | Items Per Page
+ |--------------------------------------------------------------------------
+ |
+ | The default number of results shown in a single page.
+ |
+ */
+ public $perPage = 20;
+}
diff --git a/application/Config/Paths.php b/application/Config/Paths.php
new file mode 100644
index 00000000..a9b78b19
--- /dev/null
+++ b/application/Config/Paths.php
@@ -0,0 +1,91 @@
+defaultNamespace()
+ *
+ * Modifies the namespace that is added to a controller if it doesn't
+ * already have one. By default this is the global namespace (\).
+ *
+ * $routes->defaultController()
+ *
+ * Changes the name of the class used as a controller when the route
+ * points to a folder instead of a class.
+ *
+ * $routes->defaultMethod()
+ *
+ * Assigns the method inside the controller that is ran when the
+ * Router is unable to determine the appropriate method to run.
+ *
+ * $routes->setAutoRoute()
+ *
+ * Determines whether the Router will attempt to match URIs to
+ * Controllers when no specific route has been defined. If false,
+ * only routes that have been defined here will be available.
+ */
+$routes->setDefaultNamespace('App\Controllers');
+$routes->setDefaultController('Home');
+$routes->setDefaultMethod('index');
+$routes->setTranslateURIDashes(false);
+$routes->set404Override();
+$routes->setAutoRoute(true);
+
+/**
+ * --------------------------------------------------------------------
+ * Route Definitions
+ * --------------------------------------------------------------------
+ */
+
+// We get a performance increase by specifying the default
+// route since we don't have to scan directories.
+$routes->get('/', 'Home::index');
+
+/**
+ * --------------------------------------------------------------------
+ * Additional Routing
+ * --------------------------------------------------------------------
+ *
+ * There will often be times that you need additional routing and you
+ * need to it be able to override any defaults in this file. Environment
+ * based routes is one such time. require() additional route files here
+ * to make that happen.
+ *
+ * You will have access to the $routes object within that file without
+ * needing to reload it.
+ */
+if (file_exists(APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php'))
+{
+ require APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php';
+}
diff --git a/application/Config/Services.php b/application/Config/Services.php
new file mode 100644
index 00000000..061d0d78
--- /dev/null
+++ b/application/Config/Services.php
@@ -0,0 +1,49 @@
+ 'Windows 10',
+ 'windows nt 6.3' => 'Windows 8.1',
+ 'windows nt 6.2' => 'Windows 8',
+ 'windows nt 6.1' => 'Windows 7',
+ 'windows nt 6.0' => 'Windows Vista',
+ 'windows nt 5.2' => 'Windows 2003',
+ 'windows nt 5.1' => 'Windows XP',
+ 'windows nt 5.0' => 'Windows 2000',
+ 'windows nt 4.0' => 'Windows NT 4.0',
+ 'winnt4.0' => 'Windows NT 4.0',
+ 'winnt 4.0' => 'Windows NT',
+ 'winnt' => 'Windows NT',
+ 'windows 98' => 'Windows 98',
+ 'win98' => 'Windows 98',
+ 'windows 95' => 'Windows 95',
+ 'win95' => 'Windows 95',
+ 'windows phone' => 'Windows Phone',
+ 'windows' => 'Unknown Windows OS',
+ 'android' => 'Android',
+ 'blackberry' => 'BlackBerry',
+ 'iphone' => 'iOS',
+ 'ipad' => 'iOS',
+ 'ipod' => 'iOS',
+ 'os x' => 'Mac OS X',
+ 'ppc mac' => 'Power PC Mac',
+ 'freebsd' => 'FreeBSD',
+ 'ppc' => 'Macintosh',
+ 'linux' => 'Linux',
+ 'debian' => 'Debian',
+ 'sunos' => 'Sun Solaris',
+ 'beos' => 'BeOS',
+ 'apachebench' => 'ApacheBench',
+ 'aix' => 'AIX',
+ 'irix' => 'Irix',
+ 'osf' => 'DEC OSF',
+ 'hp-ux' => 'HP-UX',
+ 'netbsd' => 'NetBSD',
+ 'bsdi' => 'BSDi',
+ 'openbsd' => 'OpenBSD',
+ 'gnu' => 'GNU/Linux',
+ 'unix' => 'Unknown Unix OS',
+ 'symbian' => 'Symbian OS',
+ ];
+
+ // The order of this array should NOT be changed. Many browsers return
+ // multiple browser types so we want to identify the sub-type first.
+ public $browsers = [
+ 'OPR' => 'Opera',
+ 'Flock' => 'Flock',
+ 'Edge' => 'Spartan',
+ 'Chrome' => 'Chrome',
+ // Opera 10+ always reports Opera/9.80 and appends Version/ to the user agent string
+ 'Opera.*?Version' => 'Opera',
+ 'Opera' => 'Opera',
+ 'MSIE' => 'Internet Explorer',
+ 'Internet Explorer' => 'Internet Explorer',
+ 'Trident.* rv' => 'Internet Explorer',
+ 'Shiira' => 'Shiira',
+ 'Firefox' => 'Firefox',
+ 'Chimera' => 'Chimera',
+ 'Phoenix' => 'Phoenix',
+ 'Firebird' => 'Firebird',
+ 'Camino' => 'Camino',
+ 'Netscape' => 'Netscape',
+ 'OmniWeb' => 'OmniWeb',
+ 'Safari' => 'Safari',
+ 'Mozilla' => 'Mozilla',
+ 'Konqueror' => 'Konqueror',
+ 'icab' => 'iCab',
+ 'Lynx' => 'Lynx',
+ 'Links' => 'Links',
+ 'hotjava' => 'HotJava',
+ 'amaya' => 'Amaya',
+ 'IBrowse' => 'IBrowse',
+ 'Maxthon' => 'Maxthon',
+ 'Ubuntu' => 'Ubuntu Web Browser',
+ 'Vivaldi' => 'Vivaldi',
+ ];
+
+ public $mobiles = [
+ // legacy array, old values commented out
+ 'mobileexplorer' => 'Mobile Explorer',
+ // 'openwave' => 'Open Wave',
+ // 'opera mini' => 'Opera Mini',
+ // 'operamini' => 'Opera Mini',
+ // 'elaine' => 'Palm',
+ 'palmsource' => 'Palm',
+ // 'digital paths' => 'Palm',
+ // 'avantgo' => 'Avantgo',
+ // 'xiino' => 'Xiino',
+ 'palmscape' => 'Palmscape',
+ // 'nokia' => 'Nokia',
+ // 'ericsson' => 'Ericsson',
+ // 'blackberry' => 'BlackBerry',
+ // 'motorola' => 'Motorola'
+
+ // Phones and Manufacturers
+ 'motorola' => 'Motorola',
+ 'nokia' => 'Nokia',
+ 'palm' => 'Palm',
+ 'iphone' => 'Apple iPhone',
+ 'ipad' => 'iPad',
+ 'ipod' => 'Apple iPod Touch',
+ 'sony' => 'Sony Ericsson',
+ 'ericsson' => 'Sony Ericsson',
+ 'blackberry' => 'BlackBerry',
+ 'cocoon' => 'O2 Cocoon',
+ 'blazer' => 'Treo',
+ 'lg' => 'LG',
+ 'amoi' => 'Amoi',
+ 'xda' => 'XDA',
+ 'mda' => 'MDA',
+ 'vario' => 'Vario',
+ 'htc' => 'HTC',
+ 'samsung' => 'Samsung',
+ 'sharp' => 'Sharp',
+ 'sie-' => 'Siemens',
+ 'alcatel' => 'Alcatel',
+ 'benq' => 'BenQ',
+ 'ipaq' => 'HP iPaq',
+ 'mot-' => 'Motorola',
+ 'playstation portable' => 'PlayStation Portable',
+ 'playstation 3' => 'PlayStation 3',
+ 'playstation vita' => 'PlayStation Vita',
+ 'hiptop' => 'Danger Hiptop',
+ 'nec-' => 'NEC',
+ 'panasonic' => 'Panasonic',
+ 'philips' => 'Philips',
+ 'sagem' => 'Sagem',
+ 'sanyo' => 'Sanyo',
+ 'spv' => 'SPV',
+ 'zte' => 'ZTE',
+ 'sendo' => 'Sendo',
+ 'nintendo dsi' => 'Nintendo DSi',
+ 'nintendo ds' => 'Nintendo DS',
+ 'nintendo 3ds' => 'Nintendo 3DS',
+ 'wii' => 'Nintendo Wii',
+ 'open web' => 'Open Web',
+ 'openweb' => 'OpenWeb',
+
+ // Operating Systems
+ 'android' => 'Android',
+ 'symbian' => 'Symbian',
+ 'SymbianOS' => 'SymbianOS',
+ 'elaine' => 'Palm',
+ 'series60' => 'Symbian S60',
+ 'windows ce' => 'Windows CE',
+
+ // Browsers
+ 'obigo' => 'Obigo',
+ 'netfront' => 'Netfront Browser',
+ 'openwave' => 'Openwave Browser',
+ 'mobilexplorer' => 'Mobile Explorer',
+ 'operamini' => 'Opera Mini',
+ 'opera mini' => 'Opera Mini',
+ 'opera mobi' => 'Opera Mobile',
+ 'fennec' => 'Firefox Mobile',
+
+ // Other
+ 'digital paths' => 'Digital Paths',
+ 'avantgo' => 'AvantGo',
+ 'xiino' => 'Xiino',
+ 'novarra' => 'Novarra Transcoder',
+ 'vodafone' => 'Vodafone',
+ 'docomo' => 'NTT DoCoMo',
+ 'o2' => 'O2',
+
+ // Fallback
+ 'mobile' => 'Generic Mobile',
+ 'wireless' => 'Generic Mobile',
+ 'j2me' => 'Generic Mobile',
+ 'midp' => 'Generic Mobile',
+ 'cldc' => 'Generic Mobile',
+ 'up.link' => 'Generic Mobile',
+ 'up.browser' => 'Generic Mobile',
+ 'smartphone' => 'Generic Mobile',
+ 'cellphone' => 'Generic Mobile',
+ ];
+
+ // There are hundreds of bots but these are the most common.
+ public $robots = [
+ 'googlebot' => 'Googlebot',
+ 'msnbot' => 'MSNBot',
+ 'baiduspider' => 'Baiduspider',
+ 'bingbot' => 'Bing',
+ 'slurp' => 'Inktomi Slurp',
+ 'yahoo' => 'Yahoo',
+ 'ask jeeves' => 'Ask Jeeves',
+ 'fastcrawler' => 'FastCrawler',
+ 'infoseek' => 'InfoSeek Robot 1.0',
+ 'lycos' => 'Lycos',
+ 'yandex' => 'YandexBot',
+ 'mediapartners-google' => 'MediaPartners Google',
+ 'CRAZYWEBCRAWLER' => 'Crazy Webcrawler',
+ 'adsbot-google' => 'AdsBot Google',
+ 'feedfetcher-google' => 'Feedfetcher Google',
+ 'curious george' => 'Curious George',
+ 'ia_archiver' => 'Alexa Crawler',
+ 'MJ12bot' => 'Majestic-12',
+ 'Uptimebot' => 'Uptimebot',
+ ];
+}
diff --git a/application/Config/Validation.php b/application/Config/Validation.php
new file mode 100644
index 00000000..97f08c75
--- /dev/null
+++ b/application/Config/Validation.php
@@ -0,0 +1,36 @@
+ 'CodeIgniter\Validation\Views\list',
+ 'single' => 'CodeIgniter\Validation\Views\single',
+ ];
+
+ //--------------------------------------------------------------------
+ // Rules
+ //--------------------------------------------------------------------
+}
diff --git a/application/Config/View.php b/application/Config/View.php
new file mode 100644
index 00000000..f66b2532
--- /dev/null
+++ b/application/Config/View.php
@@ -0,0 +1,34 @@
+isCLI())
+ {
+ return;
+ }
+
+ $security = Services::security();
+
+ try
+ {
+ $security->CSRFVerify($request);
+ }
+ catch (SecurityException $e)
+ {
+ if (config('App')->CSRFRedirect && ! $request->isAJAX())
+ {
+ return redirect()->back()->with('error', $e->getMessage());
+ }
+
+ throw $e;
+ }
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * We don't have anything to do here.
+ *
+ * @param RequestInterface|\CodeIgniter\HTTP\IncomingRequest $request
+ * @param ResponseInterface|\CodeIgniter\HTTP\Response $response
+ *
+ * @return mixed
+ */
+ public function after(RequestInterface $request, ResponseInterface $response)
+ {
+ }
+
+ //--------------------------------------------------------------------
+}
diff --git a/application/Filters/DebugToolbar.php b/application/Filters/DebugToolbar.php
new file mode 100644
index 00000000..145f97df
--- /dev/null
+++ b/application/Filters/DebugToolbar.php
@@ -0,0 +1,91 @@
+getPerformanceStats();
+ $data = $toolbar->run(
+ $stats['startTime'],
+ $stats['totalTime'],
+ $request,
+ $response
+ );
+
+ helper('filesystem');
+
+ // Updated to time() so we can get history
+ $time = time();
+
+ if (! is_dir(WRITEPATH . 'debugbar'))
+ {
+ mkdir(WRITEPATH . 'debugbar', 0777);
+ }
+
+ write_file(WRITEPATH . 'debugbar/' . 'debugbar_' . $time, $data, 'w+');
+
+ $format = $response->getHeaderLine('content-type');
+
+ // Non-HTML formats should not include the debugbar
+ // then we send headers saying where to find the debug data
+ // for this response
+ if ($request->isAJAX() || strpos($format, 'html') === false)
+ {
+ return $response->setHeader('Debugbar-Time', (string)$time)
+ ->setHeader('Debugbar-Link', site_url("?debugbar_time={$time}"))
+ ->getBody();
+ }
+
+ $script = PHP_EOL
+ . ''
+ . ''
+ . ''
+ . PHP_EOL;
+
+ if (strpos($response->getBody(), '
+
+
404 - File Not Found
+
+
+
+ = esc($message) ?>
+
+ Sorry! Cannot seem to find the page you were looking for.
+
+
+
+') !== false)
+ {
+ return $response->setBody(str_replace('', $script . '',
+ $response->getBody()));
+ }
+
+ return $response->appendBody($script);
+ }
+ }
+
+ //--------------------------------------------------------------------
+}
diff --git a/application/Filters/Honeypot.php b/application/Filters/Honeypot.php
new file mode 100644
index 00000000..a16a55c0
--- /dev/null
+++ b/application/Filters/Honeypot.php
@@ -0,0 +1,44 @@
+hasContent($request))
+ {
+ throw HoneypotException::isBot();
+ }
+ }
+
+ /**
+ * Attach a honypot to the current response.
+ *
+ * @param CodeIgniter\HTTP\RequestInterface $request
+ * @param CodeIgniter\HTTP\ResponseInterface $response
+ * @return mixed
+ */
+ public function after(RequestInterface $request, ResponseInterface $response)
+ {
+ $honeypot = Services::honeypot(new \Config\Honeypot());
+ $honeypot->attachHoneypot($response);
+ }
+
+}
diff --git a/application/Filters/Throttle.php b/application/Filters/Throttle.php
new file mode 100644
index 00000000..b2659e54
--- /dev/null
+++ b/application/Filters/Throttle.php
@@ -0,0 +1,46 @@
+check($request->getIPAddress(), 60, MINUTE) === false)
+ {
+ return Services::response()->setStatusCode(429);
+ }
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * We don't have anything to do here.
+ *
+ * @param RequestInterface|\CodeIgniter\HTTP\IncomingRequest $request
+ * @param ResponseInterface|\CodeIgniter\HTTP\Response $response
+ *
+ * @return mixed
+ */
+ public function after(RequestInterface $request, ResponseInterface $response)
+ {
+ }
+
+ //--------------------------------------------------------------------
+}
diff --git a/application/Helpers/.gitkeep b/application/Helpers/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/application/Language/.gitkeep b/application/Language/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/application/Libraries/.gitkeep b/application/Libraries/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/application/Models/.gitkeep b/application/Models/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/application/ThirdParty/.gitkeep b/application/ThirdParty/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/application/Views/errors/cli/error_404.php b/application/Views/errors/cli/error_404.php
new file mode 100644
index 00000000..d5bccb43
--- /dev/null
+++ b/application/Views/errors/cli/error_404.php
@@ -0,0 +1,6 @@
+
+Message: = $message, "\n"; ?>
+Filename: = $exception->getFile(), "\n"; ?>
+Line Number: = $exception->getLine(); ?>
+
+
+
+ Backtrace:
+ getTrace() as $error): ?>
+
+= trim('-'. $error['line'] .' - '. $error['file'] .'::'. $error['function']) ."\n" ?>
+
+
+
+
diff --git a/application/Views/errors/cli/production.php b/application/Views/errors/cli/production.php
new file mode 100644
index 00000000..f04d517d
--- /dev/null
+++ b/application/Views/errors/cli/production.php
@@ -0,0 +1,5 @@
+
+
+