Implemented many CodeIgniter classes.
Preparing for Factory Build
This commit is contained in:
parent
02206f4bda
commit
3343c08594
|
@ -5,10 +5,56 @@ return array(
|
|||
'SITE_DOMAIN' => '',
|
||||
'SERVER_NAME' => '',
|
||||
'SITE_LOGO_URL' => '',
|
||||
|
||||
'administrator_mail' => '',
|
||||
|
||||
'default_controller' => 'standard',
|
||||
'default_function' => 'index',
|
||||
'application_prefix' => 'MY_',
|
||||
'charset' => 'utf8',
|
||||
'language' => 'english'
|
||||
|
||||
'charset' => 'utf-8',
|
||||
'language' => 'english',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cookie Related Variables
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| 'cookie_prefix' = Set a cookie name prefix if you need to avoid collisions
|
||||
| 'cookie_domain' = Set to .your-domain.com for site-wide cookies
|
||||
| 'cookie_path' = Typically will be a forward slash
|
||||
| 'cookie_secure' = Cookie will only be set if a secure HTTPS connection exists.
|
||||
| 'cookie_httponly' = Cookie will only be accessible via HTTP(S) (no javascript)
|
||||
|
|
||||
| Note: These settings (with the exception of 'cookie_prefix' and
|
||||
| 'cookie_httponly') will also affect sessions.
|
||||
|
|
||||
*/
|
||||
'cookie_prefix' => '',
|
||||
'cookie_domain' => '',
|
||||
'cookie_path' => '/',
|
||||
'cookie_secure' => FALSE,
|
||||
'cookie_httponly' => FALSE,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Output Compression
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Enables Gzip output compression for faster page loads. When enabled,
|
||||
| the output class will test whether your server supports Gzip.
|
||||
| Even if it does, however, not all browsers support compression
|
||||
| so enable only if you are reasonably sure your visitors can handle it.
|
||||
|
|
||||
| Only used if zlib.output_compression is turned off in your php.ini.
|
||||
| Please do not use it together with httpd-level output compression.
|
||||
|
|
||||
| VERY IMPORTANT: If you are getting a blank page when compression is enabled it
|
||||
| means you are prematurely outputting something to your browser. It could
|
||||
| even be a line of whitespace at the end of one of your scripts. For
|
||||
| compression to work, nothing can be sent before the output buffer is called
|
||||
| by the output class. Do not 'echo' any values with compression enabled.
|
||||
|
|
||||
*/
|
||||
'compress_output' => FALSE,
|
||||
);
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Enable Query Strings
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| By default CodeIgniter uses search-engine friendly segment based URLs:
|
||||
| example.com/who/what/where/
|
||||
|
|
||||
| By default CodeIgniter enables access to the $_GET array. If for some
|
||||
| reason you would like to disable it, set 'allow_get_array' to FALSE.
|
||||
|
|
||||
| You can optionally enable standard query string based URLs:
|
||||
| example.com?who=me&what=something&where=here
|
||||
|
|
||||
| Options are: TRUE or FALSE (boolean)
|
||||
|
|
||||
| The other items let you set the query string 'words' that will
|
||||
| invoke your controllers and its functions:
|
||||
| example.com/index.php?c=controller&m=function
|
||||
|
|
||||
| Please note that some of the helpers won't work as expected when
|
||||
| this feature is enabled, since CodeIgniter is designed primarily to
|
||||
| use segment based URLs.
|
||||
|
|
||||
*/
|
||||
'allow_get_array' => TRUE,
|
||||
'enable_query_strings' => FALSE,
|
||||
'controller_trigger' => 'c',
|
||||
'function_trigger' => 'm',
|
||||
'directory_trigger' => 'd',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Allowed URL Characters
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This lets you specify which characters are permitted within your URLs.
|
||||
| When someone tries to submit a URL with disallowed characters they will
|
||||
| get a warning message.
|
||||
|
|
||||
| As a security measure you are STRONGLY encouraged to restrict URLs to
|
||||
| as few characters as possible. By default only these are allowed: a-z 0-9~%.:_-
|
||||
|
|
||||
| Leave blank to allow all characters -- but only if you are insane.
|
||||
|
|
||||
| The configured value is actually a regular expression character group
|
||||
| and it will be executed as: ! preg_match('/^[<permitted_uri_chars>]+$/i
|
||||
|
|
||||
| DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!!
|
||||
|
|
||||
*/
|
||||
'permitted_uri_chars' => 'a-z 0-9~%.:_\-',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| URI PROTOCOL
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This item determines which server global should be used to retrieve the
|
||||
| URI string. The default setting of 'REQUEST_URI' works for most servers.
|
||||
| If your links do not seem to work, try one of the other delicious flavors:
|
||||
|
|
||||
| 'REQUEST_URI' Uses $_SERVER['REQUEST_URI']
|
||||
| 'QUERY_STRING' Uses $_SERVER['QUERY_STRING']
|
||||
| 'PATH_INFO' Uses $_SERVER['PATH_INFO']
|
||||
|
|
||||
| WARNING: If you set this to 'PATH_INFO', URIs will always be URL-decoded!
|
||||
*/
|
||||
'uri_protocol' => 'REQUEST_URI',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| URL suffix
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option allows you to add a suffix to all URLs generated by CodeIgniter.
|
||||
| For more information please see the user guide:
|
||||
|
|
||||
| https://codeigniter.com/user_guide/general/urls.html
|
||||
*/
|
||||
'url_suffix' => '',
|
||||
|
||||
);
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cross Site Request Forgery
|
||||
|--------------------------------------------------------------------------
|
||||
| Enables a CSRF cookie token to be set. When set to TRUE, token will be
|
||||
| checked on a submitted form. If you are accepting user data, it is strongly
|
||||
| recommended CSRF protection be enabled.
|
||||
|
|
||||
| 'csrf_token_name' = The token name
|
||||
| 'csrf_cookie_name' = The cookie name
|
||||
| 'csrf_expire' = The number in seconds the token should expire.
|
||||
| 'csrf_regenerate' = Regenerate token on every submission
|
||||
| 'csrf_exclude_uris' = Array of URIs which ignore CSRF checks
|
||||
*/
|
||||
'csrf_protection' => true,
|
||||
'csrf_token_name' => 'csrf_test_name',
|
||||
'csrf_cookie_name' => 'csrf_cookie_name',
|
||||
'csrf_expire' => 7200,
|
||||
'csrf_regenerate' => TRUE,
|
||||
'csrf_exclude_uris' => array(),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Standardize newlines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Determines whether to standardize newline characters in input data,
|
||||
| meaning to replace \r\n, \r, \n occurrences with the PHP_EOL value.
|
||||
|
|
||||
| This is particularly useful for portability between UNIX-based OSes,
|
||||
| (usually \n) and Windows (\r\n).
|
||||
|
|
||||
*/
|
||||
'standardize_newlines' => FALSE,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Global XSS Filtering
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Determines whether the XSS filter is always active when GET, POST or
|
||||
| COOKIE data is encountered
|
||||
|
|
||||
| WARNING: This feature is DEPRECATED and currently available only
|
||||
| for backwards compatibility purposes!
|
||||
|
|
||||
*/
|
||||
'global_xss_filtering' => FALSE,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Reverse Proxy IPs
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If your server is behind a reverse proxy, you must whitelist the proxy
|
||||
| IP addresses from which CodeIgniter should trust headers such as
|
||||
| HTTP_X_FORWARDED_FOR and HTTP_CLIENT_IP in order to properly identify
|
||||
| the visitor's IP address.
|
||||
|
|
||||
| You can use both an array or a comma-separated list of proxy addresses,
|
||||
| as well as specifying whole subnets. Here are a few examples:
|
||||
|
|
||||
| Comma-separated: '10.0.1.200,192.168.5.0/24'
|
||||
| Array: array('10.0.1.200', '192.168.5.0/24')
|
||||
*/
|
||||
'proxy_ips' => ''
|
||||
|
||||
);
|
|
@ -154,108 +154,6 @@ if ( ! function_exists('is_cli'))
|
|||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
if ( ! function_exists('show_error'))
|
||||
{
|
||||
/**
|
||||
* Error Handler
|
||||
*
|
||||
* This function lets us invoke the exception class and
|
||||
* display errors using the standard error template located
|
||||
* in application/views/errors/error_general.php
|
||||
* This function will send the error page directly to the
|
||||
* browser and exit.
|
||||
*
|
||||
* @param string
|
||||
* @param int
|
||||
* @param string
|
||||
* @return void
|
||||
*/
|
||||
function show_error($message, $status_code = 500, $heading = 'An Error Was Encountered')
|
||||
{
|
||||
$status_code = abs($status_code);
|
||||
if ($status_code < 100)
|
||||
{
|
||||
$exit_status = $status_code + 9; // 9 is EXIT__AUTO_MIN
|
||||
if ($exit_status > 125) // 125 is EXIT__AUTO_MAX
|
||||
{
|
||||
$exit_status = 1; // EXIT_ERROR
|
||||
}
|
||||
|
||||
$status_code = 500;
|
||||
}
|
||||
else
|
||||
{
|
||||
$exit_status = 1; // EXIT_ERROR
|
||||
}
|
||||
|
||||
Logger::logError($heading . ' | ' . $message . ' | ' . $status_code);
|
||||
Logger::http_error(500);
|
||||
exit($exit_status);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
if ( ! function_exists('show_404'))
|
||||
{
|
||||
/**
|
||||
* 404 Page Handler
|
||||
*
|
||||
* This function is similar to the show_error() function above
|
||||
* However, instead of the standard error template it displays
|
||||
* 404 errors.
|
||||
*
|
||||
* @param string
|
||||
* @param bool
|
||||
* @return void
|
||||
*/
|
||||
function show_404($page = '', $log_error = TRUE)
|
||||
{
|
||||
Logger::http_error(404);
|
||||
exit(4); // EXIT_UNKNOWN_FILE
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
if ( ! function_exists('log_message'))
|
||||
{
|
||||
/**
|
||||
* Error Logging Interface
|
||||
*
|
||||
* We use this as a simple mechanism to access the logging
|
||||
* class and send messages to be logged.
|
||||
*
|
||||
* @param string the error level: 'error', 'debug' or 'info'
|
||||
* @param string the error message
|
||||
* @return void
|
||||
*/
|
||||
function log_message($level, $message)
|
||||
{
|
||||
switch (strtoupper($level)) {
|
||||
case 'INFO':
|
||||
Logger::logInfo($message);
|
||||
break;
|
||||
case 'ERROR':
|
||||
Logger::logError($message);
|
||||
break;
|
||||
case 'DEBUG':
|
||||
Logger::logDebug($message);
|
||||
break;
|
||||
case 'ALL':
|
||||
Logger::logInfo($message);
|
||||
break;
|
||||
default:
|
||||
Logger::newLevel("Invalid logging message of type '".$level."'");
|
||||
Logger::logWarning($message);
|
||||
Logger::stopLevel();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
if ( ! function_exists('set_status_header'))
|
||||
{
|
||||
/**
|
||||
|
@ -274,7 +172,7 @@ if ( ! function_exists('set_status_header'))
|
|||
|
||||
if (empty($code) OR ! is_numeric($code))
|
||||
{
|
||||
show_error('Status codes must be numeric', 500);
|
||||
throw new Exception('Status codes must be numeric', 1);
|
||||
}
|
||||
|
||||
if (empty($text))
|
||||
|
|
|
@ -95,8 +95,7 @@ if ( ! function_exists('force_download'))
|
|||
}
|
||||
|
||||
// Load the mime types
|
||||
FuzeWorks\Helpers::load('common');
|
||||
$mimes =& get_mimes();
|
||||
$mimes = Config::get('mimes')->toArray();
|
||||
|
||||
// Only change the default MIME if we can find one
|
||||
if (isset($mimes[$extension]))
|
||||
|
|
|
@ -86,12 +86,6 @@ class Core
|
|||
// Load the config file of the FuzeWorks core
|
||||
$config = Config::get('core');
|
||||
|
||||
// Load the logger
|
||||
Logger::init();
|
||||
|
||||
// And initialize the router paths
|
||||
Router::init();
|
||||
|
||||
// Disable events if requested to do so
|
||||
if (!$config->enable_events)
|
||||
{
|
||||
|
@ -152,6 +146,11 @@ class Core
|
|||
include_once 'Core/System/class.helpers.php';
|
||||
include_once 'Core/System/class.database.php';
|
||||
include_once 'Core/System/class.language.php';
|
||||
include_once 'Core/System/class.utf8.php';
|
||||
include_once 'Core/System/class.uri.php';
|
||||
include_once 'Core/System/class.security.php';
|
||||
include_once 'Core/System/class.input.php';
|
||||
include_once 'Core/System/class.output.php';
|
||||
|
||||
// Load the core classes
|
||||
new Config();
|
||||
|
@ -159,12 +158,17 @@ class Core
|
|||
new Events();
|
||||
new Models();
|
||||
new Layout();
|
||||
new Router();
|
||||
new Modules();
|
||||
new Libraries();
|
||||
new Helpers();
|
||||
new Database();
|
||||
new Language();
|
||||
new Utf8();
|
||||
new URI();
|
||||
new Security();
|
||||
new Input();
|
||||
new Router();
|
||||
new Output();
|
||||
|
||||
self::$loaded = true;
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ class Database
|
|||
* @param string $parameters
|
||||
* @param bool $newInstance
|
||||
* @param bool $queryBuilder
|
||||
* @return type FW_DB
|
||||
* @return FW_DB
|
||||
*/
|
||||
public static function get($parameters = '', $newInstance = false, $queryBuilder = null)
|
||||
{
|
||||
|
|
|
@ -160,4 +160,24 @@ class HelperException extends Exception
|
|||
*/
|
||||
class LanguageException extends Exception
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Class UriException.
|
||||
*
|
||||
* @author Abel Hoogeveen <abel@techfuze.net>
|
||||
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
|
||||
*/
|
||||
class UriException extends Exception
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Class SecurityException.
|
||||
*
|
||||
* @author Abel Hoogeveen <abel@techfuze.net>
|
||||
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
|
||||
*/
|
||||
class SecurityException extends Exception
|
||||
{
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
/**
|
||||
* FuzeWorks.
|
||||
*
|
||||
* The FuzeWorks MVC PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2015 TechFuze
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
|
||||
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
|
||||
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
|
||||
*
|
||||
* @link http://fuzeworks.techfuze.net
|
||||
* @since Version 0.0.1
|
||||
*
|
||||
* @version Version 0.0.1
|
||||
*/
|
||||
|
||||
namespace FuzeWorks;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Abel Hoogeveen <abel@techfuze.net>
|
||||
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
|
||||
*/
|
||||
class Factory
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,878 @@
|
|||
<?php
|
||||
/**
|
||||
* FuzeWorks.
|
||||
*
|
||||
* The FuzeWorks MVC PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2015 TechFuze
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
|
||||
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
|
||||
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
|
||||
*
|
||||
* @link http://fuzeworks.techfuze.net
|
||||
* @since Version 0.0.1
|
||||
*
|
||||
* @version Version 0.0.1
|
||||
*/
|
||||
|
||||
namespace FuzeWorks;
|
||||
|
||||
/**
|
||||
* Input Class
|
||||
*
|
||||
* Pre-processes global input data for security
|
||||
*
|
||||
* @author EllisLab Dev Team
|
||||
* @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
|
||||
* @copyright Copyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)
|
||||
*/
|
||||
class Input {
|
||||
|
||||
/**
|
||||
* IP address of the current user
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $ip_address = FALSE;
|
||||
|
||||
/**
|
||||
* Allow GET array flag
|
||||
*
|
||||
* If set to FALSE, then $_GET will be set to an empty array.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $_allow_get_array = TRUE;
|
||||
|
||||
/**
|
||||
* Standardize new lines flag
|
||||
*
|
||||
* If set to TRUE, then newlines are standardized.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $_standardize_newlines;
|
||||
|
||||
/**
|
||||
* Enable XSS flag
|
||||
*
|
||||
* Determines whether the XSS filter is always active when
|
||||
* GET, POST or COOKIE data is encountered.
|
||||
* Set automatically based on config setting.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $_enable_xss = FALSE;
|
||||
|
||||
/**
|
||||
* Enable CSRF flag
|
||||
*
|
||||
* Enables a CSRF cookie token to be set.
|
||||
* Set automatically based on config setting.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $_enable_csrf = FALSE;
|
||||
|
||||
/**
|
||||
* List of all HTTP request headers
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $headers = array();
|
||||
|
||||
/**
|
||||
* Raw input stream data
|
||||
*
|
||||
* Holds a cache of php://input contents
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_raw_input_stream;
|
||||
|
||||
/**
|
||||
* Parsed input stream data
|
||||
*
|
||||
* Parsed from php://input at runtime
|
||||
*
|
||||
* @see CI_Input::input_stream()
|
||||
* @var array
|
||||
*/
|
||||
protected $_input_stream;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* Determines whether to globally enable the XSS processing
|
||||
* and whether to allow the $_GET array.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->_allow_get_array = (Config::get('routing')->allow_get_array === TRUE);
|
||||
$this->_enable_xss = (Config::get('security')->global_xss_filtering === TRUE);
|
||||
$this->_enable_csrf = (Config::get('security')->csrf_protection === TRUE);
|
||||
$this->_standardize_newlines = (bool) Config::get('security')->standardize_newlines;
|
||||
|
||||
// Sanitize global arrays
|
||||
$this->_sanitize_globals();
|
||||
|
||||
// CSRF Protection check
|
||||
if ($this->_enable_csrf === TRUE && ! $this->is_cli_request())
|
||||
{
|
||||
Security::csrf_verify();
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Fetch from array
|
||||
*
|
||||
* Internal method used to retrieve values from global arrays.
|
||||
*
|
||||
* @param array &$array $_GET, $_POST, $_COOKIE, $_SERVER, etc.
|
||||
* @param mixed $index Index for item to be fetched from $array
|
||||
* @param bool $xss_clean Whether to apply XSS filtering
|
||||
* @return mixed
|
||||
*/
|
||||
protected function _fetch_from_array(&$array, $index = NULL, $xss_clean = NULL)
|
||||
{
|
||||
is_bool($xss_clean) OR $xss_clean = $this->_enable_xss;
|
||||
|
||||
// If $index is NULL, it means that the whole $array is requested
|
||||
isset($index) OR $index = array_keys($array);
|
||||
|
||||
// allow fetching multiple keys at once
|
||||
if (is_array($index))
|
||||
{
|
||||
$output = array();
|
||||
foreach ($index as $key)
|
||||
{
|
||||
$output[$key] = $this->_fetch_from_array($array, $key, $xss_clean);
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
if (isset($array[$index]))
|
||||
{
|
||||
$value = $array[$index];
|
||||
}
|
||||
elseif (($count = preg_match_all('/(?:^[^\[]+)|\[[^]]*\]/', $index, $matches)) > 1) // Does the index contain array notation
|
||||
{
|
||||
$value = $array;
|
||||
for ($i = 0; $i < $count; $i++)
|
||||
{
|
||||
$key = trim($matches[0][$i], '[]');
|
||||
if ($key === '') // Empty notation will return the value as array
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (isset($value[$key]))
|
||||
{
|
||||
$value = $value[$key];
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ($xss_clean === TRUE)
|
||||
? Security::xss_clean($value)
|
||||
: $value;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Fetch an item from the GET array
|
||||
*
|
||||
* @param mixed $index Index for item to be fetched from $_GET
|
||||
* @param bool $xss_clean Whether to apply XSS filtering
|
||||
* @return mixed
|
||||
*/
|
||||
public function get($index = NULL, $xss_clean = NULL)
|
||||
{
|
||||
return $this->_fetch_from_array($_GET, $index, $xss_clean);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Fetch an item from the POST array
|
||||
*
|
||||
* @param mixed $index Index for item to be fetched from $_POST
|
||||
* @param bool $xss_clean Whether to apply XSS filtering
|
||||
* @return mixed
|
||||
*/
|
||||
public function post($index = NULL, $xss_clean = NULL)
|
||||
{
|
||||
return $this->_fetch_from_array($_POST, $index, $xss_clean);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Fetch an item from POST data with fallback to GET
|
||||
*
|
||||
* @param string $index Index for item to be fetched from $_POST or $_GET
|
||||
* @param bool $xss_clean Whether to apply XSS filtering
|
||||
* @return mixed
|
||||
*/
|
||||
public function post_get($index, $xss_clean = NULL)
|
||||
{
|
||||
return isset($_POST[$index])
|
||||
? $this->post($index, $xss_clean)
|
||||
: $this->get($index, $xss_clean);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Fetch an item from GET data with fallback to POST
|
||||
*
|
||||
* @param string $index Index for item to be fetched from $_GET or $_POST
|
||||
* @param bool $xss_clean Whether to apply XSS filtering
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_post($index, $xss_clean = NULL)
|
||||
{
|
||||
return isset($_GET[$index])
|
||||
? $this->get($index, $xss_clean)
|
||||
: $this->post($index, $xss_clean);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Fetch an item from the COOKIE array
|
||||
*
|
||||
* @param mixed $index Index for item to be fetched from $_COOKIE
|
||||
* @param bool $xss_clean Whether to apply XSS filtering
|
||||
* @return mixed
|
||||
*/
|
||||
public function cookie($index = NULL, $xss_clean = NULL)
|
||||
{
|
||||
return $this->_fetch_from_array($_COOKIE, $index, $xss_clean);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Fetch an item from the SERVER array
|
||||
*
|
||||
* @param mixed $index Index for item to be fetched from $_SERVER
|
||||
* @param bool $xss_clean Whether to apply XSS filtering
|
||||
* @return mixed
|
||||
*/
|
||||
public function server($index, $xss_clean = NULL)
|
||||
{
|
||||
return $this->_fetch_from_array($_SERVER, $index, $xss_clean);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Fetch an item from the php://input stream
|
||||
*
|
||||
* Useful when you need to access PUT, DELETE or PATCH request data.
|
||||
*
|
||||
* @param string $index Index for item to be fetched
|
||||
* @param bool $xss_clean Whether to apply XSS filtering
|
||||
* @return mixed
|
||||
*/
|
||||
public function input_stream($index = NULL, $xss_clean = NULL)
|
||||
{
|
||||
// Prior to PHP 5.6, the input stream can only be read once,
|
||||
// so we'll need to check if we have already done that first.
|
||||
if ( ! is_array($this->_input_stream))
|
||||
{
|
||||
// $this->raw_input_stream will trigger __get().
|
||||
parse_str($this->raw_input_stream, $this->_input_stream);
|
||||
is_array($this->_input_stream) OR $this->_input_stream = array();
|
||||
}
|
||||
|
||||
return $this->_fetch_from_array($this->_input_stream, $index, $xss_clean);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set cookie
|
||||
*
|
||||
* Accepts an arbitrary number of parameters (up to 7) or an associative
|
||||
* array in the first parameter containing all the values.
|
||||
*
|
||||
* @param string|mixed[] $name Cookie name or an array containing parameters
|
||||
* @param string $value Cookie value
|
||||
* @param int $expire Cookie expiration time in seconds
|
||||
* @param string $domain Cookie domain (e.g.: '.yourdomain.com')
|
||||
* @param string $path Cookie path (default: '/')
|
||||
* @param string $prefix Cookie name prefix
|
||||
* @param bool $secure Whether to only transfer cookies via SSL
|
||||
* @param bool $httponly Whether to only makes the cookie accessible via HTTP (no javascript)
|
||||
* @return void
|
||||
*/
|
||||
public function set_cookie($name, $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = FALSE, $httponly = FALSE)
|
||||
{
|
||||
if (is_array($name))
|
||||
{
|
||||
// always leave 'name' in last place, as the loop will break otherwise, due to $$item
|
||||
foreach (array('value', 'expire', 'domain', 'path', 'prefix', 'secure', 'httponly', 'name') as $item)
|
||||
{
|
||||
if (isset($name[$item]))
|
||||
{
|
||||
$$item = $name[$item];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the variables
|
||||
$cfg = Config::get('main');
|
||||
|
||||
if ($prefix === '' && $cfg->cookie_prefix !== '')
|
||||
{
|
||||
$prefix = $cfg->cookie_prefix;
|
||||
}
|
||||
|
||||
if ($domain == '' && $cfg->cookie_domain != '')
|
||||
{
|
||||
$domain = $cfg->cookie_domain;
|
||||
}
|
||||
|
||||
if ($path === '/' && $cfg->cookie_path !== '/')
|
||||
{
|
||||
$path = $cfg->cookie_path;
|
||||
}
|
||||
|
||||
if ($secure === FALSE && $cfg->cookie_secure === TRUE)
|
||||
{
|
||||
$secure = $cfg->cookie_secure;
|
||||
}
|
||||
|
||||
if ($httponly === FALSE && $cfg->cookie_httponly !== FALSE)
|
||||
{
|
||||
$httponly = $cfg->cookie_httponly;
|
||||
}
|
||||
|
||||
if ( ! is_numeric($expire))
|
||||
{
|
||||
$expire = time() - 86500;
|
||||
}
|
||||
else
|
||||
{
|
||||
$expire = ($expire > 0) ? time() + $expire : 0;
|
||||
}
|
||||
|
||||
setcookie($prefix.$name, $value, $expire, $path, $domain, $secure, $httponly);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Fetch the IP Address
|
||||
*
|
||||
* Determines and validates the visitor's IP address.
|
||||
*
|
||||
* @return string IP address
|
||||
*/
|
||||
public function ip_address()
|
||||
{
|
||||
if ($this->ip_address !== FALSE)
|
||||
{
|
||||
return $this->ip_address;
|
||||
}
|
||||
|
||||
$proxy_ips = Config::get('security')->proxy_ips;
|
||||
if ( ! empty($proxy_ips) && ! is_array($proxy_ips))
|
||||
{
|
||||
$proxy_ips = explode(',', str_replace(' ', '', $proxy_ips));
|
||||
}
|
||||
|
||||
$this->ip_address = $this->server('REMOTE_ADDR');
|
||||
|
||||
if ($proxy_ips)
|
||||
{
|
||||
foreach (array('HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'HTTP_X_CLIENT_IP', 'HTTP_X_CLUSTER_CLIENT_IP') as $header)
|
||||
{
|
||||
if (($spoof = $this->server($header)) !== NULL)
|
||||
{
|
||||
// Some proxies typically list the whole chain of IP
|
||||
// addresses through which the client has reached us.
|
||||
// e.g. client_ip, proxy_ip1, proxy_ip2, etc.
|
||||
sscanf($spoof, '%[^,]', $spoof);
|
||||
|
||||
if ( ! $this->valid_ip($spoof))
|
||||
{
|
||||
$spoof = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($spoof)
|
||||
{
|
||||
for ($i = 0, $c = count($proxy_ips); $i < $c; $i++)
|
||||
{
|
||||
// Check if we have an IP address or a subnet
|
||||
if (strpos($proxy_ips[$i], '/') === FALSE)
|
||||
{
|
||||
// An IP address (and not a subnet) is specified.
|
||||
// We can compare right away.
|
||||
if ($proxy_ips[$i] === $this->ip_address)
|
||||
{
|
||||
$this->ip_address = $spoof;
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// We have a subnet ... now the heavy lifting begins
|
||||
isset($separator) OR $separator = $this->valid_ip($this->ip_address, 'ipv6') ? ':' : '.';
|
||||
|
||||
// If the proxy entry doesn't match the IP protocol - skip it
|
||||
if (strpos($proxy_ips[$i], $separator) === FALSE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Convert the REMOTE_ADDR IP address to binary, if needed
|
||||
if ( ! isset($ip, $sprintf))
|
||||
{
|
||||
if ($separator === ':')
|
||||
{
|
||||
// Make sure we're have the "full" IPv6 format
|
||||
$ip = explode(':',
|
||||
str_replace('::',
|
||||
str_repeat(':', 9 - substr_count($this->ip_address, ':')),
|
||||
$this->ip_address
|
||||
)
|
||||
);
|
||||
|
||||
for ($j = 0; $j < 8; $j++)
|
||||
{
|
||||
$ip[$j] = intval($ip[$j], 16);
|
||||
}
|
||||
|
||||
$sprintf = '%016b%016b%016b%016b%016b%016b%016b%016b';
|
||||
}
|
||||
else
|
||||
{
|
||||
$ip = explode('.', $this->ip_address);
|
||||
$sprintf = '%08b%08b%08b%08b';
|
||||
}
|
||||
|
||||
$ip = vsprintf($sprintf, $ip);
|
||||
}
|
||||
|
||||
// Split the netmask length off the network address
|
||||
sscanf($proxy_ips[$i], '%[^/]/%d', $netaddr, $masklen);
|
||||
|
||||
// Again, an IPv6 address is most likely in a compressed form
|
||||
if ($separator === ':')
|
||||
{
|
||||
$netaddr = explode(':', str_replace('::', str_repeat(':', 9 - substr_count($netaddr, ':')), $netaddr));
|
||||
for ($i = 0; $i < 8; $i++)
|
||||
{
|
||||
$netaddr[$i] = intval($netaddr[$i], 16);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$netaddr = explode('.', $netaddr);
|
||||
}
|
||||
|
||||
// Convert to binary and finally compare
|
||||
if (strncmp($ip, vsprintf($sprintf, $netaddr), $masklen) === 0)
|
||||
{
|
||||
$this->ip_address = $spoof;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $this->valid_ip($this->ip_address))
|
||||
{
|
||||
return $this->ip_address = '0.0.0.0';
|
||||
}
|
||||
|
||||
return $this->ip_address;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Validate IP Address
|
||||
*
|
||||
* @param string $ip IP address
|
||||
* @param string $which IP protocol: 'ipv4' or 'ipv6'
|
||||
* @return bool
|
||||
*/
|
||||
public function valid_ip($ip, $which = '')
|
||||
{
|
||||
switch (strtolower($which))
|
||||
{
|
||||
case 'ipv4':
|
||||
$which = FILTER_FLAG_IPV4;
|
||||
break;
|
||||
case 'ipv6':
|
||||
$which = FILTER_FLAG_IPV6;
|
||||
break;
|
||||
default:
|
||||
$which = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
return (bool) filter_var($ip, FILTER_VALIDATE_IP, $which);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Fetch User Agent string
|
||||
*
|
||||
* @return string|null User Agent string or NULL if it doesn't exist
|
||||
*/
|
||||
public function user_agent($xss_clean = NULL)
|
||||
{
|
||||
return $this->_fetch_from_array($_SERVER, 'HTTP_USER_AGENT', $xss_clean);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Sanitize Globals
|
||||
*
|
||||
* Internal method serving for the following purposes:
|
||||
*
|
||||
* - Unsets $_GET data, if query strings are not enabled
|
||||
* - Cleans POST, COOKIE and SERVER data
|
||||
* - Standardizes newline characters to PHP_EOL
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function _sanitize_globals()
|
||||
{
|
||||
// Is $_GET data allowed? If not we'll set the $_GET to an empty array
|
||||
if ($this->_allow_get_array === FALSE)
|
||||
{
|
||||
$_GET = array();
|
||||
}
|
||||
elseif (is_array($_GET))
|
||||
{
|
||||
foreach ($_GET as $key => $val)
|
||||
{
|
||||
$_GET[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean $_POST Data
|
||||
if (is_array($_POST))
|
||||
{
|
||||
foreach ($_POST as $key => $val)
|
||||
{
|
||||
$_POST[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean $_COOKIE Data
|
||||
if (is_array($_COOKIE))
|
||||
{
|
||||
// Also get rid of specially treated cookies that might be set by a server
|
||||
// or silly application, that are of no use to a CI application anyway
|
||||
// but that when present will trip our 'Disallowed Key Characters' alarm
|
||||
// http://www.ietf.org/rfc/rfc2109.txt
|
||||
// note that the key names below are single quoted strings, and are not PHP variables
|
||||
unset(
|
||||
$_COOKIE['$Version'],
|
||||
$_COOKIE['$Path'],
|
||||
$_COOKIE['$Domain']
|
||||
);
|
||||
|
||||
foreach ($_COOKIE as $key => $val)
|
||||
{
|
||||
if (($cookie_key = $this->_clean_input_keys($key)) !== FALSE)
|
||||
{
|
||||
$_COOKIE[$cookie_key] = $this->_clean_input_data($val);
|
||||
}
|
||||
else
|
||||
{
|
||||
unset($_COOKIE[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sanitize PHP_SELF
|
||||
$_SERVER['PHP_SELF'] = strip_tags($_SERVER['PHP_SELF']);
|
||||
|
||||
Logger::logDebug('Global POST, GET and COOKIE data sanitized');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Clean Input Data
|
||||
*
|
||||
* Internal method that aids in escaping data and
|
||||
* standardizing newline characters to PHP_EOL.
|
||||
*
|
||||
* @param string|string[] $str Input string(s)
|
||||
* @return string
|
||||
*/
|
||||
protected function _clean_input_data($str)
|
||||
{
|
||||
if (is_array($str))
|
||||
{
|
||||
$new_array = array();
|
||||
foreach (array_keys($str) as $key)
|
||||
{
|
||||
$new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($str[$key]);
|
||||
}
|
||||
return $new_array;
|
||||
}
|
||||
|
||||
/* We strip slashes if magic quotes is on to keep things consistent
|
||||
|
||||
NOTE: In PHP 5.4 get_magic_quotes_gpc() will always return 0 and
|
||||
it will probably not exist in future versions at all.
|
||||
*/
|
||||
if ( ! Core::isPHP('5.4') && get_magic_quotes_gpc())
|
||||
{
|
||||
$str = stripslashes($str);
|
||||
}
|
||||
|
||||
// Clean UTF-8 if supported
|
||||
if (UTF8_ENABLED === TRUE)
|
||||
{
|
||||
$str = UTF8::clean_string($str);
|
||||
}
|
||||
|
||||
// Remove control characters
|
||||
$str = UTF8::remove_invisible_characters($str, FALSE);
|
||||
|
||||
// Standardize newlines if needed
|
||||
if ($this->_standardize_newlines === TRUE)
|
||||
{
|
||||
return preg_replace('/(?:\r\n|[\r\n])/', PHP_EOL, $str);
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Clean Keys
|
||||
*
|
||||
* Internal method that helps to prevent malicious users
|
||||
* from trying to exploit keys we make sure that keys are
|
||||
* only named with alpha-numeric text and a few other items.
|
||||
*
|
||||
* @param string $str Input string
|
||||
* @param bool $fatal Whether to terminate script exection
|
||||
* or to return FALSE if an invalid
|
||||
* key is encountered
|
||||
* @return string|bool
|
||||
*/
|
||||
protected function _clean_input_keys($str, $fatal = TRUE)
|
||||
{
|
||||
if ( ! preg_match('/^[a-z0-9:_\/|-]+$/i', $str))
|
||||
{
|
||||
if ($fatal === TRUE)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
set_status_header(503);
|
||||
echo 'Disallowed Key Characters.';
|
||||
exit(7); // EXIT_USER_INPUT
|
||||
}
|
||||
}
|
||||
|
||||
// Clean UTF-8 if supported
|
||||
if (UTF8_ENABLED === TRUE)
|
||||
{
|
||||
return UTF8::clean_string($str);
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Request Headers
|
||||
*
|
||||
* @param bool $xss_clean Whether to apply XSS filtering
|
||||
* @return array
|
||||
*/
|
||||
public function request_headers($xss_clean = FALSE)
|
||||
{
|
||||
// If header is already defined, return it immediately
|
||||
if ( ! empty($this->headers))
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
// In Apache, you can simply call apache_request_headers()
|
||||
if (function_exists('apache_request_headers'))
|
||||
{
|
||||
return $this->headers = apache_request_headers();
|
||||
}
|
||||
|
||||
$this->headers['Content-Type'] = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : @getenv('CONTENT_TYPE');
|
||||
|
||||
foreach ($_SERVER as $key => $val)
|
||||
{
|
||||
if (sscanf($key, 'HTTP_%s', $header) === 1)
|
||||
{
|
||||
// take SOME_HEADER and turn it into Some-Header
|
||||
$header = str_replace('_', ' ', strtolower($header));
|
||||
$header = str_replace(' ', '-', ucwords($header));
|
||||
|
||||
$this->headers[$header] = $this->_fetch_from_array($_SERVER, $key, $xss_clean);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Get Request Header
|
||||
*
|
||||
* Returns the value of a single member of the headers class member
|
||||
*
|
||||
* @param string $index Header name
|
||||
* @param bool $xss_clean Whether to apply XSS filtering
|
||||
* @return string|null The requested header on success or NULL on failure
|
||||
*/
|
||||
public function get_request_header($index, $xss_clean = FALSE)
|
||||
{
|
||||
static $headers;
|
||||
|
||||
if ( ! isset($headers))
|
||||
{
|
||||
empty($this->headers) && $this->request_headers();
|
||||
foreach ($this->headers as $key => $value)
|
||||
{
|
||||
$headers[strtolower($key)] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$index = strtolower($index);
|
||||
|
||||
if ( ! isset($headers[$index]))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ($xss_clean === TRUE)
|
||||
? Security::xss_clean($headers[$index])
|
||||
: $headers[$index];
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Is AJAX request?
|
||||
*
|
||||
* Test to see if a request contains the HTTP_X_REQUESTED_WITH header.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_ajax_request()
|
||||
{
|
||||
return ( ! empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Is CLI request?
|
||||
*
|
||||
* Test to see if a request was made from the command line.
|
||||
*
|
||||
* @deprecated 3.0.0 Use is_cli() instead
|
||||
* @return bool
|
||||
*/
|
||||
public function is_cli_request()
|
||||
{
|
||||
return (PHP_SAPI === 'cli' OR defined('STDIN'));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Get Request Method
|
||||
*
|
||||
* Return the request method
|
||||
*
|
||||
* @param bool $upper Whether to return in upper or lower case
|
||||
* (default: FALSE)
|
||||
* @return string
|
||||
*/
|
||||
public function method($upper = FALSE)
|
||||
{
|
||||
return ($upper)
|
||||
? strtoupper($this->server('REQUEST_METHOD'))
|
||||
: strtolower($this->server('REQUEST_METHOD'));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Magic __get()
|
||||
*
|
||||
* Allows read access to protected properties
|
||||
*
|
||||
* @param string $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
if ($name === 'raw_input_stream')
|
||||
{
|
||||
isset($this->_raw_input_stream) OR $this->_raw_input_stream = file_get_contents('php://input');
|
||||
return $this->_raw_input_stream;
|
||||
}
|
||||
elseif ($name === 'ip_address')
|
||||
{
|
||||
return $this->ip_address;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -34,6 +34,7 @@ namespace FuzeWorks;
|
|||
|
||||
/**
|
||||
* @todo add documentation
|
||||
* @todo Add configuration load if no config parameter provided
|
||||
*
|
||||
* @author Abel Hoogeveen <abel@techfuze.net>
|
||||
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
|
||||
|
|
|
@ -106,7 +106,7 @@ class Logger {
|
|||
*
|
||||
* Registers the error and exception handler, when required to do so by configuration
|
||||
*/
|
||||
public static function init() {
|
||||
public function __construct() {
|
||||
// Register the error handler
|
||||
if (Config::get('error')->error_reporting == true) {
|
||||
set_error_handler(array('\FuzeWorks\Logger', 'errorHandler'), E_ALL);
|
||||
|
@ -138,7 +138,6 @@ class Logger {
|
|||
|
||||
// Log it!
|
||||
self::errorHandler($errno, $errstr, $errfile, $errline);
|
||||
self::logInfo(self::backtrace());
|
||||
}
|
||||
|
||||
// And finally stop the Logging
|
||||
|
|
|
@ -383,16 +383,28 @@ class Modules
|
|||
{
|
||||
// First check if the caching engine can be used
|
||||
if ($cache)
|
||||
{
|
||||
{
|
||||
// Retrieve the cache if possible
|
||||
$cache = Libraries::getDriver('cache');
|
||||
$moduleRegister = $cache->$cachingMethod->get('moduleRegister');
|
||||
$eventRegister = $cache->$cachingMethod->get('eventRegister');
|
||||
$cacheData = $cache->$cachingMethod->get('moduleRegisters');
|
||||
|
||||
if ( ! is_bool($moduleRegister) && ! is_bool($eventRegister) )
|
||||
if ( ! is_bool($cacheData) )
|
||||
{
|
||||
// Separate the data
|
||||
$moduleRegister = $cacheData['moduleRegister'];
|
||||
$eventRegister = $cacheData['eventRegister'];
|
||||
$routeRegister = $cacheData['routeRegister'];
|
||||
$advertiseRegister = $cacheData['advertiseRegister'];
|
||||
|
||||
// And register it all
|
||||
Logger::newLevel("Loadig Module Headers from Cache");
|
||||
self::$register = $moduleRegister;
|
||||
Events::$register = $eventRegister;
|
||||
self::$advertiseRegister = $advertiseRegister;
|
||||
self::$module_routes = $routeRegister;
|
||||
foreach ($routeRegister as $route => $name) {
|
||||
Router::addRoute($route, array('\FuzeWorks\Modules', 'moduleCallable'), true);
|
||||
}
|
||||
Logger::stopLevel();
|
||||
return true;
|
||||
}
|
||||
|
@ -534,8 +546,13 @@ class Modules
|
|||
if ($cache)
|
||||
{
|
||||
Logger::log("Saving registry to cache");
|
||||
$cache->$cachingMethod->save('moduleRegister', $register, $cachingTime);
|
||||
$cache->$cachingMethod->save('eventRegister', $event_register, $cachingTime);
|
||||
$cacheData = array(
|
||||
'moduleRegister' => $register,
|
||||
'eventRegister' => $event_register,
|
||||
'routeRegister' => self::$module_routes,
|
||||
'advertiseRegister' => self::$advertiseRegister
|
||||
);
|
||||
$cache->$cachingMethod->save('moduleRegisters', $cacheData, $cachingTime);
|
||||
}
|
||||
|
||||
// And apply the registers to their dedicate location
|
||||
|
|
|
@ -0,0 +1,808 @@
|
|||
<?php
|
||||
/**
|
||||
* FuzeWorks.
|
||||
*
|
||||
* The FuzeWorks MVC PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2015 TechFuze
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
|
||||
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
|
||||
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
|
||||
*
|
||||
* @link http://fuzeworks.techfuze.net
|
||||
* @since Version 0.0.1
|
||||
*
|
||||
* @version Version 0.0.1
|
||||
*/
|
||||
|
||||
namespace FuzeWorks;
|
||||
|
||||
/**
|
||||
* Output Class
|
||||
*
|
||||
* Responsible for sending final output to the browser.
|
||||
*
|
||||
* @author EllisLab Dev Team
|
||||
* @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
|
||||
* @copyright Copyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)
|
||||
*/
|
||||
class Output {
|
||||
|
||||
/**
|
||||
* Final output string
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $final_output;
|
||||
|
||||
/**
|
||||
* Cache expiration time
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $cache_expiration = 0;
|
||||
|
||||
/**
|
||||
* List of server headers
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $headers = array();
|
||||
|
||||
/**
|
||||
* List of mime types
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $mimes = array();
|
||||
|
||||
/**
|
||||
* Mime-type for the current page
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $mime_type = 'text/html';
|
||||
|
||||
/**
|
||||
* Enable Profiler flag
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $enable_profiler = FALSE;
|
||||
|
||||
/**
|
||||
* php.ini zlib.output_compression flag
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $_zlib_oc = FALSE;
|
||||
|
||||
/**
|
||||
* CI output compression flag
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $_compress_output = FALSE;
|
||||
|
||||
/**
|
||||
* List of profiler sections
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_profiler_sections = array();
|
||||
|
||||
/**
|
||||
* Parse markers flag
|
||||
*
|
||||
* Whether or not to parse variables like {elapsed_time} and {memory_usage}.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $parse_exec_vars = TRUE;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* Determines whether zLib output compression will be used.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->_zlib_oc = (bool) ini_get('zlib.output_compression');
|
||||
$this->_compress_output = (
|
||||
$this->_zlib_oc === FALSE
|
||||
&& Config::get('main')->compress_output === TRUE
|
||||
&& extension_loaded('zlib')
|
||||
);
|
||||
|
||||
// Get mime types for later
|
||||
$this->mimes = Config::get('mimes')->toArray();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Get Output
|
||||
*
|
||||
* Returns the current output string.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_output()
|
||||
{
|
||||
return $this->final_output;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set Output
|
||||
*
|
||||
* Sets the output string.
|
||||
*
|
||||
* @param string $output Output data
|
||||
* @return CI_Output
|
||||
*/
|
||||
public function set_output($output)
|
||||
{
|
||||
$this->final_output = $output;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Append Output
|
||||
*
|
||||
* Appends data onto the output string.
|
||||
*
|
||||
* @param string $output Data to append
|
||||
* @return CI_Output
|
||||
*/
|
||||
public function append_output($output)
|
||||
{
|
||||
$this->final_output .= $output;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set Header
|
||||
*
|
||||
* Lets you set a server header which will be sent with the final output.
|
||||
*
|
||||
* Note: If a file is cached, headers will not be sent.
|
||||
* @todo We need to figure out how to permit headers to be cached.
|
||||
*
|
||||
* @param string $header Header
|
||||
* @param bool $replace Whether to replace the old header value, if already set
|
||||
* @return CI_Output
|
||||
*/
|
||||
public function set_header($header, $replace = TRUE)
|
||||
{
|
||||
// If zlib.output_compression is enabled it will compress the output,
|
||||
// but it will not modify the content-length header to compensate for
|
||||
// the reduction, causing the browser to hang waiting for more data.
|
||||
// We'll just skip content-length in those cases.
|
||||
if ($this->_zlib_oc && strncasecmp($header, 'content-length', 14) === 0)
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->headers[] = array($header, $replace);
|
||||
return $this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set Content-Type Header
|
||||
*
|
||||
* @param string $mime_type Extension of the file we're outputting
|
||||
* @param string $charset Character set (default: NULL)
|
||||
* @return CI_Output
|
||||
*/
|
||||
public function set_content_type($mime_type, $charset = NULL)
|
||||
{
|
||||
if (strpos($mime_type, '/') === FALSE)
|
||||
{
|
||||
$extension = ltrim($mime_type, '.');
|
||||
|
||||
// Is this extension supported?
|
||||
if (isset($this->mimes[$extension]))
|
||||
{
|
||||
$mime_type =& $this->mimes[$extension];
|
||||
|
||||
if (is_array($mime_type))
|
||||
{
|
||||
$mime_type = current($mime_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->mime_type = $mime_type;
|
||||
|
||||
if (empty($charset))
|
||||
{
|
||||
$charset = Config::get('main')->charset;
|
||||
}
|
||||
|
||||
$header = 'Content-Type: '.$mime_type
|
||||
.(empty($charset) ? '' : '; charset='.$charset);
|
||||
|
||||
$this->headers[] = array($header, TRUE);
|
||||
return $this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Get Current Content-Type Header
|
||||
*
|
||||
* @return string 'text/html', if not already set
|
||||
*/
|
||||
public function get_content_type()
|
||||
{
|
||||
for ($i = 0, $c = count($this->headers); $i < $c; $i++)
|
||||
{
|
||||
if (sscanf($this->headers[$i][0], 'Content-Type: %[^;]', $content_type) === 1)
|
||||
{
|
||||
return $content_type;
|
||||
}
|
||||
}
|
||||
|
||||
return 'text/html';
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Get Header
|
||||
*
|
||||
* @param string $header_name
|
||||
* @return string
|
||||
*/
|
||||
public function get_header($header)
|
||||
{
|
||||
// Combine headers already sent with our batched headers
|
||||
$headers = array_merge(
|
||||
// We only need [x][0] from our multi-dimensional array
|
||||
array_map('array_shift', $this->headers),
|
||||
headers_list()
|
||||
);
|
||||
|
||||
if (empty($headers) OR empty($header))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for ($i = 0, $c = count($headers); $i < $c; $i++)
|
||||
{
|
||||
if (strncasecmp($header, $headers[$i], $l = strlen($header)) === 0)
|
||||
{
|
||||
return trim(substr($headers[$i], $l+1));
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set HTTP Status Header
|
||||
*
|
||||
* As of version 1.7.2, this is an alias for common function
|
||||
* set_status_header().
|
||||
*
|
||||
* @param int $code Status code (default: 200)
|
||||
* @param string $text Optional message
|
||||
* @todo Fix this
|
||||
* @return CI_Output
|
||||
*/
|
||||
public function set_status_header($code = 200, $text = '')
|
||||
{
|
||||
return $this;
|
||||
set_status_header($code, $text);
|
||||
return $this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Enable/disable Profiler
|
||||
*
|
||||
* @param bool $val TRUE to enable or FALSE to disable
|
||||
* @return CI_Output
|
||||
*/
|
||||
public function enable_profiler($val = TRUE)
|
||||
{
|
||||
$this->enable_profiler = is_bool($val) ? $val : TRUE;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set Profiler Sections
|
||||
*
|
||||
* Allows override of default/config settings for
|
||||
* Profiler section display.
|
||||
*
|
||||
* @param array $sections Profiler sections
|
||||
* @return CI_Output
|
||||
*/
|
||||
public function set_profiler_sections($sections)
|
||||
{
|
||||
if (isset($sections['query_toggle_count']))
|
||||
{
|
||||
$this->_profiler_sections['query_toggle_count'] = (int) $sections['query_toggle_count'];
|
||||
unset($sections['query_toggle_count']);
|
||||
}
|
||||
|
||||
foreach ($sections as $section => $enable)
|
||||
{
|
||||
$this->_profiler_sections[$section] = ($enable !== FALSE);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set Cache
|
||||
*
|
||||
* @param int $time Cache expiration time in minutes
|
||||
* @return CI_Output
|
||||
*/
|
||||
public function cache($time)
|
||||
{
|
||||
$this->cache_expiration = is_numeric($time) ? $time : 0;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Display Output
|
||||
*
|
||||
* Processes and sends finalized output data to the browser along
|
||||
* with any server headers and profile data. It also stops benchmark
|
||||
* timers so the page rendering speed and memory usage can be shown.
|
||||
*
|
||||
* Note: All "view" data is automatically put into $this->final_output
|
||||
* by controller class.
|
||||
*
|
||||
* @uses CI_Output::$final_output
|
||||
* @param string $output Output data override
|
||||
* @return void
|
||||
* @todo Implement cache
|
||||
*/
|
||||
public function _display($output = '')
|
||||
{
|
||||
// Note: We use load_class() because we can't use $CI =& get_instance()
|
||||
// since this function is sometimes called by the caching mechanism,
|
||||
// which happens before the CI super object is available.
|
||||
$BM =& load_class('Benchmark', 'core');
|
||||
$CFG =& load_class('Config', 'core');
|
||||
|
||||
// Grab the super object if we can.
|
||||
if (class_exists('CI_Controller', FALSE))
|
||||
{
|
||||
$CI =& get_instance();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// Set the output data
|
||||
if ($output === '')
|
||||
{
|
||||
$output =& $this->final_output;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// Do we need to write a cache file? Only if the controller does not have its
|
||||
// own _output() method and we are not dealing with a cache file, which we
|
||||
// can determine by the existence of the $CI object above
|
||||
//if ($this->cache_expiration > 0 && isset($CI) && ! method_exists($CI, '_output'))
|
||||
//{
|
||||
// $this->_write_cache($output);
|
||||
//}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// Parse out the elapsed time and memory usage,
|
||||
// then swap the pseudo-variables with the data
|
||||
|
||||
$elapsed = Logger::elapsedTime('total_execution_time_start', 'total_execution_time_end');
|
||||
|
||||
if ($this->parse_exec_vars === TRUE)
|
||||
{
|
||||
$memory = round(memory_get_usage() / 1024 / 1024, 2).'MB';
|
||||
$output = str_replace(array('{elapsed_time}', '{memory_usage}'), array($elapsed, $memory), $output);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// Is compression requested?
|
||||
//if (isset($CI) // This means that we're not serving a cache file, if we were, it would already be compressed
|
||||
// && $this->_compress_output === TRUE
|
||||
// && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE)
|
||||
//{
|
||||
// ob_start('ob_gzhandler');
|
||||
//}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// Are there any server headers to send?
|
||||
if (count($this->headers) > 0)
|
||||
{
|
||||
foreach ($this->headers as $header)
|
||||
{
|
||||
@header($header[0], $header[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// Does the $CI object exist?
|
||||
// If not we know we are dealing with a cache file so we'll
|
||||
// simply echo out the data and exit.
|
||||
if ( ! isset($CI))
|
||||
{
|
||||
if ($this->_compress_output === TRUE)
|
||||
{
|
||||
if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE)
|
||||
{
|
||||
header('Content-Encoding: gzip');
|
||||
header('Content-Length: '.strlen($output));
|
||||
}
|
||||
else
|
||||
{
|
||||
// User agent doesn't support gzip compression,
|
||||
// so we'll have to decompress our cache
|
||||
$output = gzinflate(substr($output, 10, -8));
|
||||
}
|
||||
}
|
||||
|
||||
echo $output;
|
||||
Logger::log('Final output sent to browser');
|
||||
Logger::logDebug('Total execution time: '.$elapsed);
|
||||
return;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
// Do we need to generate profile data?
|
||||
// If so, load the Profile class and run it.
|
||||
/*if ($this->enable_profiler === TRUE)
|
||||
{
|
||||
$CI->load->library('profiler');
|
||||
if ( ! empty($this->_profiler_sections))
|
||||
{
|
||||
$CI->profiler->set_sections($this->_profiler_sections);
|
||||
}
|
||||
|
||||
// If the output data contains closing </body> and </html> tags
|
||||
// we will remove them and add them back after we insert the profile data
|
||||
$output = preg_replace('|</body>.*?</html>|is', '', $output, -1, $count).$CI->profiler->run();
|
||||
if ($count > 0)
|
||||
{
|
||||
$output .= '</body></html>';
|
||||
}
|
||||
}
|
||||
|
||||
// Does the controller contain a function named _output()?
|
||||
// If so send the output there. Otherwise, echo it.
|
||||
if (method_exists($CI, '_output'))
|
||||
{
|
||||
$CI->_output($output);
|
||||
}
|
||||
else
|
||||
{
|
||||
echo $output; // Send it to the browser!
|
||||
}*/
|
||||
|
||||
Logger::log('Final output sent to browser');
|
||||
Logger::logDebug('Total execution time: '.$elapsed);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Write Cache
|
||||
*
|
||||
* @param string $output Output data to cache
|
||||
* @todo Implement cache
|
||||
* @return void
|
||||
*/
|
||||
public function _write_cache($output)
|
||||
{
|
||||
Logger::logWarning("Cache is not implemented as of yet");
|
||||
return;
|
||||
|
||||
|
||||
$CI =& get_instance();
|
||||
$path = $CI->config->item('cache_path');
|
||||
$cache_path = ($path === '') ? APPPATH.'cache/' : $path;
|
||||
|
||||
if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path))
|
||||
{
|
||||
log_message('error', 'Unable to write cache file: '.$cache_path);
|
||||
return;
|
||||
}
|
||||
|
||||
$uri = $CI->config->item('base_url')
|
||||
.$CI->config->item('index_page')
|
||||
.$CI->uri->uri_string();
|
||||
|
||||
if (($cache_query_string = $CI->config->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))
|
||||
{
|
||||
if (is_array($cache_query_string))
|
||||
{
|
||||
$uri .= '?'.http_build_query(array_intersect_key($_GET, array_flip($cache_query_string)));
|
||||
}
|
||||
else
|
||||
{
|
||||
$uri .= '?'.$_SERVER['QUERY_STRING'];
|
||||
}
|
||||
}
|
||||
|
||||
$cache_path .= md5($uri);
|
||||
|
||||
if ( ! $fp = @fopen($cache_path, 'w+b'))
|
||||
{
|
||||
log_message('error', 'Unable to write cache file: '.$cache_path);
|
||||
return;
|
||||
}
|
||||
|
||||
if (flock($fp, LOCK_EX))
|
||||
{
|
||||
// If output compression is enabled, compress the cache
|
||||
// itself, so that we don't have to do that each time
|
||||
// we're serving it
|
||||
if ($this->_compress_output === TRUE)
|
||||
{
|
||||
$output = gzencode($output);
|
||||
|
||||
if ($this->get_header('content-type') === NULL)
|
||||
{
|
||||
$this->set_content_type($this->mime_type);
|
||||
}
|
||||
}
|
||||
|
||||
$expire = time() + ($this->cache_expiration * 60);
|
||||
|
||||
// Put together our serialized info.
|
||||
$cache_info = serialize(array(
|
||||
'expire' => $expire,
|
||||
'headers' => $this->headers
|
||||
));
|
||||
|
||||
$output = $cache_info.'ENDCI--->'.$output;
|
||||
|
||||
for ($written = 0, $length = strlen($output); $written < $length; $written += $result)
|
||||
{
|
||||
if (($result = fwrite($fp, substr($output, $written))) === FALSE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
flock($fp, LOCK_UN);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_message('error', 'Unable to secure a file lock for file at: '.$cache_path);
|
||||
return;
|
||||
}
|
||||
|
||||
fclose($fp);
|
||||
|
||||
if (is_int($result))
|
||||
{
|
||||
chmod($cache_path, 0640);
|
||||
log_message('debug', 'Cache file written: '.$cache_path);
|
||||
|
||||
// Send HTTP cache-control headers to browser to match file cache settings.
|
||||
$this->set_cache_header($_SERVER['REQUEST_TIME'], $expire);
|
||||
}
|
||||
else
|
||||
{
|
||||
@unlink($cache_path);
|
||||
log_message('error', 'Unable to write the complete cache content at: '.$cache_path);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Update/serve cached output
|
||||
*
|
||||
* @uses CI_Config
|
||||
* @uses CI_URI
|
||||
* @todo Implement
|
||||
*
|
||||
* @param object &$CFG CI_Config class instance
|
||||
* @param object &$URI CI_URI class instance
|
||||
* @return bool TRUE on success or FALSE on failure
|
||||
*/
|
||||
public function _display_cache(&$CFG, &$URI)
|
||||
{
|
||||
Logger::logWarning("Cache is not implemented as of yet");
|
||||
return false;
|
||||
|
||||
|
||||
$cache_path = ($CFG->item('cache_path') === '') ? APPPATH.'cache/' : $CFG->item('cache_path');
|
||||
|
||||
// Build the file path. The file name is an MD5 hash of the full URI
|
||||
$uri = $CFG->item('base_url').$CFG->item('index_page').$URI->uri_string;
|
||||
|
||||
if (($cache_query_string = $CFG->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))
|
||||
{
|
||||
if (is_array($cache_query_string))
|
||||
{
|
||||
$uri .= '?'.http_build_query(array_intersect_key($_GET, array_flip($cache_query_string)));
|
||||
}
|
||||
else
|
||||
{
|
||||
$uri .= '?'.$_SERVER['QUERY_STRING'];
|
||||
}
|
||||
}
|
||||
|
||||
$filepath = $cache_path.md5($uri);
|
||||
|
||||
if ( ! file_exists($filepath) OR ! $fp = @fopen($filepath, 'rb'))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
flock($fp, LOCK_SH);
|
||||
|
||||
$cache = (filesize($filepath) > 0) ? fread($fp, filesize($filepath)) : '';
|
||||
|
||||
flock($fp, LOCK_UN);
|
||||
fclose($fp);
|
||||
|
||||
// Look for embedded serialized file info.
|
||||
if ( ! preg_match('/^(.*)ENDCI--->/', $cache, $match))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$cache_info = unserialize($match[1]);
|
||||
$expire = $cache_info['expire'];
|
||||
|
||||
$last_modified = filemtime($filepath);
|
||||
|
||||
// Has the file expired?
|
||||
if ($_SERVER['REQUEST_TIME'] >= $expire && is_really_writable($cache_path))
|
||||
{
|
||||
// If so we'll delete it.
|
||||
@unlink($filepath);
|
||||
log_message('debug', 'Cache file has expired. File deleted.');
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Or else send the HTTP cache control headers.
|
||||
$this->set_cache_header($last_modified, $expire);
|
||||
}
|
||||
|
||||
// Add headers from cache file.
|
||||
foreach ($cache_info['headers'] as $header)
|
||||
{
|
||||
$this->set_header($header[0], $header[1]);
|
||||
}
|
||||
|
||||
// Display the cache
|
||||
$this->_display(substr($cache, strlen($match[0])));
|
||||
log_message('debug', 'Cache file is current. Sending it to browser.');
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Delete cache
|
||||
*
|
||||
* @param string $uri URI string
|
||||
* @return bool
|
||||
* @todo Implement
|
||||
*/
|
||||
public function delete_cache($uri = '')
|
||||
{
|
||||
Logger::logWarning("Caching is not implemented as of yet");
|
||||
return false;
|
||||
|
||||
$CI =& get_instance();
|
||||
$cache_path = $CI->config->item('cache_path');
|
||||
if ($cache_path === '')
|
||||
{
|
||||
$cache_path = APPPATH.'cache/';
|
||||
}
|
||||
|
||||
if ( ! is_dir($cache_path))
|
||||
{
|
||||
log_message('error', 'Unable to find cache path: '.$cache_path);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (empty($uri))
|
||||
{
|
||||
$uri = $CI->uri->uri_string();
|
||||
|
||||
if (($cache_query_string = $CI->config->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))
|
||||
{
|
||||
if (is_array($cache_query_string))
|
||||
{
|
||||
$uri .= '?'.http_build_query(array_intersect_key($_GET, array_flip($cache_query_string)));
|
||||
}
|
||||
else
|
||||
{
|
||||
$uri .= '?'.$_SERVER['QUERY_STRING'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$cache_path .= md5($CI->config->item('base_url').$CI->config->item('index_page').ltrim($uri, '/'));
|
||||
|
||||
if ( ! @unlink($cache_path))
|
||||
{
|
||||
log_message('error', 'Unable to delete cache file for '.$uri);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set Cache Header
|
||||
*
|
||||
* Set the HTTP headers to match the server-side file cache settings
|
||||
* in order to reduce bandwidth.
|
||||
*
|
||||
* @param int $last_modified Timestamp of when the page was last modified
|
||||
* @param int $expiration Timestamp of when should the requested page expire from cache
|
||||
* @return void
|
||||
*/
|
||||
public function set_cache_header($last_modified, $expiration)
|
||||
{
|
||||
$max_age = $expiration - $_SERVER['REQUEST_TIME'];
|
||||
|
||||
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $last_modified <= strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']))
|
||||
{
|
||||
$this->set_status_header(304);
|
||||
exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
header('Pragma: public');
|
||||
header('Cache-Control: max-age='.$max_age.', public');
|
||||
header('Expires: '.gmdate('D, d M Y H:i:s', $expiration).' GMT');
|
||||
header('Last-modified: '.gmdate('D, d M Y H:i:s', $last_modified).' GMT');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -106,7 +106,7 @@ class Router
|
|||
/**
|
||||
* The constructor adds the default route to the routing table.
|
||||
*/
|
||||
public static function init()
|
||||
public function __construct()
|
||||
{
|
||||
foreach (Config::get('routes') as $route => $callable) {
|
||||
if (is_int($route)) {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,644 @@
|
|||
<?php
|
||||
/**
|
||||
* FuzeWorks.
|
||||
*
|
||||
* The FuzeWorks MVC PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2015 TechFuze
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
|
||||
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
|
||||
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
|
||||
*
|
||||
* @link http://fuzeworks.techfuze.net
|
||||
* @since Version 0.0.1
|
||||
*
|
||||
* @version Version 0.0.1
|
||||
*/
|
||||
|
||||
namespace FuzeWorks;
|
||||
|
||||
/**
|
||||
* URI Class
|
||||
*
|
||||
* Parses URIs and determines routing
|
||||
*
|
||||
* @author EllisLab Dev Team
|
||||
* @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
|
||||
* @copyright Copyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)
|
||||
*/
|
||||
class URI {
|
||||
|
||||
/**
|
||||
* List of cached URI segments
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $keyval = array();
|
||||
|
||||
/**
|
||||
* Current URI string
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $uri_string = '';
|
||||
|
||||
/**
|
||||
* List of URI segments
|
||||
*
|
||||
* Starts at 1 instead of 0.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $segments = array();
|
||||
|
||||
/**
|
||||
* List of routed URI segments
|
||||
*
|
||||
* Starts at 1 instead of 0.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $rsegments = array();
|
||||
|
||||
/**
|
||||
* Permitted URI chars
|
||||
*
|
||||
* PCRE character group allowed in URI segments
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected static $_permitted_uri_chars;
|
||||
|
||||
/**
|
||||
* The configuration of this class
|
||||
*
|
||||
* @var ConfigORM
|
||||
*/
|
||||
private static $config;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
self::$config = Config::get('routing');
|
||||
|
||||
// If query strings are enabled, we don't need to parse any segments.
|
||||
// However, they don't make sense under CLI.
|
||||
if ((PHP_SAPI === 'cli' OR defined('STDIN')) OR self::$config->enable_query_strings !== TRUE)
|
||||
{
|
||||
self::$_permitted_uri_chars = self::$config->permitted_uri_chars;
|
||||
|
||||
// If it's a CLI request, ignore the configuration
|
||||
if ( (PHP_SAPI === 'cli' OR defined('STDIN')) )
|
||||
{
|
||||
$uri = self::_parse_argv();
|
||||
}
|
||||
else
|
||||
{
|
||||
$protocol = self::$config->uri_protocol;
|
||||
empty($protocol) && $protocol = 'REQUEST_URI';
|
||||
|
||||
switch ($protocol)
|
||||
{
|
||||
case 'AUTO': // For BC purposes only
|
||||
case 'REQUEST_URI':
|
||||
$uri = self::_parse_request_uri();
|
||||
break;
|
||||
case 'QUERY_STRING':
|
||||
$uri = self::_parse_query_string();
|
||||
break;
|
||||
case 'PATH_INFO':
|
||||
default:
|
||||
$uri = isset($_SERVER[$protocol])
|
||||
? $_SERVER[$protocol]
|
||||
: self::_parse_request_uri();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
self::_set_uri_string($uri);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set URI String
|
||||
*
|
||||
* @param string $str
|
||||
* @return void
|
||||
*/
|
||||
protected static function _set_uri_string($str)
|
||||
{
|
||||
// Filter out control characters and trim slashes
|
||||
self::$uri_string = trim(Utf8::remove_invisible_characters($str, FALSE), '/');
|
||||
|
||||
if (self::$uri_string !== '')
|
||||
{
|
||||
// Remove the URL suffix, if present
|
||||
if (($suffix = (string) self::$config->url_suffix) !== '')
|
||||
{
|
||||
$slen = strlen($suffix);
|
||||
|
||||
if (substr(self::$uri_string, -$slen) === $suffix)
|
||||
{
|
||||
self::$uri_string = substr(self::$uri_string, 0, -$slen);
|
||||
}
|
||||
}
|
||||
|
||||
self::$segments[0] = NULL;
|
||||
// Populate the segments array
|
||||
foreach (explode('/', trim(self::$uri_string, '/')) as $val)
|
||||
{
|
||||
$val = trim($val);
|
||||
// Filter segments for security
|
||||
self::filter_uri($val);
|
||||
|
||||
if ($val !== '')
|
||||
{
|
||||
self::$segments[] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
unset(self::$segments[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Parse REQUEST_URI
|
||||
*
|
||||
* Will parse REQUEST_URI and automatically detect the URI from it,
|
||||
* while fixing the query string if necessary.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function _parse_request_uri()
|
||||
{
|
||||
if ( ! isset($_SERVER['REQUEST_URI'], $_SERVER['SCRIPT_NAME']))
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
// parse_url() returns false if no host is present, but the path or query string
|
||||
// contains a colon followed by a number
|
||||
$uri = parse_url('http://dummy'.$_SERVER['REQUEST_URI']);
|
||||
$query = isset($uri['query']) ? $uri['query'] : '';
|
||||
$uri = isset($uri['path']) ? $uri['path'] : '';
|
||||
|
||||
if (isset($_SERVER['SCRIPT_NAME'][0]))
|
||||
{
|
||||
if (strpos($uri, $_SERVER['SCRIPT_NAME']) === 0)
|
||||
{
|
||||
$uri = (string) substr($uri, strlen($_SERVER['SCRIPT_NAME']));
|
||||
}
|
||||
elseif (strpos($uri, dirname($_SERVER['SCRIPT_NAME'])) === 0)
|
||||
{
|
||||
$uri = (string) substr($uri, strlen(dirname($_SERVER['SCRIPT_NAME'])));
|
||||
}
|
||||
}
|
||||
|
||||
// This section ensures that even on servers that require the URI to be in the query string (Nginx) a correct
|
||||
// URI is found, and also fixes the QUERY_STRING server var and $_GET array.
|
||||
if (trim($uri, '/') === '' && strncmp($query, '/', 1) === 0)
|
||||
{
|
||||
$query = explode('?', $query, 2);
|
||||
$uri = $query[0];
|
||||
$_SERVER['QUERY_STRING'] = isset($query[1]) ? $query[1] : '';
|
||||
}
|
||||
else
|
||||
{
|
||||
$_SERVER['QUERY_STRING'] = $query;
|
||||
}
|
||||
|
||||
parse_str($_SERVER['QUERY_STRING'], $_GET);
|
||||
|
||||
if ($uri === '/' OR $uri === '')
|
||||
{
|
||||
return '/';
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Do some final cleaning of the URI and return it
|
||||
return self::_remove_relative_directory($uri);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Parse QUERY_STRING
|
||||
*
|
||||
* Will parse QUERY_STRING and automatically detect the URI from it.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function _parse_query_string()
|
||||
{
|
||||
$uri = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING');
|
||||
|
||||
if (trim($uri, '/') === '')
|
||||
{
|
||||
return '';
|
||||
}
|
||||
elseif (strncmp($uri, '/', 1) === 0)
|
||||
{
|
||||
$uri = explode('?', $uri, 2);
|
||||
$_SERVER['QUERY_STRING'] = isset($uri[1]) ? $uri[1] : '';
|
||||
$uri = $uri[0];
|
||||
}
|
||||
|
||||
parse_str($_SERVER['QUERY_STRING'], $_GET);
|
||||
|
||||
return self::_remove_relative_directory($uri);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Parse CLI arguments
|
||||
*
|
||||
* Take each command line argument and assume it is a URI segment.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function _parse_argv()
|
||||
{
|
||||
$args = array_slice($_SERVER['argv'], 1);
|
||||
return $args ? implode('/', $args) : '';
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Remove relative directory (../) and multi slashes (///)
|
||||
*
|
||||
* Do some final cleaning of the URI and return it, currently only used in self::_parse_request_uri()
|
||||
*
|
||||
* @param string $uri
|
||||
* @return string
|
||||
*/
|
||||
protected static function _remove_relative_directory($uri)
|
||||
{
|
||||
$uris = array();
|
||||
$tok = strtok($uri, '/');
|
||||
while ($tok !== FALSE)
|
||||
{
|
||||
if (( ! empty($tok) OR $tok === '0') && $tok !== '..')
|
||||
{
|
||||
$uris[] = $tok;
|
||||
}
|
||||
$tok = strtok('/');
|
||||
}
|
||||
|
||||
return implode('/', $uris);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Filter URI
|
||||
*
|
||||
* Filters segments for malicious characters.
|
||||
*
|
||||
* @param string $str
|
||||
* @return void
|
||||
*/
|
||||
public static function filter_uri(&$str)
|
||||
{
|
||||
if ( ! empty($str) && ! empty(self::$_permitted_uri_chars) && ! preg_match('/^['.self::$_permitted_uri_chars.']+$/i'.(UTF8_ENABLED ? 'u' : ''), $str))
|
||||
{
|
||||
throw new UriException('The URI you submitted has disallowed characters.', 1);
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Fetch URI Segment
|
||||
*
|
||||
* @see CI_URI::$segments
|
||||
* @param int $n Index
|
||||
* @param mixed $no_result What to return if the segment index is not found
|
||||
* @return mixed
|
||||
*/
|
||||
public static function segment($n, $no_result = NULL)
|
||||
{
|
||||
return isset(self::$segments[$n]) ? self::$segments[$n] : $no_result;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Fetch URI "routed" Segment
|
||||
*
|
||||
* Returns the re-routed URI segment (assuming routing rules are used)
|
||||
* based on the index provided. If there is no routing, will return
|
||||
* the same result as CI_URI::segment().
|
||||
*
|
||||
* @see CI_URI::$rsegments
|
||||
* @see CI_URI::segment()
|
||||
* @param int $n Index
|
||||
* @param mixed $no_result What to return if the segment index is not found
|
||||
* @return mixed
|
||||
*/
|
||||
public static function rsegment($n, $no_result = NULL)
|
||||
{
|
||||
return isset(self::$rsegments[$n]) ? self::$rsegments[$n] : $no_result;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* URI to assoc
|
||||
*
|
||||
* Generates an associative array of URI data starting at the supplied
|
||||
* segment index. For example, if this is your URI:
|
||||
*
|
||||
* example.com/user/search/name/joe/location/UK/gender/male
|
||||
*
|
||||
* You can use this method to generate an array with this prototype:
|
||||
*
|
||||
* array (
|
||||
* name => joe
|
||||
* location => UK
|
||||
* gender => male
|
||||
* )
|
||||
*
|
||||
* @param int $n Index (default: 3)
|
||||
* @param array $default Default values
|
||||
* @return array
|
||||
*/
|
||||
public static function uri_to_assoc($n = 3, $default = array())
|
||||
{
|
||||
return self::_uri_to_assoc($n, $default, 'segment');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Routed URI to assoc
|
||||
*
|
||||
* Identical to CI_URI::uri_to_assoc(), only it uses the re-routed
|
||||
* segment array.
|
||||
*
|
||||
* @see CI_URI::uri_to_assoc()
|
||||
* @param int $n Index (default: 3)
|
||||
* @param array $default Default values
|
||||
* @return array
|
||||
*/
|
||||
public static function ruri_to_assoc($n = 3, $default = array())
|
||||
{
|
||||
return self::_uri_to_assoc($n, $default, 'rsegment');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Internal URI-to-assoc
|
||||
*
|
||||
* Generates a key/value pair from the URI string or re-routed URI string.
|
||||
*
|
||||
* @used-by CI_URI::uri_to_assoc()
|
||||
* @used-by CI_URI::ruri_to_assoc()
|
||||
* @param int $n Index (default: 3)
|
||||
* @param array $default Default values
|
||||
* @param string $which Array name ('segment' or 'rsegment')
|
||||
* @return array
|
||||
*/
|
||||
protected static function _uri_to_assoc($n = 3, $default = array(), $which = 'segment')
|
||||
{
|
||||
if ( ! is_numeric($n))
|
||||
{
|
||||
return $default;
|
||||
}
|
||||
|
||||
if (isset(self::$keyval[$which], self::$keyval[$which][$n]))
|
||||
{
|
||||
return self::$keyval[$which][$n];
|
||||
}
|
||||
|
||||
$total_segments = "total_{$which}s";
|
||||
$segment_array = "{$which}_array";
|
||||
|
||||
if (self::$total_segments() < $n)
|
||||
{
|
||||
return (count($default) === 0)
|
||||
? array()
|
||||
: array_fill_keys($default, NULL);
|
||||
}
|
||||
|
||||
$segments = array_slice(self::$segment_array(), ($n - 1));
|
||||
$i = 0;
|
||||
$lastval = '';
|
||||
$retval = array();
|
||||
foreach ($segments as $seg)
|
||||
{
|
||||
if ($i % 2)
|
||||
{
|
||||
$retval[$lastval] = $seg;
|
||||
}
|
||||
else
|
||||
{
|
||||
$retval[$seg] = NULL;
|
||||
$lastval = $seg;
|
||||
}
|
||||
|
||||
$i++;
|
||||
}
|
||||
|
||||
if (count($default) > 0)
|
||||
{
|
||||
foreach ($default as $val)
|
||||
{
|
||||
if ( ! array_key_exists($val, $retval))
|
||||
{
|
||||
$retval[$val] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cache the array for reuse
|
||||
isset(self::$keyval[$which]) OR self::$keyval[$which] = array();
|
||||
self::$keyval[$which][$n] = $retval;
|
||||
return $retval;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Assoc to URI
|
||||
*
|
||||
* Generates a URI string from an associative array.
|
||||
*
|
||||
* @param array $array Input array of key/value pairs
|
||||
* @return string URI string
|
||||
*/
|
||||
public static function assoc_to_uri($array)
|
||||
{
|
||||
$temp = array();
|
||||
foreach ((array) $array as $key => $val)
|
||||
{
|
||||
$temp[] = $key;
|
||||
$temp[] = $val;
|
||||
}
|
||||
|
||||
return implode('/', $temp);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Slash segment
|
||||
*
|
||||
* Fetches an URI segment with a slash.
|
||||
*
|
||||
* @param int $n Index
|
||||
* @param string $where Where to add the slash ('trailing' or 'leading')
|
||||
* @return string
|
||||
*/
|
||||
public static function slash_segment($n, $where = 'trailing')
|
||||
{
|
||||
return self::_slash_segment($n, $where, 'segment');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Slash routed segment
|
||||
*
|
||||
* Fetches an URI routed segment with a slash.
|
||||
*
|
||||
* @param int $n Index
|
||||
* @param string $where Where to add the slash ('trailing' or 'leading')
|
||||
* @return string
|
||||
*/
|
||||
public static function slash_rsegment($n, $where = 'trailing')
|
||||
{
|
||||
return self::_slash_segment($n, $where, 'rsegment');
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Internal Slash segment
|
||||
*
|
||||
* Fetches an URI Segment and adds a slash to it.
|
||||
*
|
||||
* @used-by CI_URI::slash_segment()
|
||||
* @used-by CI_URI::slash_rsegment()
|
||||
*
|
||||
* @param int $n Index
|
||||
* @param string $where Where to add the slash ('trailing' or 'leading')
|
||||
* @param string $which Array name ('segment' or 'rsegment')
|
||||
* @return string
|
||||
*/
|
||||
protected static function _slash_segment($n, $where = 'trailing', $which = 'segment')
|
||||
{
|
||||
$leading = $trailing = '/';
|
||||
|
||||
if ($where === 'trailing')
|
||||
{
|
||||
$leading = '';
|
||||
}
|
||||
elseif ($where === 'leading')
|
||||
{
|
||||
$trailing = '';
|
||||
}
|
||||
|
||||
return $leading.self::$which($n).$trailing;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Segment Array
|
||||
*
|
||||
* @return array CI_URI::$segments
|
||||
*/
|
||||
public static function segment_array()
|
||||
{
|
||||
return self::$segments;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Routed Segment Array
|
||||
*
|
||||
* @return array CI_URI::$rsegments
|
||||
*/
|
||||
public static function rsegment_array()
|
||||
{
|
||||
return self::$rsegments;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Total number of segments
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function total_segments()
|
||||
{
|
||||
return count(self::$segments);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Total number of routed segments
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function total_rsegments()
|
||||
{
|
||||
return count(self::$rsegments);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Fetch URI string
|
||||
*
|
||||
* @return string CI_URI::$uri_string
|
||||
*/
|
||||
public static function uri_string()
|
||||
{
|
||||
return self::$uri_string;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Fetch Re-routed URI string
|
||||
*
|
||||
* @return string
|
||||
* @todo Implement router
|
||||
*/
|
||||
public static function ruri_string()
|
||||
{
|
||||
return ltrim(load_class('Router', 'core')->directory, '/').implode('/', self::$rsegments);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,246 @@
|
|||
<?php
|
||||
/**
|
||||
* FuzeWorks.
|
||||
*
|
||||
* The FuzeWorks MVC PHP FrameWork
|
||||
*
|
||||
* Copyright (C) 2015 TechFuze
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @author TechFuze
|
||||
* @copyright Copyright (c) 2013 - 2016, Techfuze. (http://techfuze.net)
|
||||
* @copyright Copyright (c) 1996 - 2015, Free Software Foundation, Inc. (http://www.fsf.org/)
|
||||
* @license http://opensource.org/licenses/GPL-3.0 GPLv3 License
|
||||
*
|
||||
* @link http://fuzeworks.techfuze.net
|
||||
* @since Version 0.0.1
|
||||
*
|
||||
* @version Version 0.0.1
|
||||
*/
|
||||
|
||||
namespace FuzeWorks;
|
||||
|
||||
/**
|
||||
* Utf8 Class
|
||||
*
|
||||
* Provides support for UTF-8 environments
|
||||
*
|
||||
* @author EllisLab Dev Team
|
||||
* @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
|
||||
* @copyright Copyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)
|
||||
*/
|
||||
class Utf8 {
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* Determines if UTF-8 support is to be enabled.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$charset = strtoupper(Config::get('main')->charset);
|
||||
ini_set('default_charset', $charset);
|
||||
|
||||
/*
|
||||
* Configure mbstring and/or iconv if they are enabled
|
||||
* and set MB_ENABLED and ICONV_ENABLED constants, so
|
||||
* that we don't repeatedly do extension_loaded() or
|
||||
* function_exists() calls.
|
||||
*/
|
||||
if (extension_loaded('mbstring'))
|
||||
{
|
||||
define('MB_ENABLED', TRUE);
|
||||
// mbstring.internal_encoding is deprecated starting with PHP 5.6
|
||||
// and it's usage triggers E_DEPRECATED messages.
|
||||
if (! Core::isPHP('5.6'))
|
||||
{
|
||||
@ini_set('mbstring.internal_encoding', $charset);
|
||||
}
|
||||
else
|
||||
{
|
||||
mb_internal_encoding($charset);
|
||||
}
|
||||
// This is required for mb_convert_encoding() to strip invalid characters.
|
||||
// That's utilized by CI_Utf8, but it's also done for consistency with iconv.
|
||||
mb_substitute_character('none');
|
||||
}
|
||||
else
|
||||
{
|
||||
define('MB_ENABLED', FALSE);
|
||||
}
|
||||
|
||||
// There's an ICONV_IMPL constant, but the PHP manual says that using
|
||||
// iconv's predefined constants is "strongly discouraged".
|
||||
if (extension_loaded('iconv'))
|
||||
{
|
||||
define('ICONV_ENABLED', TRUE);
|
||||
// iconv.internal_encoding is deprecated starting with PHP 5.6
|
||||
// and it's usage triggers E_DEPRECATED messages.
|
||||
if ( ! Core::isPHP(5.6) )
|
||||
{
|
||||
@ini_set('iconv.internal_encoding', $charset);
|
||||
}
|
||||
else
|
||||
{
|
||||
ini_set('default_encoding', $charset);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
define('ICONV_ENABLED', FALSE);
|
||||
}
|
||||
|
||||
if (Core::isPHP('5.6'))
|
||||
{
|
||||
ini_set('php.internal_encoding', $charset);
|
||||
}
|
||||
|
||||
if (
|
||||
defined('PREG_BAD_UTF8_ERROR') // PCRE must support UTF-8
|
||||
&& (ICONV_ENABLED === TRUE OR MB_ENABLED === TRUE) // iconv or mbstring must be installed
|
||||
&& strtoupper($charset) === 'UTF-8' // Application charset must be UTF-8
|
||||
)
|
||||
{
|
||||
define('UTF8_ENABLED', TRUE);
|
||||
Logger::log('UTF-8 Support Enabled');
|
||||
}
|
||||
else
|
||||
{
|
||||
define('UTF8_ENABLED', FALSE);
|
||||
Logger::log('UTF-8 Support Disabled');
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Clean UTF-8 strings
|
||||
*
|
||||
* Ensures strings contain only valid UTF-8 characters.
|
||||
*
|
||||
* @param string $str String to clean
|
||||
* @return string
|
||||
*/
|
||||
public static function clean_string($str)
|
||||
{
|
||||
if (self::is_ascii($str) === FALSE)
|
||||
{
|
||||
if (MB_ENABLED)
|
||||
{
|
||||
$str = mb_convert_encoding($str, 'UTF-8', 'UTF-8');
|
||||
}
|
||||
elseif (ICONV_ENABLED)
|
||||
{
|
||||
$str = @iconv('UTF-8', 'UTF-8//IGNORE', $str);
|
||||
}
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Remove ASCII control characters
|
||||
*
|
||||
* Removes all ASCII control characters except horizontal tabs,
|
||||
* line feeds, and carriage returns, as all others can cause
|
||||
* problems in XML.
|
||||
*
|
||||
* @param string $str String to clean
|
||||
* @return string
|
||||
*/
|
||||
public static function safe_ascii_for_xml($str)
|
||||
{
|
||||
Helpers::load('common');
|
||||
return remove_invisible_characters($str, FALSE);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Convert to UTF-8
|
||||
*
|
||||
* Attempts to convert a string to UTF-8.
|
||||
*
|
||||
* @param string $str Input string
|
||||
* @param string $encoding Input encoding
|
||||
* @return string $str encoded in UTF-8 or FALSE on failure
|
||||
*/
|
||||
public static function convert_to_utf8($str, $encoding)
|
||||
{
|
||||
if (MB_ENABLED)
|
||||
{
|
||||
return mb_convert_encoding($str, 'UTF-8', $encoding);
|
||||
}
|
||||
elseif (ICONV_ENABLED)
|
||||
{
|
||||
return @iconv($encoding, 'UTF-8', $str);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Is ASCII?
|
||||
*
|
||||
* Tests if a string is standard 7-bit ASCII or not.
|
||||
*
|
||||
* @param string $str String to check
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_ascii($str)
|
||||
{
|
||||
return (preg_match('/[^\x00-\x7F]/S', $str) === 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Invisible Characters
|
||||
*
|
||||
* This prevents sandwiching null characters
|
||||
* between ascii characters, like Java\0script.
|
||||
*
|
||||
* @param string
|
||||
* @param bool
|
||||
* @return string
|
||||
*/
|
||||
public static function remove_invisible_characters($str, $url_encoded = TRUE)
|
||||
{
|
||||
$non_displayables = array();
|
||||
|
||||
// every control character except newline (dec 10),
|
||||
// carriage return (dec 13) and horizontal tab (dec 09)
|
||||
if ($url_encoded)
|
||||
{
|
||||
$non_displayables[] = '/%0[0-8bcef]/'; // url encoded 00-08, 11, 12, 14, 15
|
||||
$non_displayables[] = '/%1[0-9a-f]/'; // url encoded 16-31
|
||||
}
|
||||
|
||||
$non_displayables[] = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S'; // 00-08, 11, 12, 14-31, 127
|
||||
|
||||
do
|
||||
{
|
||||
$str = preg_replace($non_displayables, '', $str, -1, $count);
|
||||
}
|
||||
while ($count);
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"require": {
|
||||
"php": ">=5.3.0",
|
||||
"php": ">=5.4.0",
|
||||
"ext-curl": "*",
|
||||
"ext-json": "*",
|
||||
"smarty/smarty": "~3.1"
|
||||
|
|
Loading…
Reference in New Issue