From f4a4bd8fac188ebc9cda822ffc811c218fd92b45 Mon Sep 17 00:00:00 2001 From: Derek Jones Date: Thu, 20 Oct 2011 12:18:42 -0500 Subject: adding new license file (OSL 3.0) and updating readme to ReST added notice of license to all source files. OSL to all except the few files we ship inside of the application folder, those are AFL. Updated license in user guide. incrementing next dev version to 3.0 due to licensing change --- system/core/Output.php | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'system/core/Output.php') diff --git a/system/core/Output.php b/system/core/Output.php index ccecafd2b..7b53f8e3e 100755 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -4,10 +4,22 @@ * * An open source application development framework for PHP 5.1.6 or newer * + * NOTICE OF LICENSE + * + * Licensed under the Open Software License version 3.0 + * + * This source file is subject to the Open Software License (OSL 3.0) that is + * bundled with this package in the files license.txt / license.rst. It is + * also available through the world wide web at this URL: + * http://opensource.org/licenses/OSL-3.0 + * If you did not receive a copy of the license and are unable to obtain it + * through the world wide web, please send an email to + * licensing@ellislab.com so we can send you a copy immediately. + * * @package CodeIgniter - * @author ExpressionEngine Dev Team - * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc. - * @license http://codeigniter.com/user_guide/license.html + * @author EllisLab Dev Team + * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc. (http://ellislab.com/) + * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com * @since Version 1.0 * @filesource @@ -23,7 +35,7 @@ * @package CodeIgniter * @subpackage Libraries * @category Output - * @author ExpressionEngine Dev Team + * @author EllisLab Dev Team * @link http://codeigniter.com/user_guide/libraries/output.html */ class CI_Output { -- cgit v1.2.3-24-g4f1b From 03abee3df4534028c795e3c3da91034a3d3ee0f4 Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Sun, 25 Dec 2011 00:31:29 -0600 Subject: Fixing soft tabs in a few files. --- system/core/Output.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'system/core/Output.php') diff --git a/system/core/Output.php b/system/core/Output.php index 7b53f8e3e..9727a184f 100755 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -108,7 +108,7 @@ class CI_Output { // Get mime types for later if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/mimes.php')) { - include APPPATH.'config/'.ENVIRONMENT.'/mimes.php'; + include APPPATH.'config/'.ENVIRONMENT.'/mimes.php'; } else { -- cgit v1.2.3-24-g4f1b From 5c1aa631c5f5ec2f6b75ba1158178418e50ba11a Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Sun, 25 Dec 2011 01:24:29 -0600 Subject: Abstracting the loading of files in the config directory depending on environments. --- system/core/Output.php | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'system/core/Output.php') diff --git a/system/core/Output.php b/system/core/Output.php index 9727a184f..4d1036ceb 100755 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -106,15 +106,7 @@ class CI_Output { $this->_zlib_oc = @ini_get('zlib.output_compression'); // Get mime types for later - if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/mimes.php')) - { - include APPPATH.'config/'.ENVIRONMENT.'/mimes.php'; - } - else - { - include APPPATH.'config/mimes.php'; - } - + load_environ_config('mimes'); $this->mime_types = $mimes; -- cgit v1.2.3-24-g4f1b From d96f88277c1e9a4c069c2e2ee3d779385549f31a Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Tue, 27 Dec 2011 16:23:47 -0600 Subject: Revert "Abstracting the loading of files in the config directory depending on environments." This reverts commit 5c1aa631c5f5ec2f6b75ba1158178418e50ba11a. --- system/core/Output.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'system/core/Output.php') diff --git a/system/core/Output.php b/system/core/Output.php index 4d1036ceb..9727a184f 100755 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -106,7 +106,15 @@ class CI_Output { $this->_zlib_oc = @ini_get('zlib.output_compression'); // Get mime types for later - load_environ_config('mimes'); + if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/mimes.php')) + { + include APPPATH.'config/'.ENVIRONMENT.'/mimes.php'; + } + else + { + include APPPATH.'config/mimes.php'; + } + $this->mime_types = $mimes; -- cgit v1.2.3-24-g4f1b From 0defe5d33ee2633f377a109519ca818becc60f64 Mon Sep 17 00:00:00 2001 From: Greg Aker Date: Sun, 1 Jan 2012 18:46:41 -0600 Subject: Updating copyright date to 2012 --- system/core/Output.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'system/core/Output.php') diff --git a/system/core/Output.php b/system/core/Output.php index 9727a184f..e529f914d 100755 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -18,7 +18,7 @@ * * @package CodeIgniter * @author EllisLab Dev Team - * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc. (http://ellislab.com/) + * @copyright Copyright (c) 2008 - 2012, EllisLab, Inc. (http://ellislab.com/) * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) * @link http://codeigniter.com * @since Version 1.0 -- cgit v1.2.3-24-g4f1b From 1f5fbb6cb35f5d234f9f2c95f730b13a9015f3c2 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Sat, 7 Jan 2012 20:53:29 +0200 Subject: Improve the core Output library --- system/core/Output.php | 150 +++++++++++++++---------------------------------- 1 file changed, 46 insertions(+), 104 deletions(-) (limited to 'system/core/Output.php') diff --git a/system/core/Output.php b/system/core/Output.php index e529f914d..272545046 100755 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -1,13 +1,13 @@ -_zlib_oc = @ini_get('zlib.output_compression'); @@ -117,8 +105,7 @@ class CI_Output { $this->mime_types = $mimes; - - log_message('debug', "Output Class Initialized"); + log_message('debug', 'Output Class Initialized'); } // -------------------------------------------------------------------- @@ -128,10 +115,9 @@ class CI_Output { * * Returns the current output string * - * @access public * @return string */ - function get_output() + public function get_output() { return $this->final_output; } @@ -147,10 +133,9 @@ class CI_Output { * @param string * @return void */ - function set_output($output) + public function set_output($output) { $this->final_output = $output; - return $this; } @@ -161,11 +146,10 @@ class CI_Output { * * Appends data onto the output string * - * @access public * @param string * @return void */ - function append_output($output) + public function append_output($output) { if ($this->final_output == '') { @@ -189,25 +173,22 @@ class CI_Output { * Note: If a file is cached, headers will not be sent. We need to figure out * how to permit header data to be saved with the cache data... * - * @access public * @param string * @param bool * @return void */ - function set_header($header, $replace = TRUE) + 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->headers[] = array($header, $replace); - return $this; } @@ -216,11 +197,10 @@ class CI_Output { /** * Set Content Type Header * - * @access public * @param string extension of the file we're outputting * @return void */ - function set_content_type($mime_type) + public function set_content_type($mime_type) { if (strpos($mime_type, '/') === FALSE) { @@ -241,7 +221,6 @@ class CI_Output { $header = 'Content-Type: '.$mime_type; $this->headers[] = array($header, TRUE); - return $this; } @@ -251,15 +230,13 @@ class CI_Output { * Set HTTP Status Header * moved to Common procedural functions in 1.7.2 * - * @access public * @param int the status code * @param string * @return void */ - function set_status_header($code = 200, $text = '') + public function set_status_header($code = 200, $text = '') { set_status_header($code, $text); - return $this; } @@ -268,14 +245,12 @@ class CI_Output { /** * Enable/disable Profiler * - * @access public * @param bool * @return void */ - function enable_profiler($val = TRUE) + public function enable_profiler($val = TRUE) { $this->enable_profiler = (is_bool($val)) ? $val : TRUE; - return $this; } @@ -286,11 +261,10 @@ class CI_Output { * * Allows override of default / config settings for Profiler section display * - * @access public * @param array * @return void */ - function set_profiler_sections($sections) + public function set_profiler_sections($sections) { foreach ($sections as $section => $enable) { @@ -305,14 +279,12 @@ class CI_Output { /** * Set Cache * - * @access public * @param integer * @return void */ - function cache($time) + publi function cache($time) { $this->cache_expiration = ( ! is_numeric($time)) ? 0 : $time; - return $this; } @@ -329,11 +301,10 @@ class CI_Output { * with any server headers and profile data. It also stops the * benchmark timer so the page rendering speed and memory usage can be shown. * - * @access public * @param string * @return mixed */ - function _display($output = '') + public function _display($output = '') { // Note: We use globals because we can't use $CI =& get_instance() // since this function is sometimes called by the caching mechanism, @@ -375,22 +346,17 @@ class CI_Output { { $memory = ( ! function_exists('memory_get_usage')) ? '0' : round(memory_get_usage()/1024/1024, 2).'MB'; - $output = str_replace('{elapsed_time}', $elapsed, $output); - $output = str_replace('{memory_usage}', $memory, $output); + $output = str_replace(array('{elapsed_time}', '{memory_usage}'), array($elapsed, $memory), $output); } // -------------------------------------------------------------------- // Is compression requested? - if ($CFG->item('compress_output') === TRUE && $this->_zlib_oc == FALSE) + if ($CFG->item('compress_output') === TRUE && $this->_zlib_oc == FALSE + && extension_loaded('zlib') + && isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE) { - if (extension_loaded('zlib')) - { - if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) AND strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE) - { - ob_start('ob_gzhandler'); - } - } + ob_start('ob_gzhandler'); } // -------------------------------------------------------------------- @@ -412,8 +378,8 @@ class CI_Output { if ( ! isset($CI)) { echo $output; - log_message('debug', "Final output sent to browser"); - log_message('debug', "Total execution time: ".$elapsed); + log_message('debug', 'Final output sent to browser'); + log_message('debug', 'Total execution time: '.$elapsed); return TRUE; } @@ -424,7 +390,6 @@ class CI_Output { if ($this->enable_profiler == TRUE) { $CI->load->library('profiler'); - if ( ! empty($this->_profiler_sections)) { $CI->profiler->set_sections($this->_profiler_sections); @@ -432,16 +397,11 @@ class CI_Output { // If the output data contains closing and tags // we will remove them and add them back after we insert the profile data - if (preg_match("|.*?|is", $output)) + $output = preg_replace('|.*?|is', '', $output, $count).$CI->profiler->run(); + if ($count > 0) { - $output = preg_replace("|.*?|is", '', $output); - $output .= $CI->profiler->run(); $output .= ''; } - else - { - $output .= $CI->profiler->run(); - } } // -------------------------------------------------------------------- @@ -457,8 +417,8 @@ class CI_Output { echo $output; // Send it to the browser! } - log_message('debug', "Final output sent to browser"); - log_message('debug', "Total execution time: ".$elapsed); + log_message('debug', 'Final output sent to browser'); + log_message('debug', 'Total execution time: '.$elapsed); } // -------------------------------------------------------------------- @@ -466,20 +426,18 @@ class CI_Output { /** * Write a Cache File * - * @access public * @param string * @return void */ - function _write_cache($output) + public function _write_cache($output) { $CI =& get_instance(); $path = $CI->config->item('cache_path'); - $cache_path = ($path == '') ? APPPATH.'cache/' : $path; if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path)) { - log_message('error', "Unable to write cache file: ".$cache_path); + log_message('error', 'Unable to write cache file: '.$cache_path); return; } @@ -491,7 +449,7 @@ class CI_Output { if ( ! $fp = @fopen($cache_path, FOPEN_WRITE_CREATE_DESTRUCTIVE)) { - log_message('error', "Unable to write cache file: ".$cache_path); + log_message('error', 'Unable to write cache file: '.$cache_path); return; } @@ -504,13 +462,13 @@ class CI_Output { } else { - log_message('error', "Unable to secure a file lock for file at: ".$cache_path); + log_message('error', 'Unable to secure a file lock for file at: '.$cache_path); return; } fclose($fp); @chmod($cache_path, FILE_WRITE_MODE); - log_message('debug', "Cache file written: ".$cache_path); + log_message('debug', 'Cache file written: '.$cache_path); } // -------------------------------------------------------------------- @@ -518,69 +476,53 @@ class CI_Output { /** * Update/serve a cached file * - * @access public * @param object config class * @param object uri class * @return void */ - function _display_cache(&$CFG, &$URI) + public function _display_cache(&$CFG, &$URI) { $cache_path = ($CFG->item('cache_path') == '') ? APPPATH.'cache/' : $CFG->item('cache_path'); - // Build the file path. The file name is an MD5 hash of the full URI - $uri = $CFG->item('base_url'). - $CFG->item('index_page'). - $URI->uri_string; - + // 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; $filepath = $cache_path.md5($uri); - if ( ! @file_exists($filepath)) - { - return FALSE; - } - - if ( ! $fp = @fopen($filepath, FOPEN_READ)) + if ( ! @file_exists($filepath) + OR ! $fp = @fopen($filepath, FOPEN_READ)) { return FALSE; } flock($fp, LOCK_SH); - $cache = ''; - if (filesize($filepath) > 0) - { - $cache = fread($fp, filesize($filepath)); - } + $cache = (filesize($filepath) > 0) ? fread($fp, filesize($filepath)) : ''; flock($fp, LOCK_UN); fclose($fp); // Strip out the embedded timestamp - if ( ! preg_match("/(\d+TS--->)/", $cache, $match)) + if ( ! preg_match('/(\d+TS--->)/', $cache, $match)) { return FALSE; } // Has the file expired? If so we'll delete it. - if (time() >= trim(str_replace('TS--->', '', $match['1']))) + if (time() >= trim(str_replace('TS--->', '', $match[1])) + AND is_really_writable($cache_path)) { - if (is_really_writable($cache_path)) - { - @unlink($filepath); - log_message('debug', "Cache file has expired. File deleted"); - return FALSE; - } + @unlink($filepath); + log_message('debug', 'Cache file has expired. File deleted.'); + return FALSE; } // Display the cache - $this->_display(str_replace($match['0'], '', $cache)); - log_message('debug', "Cache file is current. Sending it to browser."); + $this->_display(str_replace($match[0], '', $cache)); + log_message('debug', 'Cache file is current. Sending it to browser.'); return TRUE; } - } -// END Output Class /* End of file Output.php */ -/* Location: ./system/core/Output.php */ \ No newline at end of file +/* Location: ./system/core/Output.php */ -- cgit v1.2.3-24-g4f1b From c90d651e8531142d36326d5c3451d7899fb00f76 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Sun, 8 Jan 2012 04:35:02 +0200 Subject: Style guide stuff --- system/core/Output.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'system/core/Output.php') diff --git a/system/core/Output.php b/system/core/Output.php index 272545046..1beee734f 100755 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -488,8 +488,7 @@ class CI_Output { $uri = $CFG->item('base_url').$CFG->item('index_page').$URI->uri_string; $filepath = $cache_path.md5($uri); - if ( ! @file_exists($filepath) - OR ! $fp = @fopen($filepath, FOPEN_READ)) + if ( ! @file_exists($filepath) OR ! $fp = @fopen($filepath, FOPEN_READ)) { return FALSE; } @@ -508,8 +507,7 @@ class CI_Output { } // Has the file expired? If so we'll delete it. - if (time() >= trim(str_replace('TS--->', '', $match[1])) - AND is_really_writable($cache_path)) + if (time() >= trim(str_replace('TS--->', '', $match[1])) && is_really_writable($cache_path)) { @unlink($filepath); log_message('debug', 'Cache file has expired. File deleted.'); -- cgit v1.2.3-24-g4f1b From 0609d588a4340fc9a9cfbc0ff76c39bba9ab09fb Mon Sep 17 00:00:00 2001 From: Michiel Vugteveen Date: Sun, 8 Jan 2012 13:26:17 +0100 Subject: Fixes for issue 896 --- system/core/Output.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'system/core/Output.php') diff --git a/system/core/Output.php b/system/core/Output.php index 1beee734f..da5c29044 100755 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -129,7 +129,6 @@ class CI_Output { * * Sets the output string * - * @access public * @param string * @return void */ @@ -282,7 +281,7 @@ class CI_Output { * @param integer * @return void */ - publi function cache($time) + public function cache($time) { $this->cache_expiration = ( ! is_numeric($time)) ? 0 : $time; return $this; -- cgit v1.2.3-24-g4f1b From edc875593d3ddbd0fe86caf6380a62b00a20f245 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Mon, 9 Jan 2012 09:35:10 +0200 Subject: Fix a possible notice in Output library --- system/core/Output.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'system/core/Output.php') diff --git a/system/core/Output.php b/system/core/Output.php index da5c29044..69a2e5f88 100755 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -397,14 +397,12 @@ class CI_Output { // If the output data contains closing and tags // we will remove them and add them back after we insert the profile data $output = preg_replace('|.*?|is', '', $output, $count).$CI->profiler->run(); - if ($count > 0) + if (isset($count) && $count > 0) { $output .= ''; } } - // -------------------------------------------------------------------- - // Does the controller contain a function named _output()? // If so send the output there. Otherwise, echo it. if (method_exists($CI, '_output')) @@ -413,7 +411,7 @@ class CI_Output { } else { - echo $output; // Send it to the browser! + echo $output; // Send it to the browser! } log_message('debug', 'Final output sent to browser'); -- cgit v1.2.3-24-g4f1b From cba20b164fdb1e60225b4f1fc04b7a31c4ffa106 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Mon, 9 Jan 2012 10:16:41 +0200 Subject: Really fix this ... --- system/core/Output.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'system/core/Output.php') diff --git a/system/core/Output.php b/system/core/Output.php index 69a2e5f88..d27133d37 100755 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -396,8 +396,9 @@ class CI_Output { // If the output data contains closing and tags // we will remove them and add them back after we insert the profile data - $output = preg_replace('|.*?|is', '', $output, $count).$CI->profiler->run(); - if (isset($count) && $count > 0) + $count = 0; + $output = preg_replace('|.*?|is', '', $output, -1, $count).$CI->profiler->run(); + if ($count > 0) { $output .= ''; } -- cgit v1.2.3-24-g4f1b From a96a9c8e6c7a113c808ba047808180b33360d3dd Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Mon, 9 Jan 2012 11:01:15 +0200 Subject: Remove once again ... --- system/core/Output.php | 1 - 1 file changed, 1 deletion(-) (limited to 'system/core/Output.php') diff --git a/system/core/Output.php b/system/core/Output.php index d27133d37..abd8a0ea9 100755 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -396,7 +396,6 @@ class CI_Output { // If the output data contains closing and tags // we will remove them and add them back after we insert the profile data - $count = 0; $output = preg_replace('|.*?|is', '', $output, -1, $count).$CI->profiler->run(); if ($count > 0) { -- cgit v1.2.3-24-g4f1b From c8efb8033ae775a5c1c840f867def4e6253b3d9a Mon Sep 17 00:00:00 2001 From: "Thor (atiredmachine)" Date: Tue, 24 Jan 2012 13:33:39 -0800 Subject: Output class now sets HTTP headers match caching settings. --- system/core/Output.php | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) (limited to 'system/core/Output.php') diff --git a/system/core/Output.php b/system/core/Output.php index abd8a0ea9..1f214a0b3 100755 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -466,6 +466,9 @@ class CI_Output { @chmod($cache_path, FILE_WRITE_MODE); 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); } // -------------------------------------------------------------------- @@ -503,13 +506,22 @@ class CI_Output { return FALSE; } - // Has the file expired? If so we'll delete it. - if (time() >= trim(str_replace('TS--->', '', $match[1])) && is_really_writable($cache_path)) + $last_modified = filemtime($cache_path); + $expire = trim(str_replace('TS--->', '', $match[1])); + + // 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); + } // Display the cache $this->_display(str_replace($match[0], '', $cache)); @@ -517,6 +529,35 @@ class CI_Output { return TRUE; } + + // -------------------------------------------------------------------- + /** + * Set the HTTP headers to match the server-side file cache settings + * in order to reduce bandwidth. + * + * @param int timestamp of when the page was last modified + * @param int 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'); + } + } + + } /* End of file Output.php */ -- cgit v1.2.3-24-g4f1b From 63678a27864fdd6bb0ed89e6940a1d331121072a Mon Sep 17 00:00:00 2001 From: "Thor (atiredmachine)" Date: Tue, 24 Jan 2012 16:56:01 -0800 Subject: Rudimentary minifying of output. --- system/core/Output.php | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'system/core/Output.php') diff --git a/system/core/Output.php b/system/core/Output.php index 1f214a0b3..55a505c34 100755 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -323,6 +323,15 @@ class CI_Output { { $output =& $this->final_output; } + + // -------------------------------------------------------------------- + + // Is minify requested? + if ($CFG->item('minify_output') === TRUE) + { + $output = $this->minify($output); + } + // -------------------------------------------------------------------- @@ -558,6 +567,33 @@ class CI_Output { } + + + // -------------------------------------------------------------------- + /** + * Reduce excessive size of HTML content. + * + * @param string + * @param string + * @return string + */ + public function minify($output,$type='html') + { + switch ($type) + { + case 'html': + + // Replaces multiple spaces with a single space. + $output = preg_replace('!\s{2,}!',' ',$output); + + // ... + break; + } + + return $output; + } + + } /* End of file Output.php */ -- cgit v1.2.3-24-g4f1b From 79db4cdba1a1a80634cd76ab8fc69fce7b1a7ea6 Mon Sep 17 00:00:00 2001 From: "Thor (atiredmachine)" Date: Tue, 24 Jan 2012 20:44:51 -0800 Subject: Improved minifier to restore
 contents, remove even more spaces,
 and process CSS with its own rules.

---
 system/core/Output.php | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 55a505c34..bb39a7f31 100755
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -582,12 +582,45 @@ class CI_Output {
 		switch ($type)
 		{
 			case 'html':
+			
+				// Keep track of 
 tags as they were before processing.
+				// We'll want to return them to this state later.
+				preg_match_all('{}msU',$output,$pres_clean);
+
+				// Keep track of 
 tags as they were before processing.
+				// We'll want to return them to this state later.
+				preg_match_all('{}msU',$output,$style_clean);
 				
+				// Run }msU',$output,$style_clean);
-				
-				// Run }msU',$output,$style_clean);
 				foreach ($style_clean[0] as $s)
 				{
-					$output = str_replace($s, $this->minify($s,'css'), $output);
+					$output = str_replace($s, $this->minify($s,'text/css'), $output);
 				}
 
 				// Replace multiple spaces with a single space.
@@ -614,7 +614,7 @@ class CI_Output {
 			break;
 			
 			
-			case 'css':
+			case 'text/css':
 			
 				// Remove spaces around curly brackets, colons, and semi-colons
 				$output = preg_replace('!\s*(:|;|}|{)\s*!','$1',$output);
-- 
cgit v1.2.3-24-g4f1b


From 5de117549f69465a1ce0f2e128428d9adadd8a6d Mon Sep 17 00:00:00 2001
From: "Thor (atiredmachine)" 
Date: Tue, 24 Jan 2012 22:08:36 -0800
Subject: Strips out HTML comments.

---
 system/core/Output.php | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 47c00acd8..8992fc1f1 100755
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -600,6 +600,9 @@ class CI_Output {
 				// Replace multiple spaces with a single space.
 				$output = preg_replace('!\s{2,}!',"\n",$output);
 				
+				// Remove comments (non-MSIE conditionals)
+				$output = preg_replace('{\s*\s*}msU','',$output);
+
 				// Remove spaces around block-level elements.
 				$output = preg_replace('{\s*()\s*}', '$1', $output);
 
-- 
cgit v1.2.3-24-g4f1b


From f59ec6fe4fab3bd5ff71d920e13f983454a9fb65 Mon Sep 17 00:00:00 2001
From: "Thor (atiredmachine)" 
Date: Tue, 24 Jan 2012 22:19:14 -0800
Subject: Logs 'debug' message that shows how much % was shaved off.

---
 system/core/Output.php | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 8992fc1f1..c95f551ec 100755
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -582,7 +582,9 @@ class CI_Output {
 		switch ($type)
 		{
 			case 'text/html':
-			
+
+				$size_before = strlen($output);
+
 				// Keep track of 
  and }msU',$output,$textareas_clean);
+				preg_match_all('{}msU', $output, $pres_clean);
+				preg_match_all('{}msU', $output, $codes_clean);
+				preg_match_all('{}msU', $output, $textareas_clean);
 
 				// Minify the CSS in all the }msU',$output,$style_clean);
+				preg_match_all('{}msU', $output, $style_clean);
 				foreach ($style_clean[0] as $s)
 				{
 					$output = str_replace($s, $this->minify($s,'text/css'), $output);
 				}
 
 				// Replace multiple spaces with a single space.
-				$output = preg_replace('!\s{2,}!',"\n",$output);
+				$output = preg_replace('!\s{2,}!', "\n", $output);
 				
 				// Remove comments (non-MSIE conditionals)
-				$output = preg_replace('{\s*\s*}msU','',$output);
+				$output = preg_replace('{\s*\s*}msU', '', $output);
 
 				// Remove spaces around block-level elements.
 				$output = preg_replace('{\s*()\s*}', '$1', $output);
 
 				// Replace mangled 
 etc. tags with unprocessed ones.
-				preg_match_all('{}msU',$output,$pres_messed);
-				preg_match_all('{}msU',$output,$codes_messed);
-				preg_match_all('{}msU',$output,$textareas_messed);
-				$output = str_replace($pres_messed[0],$pres_clean[0],$output);
-				$output = str_replace($codes_messed[0],$codes_clean[0],$output);
-				$output = str_replace($textareas_messed[0],$textareas_clean[0],$output);
+				preg_match_all('{}msU', $output, $pres_messed);
+				preg_match_all('{}msU', $output, $codes_messed);
+				preg_match_all('{}msU', $output, $textareas_messed);
+				$output = str_replace($pres_messed[0], $pres_clean[0], $output);
+				$output = str_replace($codes_messed[0], $codes_clean[0], $output);
+				$output = str_replace($textareas_messed[0], $textareas_clean[0], $output);
 				
 				$size_after = strlen($output);
 				$savings_percent = round(100 - ($size_after / $size_before * 100));
@@ -640,10 +635,10 @@ class CI_Output {
 			case 'text/css':
 			
 				// Remove spaces around curly brackets, colons, and semi-colons
-				$output = preg_replace('!\s*(:|;|}|{)\s*!','$1',$output);
+				$output = preg_replace('!\s*(:|;|}|{)\s*!', '$1', $output);
 				
 				// Replace spaces with line breaks to limit line lengths
-				$output = preg_replace('!\s+!',"\n",$output);
+				$output = preg_replace('!\s+!', "\n", $output);
 
 			break;
 		}
-- 
cgit v1.2.3-24-g4f1b


From 5c078ceeb926119fc3b4e55ca7c33ff2d1a207cd Mon Sep 17 00:00:00 2001
From: "Thor (atiredmachine)" 
Date: Thu, 26 Jan 2012 17:18:35 -0800
Subject: Added javascript. Improved based on comments.

---
 system/core/Output.php | 74 +++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 55 insertions(+), 19 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 9bc02fc84..c4eba30bb 100755
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -593,12 +593,12 @@ class CI_Output {
 
 				$size_before = strlen($output);
 
-				// Keep track of 
  and }msU', $output, $textareas_clean);
+				preg_match_all('{}msU', $output, $javascript_clean);
 
 				// Minify the CSS in all the }msU', $output, $style_clean);
@@ -606,39 +606,75 @@ class CI_Output {
 				{
 					$output = str_replace($s, $this->minify($s,'text/css'), $output);
 				}
+				
+				// Minify the javascript in }msU', $output, $javascript_messed);
+					$output = str_replace($javascript_messed[0], $javascript_mini, $output);
+				}
+				
+				$size_removed = $size_before - strlen($output);
+				$savings_percent = round(($size_removed / $size_before * 100));
+
+				log_message('debug', 'Minifier shaved '.($size_removed / 1000).'KB ('.$savings_percent.'%) off final HTML output.');
 
 			break;
 			
 			
 			case 'text/css':
 			
-				// Remove spaces around curly brackets, colons, and semi-colons
-				$output = preg_replace('!\s*(:|;|}|{)\s*!', '$1', $output);
-				
-				// Replace spaces with line breaks to limit line lengths
-				$output = preg_replace('!\s+!', "\n", $output);
+				//Remove CSS comments
+				$output = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $output);
+			
+				// Remove spaces around curly brackets, colons,
+				// semi-colons, parenthesis, commas
+				$output = preg_replace('!\s*(:|;|,|}|{|\(|\))\s*!', '$1', $output);
+
+			break;
+			
+			
+			case 'text/javascript':
+
+				// Replace multiple spaces with a single newline.
+				$output = preg_replace('!\s{2,}!',"\n", $output);
+
+				// Remove excessive newlines.
+				$output = preg_replace('!(;|{|})\n!','$1', $output);
 
 			break;
 		}
-- 
cgit v1.2.3-24-g4f1b


From 6c5992da5cf3579a29079b0aae3e9ba0700fda5c Mon Sep 17 00:00:00 2001
From: "Thor (atiredmachine)" 
Date: Thu, 26 Jan 2012 18:45:57 -0800
Subject: Removed javascript for now...

---
 system/core/Output.php | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index c4eba30bb..d8c230968 100755
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -670,11 +670,11 @@ class CI_Output {
 			
 			case 'text/javascript':
 
-				// Replace multiple spaces with a single newline.
-				$output = preg_replace('!\s{2,}!',"\n", $output);
+				// Replace multiple whitespace characters with a single newline.
+				//$output = preg_replace('!\s{2,}!',"\n", $output);
 
 				// Remove excessive newlines.
-				$output = preg_replace('!(;|{|})\n!','$1', $output);
+				//$output = preg_replace('!(;|{|})\n!','$1', $output);
 
 			break;
 		}
-- 
cgit v1.2.3-24-g4f1b


From 1b8d0ef6491b77375bb068711bc5e10fe4ca4b8f Mon Sep 17 00:00:00 2001
From: Thor 
Date: Sat, 28 Jan 2012 01:48:04 -0800
Subject: Fixed some spaces.

---
 system/core/Output.php | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index d8c230968..468274002 100755
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -604,17 +604,17 @@ class CI_Output {
 				preg_match_all('{}msU', $output, $style_clean);
 				foreach ($style_clean[0] as $s)
 				{
-					$output = str_replace($s, $this->minify($s,'text/css'), $output);
+					$output = str_replace($s, $this->minify($s, 'text/css'), $output);
 				}
 				
 				// Minify the javascript in }msU', $output, $javascript_messed);
 					$output = str_replace($javascript_messed[0], $javascript_mini, $output);
 				}
-				
+
 				$size_removed = $size_before - strlen($output);
 				$savings_percent = round(($size_removed / $size_before * 100));
 
 				log_message('debug', 'Minifier shaved '.($size_removed / 1000).'KB ('.$savings_percent.'%) off final HTML output.');
 
 			break;
-			
-			
+
 			case 'text/css':
-			
+
 				//Remove CSS comments
 				$output = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $output);
-			
+
 				// Remove spaces around curly brackets, colons,
 				// semi-colons, parenthesis, commas
 				$output = preg_replace('!\s*(:|;|,|}|{|\(|\))\s*!', '$1', $output);
 
 			break;
-			
-			
+
 			case 'text/javascript':
 
 				// Currently leaves JavaScript untouched.
 			break;
+
+			default: break;
 		}
-		
+
 		return $output;
 	}
 
-
 }
 
 /* End of file Output.php */
-/* Location: ./system/core/Output.php */
+/* Location: ./system/core/Output.php */
\ No newline at end of file
-- 
cgit v1.2.3-24-g4f1b


From f512b73bc78760198a5409f2c4da71fe749b1301 Mon Sep 17 00:00:00 2001
From: Alex Bilbie 
Date: Sat, 16 Jun 2012 11:15:19 +0100
Subject: Spelling fixes - `wether` to `whether`

Interestingly `wether` means a castrated ram in old English
---
 system/core/Output.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 570d4ebc9..ed294f116 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -74,7 +74,7 @@ class CI_Output {
 	protected $mime_type		= 'text/html';
 
 	/**
-	 * Determines wether profiler is enabled
+	 * Determines whether profiler is enabled
 	 *
 	 * @var book
 	 */
-- 
cgit v1.2.3-24-g4f1b


From 3b6af434b13168828429d06aae7699f6f9537a87 Mon Sep 17 00:00:00 2001
From: Phil Sturgeon 
Date: Thu, 21 Jun 2012 09:21:17 -0500
Subject: Replaced block tag minification regex with a less greedy solution.

---
 system/core/Output.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index ed294f116..4fdf18f14 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -652,7 +652,7 @@ class CI_Output {
 				$output = preg_replace('{\s*\s*}msU', '', $output);
 
 				// Remove spaces around block-level elements.
-				$output = preg_replace('{\s*()\s+}msU', '$1', $output);
+				$output = preg_replace('/\s*(<\/?(html|head|title|meta|script|link|style|body|h[1-6]|div|p|br)[^>]*>)\s*/is', '$1', $output);
 
 				// Replace mangled 
 etc. tags with unprocessed ones.
 
-- 
cgit v1.2.3-24-g4f1b


From 7a744a8ba8f07ba1ec3a48f1d5de641b4025ce20 Mon Sep 17 00:00:00 2001
From: Phil Sturgeon 
Date: Sat, 23 Jun 2012 17:21:00 +0100
Subject: If there is no output then no need to try minifying it

---
 system/core/Output.php | 5 +++++
 1 file changed, 5 insertions(+)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 4fdf18f14..5ec8c4bc0 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -625,6 +625,11 @@ class CI_Output {
 
 				$size_before = strlen($output);
 
+				if ($size_before === 0)
+				{
+					return '';
+				}
+
 				// Find all the 
,,}msU', $output, $textareas_clean);
-				preg_match_all('{}msU', $output, $javascript_clean);
+                // Find all the 
,,}msU', $output, $textareas_clean);
+                preg_match_all('{}msU', $output, $javascript_clean);
 
-				// Minify the CSS in all the }msU', $output, $style_clean);
-				foreach ($style_clean[0] as $s)
-				{
-					$output = str_replace($s, $this->minify($s, 'text/css'), $output);
-				}
+                // Minify the CSS in all the }msU', $output, $style_clean);
+                foreach ($style_clean[0] as $s)
+                {
+                    $output = str_replace($s, $this->_minify_script_style($s, $type), $output);
+                }
 
-				// Minify the javascript in }msU', $output, $javascript_messed);
-					$output = str_replace($javascript_messed[0], $javascript_mini, $output);
-				}
+                if (isset($javascript_mini))
+                {
+                    preg_match_all('{}msU', $output, $javascript_messed);
+                    $output = str_replace($javascript_messed[0], $javascript_mini, $output);
+                }
 
-				$size_removed = $size_before - strlen($output);
-				$savings_percent = round(($size_removed / $size_before * 100));
+                $size_removed = $size_before - strlen($output);
+                $savings_percent = round(($size_removed / $size_before * 100));
 
-				log_message('debug', 'Minifier shaved '.($size_removed / 1000).'KB ('.$savings_percent.'%) off final HTML output.');
+                log_message('debug', 'Minifier shaved '.($size_removed / 1000).'KB ('.$savings_percent.'%) off final HTML output.');
 
-			break;
+            break;
 
-			case 'text/css':
-			case 'text/javascript':
+            case 'text/css':
+            case 'text/javascript':
 
-				//Remove CSS comments
-				$output = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $output);
+                $output = $this->_minify_scripts_css($output, $type);
 
-				// Remove spaces around curly brackets, colons,
-				// semi-colons, parenthesis, commas
-				$output = preg_replace('!\s*(:|;|,|}|{|\(|\))\s*!', '$1', $output);
+            break;
 
-				// Remove spaces
-			        $output =  preg_replace('/  /s', ' ', $output);
+            default: break;
+        }
 
-			        // Remove breaklines and tabs
-			        $output =  preg_replace('/[\r\n\t]/', '', $output);
+        return $output;
+    }
 
-			break;
 
-			default: break;
-		}
+    // --------------------------------------------------------------------
 
-		return $output;
-	}
+	/**
+	 * Minify Style and Script
+	 *
+	 * Reduce excessive size of CSS/JavaScript content.  To remove spaces this
+     * script walks the string as an array and determines if the pointer is inside
+     * a string created by single quotes or double quotes.  spaces inside those
+     * strings are not stripped.  Opening and closing tags are severed from
+     * the string initially and saved without stripping whitespace to preserve
+     * the tags and any associated properties if tags are present
+	 *
+	 * @param	string	$output	Output to minify
+     * @param   string  $type Output content MIME type
+	 * @return	string	Minified output
+	 */
+    protected function _minify_script_style($output, $type = 'text/html')
+    {
+        // We only need this if there are tags in the file
+        if ($type == 'text/html')
+        {
+            // Remove opening tag and save for later
+            $pos = strpos($output, '>');
+            $open_tag = substr($output, 0, $pos);
+            $output = substr_replace($output, '', 0, $pos);
+
+            // Remove closing tag and save it for later
+            $end_pos = strlen($output);
+            $pos = strpos($output, ' $value)
+        {
+            if ($in_string === FALSE and $in_dstring === FALSE)
+            {
+                if ($value == ' ')
+                {
+                    unset($array_output[$key]);
+                }
+            }
+
+            if ($value == "'")
+            {
+                $in_string = !$in_string;
+            }
+
+            if ($value == '"')
+            {
+                $in_dstring = !$in_dstring;
+            }
+        }
+
+        $output =  implode($array_output);
+
+        // Remove breaklines and tabs
+        $output =  preg_replace('/[\r\n\t]/', '', $output);
+
+        // Put the opening and closing tags back if applicable
+        if (isset($open_tag))
+        {
+            $output = $open_tag . $output . $closing_tag;
+        }
+
+        return $output;
+    }
 
 }
 
-- 
cgit v1.2.3-24-g4f1b


From 79503c59f5c1b6dea906c62adde63e291347fac0 Mon Sep 17 00:00:00 2001
From: Andrew Podner 
Date: Tue, 18 Dec 2012 07:47:38 -0500
Subject: fixes #2078: refinement of the minify function for CSS and scripts.

---
 system/core/Output.php | 268 ++++++++++++++++++++++++-------------------------
 1 file changed, 134 insertions(+), 134 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 1fafa848b..e33f4b0b7 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -705,172 +705,172 @@ class CI_Output {
 	 * @return	string	Minified output
 	 */
 	public function minify($output, $type = 'text/html')
-    {
-        switch ($type)
-        {
-            case 'text/html':
+	{
+		switch ($type)
+		{
+			case 'text/html':
 
-                $size_before = strlen($output);
+				$size_before = strlen($output);
 
-                if ($size_before === 0)
-                {
-                    return '';
-                }
+				if ($size_before === 0)
+				{
+					return '';
+				}
 
-                // Find all the 
,,}msU', $output, $textareas_clean);
-                preg_match_all('{}msU', $output, $javascript_clean);
+				// Find all the 
,,}msU', $output, $textareas_clean);
+				preg_match_all('{}msU', $output, $javascript_clean);
 
-                // Minify the CSS in all the }msU', $output, $style_clean);
-                foreach ($style_clean[0] as $s)
-                {
-                    $output = str_replace($s, $this->_minify_script_style($s, $type), $output);
-                }
+				// Minify the CSS in all the }msU', $output, $style_clean);
+				foreach ($style_clean[0] as $s)
+				{
+					$output = str_replace($s, $this->_minify_script_style($s, $type), $output);
+				}
 
-                // Minify the javascript in }msU', $output, $javascript_messed);
-                    $output = str_replace($javascript_messed[0], $javascript_mini, $output);
-                }
+				if (isset($javascript_mini))
+				{
+					preg_match_all('{}msU', $output, $javascript_messed);
+					$output = str_replace($javascript_messed[0], $javascript_mini, $output);
+				}
 
-                $size_removed = $size_before - strlen($output);
-                $savings_percent = round(($size_removed / $size_before * 100));
+				$size_removed = $size_before - strlen($output);
+				$savings_percent = round(($size_removed / $size_before * 100));
 
-                log_message('debug', 'Minifier shaved '.($size_removed / 1000).'KB ('.$savings_percent.'%) off final HTML output.');
+				log_message('debug', 'Minifier shaved '.($size_removed / 1000).'KB ('.$savings_percent.'%) off final HTML output.');
 
-            break;
+			break;
 
-            case 'text/css':
-            case 'text/javascript':
+			case 'text/css':
+			case 'text/javascript':
 
-                $output = $this->_minify_scripts_css($output, $type);
+				$output = $this->_minify_scripts_css($output, $type);
 
-            break;
+			break;
 
-            default: break;
-        }
+			default: break;
+		}
 
-        return $output;
-    }
+		return $output;
+	}
 
 
-    // --------------------------------------------------------------------
+	// --------------------------------------------------------------------
 
 	/**
 	 * Minify Style and Script
 	 *
 	 * Reduce excessive size of CSS/JavaScript content.  To remove spaces this
-     * script walks the string as an array and determines if the pointer is inside
-     * a string created by single quotes or double quotes.  spaces inside those
-     * strings are not stripped.  Opening and closing tags are severed from
-     * the string initially and saved without stripping whitespace to preserve
-     * the tags and any associated properties if tags are present
+	 * script walks the string as an array and determines if the pointer is inside
+	 * a string created by single quotes or double quotes.  spaces inside those
+	 * strings are not stripped.  Opening and closing tags are severed from
+	 * the string initially and saved without stripping whitespace to preserve
+	 * the tags and any associated properties if tags are present
 	 *
 	 * @param	string	$output	Output to minify
-     * @param   string  $type Output content MIME type
+	 * @param	string  $type Output content MIME type
 	 * @return	string	Minified output
 	 */
-    protected function _minify_script_style($output, $type = 'text/html')
-    {
-        // We only need this if there are tags in the file
-        if ($type == 'text/html')
-        {
-            // Remove opening tag and save for later
-            $pos = strpos($output, '>');
-            $open_tag = substr($output, 0, $pos);
-            $output = substr_replace($output, '', 0, $pos);
-
-            // Remove closing tag and save it for later
-            $end_pos = strlen($output);
-            $pos = strpos($output, ' $value)
-        {
-            if ($in_string === FALSE and $in_dstring === FALSE)
-            {
-                if ($value == ' ')
-                {
-                    unset($array_output[$key]);
-                }
-            }
-
-            if ($value == "'")
-            {
-                $in_string = !$in_string;
-            }
-
-            if ($value == '"')
-            {
-                $in_dstring = !$in_dstring;
-            }
-        }
-
-        $output =  implode($array_output);
-
-        // Remove breaklines and tabs
-        $output =  preg_replace('/[\r\n\t]/', '', $output);
-
-        // Put the opening and closing tags back if applicable
-        if (isset($open_tag))
-        {
-            $output = $open_tag . $output . $closing_tag;
-        }
-
-        return $output;
-    }
+	protected function _minify_script_style($output, $type = 'text/html')
+	{
+		// We only need this if there are tags in the file
+		if ($type == 'text/html')
+		{
+			// Remove opening tag and save for later
+			$pos = strpos($output, '>');
+			$open_tag = substr($output, 0, $pos);
+			$output = substr_replace($output, '', 0, $pos);
+
+			// Remove closing tag and save it for later
+			$end_pos = strlen($output);
+			$pos = strpos($output, ' $value)
+		{
+			if ($in_string === FALSE and $in_dstring === FALSE)
+			{
+				if ($value == ' ')
+				{
+					unset($array_output[$key]);
+				}
+			}
+
+			if ($value == "'")
+			{
+				$in_string = !$in_string;
+			}
+
+			if ($value == '"')
+			{
+				$in_dstring = !$in_dstring;
+			}
+		}
+
+		$output = implode($array_output);
+
+		// Remove breaklines and tabs
+		$output = preg_replace('/[\r\n\t]/', '', $output);
+
+		// Put the opening and closing tags back if applicable
+		if (isset($open_tag))
+		{
+			$output = $open_tag . $output . $closing_tag;
+		}
+
+		return $output;
+	}
 
 }
 
-- 
cgit v1.2.3-24-g4f1b


From 7747f0a2eecd85285a7f2acd223df6f54b543e0e Mon Sep 17 00:00:00 2001
From: Andrew Podner 
Date: Tue, 18 Dec 2012 13:13:15 -0500
Subject: fixes #2078: formatting / styleguide cleanup

---
 system/core/Output.php | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index e33f4b0b7..338c8b7e6 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -839,22 +839,22 @@ class CI_Output {
 		$array_output = str_split($output);
 		foreach ($array_output as $key => $value)
 		{
-			if ($in_string === FALSE and $in_dstring === FALSE)
+			if ($in_string === FALSE && $in_dstring === FALSE)
 			{
-				if ($value == ' ')
+				if ($value === ' ')
 				{
 					unset($array_output[$key]);
 				}
 			}
 
-			if ($value == "'")
+			if ($value === "'")
 			{
-				$in_string = !$in_string;
+				$in_string = ! $in_string;
 			}
 
-			if ($value == '"')
+			if ($value === '"')
 			{
-				$in_dstring = !$in_dstring;
+				$in_dstring = ! $in_dstring;
 			}
 		}
 
@@ -866,7 +866,7 @@ class CI_Output {
 		// Put the opening and closing tags back if applicable
 		if (isset($open_tag))
 		{
-			$output = $open_tag . $output . $closing_tag;
+			$output = $open_tag.$output.$closing_tag;
 		}
 
 		return $output;
-- 
cgit v1.2.3-24-g4f1b


From 9a171a0f7120e61e8bed44abda4930c5d8eeb256 Mon Sep 17 00:00:00 2001
From: Andrew Podner 
Date: Tue, 18 Dec 2012 13:18:25 -0500
Subject: fixes #2078: formatting / styleguide cleanup (take2)

---
 system/core/Output.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 338c8b7e6..3a94d97e1 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -782,7 +782,7 @@ class CI_Output {
 			case 'text/css':
 			case 'text/javascript':
 
-				$output = $this->_minify_scripts_css($output, $type);
+				$output = $this->_minify_script_style($output, $type);
 
 			break;
 
-- 
cgit v1.2.3-24-g4f1b


From 9dfceda245c7833edd3311ed0e5e5704db34e847 Mon Sep 17 00:00:00 2001
From: Andrew Podner 
Date: Tue, 18 Dec 2012 19:37:22 -0500
Subject: fixes #2078: changing type variable to boolean in protected method

---
 system/core/Output.php | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 3a94d97e1..2793d4132 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -728,13 +728,13 @@ class CI_Output {
 				preg_match_all('{}msU', $output, $style_clean);
 				foreach ($style_clean[0] as $s)
 				{
-					$output = str_replace($s, $this->_minify_script_style($s, $type), $output);
+					$output = str_replace($s, $this->_minify_script_style($s, TRUE), $output);
 				}
 
 				// Minify the javascript in }msU', $output, $javascript_clean);
-
-				// Minify the CSS in all the }msU', $output, $style_clean);
-				foreach ($style_clean[0] as $s)
-				{
-					$output = str_replace($s, $this->_minify_script_style($s, TRUE), $output);
-				}
-
-				// Minify the javascript in }msU', $output, $javascript_messed);
-					$output = str_replace($javascript_messed[0], $javascript_mini, $output);
-				}
-
-				$size_removed = $size_before - strlen($output);
-				$savings_percent = round(($size_removed / $size_before * 100));
-
-				log_message('debug', 'Minifier shaved '.($size_removed / 1000).'KB ('.$savings_percent.'%) off final HTML output.');
-
-			break;
-
-			case 'text/css':
-			case 'text/javascript':
-
-				$output = $this->_minify_script_style($output);
-
-			break;
-
-			default: break;
-		}
-
-		return $output;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Minify Style and Script
-	 *
-	 * Reduce excessive size of CSS/JavaScript content.  To remove spaces this
-	 * script walks the string as an array and determines if the pointer is inside
-	 * a string created by single quotes or double quotes.  spaces inside those
-	 * strings are not stripped.  Opening and closing tags are severed from
-	 * the string initially and saved without stripping whitespace to preserve
-	 * the tags and any associated properties if tags are present
-	 *
-	 * Minification logic/workflow is similar to methods used by Douglas Crockford
-	 * in JSMIN. http://www.crockford.com/javascript/jsmin.html
-	 *
-	 * KNOWN ISSUE: ending a line with a closing parenthesis ')' and no semicolon
-	 * where there should be one will break the Javascript. New lines after a
-	 * closing parenthesis are not recognized by the script. For best results
-	 * be sure to terminate lines with a semicolon when appropriate.
-	 *
-	 * @param	string	$output		Output to minify
-	 * @param	bool	$has_tags	Specify if the output has style or script tags
-	 * @return	string	Minified output
-	 */
-	protected function _minify_script_style($output, $has_tags = FALSE)
-	{
-		// We only need this if there are tags in the file
-		if ($has_tags === TRUE)
-		{
-			// Remove opening tag and save for later
-			$pos = strpos($output, '>') + 1;
-			$open_tag = substr($output, 0, $pos);
-			$output = substr_replace($output, '', 0, $pos);
-
-			// Remove closing tag and save it for later
-			$end_pos = strlen($output);
-			$pos = strpos($output, ' $value)
-		{
-			if ($in_string === FALSE && $in_dstring === FALSE)
-			{
-				if ($value === ' ')
-				{
-					// Get the next element in the array for comparisons
-					$next = $array_output[$key + 1];
-
-					// Strip spaces preceded/followed by a non-ASCII character
-					// or not preceded/followed by an alphanumeric
-					// or not preceded/followed \ $ and _
-					if ((preg_match('/^[\x20-\x7f]*$/D', $next) OR preg_match('/^[\x20-\x7f]*$/D', $prev))
-						&& ( ! ctype_alnum($next) OR ! ctype_alnum($prev))
-						&& ! in_array($next, array('\\', '_', '$'), TRUE)
-						&& ! in_array($prev, array('\\', '_', '$'), TRUE)
-					)
-					{
-						unset($array_output[$key]);
-					}
-				}
-				else
-				{
-					// Save this value as previous for the next iteration
-					// if it is not a blank space
-					$prev = $value;
-				}
-			}
-
-			if ($value === "'")
-			{
-				$in_string = ! $in_string;
-			}
-			elseif ($value === '"')
-			{
-				$in_dstring = ! $in_dstring;
-			}
-		}
-
-		// Put the string back together after spaces have been stripped
-		$output = implode($array_output);
-
-		// Remove new line characters unless previous or next character is
-		// printable or Non-ASCII
-		preg_match_all('/[\n]/', $output, $lf, PREG_OFFSET_CAPTURE);
-		$removed_lf = 0;
-		foreach ($lf as $feed_position)
-		{
-			foreach ($feed_position as $position)
-			{
-				$position = $position[1] - $removed_lf;
-				$next = $output[$position + 1];
-				$prev = $output[$position - 1];
-				if ( ! ctype_print($next) && ! ctype_print($prev)
-					&& ! preg_match('/^[\x20-\x7f]*$/D', $next)
-					&& ! preg_match('/^[\x20-\x7f]*$/D', $prev)
-				)
-				{
-					$output = substr_replace($output, '', $position, 1);
-					$removed_lf++;
-				}
-			}
-		}
-
-		// Put the opening and closing tags back if applicable
-		return isset($open_tag)
-			? $open_tag.$output.$closing_tag
-			: $output;
-	}
-
-}
-
-/* End of file Output.php */
+_zlib_oc = (bool) @ini_get('zlib.output_compression');
+
+		// Get mime types for later
+		$this->mimes =& get_mimes();
+
+		log_message('debug', 'Output Class Initialized');
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Get Output
+	 *
+	 * Returns the current output string.
+	 *
+	 * @return	string
+	 */
+	public function get_output()
+	{
+		return $this->final_output;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Set Output
+	 *
+	 * Sets the output string.
+	 *
+	 * @param	string	$output	Output data
+	 * @return	CI_Output
+	 */
+	public function set_output($output)
+	{
+		$this->final_output = $output;
+		return $this;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Append Output
+	 *
+	 * Appends data onto the output string.
+	 *
+	 * @param	string	$output	Data to append
+	 * @return	CI_Output
+	 */
+	public function append_output($output)
+	{
+		if (empty($this->final_output))
+		{
+			$this->final_output = $output;
+		}
+		else
+		{
+			$this->final_output .= $output;
+		}
+
+		return $this;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Set Header
+	 *
+	 * Lets you set a server header which will be sent with the final output.
+	 *
+	 * Note: If a file is cached, headers will not be sent.
+	 * @todo	We need to figure out how to permit headers to be cached.
+	 *
+	 * @param	string	$header		Header
+	 * @param	bool	$replace	Whether to replace the old header value, if already set
+	 * @return	CI_Output
+	 */
+	public function set_header($header, $replace = TRUE)
+	{
+		// If zlib.output_compression is enabled it will compress the output,
+		// but it will not modify the content-length header to compensate for
+		// the reduction, causing the browser to hang waiting for more data.
+		// We'll just skip content-length in those cases.
+		if ($this->_zlib_oc && strncasecmp($header, 'content-length', 14) === 0)
+		{
+			return $this;
+		}
+
+		$this->headers[] = array($header, $replace);
+		return $this;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Set Content-Type Header
+	 *
+	 * @param	string	$mime_type	Extension of the file we're outputting
+	 * @param	string	$charset	Character set (default: NULL)
+	 * @return	CI_Output
+	 */
+	public function set_content_type($mime_type, $charset = NULL)
+	{
+		if (strpos($mime_type, '/') === FALSE)
+		{
+			$extension = ltrim($mime_type, '.');
+
+			// Is this extension supported?
+			if (isset($this->mimes[$extension]))
+			{
+				$mime_type =& $this->mimes[$extension];
+
+				if (is_array($mime_type))
+				{
+					$mime_type = current($mime_type);
+				}
+			}
+		}
+
+		$this->mime_type = $mime_type;
+
+		if (empty($charset))
+		{
+			$charset = config_item('charset');
+		}
+
+		$header = 'Content-Type: '.$mime_type
+			.(empty($charset) ? NULL : '; 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
+	 * @return	CI_Output
+	 */
+	public function set_status_header($code = 200, $text = '')
+	{
+		set_status_header($code, $text);
+		return $this;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Enable/disable Profiler
+	 *
+	 * @param	bool	$val	TRUE to enable or FALSE to disable
+	 * @return	CI_Output
+	 */
+	public function enable_profiler($val = TRUE)
+	{
+		$this->enable_profiler = is_bool($val) ? $val : TRUE;
+		return $this;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Set Profiler Sections
+	 *
+	 * Allows override of default/config settings for
+	 * Profiler section display.
+	 *
+	 * @param	array	$sections	Profiler sections
+	 * @return	CI_Output
+	 */
+	public function set_profiler_sections($sections)
+	{
+		if (isset($sections['query_toggle_count']))
+		{
+			$this->_profiler_sections['query_toggle_count'] = (int) $sections['query_toggle_count'];
+			unset($sections['query_toggle_count']);
+		}
+
+		foreach ($sections as $section => $enable)
+		{
+			$this->_profiler_sections[$section] = ($enable !== FALSE);
+		}
+
+		return $this;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Set Cache
+	 *
+	 * @param	int	$time	Cache expiration time in seconds
+	 * @return	CI_Output
+	 */
+	public function cache($time)
+	{
+		$this->cache_expiration = is_numeric($time) ? $time : 0;
+		return $this;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Display Output
+	 *
+	 * Processes sends the sends finalized output data to the browser along
+	 * with any server headers and profile data. It also stops benchmark
+	 * timers so the page rendering speed and memory usage can be shown.
+	 *
+	 * Note: All "view" data is automatically put into $this->final_output
+	 *	 by controller class.
+	 *
+	 * @uses	CI_Output::$final_output
+	 * @param	string	$output	Output data override
+	 * @return	void
+	 */
+	public function _display($output = '')
+	{
+		// Note:  We use globals 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.
+		global $BM, $CFG;
+
+		// Grab the super object if we can.
+		if (class_exists('CI_Controller'))
+		{
+			$CI =& get_instance();
+		}
+
+		// --------------------------------------------------------------------
+
+		// Set the output data
+		if ($output === '')
+		{
+			$output =& $this->final_output;
+		}
+
+		// --------------------------------------------------------------------
+
+		// Is minify requested?
+		if ($CFG->item('minify_output') === TRUE)
+		{
+			$output = $this->minify($output, $this->mime_type);
+		}
+
+		// --------------------------------------------------------------------
+
+		// Do we need to write a cache file? Only if the controller does not have its
+		// own _output() method and we are not dealing with a cache file, which we
+		// can determine by the existence of the $CI object above
+		if ($this->cache_expiration > 0 && isset($CI) && ! method_exists($CI, '_output'))
+		{
+			$this->_write_cache($output);
+		}
+
+		// --------------------------------------------------------------------
+
+		// Parse out the elapsed time and memory usage,
+		// then swap the pseudo-variables with the data
+
+		$elapsed = $BM->elapsed_time('total_execution_time_start', 'total_execution_time_end');
+
+		if ($this->parse_exec_vars === TRUE)
+		{
+			$memory	= round(memory_get_usage() / 1024 / 1024, 2).'MB';
+
+			$output = str_replace(array('{elapsed_time}', '{memory_usage}'), array($elapsed, $memory), $output);
+		}
+
+		// --------------------------------------------------------------------
+
+		// Is compression requested?
+		if ($CFG->item('compress_output') === TRUE && $this->_zlib_oc === FALSE
+			&& extension_loaded('zlib')
+			&& 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))
+		{
+			echo $output;
+			log_message('debug', 'Final output sent to browser');
+			log_message('debug', 'Total execution time: '.$elapsed);
+			return;
+		}
+
+		// --------------------------------------------------------------------
+
+		// Do we need to generate profile data?
+		// If so, load the Profile class and run it.
+		if ($this->enable_profiler === TRUE)
+		{
+			$CI->load->library('profiler');
+			if ( ! empty($this->_profiler_sections))
+			{
+				$CI->profiler->set_sections($this->_profiler_sections);
+			}
+
+			// If the output data contains closing  and  tags
+			// we will remove them and add them back after we insert the profile data
+			$output = preg_replace('|.*?|is', '', $output, -1, $count).$CI->profiler->run();
+			if ($count > 0)
+			{
+				$output .= '';
+			}
+		}
+
+		// Does the controller contain a function named _output()?
+		// If so send the output there.  Otherwise, echo it.
+		if (method_exists($CI, '_output'))
+		{
+			$CI->_output($output);
+		}
+		else
+		{
+			echo $output; // Send it to the browser!
+		}
+
+		log_message('debug', 'Final output sent to browser');
+		log_message('debug', 'Total execution time: '.$elapsed);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Write Cache
+	 *
+	 * @param	string	$output	Output data to cache
+	 * @return	void
+	 */
+	public function _write_cache($output)
+	{
+		$CI =& get_instance();
+		$path = $CI->config->item('cache_path');
+		$cache_path = ($path === '') ? APPPATH.'cache/' : $path;
+
+		if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path))
+		{
+			log_message('error', 'Unable to write cache file: '.$cache_path);
+			return;
+		}
+
+		$uri =	$CI->config->item('base_url').
+				$CI->config->item('index_page').
+				$CI->uri->uri_string();
+
+		$cache_path .= md5($uri);
+
+		if ( ! $fp = @fopen($cache_path, FOPEN_WRITE_CREATE_DESTRUCTIVE))
+		{
+			log_message('error', 'Unable to write cache file: '.$cache_path);
+			return;
+		}
+
+		$expire = time() + ($this->cache_expiration * 60);
+
+		if (flock($fp, LOCK_EX))
+		{
+			fwrite($fp, $expire.'TS--->'.$output);
+			flock($fp, LOCK_UN);
+		}
+		else
+		{
+			log_message('error', 'Unable to secure a file lock for file at: '.$cache_path);
+			return;
+		}
+		fclose($fp);
+		@chmod($cache_path, FILE_WRITE_MODE);
+
+		log_message('debug', 'Cache file written: '.$cache_path);
+
+		// Send HTTP cache-control headers to browser to match file cache settings.
+		$this->set_cache_header($_SERVER['REQUEST_TIME'], $expire);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Update/serve cached output
+	 *
+	 * @uses	CI_Config
+	 * @uses	CI_URI
+	 *
+	 * @param	object	&$CFG	CI_Config class instance
+	 * @param	object	&$URI	CI_URI class instance
+	 * @return	bool	TRUE on success or FALSE on failure
+	 */
+	public function _display_cache(&$CFG, &$URI)
+	{
+		$cache_path = ($CFG->item('cache_path') === '') ? APPPATH.'cache/' : $CFG->item('cache_path');
+
+		// Build the file path. The file name is an MD5 hash of the full URI
+		$uri =	$CFG->item('base_url').$CFG->item('index_page').$URI->uri_string;
+		$filepath = $cache_path.md5($uri);
+
+		if ( ! @file_exists($filepath) OR ! $fp = @fopen($filepath, FOPEN_READ))
+		{
+			return FALSE;
+		}
+
+		flock($fp, LOCK_SH);
+
+		$cache = (filesize($filepath) > 0) ? fread($fp, filesize($filepath)) : '';
+
+		flock($fp, LOCK_UN);
+		fclose($fp);
+
+		// Strip out the embedded timestamp
+		if ( ! preg_match('/^(\d+)TS--->/', $cache, $match))
+		{
+			return FALSE;
+		}
+
+		$last_modified = filemtime($cache_path);
+		$expire = $match[1];
+
+		// 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);
+		}
+
+		// 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
+	 */
+	public function delete_cache($uri = '')
+	{
+		$CI =& get_instance();
+		$cache_path = $CI->config->item('cache_path');
+		if ($cache_path === '')
+		{
+			$cache_path = APPPATH.'cache/';
+		}
+
+		if ( ! is_dir($cache_path))
+		{
+			log_message('error', 'Unable to find cache path: '.$cache_path);
+			return FALSE;
+		}
+
+		if (empty($uri))
+		{
+			$uri = $CI->uri->uri_string();
+		}
+
+		$cache_path .= md5($CI->config->item('base_url').$CI->config->item('index_page').$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');
+		}
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Minify
+	 *
+	 * Reduce excessive size of HTML/CSS/JavaScript content.
+	 *
+	 * @param	string	$output	Output to minify
+	 * @param	string	$type	Output content MIME type
+	 * @return	string	Minified output
+	 */
+	public function minify($output, $type = 'text/html')
+	{
+		switch ($type)
+		{
+			case 'text/html':
+
+				if (($size_before = strlen($output)) === 0)
+				{
+					return '';
+				}
+
+				// Find all the 
,,}msU', $output, $textareas_clean);
+				preg_match_all('{}msU', $output, $javascript_clean);
+
+				// Minify the CSS in all the }msU', $output, $style_clean);
+				foreach ($style_clean[0] as $s)
+				{
+					$output = str_replace($s, $this->_minify_script_style($s, TRUE), $output);
+				}
+
+				// Minify the javascript in }msU', $output, $javascript_messed);
+					$output = str_replace($javascript_messed[0], $javascript_mini, $output);
+				}
+
+				$size_removed = $size_before - strlen($output);
+				$savings_percent = round(($size_removed / $size_before * 100));
+
+				log_message('debug', 'Minifier shaved '.($size_removed / 1000).'KB ('.$savings_percent.'%) off final HTML output.');
+
+			break;
+
+			case 'text/css':
+			case 'text/javascript':
+
+				$output = $this->_minify_script_style($output);
+
+			break;
+
+			default: break;
+		}
+
+		return $output;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Minify Style and Script
+	 *
+	 * Reduce excessive size of CSS/JavaScript content.  To remove spaces this
+	 * script walks the string as an array and determines if the pointer is inside
+	 * a string created by single quotes or double quotes.  spaces inside those
+	 * strings are not stripped.  Opening and closing tags are severed from
+	 * the string initially and saved without stripping whitespace to preserve
+	 * the tags and any associated properties if tags are present
+	 *
+	 * Minification logic/workflow is similar to methods used by Douglas Crockford
+	 * in JSMIN. http://www.crockford.com/javascript/jsmin.html
+	 *
+	 * KNOWN ISSUE: ending a line with a closing parenthesis ')' and no semicolon
+	 * where there should be one will break the Javascript. New lines after a
+	 * closing parenthesis are not recognized by the script. For best results
+	 * be sure to terminate lines with a semicolon when appropriate.
+	 *
+	 * @param	string	$output		Output to minify
+	 * @param	bool	$has_tags	Specify if the output has style or script tags
+	 * @return	string	Minified output
+	 */
+	protected function _minify_script_style($output, $has_tags = FALSE)
+	{
+		// We only need this if there are tags in the file
+		if ($has_tags === TRUE)
+		{
+			// Remove opening tag and save for later
+			$pos = strpos($output, '>') + 1;
+			$open_tag = substr($output, 0, $pos);
+			$output = substr_replace($output, '', 0, $pos);
+
+			// Remove closing tag and save it for later
+			$end_pos = strlen($output);
+			$pos = strpos($output, ' $value)
+		{
+			if ($in_string === FALSE && $in_dstring === FALSE)
+			{
+				if ($value === ' ')
+				{
+					// Get the next element in the array for comparisons
+					$next = $array_output[$key + 1];
+
+					// Strip spaces preceded/followed by a non-ASCII character
+					// or not preceded/followed by an alphanumeric
+					// or not preceded/followed \ $ and _
+					if ((preg_match('/^[\x20-\x7f]*$/D', $next) OR preg_match('/^[\x20-\x7f]*$/D', $prev))
+						&& ( ! ctype_alnum($next) OR ! ctype_alnum($prev))
+						&& ! in_array($next, array('\\', '_', '$'), TRUE)
+						&& ! in_array($prev, array('\\', '_', '$'), TRUE)
+					)
+					{
+						unset($array_output[$key]);
+					}
+				}
+				else
+				{
+					// Save this value as previous for the next iteration
+					// if it is not a blank space
+					$prev = $value;
+				}
+			}
+
+			if ($value === "'")
+			{
+				$in_string = ! $in_string;
+			}
+			elseif ($value === '"')
+			{
+				$in_dstring = ! $in_dstring;
+			}
+		}
+
+		// Put the string back together after spaces have been stripped
+		$output = implode($array_output);
+
+		// Remove new line characters unless previous or next character is
+		// printable or Non-ASCII
+		preg_match_all('/[\n]/', $output, $lf, PREG_OFFSET_CAPTURE);
+		$removed_lf = 0;
+		foreach ($lf as $feed_position)
+		{
+			foreach ($feed_position as $position)
+			{
+				$position = $position[1] - $removed_lf;
+				$next = $output[$position + 1];
+				$prev = $output[$position - 1];
+				if ( ! ctype_print($next) && ! ctype_print($prev)
+					&& ! preg_match('/^[\x20-\x7f]*$/D', $next)
+					&& ! preg_match('/^[\x20-\x7f]*$/D', $prev)
+				)
+				{
+					$output = substr_replace($output, '', $position, 1);
+					$removed_lf++;
+				}
+			}
+		}
+
+		// Put the opening and closing tags back if applicable
+		return isset($open_tag)
+			? $open_tag.$output.$closing_tag
+			: $output;
+	}
+
+}
+
+/* End of file Output.php */
 /* Location: ./system/core/Output.php */
\ No newline at end of file
-- 
cgit v1.2.3-24-g4f1b


From 362b80054ed80940064fd7891a9628279498504b Mon Sep 17 00:00:00 2001
From: Michael Dodge 
Date: Fri, 4 Jan 2013 23:18:39 -0700
Subject: Revert "Fix MSIE conditionals regex in minify output func"

This reverts commit 8e12c787042396e172a7448c65bd16c3015ffb0f.
---
 system/core/Output.php | 1842 ++++++++++++++++++++++++------------------------
 1 file changed, 921 insertions(+), 921 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index b45263942..ce0500e71 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -1,922 +1,922 @@
-_zlib_oc = (bool) @ini_get('zlib.output_compression');
-
-		// Get mime types for later
-		$this->mimes =& get_mimes();
-
-		log_message('debug', 'Output Class Initialized');
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Get Output
-	 *
-	 * Returns the current output string.
-	 *
-	 * @return	string
-	 */
-	public function get_output()
-	{
-		return $this->final_output;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Set Output
-	 *
-	 * Sets the output string.
-	 *
-	 * @param	string	$output	Output data
-	 * @return	CI_Output
-	 */
-	public function set_output($output)
-	{
-		$this->final_output = $output;
-		return $this;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Append Output
-	 *
-	 * Appends data onto the output string.
-	 *
-	 * @param	string	$output	Data to append
-	 * @return	CI_Output
-	 */
-	public function append_output($output)
-	{
-		if (empty($this->final_output))
-		{
-			$this->final_output = $output;
-		}
-		else
-		{
-			$this->final_output .= $output;
-		}
-
-		return $this;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Set Header
-	 *
-	 * Lets you set a server header which will be sent with the final output.
-	 *
-	 * Note: If a file is cached, headers will not be sent.
-	 * @todo	We need to figure out how to permit headers to be cached.
-	 *
-	 * @param	string	$header		Header
-	 * @param	bool	$replace	Whether to replace the old header value, if already set
-	 * @return	CI_Output
-	 */
-	public function set_header($header, $replace = TRUE)
-	{
-		// If zlib.output_compression is enabled it will compress the output,
-		// but it will not modify the content-length header to compensate for
-		// the reduction, causing the browser to hang waiting for more data.
-		// We'll just skip content-length in those cases.
-		if ($this->_zlib_oc && strncasecmp($header, 'content-length', 14) === 0)
-		{
-			return $this;
-		}
-
-		$this->headers[] = array($header, $replace);
-		return $this;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Set Content-Type Header
-	 *
-	 * @param	string	$mime_type	Extension of the file we're outputting
-	 * @param	string	$charset	Character set (default: NULL)
-	 * @return	CI_Output
-	 */
-	public function set_content_type($mime_type, $charset = NULL)
-	{
-		if (strpos($mime_type, '/') === FALSE)
-		{
-			$extension = ltrim($mime_type, '.');
-
-			// Is this extension supported?
-			if (isset($this->mimes[$extension]))
-			{
-				$mime_type =& $this->mimes[$extension];
-
-				if (is_array($mime_type))
-				{
-					$mime_type = current($mime_type);
-				}
-			}
-		}
-
-		$this->mime_type = $mime_type;
-
-		if (empty($charset))
-		{
-			$charset = config_item('charset');
-		}
-
-		$header = 'Content-Type: '.$mime_type
-			.(empty($charset) ? NULL : '; 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
-	 * @return	CI_Output
-	 */
-	public function set_status_header($code = 200, $text = '')
-	{
-		set_status_header($code, $text);
-		return $this;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Enable/disable Profiler
-	 *
-	 * @param	bool	$val	TRUE to enable or FALSE to disable
-	 * @return	CI_Output
-	 */
-	public function enable_profiler($val = TRUE)
-	{
-		$this->enable_profiler = is_bool($val) ? $val : TRUE;
-		return $this;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Set Profiler Sections
-	 *
-	 * Allows override of default/config settings for
-	 * Profiler section display.
-	 *
-	 * @param	array	$sections	Profiler sections
-	 * @return	CI_Output
-	 */
-	public function set_profiler_sections($sections)
-	{
-		if (isset($sections['query_toggle_count']))
-		{
-			$this->_profiler_sections['query_toggle_count'] = (int) $sections['query_toggle_count'];
-			unset($sections['query_toggle_count']);
-		}
-
-		foreach ($sections as $section => $enable)
-		{
-			$this->_profiler_sections[$section] = ($enable !== FALSE);
-		}
-
-		return $this;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Set Cache
-	 *
-	 * @param	int	$time	Cache expiration time in seconds
-	 * @return	CI_Output
-	 */
-	public function cache($time)
-	{
-		$this->cache_expiration = is_numeric($time) ? $time : 0;
-		return $this;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Display Output
-	 *
-	 * Processes sends the sends finalized output data to the browser along
-	 * with any server headers and profile data. It also stops benchmark
-	 * timers so the page rendering speed and memory usage can be shown.
-	 *
-	 * Note: All "view" data is automatically put into $this->final_output
-	 *	 by controller class.
-	 *
-	 * @uses	CI_Output::$final_output
-	 * @param	string	$output	Output data override
-	 * @return	void
-	 */
-	public function _display($output = '')
-	{
-		// Note:  We use globals 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.
-		global $BM, $CFG;
-
-		// Grab the super object if we can.
-		if (class_exists('CI_Controller'))
-		{
-			$CI =& get_instance();
-		}
-
-		// --------------------------------------------------------------------
-
-		// Set the output data
-		if ($output === '')
-		{
-			$output =& $this->final_output;
-		}
-
-		// --------------------------------------------------------------------
-
-		// Is minify requested?
-		if ($CFG->item('minify_output') === TRUE)
-		{
-			$output = $this->minify($output, $this->mime_type);
-		}
-
-		// --------------------------------------------------------------------
-
-		// Do we need to write a cache file? Only if the controller does not have its
-		// own _output() method and we are not dealing with a cache file, which we
-		// can determine by the existence of the $CI object above
-		if ($this->cache_expiration > 0 && isset($CI) && ! method_exists($CI, '_output'))
-		{
-			$this->_write_cache($output);
-		}
-
-		// --------------------------------------------------------------------
-
-		// Parse out the elapsed time and memory usage,
-		// then swap the pseudo-variables with the data
-
-		$elapsed = $BM->elapsed_time('total_execution_time_start', 'total_execution_time_end');
-
-		if ($this->parse_exec_vars === TRUE)
-		{
-			$memory	= round(memory_get_usage() / 1024 / 1024, 2).'MB';
-
-			$output = str_replace(array('{elapsed_time}', '{memory_usage}'), array($elapsed, $memory), $output);
-		}
-
-		// --------------------------------------------------------------------
-
-		// Is compression requested?
-		if ($CFG->item('compress_output') === TRUE && $this->_zlib_oc === FALSE
-			&& extension_loaded('zlib')
-			&& 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))
-		{
-			echo $output;
-			log_message('debug', 'Final output sent to browser');
-			log_message('debug', 'Total execution time: '.$elapsed);
-			return;
-		}
-
-		// --------------------------------------------------------------------
-
-		// Do we need to generate profile data?
-		// If so, load the Profile class and run it.
-		if ($this->enable_profiler === TRUE)
-		{
-			$CI->load->library('profiler');
-			if ( ! empty($this->_profiler_sections))
-			{
-				$CI->profiler->set_sections($this->_profiler_sections);
-			}
-
-			// If the output data contains closing  and  tags
-			// we will remove them and add them back after we insert the profile data
-			$output = preg_replace('|.*?|is', '', $output, -1, $count).$CI->profiler->run();
-			if ($count > 0)
-			{
-				$output .= '';
-			}
-		}
-
-		// Does the controller contain a function named _output()?
-		// If so send the output there.  Otherwise, echo it.
-		if (method_exists($CI, '_output'))
-		{
-			$CI->_output($output);
-		}
-		else
-		{
-			echo $output; // Send it to the browser!
-		}
-
-		log_message('debug', 'Final output sent to browser');
-		log_message('debug', 'Total execution time: '.$elapsed);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Write Cache
-	 *
-	 * @param	string	$output	Output data to cache
-	 * @return	void
-	 */
-	public function _write_cache($output)
-	{
-		$CI =& get_instance();
-		$path = $CI->config->item('cache_path');
-		$cache_path = ($path === '') ? APPPATH.'cache/' : $path;
-
-		if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path))
-		{
-			log_message('error', 'Unable to write cache file: '.$cache_path);
-			return;
-		}
-
-		$uri =	$CI->config->item('base_url').
-				$CI->config->item('index_page').
-				$CI->uri->uri_string();
-
-		$cache_path .= md5($uri);
-
-		if ( ! $fp = @fopen($cache_path, FOPEN_WRITE_CREATE_DESTRUCTIVE))
-		{
-			log_message('error', 'Unable to write cache file: '.$cache_path);
-			return;
-		}
-
-		$expire = time() + ($this->cache_expiration * 60);
-
-		if (flock($fp, LOCK_EX))
-		{
-			fwrite($fp, $expire.'TS--->'.$output);
-			flock($fp, LOCK_UN);
-		}
-		else
-		{
-			log_message('error', 'Unable to secure a file lock for file at: '.$cache_path);
-			return;
-		}
-		fclose($fp);
-		@chmod($cache_path, FILE_WRITE_MODE);
-
-		log_message('debug', 'Cache file written: '.$cache_path);
-
-		// Send HTTP cache-control headers to browser to match file cache settings.
-		$this->set_cache_header($_SERVER['REQUEST_TIME'], $expire);
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Update/serve cached output
-	 *
-	 * @uses	CI_Config
-	 * @uses	CI_URI
-	 *
-	 * @param	object	&$CFG	CI_Config class instance
-	 * @param	object	&$URI	CI_URI class instance
-	 * @return	bool	TRUE on success or FALSE on failure
-	 */
-	public function _display_cache(&$CFG, &$URI)
-	{
-		$cache_path = ($CFG->item('cache_path') === '') ? APPPATH.'cache/' : $CFG->item('cache_path');
-
-		// Build the file path. The file name is an MD5 hash of the full URI
-		$uri =	$CFG->item('base_url').$CFG->item('index_page').$URI->uri_string;
-		$filepath = $cache_path.md5($uri);
-
-		if ( ! @file_exists($filepath) OR ! $fp = @fopen($filepath, FOPEN_READ))
-		{
-			return FALSE;
-		}
-
-		flock($fp, LOCK_SH);
-
-		$cache = (filesize($filepath) > 0) ? fread($fp, filesize($filepath)) : '';
-
-		flock($fp, LOCK_UN);
-		fclose($fp);
-
-		// Strip out the embedded timestamp
-		if ( ! preg_match('/^(\d+)TS--->/', $cache, $match))
-		{
-			return FALSE;
-		}
-
-		$last_modified = filemtime($cache_path);
-		$expire = $match[1];
-
-		// 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);
-		}
-
-		// 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
-	 */
-	public function delete_cache($uri = '')
-	{
-		$CI =& get_instance();
-		$cache_path = $CI->config->item('cache_path');
-		if ($cache_path === '')
-		{
-			$cache_path = APPPATH.'cache/';
-		}
-
-		if ( ! is_dir($cache_path))
-		{
-			log_message('error', 'Unable to find cache path: '.$cache_path);
-			return FALSE;
-		}
-
-		if (empty($uri))
-		{
-			$uri = $CI->uri->uri_string();
-		}
-
-		$cache_path .= md5($CI->config->item('base_url').$CI->config->item('index_page').$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');
-		}
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Minify
-	 *
-	 * Reduce excessive size of HTML/CSS/JavaScript content.
-	 *
-	 * @param	string	$output	Output to minify
-	 * @param	string	$type	Output content MIME type
-	 * @return	string	Minified output
-	 */
-	public function minify($output, $type = 'text/html')
-	{
-		switch ($type)
-		{
-			case 'text/html':
-
-				if (($size_before = strlen($output)) === 0)
-				{
-					return '';
-				}
-
-				// Find all the 
,,}msU', $output, $textareas_clean);
-				preg_match_all('{}msU', $output, $javascript_clean);
-
-				// Minify the CSS in all the }msU', $output, $style_clean);
-				foreach ($style_clean[0] as $s)
-				{
-					$output = str_replace($s, $this->_minify_script_style($s, TRUE), $output);
-				}
-
-				// Minify the javascript in }msU', $output, $javascript_messed);
-					$output = str_replace($javascript_messed[0], $javascript_mini, $output);
-				}
-
-				$size_removed = $size_before - strlen($output);
-				$savings_percent = round(($size_removed / $size_before * 100));
-
-				log_message('debug', 'Minifier shaved '.($size_removed / 1000).'KB ('.$savings_percent.'%) off final HTML output.');
-
-			break;
-
-			case 'text/css':
-			case 'text/javascript':
-
-				$output = $this->_minify_script_style($output);
-
-			break;
-
-			default: break;
-		}
-
-		return $output;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Minify Style and Script
-	 *
-	 * Reduce excessive size of CSS/JavaScript content.  To remove spaces this
-	 * script walks the string as an array and determines if the pointer is inside
-	 * a string created by single quotes or double quotes.  spaces inside those
-	 * strings are not stripped.  Opening and closing tags are severed from
-	 * the string initially and saved without stripping whitespace to preserve
-	 * the tags and any associated properties if tags are present
-	 *
-	 * Minification logic/workflow is similar to methods used by Douglas Crockford
-	 * in JSMIN. http://www.crockford.com/javascript/jsmin.html
-	 *
-	 * KNOWN ISSUE: ending a line with a closing parenthesis ')' and no semicolon
-	 * where there should be one will break the Javascript. New lines after a
-	 * closing parenthesis are not recognized by the script. For best results
-	 * be sure to terminate lines with a semicolon when appropriate.
-	 *
-	 * @param	string	$output		Output to minify
-	 * @param	bool	$has_tags	Specify if the output has style or script tags
-	 * @return	string	Minified output
-	 */
-	protected function _minify_script_style($output, $has_tags = FALSE)
-	{
-		// We only need this if there are tags in the file
-		if ($has_tags === TRUE)
-		{
-			// Remove opening tag and save for later
-			$pos = strpos($output, '>') + 1;
-			$open_tag = substr($output, 0, $pos);
-			$output = substr_replace($output, '', 0, $pos);
-
-			// Remove closing tag and save it for later
-			$end_pos = strlen($output);
-			$pos = strpos($output, ' $value)
-		{
-			if ($in_string === FALSE && $in_dstring === FALSE)
-			{
-				if ($value === ' ')
-				{
-					// Get the next element in the array for comparisons
-					$next = $array_output[$key + 1];
-
-					// Strip spaces preceded/followed by a non-ASCII character
-					// or not preceded/followed by an alphanumeric
-					// or not preceded/followed \ $ and _
-					if ((preg_match('/^[\x20-\x7f]*$/D', $next) OR preg_match('/^[\x20-\x7f]*$/D', $prev))
-						&& ( ! ctype_alnum($next) OR ! ctype_alnum($prev))
-						&& ! in_array($next, array('\\', '_', '$'), TRUE)
-						&& ! in_array($prev, array('\\', '_', '$'), TRUE)
-					)
-					{
-						unset($array_output[$key]);
-					}
-				}
-				else
-				{
-					// Save this value as previous for the next iteration
-					// if it is not a blank space
-					$prev = $value;
-				}
-			}
-
-			if ($value === "'")
-			{
-				$in_string = ! $in_string;
-			}
-			elseif ($value === '"')
-			{
-				$in_dstring = ! $in_dstring;
-			}
-		}
-
-		// Put the string back together after spaces have been stripped
-		$output = implode($array_output);
-
-		// Remove new line characters unless previous or next character is
-		// printable or Non-ASCII
-		preg_match_all('/[\n]/', $output, $lf, PREG_OFFSET_CAPTURE);
-		$removed_lf = 0;
-		foreach ($lf as $feed_position)
-		{
-			foreach ($feed_position as $position)
-			{
-				$position = $position[1] - $removed_lf;
-				$next = $output[$position + 1];
-				$prev = $output[$position - 1];
-				if ( ! ctype_print($next) && ! ctype_print($prev)
-					&& ! preg_match('/^[\x20-\x7f]*$/D', $next)
-					&& ! preg_match('/^[\x20-\x7f]*$/D', $prev)
-				)
-				{
-					$output = substr_replace($output, '', $position, 1);
-					$removed_lf++;
-				}
-			}
-		}
-
-		// Put the opening and closing tags back if applicable
-		return isset($open_tag)
-			? $open_tag.$output.$closing_tag
-			: $output;
-	}
-
-}
-
-/* End of file Output.php */
+_zlib_oc = (bool) @ini_get('zlib.output_compression');
+
+		// Get mime types for later
+		$this->mimes =& get_mimes();
+
+		log_message('debug', 'Output Class Initialized');
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Get Output
+	 *
+	 * Returns the current output string.
+	 *
+	 * @return	string
+	 */
+	public function get_output()
+	{
+		return $this->final_output;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Set Output
+	 *
+	 * Sets the output string.
+	 *
+	 * @param	string	$output	Output data
+	 * @return	CI_Output
+	 */
+	public function set_output($output)
+	{
+		$this->final_output = $output;
+		return $this;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Append Output
+	 *
+	 * Appends data onto the output string.
+	 *
+	 * @param	string	$output	Data to append
+	 * @return	CI_Output
+	 */
+	public function append_output($output)
+	{
+		if (empty($this->final_output))
+		{
+			$this->final_output = $output;
+		}
+		else
+		{
+			$this->final_output .= $output;
+		}
+
+		return $this;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Set Header
+	 *
+	 * Lets you set a server header which will be sent with the final output.
+	 *
+	 * Note: If a file is cached, headers will not be sent.
+	 * @todo	We need to figure out how to permit headers to be cached.
+	 *
+	 * @param	string	$header		Header
+	 * @param	bool	$replace	Whether to replace the old header value, if already set
+	 * @return	CI_Output
+	 */
+	public function set_header($header, $replace = TRUE)
+	{
+		// If zlib.output_compression is enabled it will compress the output,
+		// but it will not modify the content-length header to compensate for
+		// the reduction, causing the browser to hang waiting for more data.
+		// We'll just skip content-length in those cases.
+		if ($this->_zlib_oc && strncasecmp($header, 'content-length', 14) === 0)
+		{
+			return $this;
+		}
+
+		$this->headers[] = array($header, $replace);
+		return $this;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Set Content-Type Header
+	 *
+	 * @param	string	$mime_type	Extension of the file we're outputting
+	 * @param	string	$charset	Character set (default: NULL)
+	 * @return	CI_Output
+	 */
+	public function set_content_type($mime_type, $charset = NULL)
+	{
+		if (strpos($mime_type, '/') === FALSE)
+		{
+			$extension = ltrim($mime_type, '.');
+
+			// Is this extension supported?
+			if (isset($this->mimes[$extension]))
+			{
+				$mime_type =& $this->mimes[$extension];
+
+				if (is_array($mime_type))
+				{
+					$mime_type = current($mime_type);
+				}
+			}
+		}
+
+		$this->mime_type = $mime_type;
+
+		if (empty($charset))
+		{
+			$charset = config_item('charset');
+		}
+
+		$header = 'Content-Type: '.$mime_type
+			.(empty($charset) ? NULL : '; 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
+	 * @return	CI_Output
+	 */
+	public function set_status_header($code = 200, $text = '')
+	{
+		set_status_header($code, $text);
+		return $this;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Enable/disable Profiler
+	 *
+	 * @param	bool	$val	TRUE to enable or FALSE to disable
+	 * @return	CI_Output
+	 */
+	public function enable_profiler($val = TRUE)
+	{
+		$this->enable_profiler = is_bool($val) ? $val : TRUE;
+		return $this;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Set Profiler Sections
+	 *
+	 * Allows override of default/config settings for
+	 * Profiler section display.
+	 *
+	 * @param	array	$sections	Profiler sections
+	 * @return	CI_Output
+	 */
+	public function set_profiler_sections($sections)
+	{
+		if (isset($sections['query_toggle_count']))
+		{
+			$this->_profiler_sections['query_toggle_count'] = (int) $sections['query_toggle_count'];
+			unset($sections['query_toggle_count']);
+		}
+
+		foreach ($sections as $section => $enable)
+		{
+			$this->_profiler_sections[$section] = ($enable !== FALSE);
+		}
+
+		return $this;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Set Cache
+	 *
+	 * @param	int	$time	Cache expiration time in seconds
+	 * @return	CI_Output
+	 */
+	public function cache($time)
+	{
+		$this->cache_expiration = is_numeric($time) ? $time : 0;
+		return $this;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Display Output
+	 *
+	 * Processes sends the sends finalized output data to the browser along
+	 * with any server headers and profile data. It also stops benchmark
+	 * timers so the page rendering speed and memory usage can be shown.
+	 *
+	 * Note: All "view" data is automatically put into $this->final_output
+	 *	 by controller class.
+	 *
+	 * @uses	CI_Output::$final_output
+	 * @param	string	$output	Output data override
+	 * @return	void
+	 */
+	public function _display($output = '')
+	{
+		// Note:  We use globals 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.
+		global $BM, $CFG;
+
+		// Grab the super object if we can.
+		if (class_exists('CI_Controller'))
+		{
+			$CI =& get_instance();
+		}
+
+		// --------------------------------------------------------------------
+
+		// Set the output data
+		if ($output === '')
+		{
+			$output =& $this->final_output;
+		}
+
+		// --------------------------------------------------------------------
+
+		// Is minify requested?
+		if ($CFG->item('minify_output') === TRUE)
+		{
+			$output = $this->minify($output, $this->mime_type);
+		}
+
+		// --------------------------------------------------------------------
+
+		// Do we need to write a cache file? Only if the controller does not have its
+		// own _output() method and we are not dealing with a cache file, which we
+		// can determine by the existence of the $CI object above
+		if ($this->cache_expiration > 0 && isset($CI) && ! method_exists($CI, '_output'))
+		{
+			$this->_write_cache($output);
+		}
+
+		// --------------------------------------------------------------------
+
+		// Parse out the elapsed time and memory usage,
+		// then swap the pseudo-variables with the data
+
+		$elapsed = $BM->elapsed_time('total_execution_time_start', 'total_execution_time_end');
+
+		if ($this->parse_exec_vars === TRUE)
+		{
+			$memory	= round(memory_get_usage() / 1024 / 1024, 2).'MB';
+
+			$output = str_replace(array('{elapsed_time}', '{memory_usage}'), array($elapsed, $memory), $output);
+		}
+
+		// --------------------------------------------------------------------
+
+		// Is compression requested?
+		if ($CFG->item('compress_output') === TRUE && $this->_zlib_oc === FALSE
+			&& extension_loaded('zlib')
+			&& 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))
+		{
+			echo $output;
+			log_message('debug', 'Final output sent to browser');
+			log_message('debug', 'Total execution time: '.$elapsed);
+			return;
+		}
+
+		// --------------------------------------------------------------------
+
+		// Do we need to generate profile data?
+		// If so, load the Profile class and run it.
+		if ($this->enable_profiler === TRUE)
+		{
+			$CI->load->library('profiler');
+			if ( ! empty($this->_profiler_sections))
+			{
+				$CI->profiler->set_sections($this->_profiler_sections);
+			}
+
+			// If the output data contains closing  and  tags
+			// we will remove them and add them back after we insert the profile data
+			$output = preg_replace('|.*?|is', '', $output, -1, $count).$CI->profiler->run();
+			if ($count > 0)
+			{
+				$output .= '';
+			}
+		}
+
+		// Does the controller contain a function named _output()?
+		// If so send the output there.  Otherwise, echo it.
+		if (method_exists($CI, '_output'))
+		{
+			$CI->_output($output);
+		}
+		else
+		{
+			echo $output; // Send it to the browser!
+		}
+
+		log_message('debug', 'Final output sent to browser');
+		log_message('debug', 'Total execution time: '.$elapsed);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Write Cache
+	 *
+	 * @param	string	$output	Output data to cache
+	 * @return	void
+	 */
+	public function _write_cache($output)
+	{
+		$CI =& get_instance();
+		$path = $CI->config->item('cache_path');
+		$cache_path = ($path === '') ? APPPATH.'cache/' : $path;
+
+		if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path))
+		{
+			log_message('error', 'Unable to write cache file: '.$cache_path);
+			return;
+		}
+
+		$uri =	$CI->config->item('base_url').
+				$CI->config->item('index_page').
+				$CI->uri->uri_string();
+
+		$cache_path .= md5($uri);
+
+		if ( ! $fp = @fopen($cache_path, FOPEN_WRITE_CREATE_DESTRUCTIVE))
+		{
+			log_message('error', 'Unable to write cache file: '.$cache_path);
+			return;
+		}
+
+		$expire = time() + ($this->cache_expiration * 60);
+
+		if (flock($fp, LOCK_EX))
+		{
+			fwrite($fp, $expire.'TS--->'.$output);
+			flock($fp, LOCK_UN);
+		}
+		else
+		{
+			log_message('error', 'Unable to secure a file lock for file at: '.$cache_path);
+			return;
+		}
+		fclose($fp);
+		@chmod($cache_path, FILE_WRITE_MODE);
+
+		log_message('debug', 'Cache file written: '.$cache_path);
+
+		// Send HTTP cache-control headers to browser to match file cache settings.
+		$this->set_cache_header($_SERVER['REQUEST_TIME'], $expire);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Update/serve cached output
+	 *
+	 * @uses	CI_Config
+	 * @uses	CI_URI
+	 *
+	 * @param	object	&$CFG	CI_Config class instance
+	 * @param	object	&$URI	CI_URI class instance
+	 * @return	bool	TRUE on success or FALSE on failure
+	 */
+	public function _display_cache(&$CFG, &$URI)
+	{
+		$cache_path = ($CFG->item('cache_path') === '') ? APPPATH.'cache/' : $CFG->item('cache_path');
+
+		// Build the file path. The file name is an MD5 hash of the full URI
+		$uri =	$CFG->item('base_url').$CFG->item('index_page').$URI->uri_string;
+		$filepath = $cache_path.md5($uri);
+
+		if ( ! @file_exists($filepath) OR ! $fp = @fopen($filepath, FOPEN_READ))
+		{
+			return FALSE;
+		}
+
+		flock($fp, LOCK_SH);
+
+		$cache = (filesize($filepath) > 0) ? fread($fp, filesize($filepath)) : '';
+
+		flock($fp, LOCK_UN);
+		fclose($fp);
+
+		// Strip out the embedded timestamp
+		if ( ! preg_match('/^(\d+)TS--->/', $cache, $match))
+		{
+			return FALSE;
+		}
+
+		$last_modified = filemtime($cache_path);
+		$expire = $match[1];
+
+		// 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);
+		}
+
+		// 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
+	 */
+	public function delete_cache($uri = '')
+	{
+		$CI =& get_instance();
+		$cache_path = $CI->config->item('cache_path');
+		if ($cache_path === '')
+		{
+			$cache_path = APPPATH.'cache/';
+		}
+
+		if ( ! is_dir($cache_path))
+		{
+			log_message('error', 'Unable to find cache path: '.$cache_path);
+			return FALSE;
+		}
+
+		if (empty($uri))
+		{
+			$uri = $CI->uri->uri_string();
+		}
+
+		$cache_path .= md5($CI->config->item('base_url').$CI->config->item('index_page').$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');
+		}
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Minify
+	 *
+	 * Reduce excessive size of HTML/CSS/JavaScript content.
+	 *
+	 * @param	string	$output	Output to minify
+	 * @param	string	$type	Output content MIME type
+	 * @return	string	Minified output
+	 */
+	public function minify($output, $type = 'text/html')
+	{
+		switch ($type)
+		{
+			case 'text/html':
+
+				if (($size_before = strlen($output)) === 0)
+				{
+					return '';
+				}
+
+				// Find all the 
,,}msU', $output, $textareas_clean);
+				preg_match_all('{}msU', $output, $javascript_clean);
+
+				// Minify the CSS in all the }msU', $output, $style_clean);
+				foreach ($style_clean[0] as $s)
+				{
+					$output = str_replace($s, $this->_minify_script_style($s, TRUE), $output);
+				}
+
+				// Minify the javascript in }msU', $output, $javascript_messed);
+					$output = str_replace($javascript_messed[0], $javascript_mini, $output);
+				}
+
+				$size_removed = $size_before - strlen($output);
+				$savings_percent = round(($size_removed / $size_before * 100));
+
+				log_message('debug', 'Minifier shaved '.($size_removed / 1000).'KB ('.$savings_percent.'%) off final HTML output.');
+
+			break;
+
+			case 'text/css':
+			case 'text/javascript':
+
+				$output = $this->_minify_script_style($output);
+
+			break;
+
+			default: break;
+		}
+
+		return $output;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Minify Style and Script
+	 *
+	 * Reduce excessive size of CSS/JavaScript content.  To remove spaces this
+	 * script walks the string as an array and determines if the pointer is inside
+	 * a string created by single quotes or double quotes.  spaces inside those
+	 * strings are not stripped.  Opening and closing tags are severed from
+	 * the string initially and saved without stripping whitespace to preserve
+	 * the tags and any associated properties if tags are present
+	 *
+	 * Minification logic/workflow is similar to methods used by Douglas Crockford
+	 * in JSMIN. http://www.crockford.com/javascript/jsmin.html
+	 *
+	 * KNOWN ISSUE: ending a line with a closing parenthesis ')' and no semicolon
+	 * where there should be one will break the Javascript. New lines after a
+	 * closing parenthesis are not recognized by the script. For best results
+	 * be sure to terminate lines with a semicolon when appropriate.
+	 *
+	 * @param	string	$output		Output to minify
+	 * @param	bool	$has_tags	Specify if the output has style or script tags
+	 * @return	string	Minified output
+	 */
+	protected function _minify_script_style($output, $has_tags = FALSE)
+	{
+		// We only need this if there are tags in the file
+		if ($has_tags === TRUE)
+		{
+			// Remove opening tag and save for later
+			$pos = strpos($output, '>') + 1;
+			$open_tag = substr($output, 0, $pos);
+			$output = substr_replace($output, '', 0, $pos);
+
+			// Remove closing tag and save it for later
+			$end_pos = strlen($output);
+			$pos = strpos($output, ' $value)
+		{
+			if ($in_string === FALSE && $in_dstring === FALSE)
+			{
+				if ($value === ' ')
+				{
+					// Get the next element in the array for comparisons
+					$next = $array_output[$key + 1];
+
+					// Strip spaces preceded/followed by a non-ASCII character
+					// or not preceded/followed by an alphanumeric
+					// or not preceded/followed \ $ and _
+					if ((preg_match('/^[\x20-\x7f]*$/D', $next) OR preg_match('/^[\x20-\x7f]*$/D', $prev))
+						&& ( ! ctype_alnum($next) OR ! ctype_alnum($prev))
+						&& ! in_array($next, array('\\', '_', '$'), TRUE)
+						&& ! in_array($prev, array('\\', '_', '$'), TRUE)
+					)
+					{
+						unset($array_output[$key]);
+					}
+				}
+				else
+				{
+					// Save this value as previous for the next iteration
+					// if it is not a blank space
+					$prev = $value;
+				}
+			}
+
+			if ($value === "'")
+			{
+				$in_string = ! $in_string;
+			}
+			elseif ($value === '"')
+			{
+				$in_dstring = ! $in_dstring;
+			}
+		}
+
+		// Put the string back together after spaces have been stripped
+		$output = implode($array_output);
+
+		// Remove new line characters unless previous or next character is
+		// printable or Non-ASCII
+		preg_match_all('/[\n]/', $output, $lf, PREG_OFFSET_CAPTURE);
+		$removed_lf = 0;
+		foreach ($lf as $feed_position)
+		{
+			foreach ($feed_position as $position)
+			{
+				$position = $position[1] - $removed_lf;
+				$next = $output[$position + 1];
+				$prev = $output[$position - 1];
+				if ( ! ctype_print($next) && ! ctype_print($prev)
+					&& ! preg_match('/^[\x20-\x7f]*$/D', $next)
+					&& ! preg_match('/^[\x20-\x7f]*$/D', $prev)
+				)
+				{
+					$output = substr_replace($output, '', $position, 1);
+					$removed_lf++;
+				}
+			}
+		}
+
+		// Put the opening and closing tags back if applicable
+		return isset($open_tag)
+			? $open_tag.$output.$closing_tag
+			: $output;
+	}
+
+}
+
+/* End of file Output.php */
 /* Location: ./system/core/Output.php */
\ No newline at end of file
-- 
cgit v1.2.3-24-g4f1b


From 4d02e356cadd9af49c915c76b7cd27d01e67edb8 Mon Sep 17 00:00:00 2001
From: Michael Dodge 
Date: Fri, 4 Jan 2013 23:22:51 -0700
Subject: Fix MSIE conditionals regex in minify output

Allows IE conditionals like the following to remain unmodified.
```html
  
```
Credit to joebert regex from

http://www.sitepoint.com/forums/showthread.php?696559-Regex-pattern-to-strip-HTML-comments-but-leave-conditonals&s=3eef4ceb0a59b2fdb946fa56220fb6fd&p=4678083&viewfull=1#post4678083
---
 system/core/Output.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index ce0500e71..27e711783 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -739,7 +739,7 @@ class CI_Output {
 				$output = preg_replace('!\s{2,}!', ' ', $output);
 
 				// Remove comments (non-MSIE conditionals)
-				$output = preg_replace('{\s*\s*}msU', '', $output);
+				$output = preg_replace('{\s*\s*}msU', '', $output);
 
 				// Remove spaces around block-level elements.
 				$output = preg_replace('/\s*(<\/?(html|head|title|meta|script|link|style|body|h[1-6]|div|p|br)[^>]*>)\s*/is', '$1', $output);
-- 
cgit v1.2.3-24-g4f1b


From c90e67ea553f1ff0fc22f280583fca22f95f9f42 Mon Sep 17 00:00:00 2001
From: Eric Roberts 
Date: Fri, 11 Jan 2013 21:20:54 -0600
Subject: Improve output cache.

---
 system/core/Output.php | 34 ++++++++++++++++++++++++----------
 1 file changed, 24 insertions(+), 10 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 27e711783..52a551858 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -58,21 +58,21 @@ class CI_Output {
 	 *
 	 * @var	array
 	 */
-	public $headers =	array();
+	public $headers = array();
 
 	/**
 	 * List of mime types
 	 *
 	 * @var	array
 	 */
-	public $mimes =		array();
+	public $mimes = array();
 
 	/**
 	 * Mime-type for the current page
 	 *
 	 * @var	string
 	 */
-	protected $mime_type	= 'text/html';
+	protected $mime_type = 'text/html';
 
 	/**
 	 * Enable Profiler flag
@@ -86,14 +86,14 @@ class CI_Output {
 	 *
 	 * @var	bool
 	 */
-	protected $_zlib_oc =		FALSE;
+	protected $_zlib_oc = FALSE;
 
 	/**
 	 * List of profiler sections
 	 *
 	 * @var	array
 	 */
-	protected $_profiler_sections =	array();
+	protected $_profiler_sections = array();
 
 	/**
 	 * Parse markers flag
@@ -102,7 +102,7 @@ class CI_Output {
 	 *
 	 * @var	bool
 	 */
-	public $parse_exec_vars =	TRUE;
+	public $parse_exec_vars = TRUE;
 
 	/**
 	 * Class constructor
@@ -543,10 +543,16 @@ class CI_Output {
 		}
 
 		$expire = time() + ($this->cache_expiration * 60);
+		
+		// Put together our serialized info.
+		$cache_info = serialize(array(
+			'expire'	=> $expire,
+			'headers'	=> $this->headers
+		));
 
 		if (flock($fp, LOCK_EX))
 		{
-			fwrite($fp, $expire.'TS--->'.$output);
+			fwrite($fp, $cache_info.'ENDCI--->'.$output);
 			flock($fp, LOCK_UN);
 		}
 		else
@@ -595,14 +601,16 @@ class CI_Output {
 		flock($fp, LOCK_UN);
 		fclose($fp);
 
-		// Strip out the embedded timestamp
-		if ( ! preg_match('/^(\d+)TS--->/', $cache, $match))
+		// 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($cache_path);
-		$expire = $match[1];
 
 		// Has the file expired?
 		if ($_SERVER['REQUEST_TIME'] >= $expire && is_really_writable($cache_path))
@@ -617,6 +625,12 @@ class CI_Output {
 			// 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])));
-- 
cgit v1.2.3-24-g4f1b


From 3e6b58215a78f63f43a62c584a1386bda2a1f3e1 Mon Sep 17 00:00:00 2001
From: Eric Roberts 
Date: Thu, 17 Jan 2013 18:30:25 -0600
Subject: Return spacing on var definitions.

Signed-off-by: Eric Roberts 
---
 system/core/Output.php | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 52a551858..e6c48b5dd 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -58,21 +58,21 @@ class CI_Output {
 	 *
 	 * @var	array
 	 */
-	public $headers = array();
+	public $headers =	array();
 
 	/**
 	 * List of mime types
 	 *
 	 * @var	array
 	 */
-	public $mimes = array();
+	public $mimes =		array();
 
 	/**
 	 * Mime-type for the current page
 	 *
 	 * @var	string
 	 */
-	protected $mime_type = 'text/html';
+	protected $mime_type	= 'text/html';
 
 	/**
 	 * Enable Profiler flag
@@ -86,14 +86,14 @@ class CI_Output {
 	 *
 	 * @var	bool
 	 */
-	protected $_zlib_oc = FALSE;
+	protected $_zlib_oc =		FALSE;
 
 	/**
 	 * List of profiler sections
 	 *
 	 * @var	array
 	 */
-	protected $_profiler_sections = array();
+	protected $_profiler_sections =	array();
 
 	/**
 	 * Parse markers flag
@@ -102,7 +102,7 @@ class CI_Output {
 	 *
 	 * @var	bool
 	 */
-	public $parse_exec_vars = TRUE;
+	public $parse_exec_vars =	TRUE;
 
 	/**
 	 * Class constructor
-- 
cgit v1.2.3-24-g4f1b


From 5dc6d51091b718d37d2c4b30da1e01b5b95333f8 Mon Sep 17 00:00:00 2001
From: Purwandi 
Date: Sat, 19 Jan 2013 17:43:08 +0700
Subject: Support minify table block

---
 system/core/Output.php | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index e6c48b5dd..cf5178a0c 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -543,7 +543,7 @@ class CI_Output {
 		}
 
 		$expire = time() + ($this->cache_expiration * 60);
-		
+
 		// Put together our serialized info.
 		$cache_info = serialize(array(
 			'expire'	=> $expire,
@@ -606,7 +606,7 @@ class CI_Output {
 		{
 			return FALSE;
 		}
-		
+
 		$cache_info = unserialize($match[1]);
 		$expire = $cache_info['expire'];
 
@@ -625,7 +625,7 @@ class CI_Output {
 			// 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)
 		{
@@ -756,7 +756,7 @@ class CI_Output {
 				$output = preg_replace('{\s*\s*}msU', '', $output);
 
 				// Remove spaces around block-level elements.
-				$output = preg_replace('/\s*(<\/?(html|head|title|meta|script|link|style|body|h[1-6]|div|p|br)[^>]*>)\s*/is', '$1', $output);
+				$output = preg_replace('/\s*(<\/?(html|head|title|meta|script|link|style|body|table|thead|tbody|tfoot|tr|th|td|h[1-6]|div|p|br)[^>]*>)\s*/is', '$1', $output);
 
 				// Replace mangled 
 etc. tags with unprocessed ones.
 
-- 
cgit v1.2.3-24-g4f1b


From 3ffce987e0d7efa68bbce2d83915b06e97bd3475 Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Mon, 21 Jan 2013 15:24:09 +0200
Subject: [ci skip] Manually apply #2162, #2163

---
 system/core/Output.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index cf5178a0c..a20841463 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -772,7 +772,7 @@ class CI_Output {
 					$output = str_replace($codes_messed[0], $codes_clean[0], $output);
 				}
 
-				if ( ! empty($codes_clean))
+				if ( ! empty($textareas_clean))
 				{
 					preg_match_all('{}msU', $output, $textareas_messed);
 					$output = str_replace($textareas_messed[0], $textareas_clean[0], $output);
-- 
cgit v1.2.3-24-g4f1b


From 49e68de96b420a444c826995746a5f09470e76d9 Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Thu, 21 Feb 2013 16:30:55 +0200
Subject: Disable autoloader call from class_exists() occurences to improve
 performance

Note: The Driver libary tests seem to depend on that, so one occurence in CI_Loader is left until we resolve that.
---
 system/core/Output.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index a20841463..25ecd496c 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -395,7 +395,7 @@ class CI_Output {
 		global $BM, $CFG;
 
 		// Grab the super object if we can.
-		if (class_exists('CI_Controller'))
+		if (class_exists('CI_Controller', FALSE))
 		{
 			$CI =& get_instance();
 		}
-- 
cgit v1.2.3-24-g4f1b


From 7b90325ceb8aa6fdb4680afe959927fc000bf548 Mon Sep 17 00:00:00 2001
From: bayssmekanique 
Date: Tue, 12 Mar 2013 13:25:24 -0700
Subject: Output Class Minify Function Change

Added 2 additional MIME types to match against for JavaScript detection.
---
 system/core/Output.php | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 25ecd496c..3320ae154 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -793,6 +793,8 @@ class CI_Output {
 
 			case 'text/css':
 			case 'text/javascript':
+			case 'application/javascript':
+			case 'application/x-javascript':
 
 				$output = $this->_minify_script_style($output);
 
-- 
cgit v1.2.3-24-g4f1b


From ccdd4290aca2ddb3c64ca3db57e1da5c34537a6a Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Fri, 5 Apr 2013 14:28:04 +0300
Subject: Fix #2387

---
 system/core/Output.php | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 3320ae154..8f4690052 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -841,9 +841,8 @@ class CI_Output {
 			$output = substr_replace($output, '', 0, $pos);
 
 			// Remove closing tag and save it for later
-			$end_pos = strlen($output);
 			$pos = strpos($output, '= 0; $i--)
+		{
+		        $output = substr_replace(
+		                $output,
+		                preg_replace('/\s*(:|;|,|}|{|\(|\))\s*/i', '$1', $chunks[$i][0]),
+		                $chunks[$i][1],
+		                strlen($chunks[$i][0])
+		        );
+		}
 
 		// Replace tabs with spaces
 		// Replace carriage returns & multiple new lines with single new line
-- 
cgit v1.2.3-24-g4f1b


From 8e038d50e8c94d610bfdedf01318462b7ddd8670 Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Fri, 5 Apr 2013 19:31:04 +0300
Subject: [ci skip] Replace spaces with tabs

---
 system/core/Output.php | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 8f4690052..06d7a866b 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -854,12 +854,12 @@ class CI_Output {
 		$chunks = preg_split('/([\'|"]).+(?![^\\\]\\1)\\1/iU', $output, -1, PREG_SPLIT_OFFSET_CAPTURE);
 		for ($i = count($chunks) - 1; $i >= 0; $i--)
 		{
-		        $output = substr_replace(
-		                $output,
-		                preg_replace('/\s*(:|;|,|}|{|\(|\))\s*/i', '$1', $chunks[$i][0]),
-		                $chunks[$i][1],
-		                strlen($chunks[$i][0])
-		        );
+			$output = substr_replace(
+				$output,
+				preg_replace('/\s*(:|;|,|}|{|\(|\))\s*/i', '$1', $chunks[$i][0]),
+				$chunks[$i][1],
+				strlen($chunks[$i][0])
+			);
 		}
 
 		// Replace tabs with spaces
-- 
cgit v1.2.3-24-g4f1b


From 67e643a475a37c53267d0f43b2c2d67efd907014 Mon Sep 17 00:00:00 2001
From: judge 
Date: Tue, 10 Sep 2013 13:59:46 +0200
Subject: fixed error in finding closing tag

---
 system/core/Output.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 06d7a866b..7bfb8cebe 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -841,7 +841,7 @@ class CI_Output {
 			$output = substr_replace($output, '', 0, $pos);
 
 			// Remove closing tag and save it for later
-			$pos = strpos($output, '
Date: Tue, 10 Sep 2013 14:54:47 +0200
Subject: Removed unnecessary parameter

---
 system/core/Output.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 7bfb8cebe..e323385ba 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -842,7 +842,7 @@ class CI_Output {
 
 			// Remove closing tag and save it for later
 			$pos = strrpos($output, '
Date: Tue, 10 Sep 2013 16:13:27 +0200
Subject: Improved detecting whether the pointer is in a string or not

---
 system/core/Output.php | 24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index e323385ba..5272ba662 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -849,6 +849,26 @@ class CI_Output {
 		// Remove CSS comments
 		$output = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!i', '', $output);
 
+		// Remove Javascript inline comments
+		if ($has_tags === TRUE && strpos(strtolower($open_tag), 'script') !== FALSE) {
+			$lines = preg_split('/((\r?\n)|(\n?\r))/',$output);
+			foreach ($lines as &$line){
+				$in_string = $in_dstring = FALSE;
+				$len = strlen($line);
+				for ($i=0; $i<$len; $i++){
+					if ( !$in_string && !$in_dstring && substr($line,$i,2)==='//'){
+						$line = substr($line,0,$i);
+						break;
+					}
+					if ( $line[$i]==='"' )
+						$in_dstring = ! $in_dstring;
+					if ( $line[$i]==="'" )
+						$in_string = ! $in_string;
+				}
+			}
+			$output = implode("\n",$lines);
+		}
+
 		// Remove spaces around curly brackets, colons,
 		// semi-colons, parenthesis, commas
 		$chunks = preg_split('/([\'|"]).+(?![^\\\]\\1)\\1/iU', $output, -1, PREG_SPLIT_OFFSET_CAPTURE);
@@ -899,11 +919,11 @@ class CI_Output {
 				}
 			}
 
-			if ($value === "'")
+			if ($value === "'" && ! $in_dstring)
 			{
 				$in_string = ! $in_string;
 			}
-			elseif ($value === '"')
+			elseif ($value === '"' && ! $in_string)
 			{
 				$in_dstring = ! $in_dstring;
 			}
-- 
cgit v1.2.3-24-g4f1b


From f57ecc141e072473c73630af29ffe06be25e850c Mon Sep 17 00:00:00 2001
From: judge 
Date: Tue, 10 Sep 2013 16:18:14 +0200
Subject: Remove Javascript inline comments + improved detecting whether the
 pointer is in a string or not

---
 system/core/Output.php | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 5272ba662..ec82ae7e8 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -856,14 +856,14 @@ class CI_Output {
 				$in_string = $in_dstring = FALSE;
 				$len = strlen($line);
 				for ($i=0; $i<$len; $i++){
-					if ( !$in_string && !$in_dstring && substr($line,$i,2)==='//'){
+					if ( ! $in_string && ! $in_dstring && substr($line,$i,2) === '//'){
 						$line = substr($line,0,$i);
 						break;
 					}
-					if ( $line[$i]==='"' )
-						$in_dstring = ! $in_dstring;
-					if ( $line[$i]==="'" )
+					if ( $line[$i]==="'" && ! $in_dstring )
 						$in_string = ! $in_string;
+					else if ( $line[$i]==='"' && ! $in_string )
+						$in_dstring = ! $in_dstring;
 				}
 			}
 			$output = implode("\n",$lines);
-- 
cgit v1.2.3-24-g4f1b


From c7df348233227ecf490ef26795022af6cd26807c Mon Sep 17 00:00:00 2001
From: judge 
Date: Tue, 10 Sep 2013 16:24:07 +0200
Subject: Fixed coding style

---
 system/core/Output.php | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index ec82ae7e8..355a139d5 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -850,23 +850,27 @@ class CI_Output {
 		$output = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!i', '', $output);
 
 		// Remove Javascript inline comments
-		if ($has_tags === TRUE && strpos(strtolower($open_tag), 'script') !== FALSE) {
-			$lines = preg_split('/((\r?\n)|(\n?\r))/',$output);
-			foreach ($lines as &$line){
+		if ($has_tags === TRUE && strpos(strtolower($open_tag), 'script') !== FALSE)
+		{
+			$lines = preg_split('/((\r?\n)|(\n?\r))/', $output);
+			foreach ($lines as &$line)
+			{
 				$in_string = $in_dstring = FALSE;
 				$len = strlen($line);
-				for ($i=0; $i<$len; $i++){
-					if ( ! $in_string && ! $in_dstring && substr($line,$i,2) === '//'){
-						$line = substr($line,0,$i);
+				for ($i=0; $i<$len; $i++)
+				{
+					if ( ! $in_string && ! $in_dstring && substr($line, $i, 2) === '//')
+					{
+						$line = substr($line, 0, $i);
 						break;
 					}
-					if ( $line[$i]==="'" && ! $in_dstring )
+					if ($line[$i] === "'" && ! $in_dstring)
 						$in_string = ! $in_string;
-					else if ( $line[$i]==='"' && ! $in_string )
+					elseif ($line[$i] === '"' && ! $in_string)
 						$in_dstring = ! $in_dstring;
 				}
 			}
-			$output = implode("\n",$lines);
+			$output = implode("\n", $lines);
 		}
 
 		// Remove spaces around curly brackets, colons,
-- 
cgit v1.2.3-24-g4f1b


From c5768dbab1f026db1bc3aa3908454eaecbc9006c Mon Sep 17 00:00:00 2001
From: judge 
Date: Thu, 12 Sep 2013 14:43:43 +0200
Subject: Fixed coding style

---
 system/core/Output.php | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 355a139d5..7c2a64d24 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -852,24 +852,29 @@ class CI_Output {
 		// Remove Javascript inline comments
 		if ($has_tags === TRUE && strpos(strtolower($open_tag), 'script') !== FALSE)
 		{
-			$lines = preg_split('/((\r?\n)|(\n?\r))/', $output);
+			$lines = preg_split('/\r?\n|\n?\r/', $output);
 			foreach ($lines as &$line)
 			{
 				$in_string = $in_dstring = FALSE;
-				$len = strlen($line);
-				for ($i=0; $i<$len; $i++)
+				for ($i = 0, $len = strlen($line); $i < $len; $i++)
 				{
 					if ( ! $in_string && ! $in_dstring && substr($line, $i, 2) === '//')
 					{
 						$line = substr($line, 0, $i);
 						break;
 					}
+
 					if ($line[$i] === "'" && ! $in_dstring)
+					{
 						$in_string = ! $in_string;
+					}
 					elseif ($line[$i] === '"' && ! $in_string)
+					{
 						$in_dstring = ! $in_dstring;
+					}
 				}
 			}
+
 			$output = implode("\n", $lines);
 		}
 
-- 
cgit v1.2.3-24-g4f1b


From 0bba6434f0ba3d6b1f677233c2e3c8f37b3195cc Mon Sep 17 00:00:00 2001
From: David Cox Jr 
Date: Sun, 22 Sep 2013 02:09:36 -0400
Subject: Fixes Issue 2637 more elegant way to make sure that the comment is
 not in a js string var

---
 system/core/Output.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 7c2a64d24..b5955c008 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -847,7 +847,7 @@ class CI_Output {
 		}
 
 		// Remove CSS comments
-		$output = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!i', '', $output);
+		$output = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/(?!.*?("|\'))!i', '', $output);
 
 		// Remove Javascript inline comments
 		if ($has_tags === TRUE && strpos(strtolower($open_tag), 'script') !== FALSE)
-- 
cgit v1.2.3-24-g4f1b


From 6d917858b5ffd012bd85a0062d511d261cd6df2d Mon Sep 17 00:00:00 2001
From: David Cox Jr 
Date: Mon, 23 Sep 2013 23:47:26 -0400
Subject: fix #2637 cleaned up the regex to remove extra qualifiers used
 character sets where possible for clarity main expression optimized

---
 system/core/Output.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index b5955c008..7a5fb66f6 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -847,7 +847,7 @@ class CI_Output {
 		}
 
 		// Remove CSS comments
-		$output = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/(?!.*?("|\'))!i', '', $output);
+		$output = preg_replace('!/\*([^/][^*]*\*)*/(?!.+?["\'])!i', '', $output);
 
 		// Remove Javascript inline comments
 		if ($has_tags === TRUE && strpos(strtolower($open_tag), 'script') !== FALSE)
-- 
cgit v1.2.3-24-g4f1b


From a442bc2bced3bd9359548c376f99027d5334a1c7 Mon Sep 17 00:00:00 2001
From: David Cox Jr 
Date: Wed, 2 Oct 2013 23:16:51 -0400
Subject: re-fixes #2637 delimiter used for regex bounds found in neg.
 lookahead causes error using @ delimiter now for this expression

---
 system/core/Output.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 7a5fb66f6..04209d920 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -847,7 +847,7 @@ class CI_Output {
 		}
 
 		// Remove CSS comments
-		$output = preg_replace('!/\*([^/][^*]*\*)*/(?!.+?["\'])!i', '', $output);
+		$output = preg_replace('@/\*([^/][^*]*\*)*/(?!.+?["\'])@i', '', $output);
 
 		// Remove Javascript inline comments
 		if ($has_tags === TRUE && strpos(strtolower($open_tag), 'script') !== FALSE)
-- 
cgit v1.2.3-24-g4f1b


From 6614367f62d2cbd9e8f979c9349cd5474b035866 Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Tue, 22 Oct 2013 15:00:11 +0300
Subject: Fix CSS minifier

---
 system/core/Output.php | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 04209d920..719c43256 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -909,12 +909,12 @@ class CI_Output {
 					$next = $array_output[$key + 1];
 
 					// Strip spaces preceded/followed by a non-ASCII character
-					// or not preceded/followed by an alphanumeric
-					// or not preceded/followed \ $ and _
+					// that are not preceded/followed by an alphanumeric character,
+					// '\', '$', '_', '.' and '#'
 					if ((preg_match('/^[\x20-\x7f]*$/D', $next) OR preg_match('/^[\x20-\x7f]*$/D', $prev))
 						&& ( ! ctype_alnum($next) OR ! ctype_alnum($prev))
-						&& ! in_array($next, array('\\', '_', '$'), TRUE)
-						&& ! in_array($prev, array('\\', '_', '$'), TRUE)
+						&& ! in_array($next, array('\\', '_', '$', '.', '#'), TRUE)
+						&& ! in_array($prev, array('\\', '_', '$', '.', '#'), TRUE)
 					)
 					{
 						unset($array_output[$key]);
-- 
cgit v1.2.3-24-g4f1b


From 6a424902ba0dbd59de2dd6e69bbf9e73d10c083d Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Mon, 28 Oct 2013 14:16:18 +0200
Subject: An alternative to CI_Output::_minify_script_style() using more
 efficient regexp patterns

---
 system/core/Output.php | 102 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 97 insertions(+), 5 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 719c43256..cae1347bc 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -740,13 +740,13 @@ class CI_Output {
 				preg_match_all('{}msU', $output, $style_clean);
 				foreach ($style_clean[0] as $s)
 				{
-					$output = str_replace($s, $this->_minify_script_style($s, TRUE), $output);
+					$output = str_replace($s, $this->_minify_js_css($s, 'css', TRUE), $output);
 				}
 
 				// Minify the javascript in }msU', $output, $javascript_clean);
-
-				// Minify the CSS in all the }msU', $output, $style_clean);
-				foreach ($style_clean[0] as $s)
-				{
-					$output = str_replace($s, $this->_minify_js_css($s, 'css', TRUE), $output);
-				}
-
-				// Minify the javascript in }msU', $output, $javascript_messed);
-					$output = str_replace($javascript_messed[0], $javascript_mini, $output);
-				}
-
-				$size_removed = $size_before - strlen($output);
-				$savings_percent = round(($size_removed / $size_before * 100));
-
-				log_message('debug', 'Minifier shaved '.($size_removed / 1000).'KB ('.$savings_percent.'%) off final HTML output.');
-
-			break;
-
-			case 'text/css':
-
-				return $this->_minify_js_css($output, 'css');
-
-			case 'text/javascript':
-			case 'application/javascript':
-			case 'application/x-javascript':
-
-				return $this->_minify_js_css($output, 'js');
-
-			default: break;
-		}
-
-		return $output;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
-	 * Minify JavaScript and CSS code
-	 *
-	 * Strips comments and excessive whitespace characters
-	 *
-	 * @param	string	$output
-	 * @param	string	$type	'js' or 'css'
-	 * @param	bool	$tags	Whether $output contains the 'script' or 'style' tag
-	 * @return	string
-	 */
-	protected function _minify_js_css($output, $type, $tags = FALSE)
-	{
-		if ($tags === TRUE)
-		{
-			$tags = array('close' => strrchr($output, '<'));
-
-			$open_length = strpos($output, '>') + 1;
-			$tags['open'] = substr($output, 0, $open_length);
-
-			$output = substr($output, $open_length, -strlen($tags['close']));
-
-			// Strip spaces from the tags
-			$tags = preg_replace('#\s{2,}#', ' ', $tags);
-		}
-
-		$output = trim($output);
-
-		if ($type === 'js')
-		{
-			// Catch all string literals and comment blocks
-			if (preg_match_all('#((?:((??@\[\]^`{|}~])\s*#'	=> '$1',	// Remove spaces following and preceeding JS-wise non-special & non-word characters
-				'#\s{2,}#'					=> ' '		// Reduce the remaining multiple whitespace characters to a single space
-			);
-		}
-		else
-		{
-			$patterns = array(
-				'#/\*.*(?=\*/)\*/#s'	=> '',		// Remove /* block comments */
-				'#\n?//[^\n]*#'		=> '',		// Remove // line comments
-				'#\s*([^\w.\#%])\s*#U'	=> '$1',	// Remove spaces following and preceeding non-word characters, excluding dots, hashes and the percent sign
-				'#\s{2,}#'		=> ' '		// Reduce the remaining multiple space characters to a single space
-			);
-		}
-
-		$$varname = preg_replace(array_keys($patterns), array_values($patterns), $$varname);
-
-		// Glue back JS quoted strings
-		if ($type === 'js')
-		{
-			$js_code += $js_literals;
-			ksort($js_code);
-			$output = implode($js_code);
-			unset($js_code, $js_literals, $varname, $patterns);
-		}
-
-		return is_array($tags)
-			? $tags['open'].$output.$tags['close']
-			: $output;
-	}
-
 }
 
 /* End of file Output.php */
-- 
cgit v1.2.3-24-g4f1b


From fe9309d22c1b088f5363954d6dac013c8c955894 Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Fri, 9 Jan 2015 17:48:58 +0200
Subject: Bulk (mostly documentation) update

 - Remove PHP version from license notices
 - Bump year number in copyright notices
 - Recommend PHP 5.4 or newer to be used
 - Tell Travis-CI to test on PHP 5.3.0 instead of the latest 5.3 version

Related: #3450
---
 system/core/Output.php | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 09d251fe2..beac6b377 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -2,11 +2,11 @@
 /**
  * CodeIgniter
  *
- * An open source application development framework for PHP 5.2.4 or newer
+ * An open source application development framework for PHP
  *
  * This content is released under the MIT License (MIT)
  *
- * Copyright (c) 2014, British Columbia Institute of Technology
+ * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -29,7 +29,7 @@
  * @package	CodeIgniter
  * @author	EllisLab Dev Team
  * @copyright	Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright	Copyright (c) 2014, British Columbia Institute of Technology (http://bcit.ca/)
+ * @copyright	Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
  * @license	http://opensource.org/licenses/MIT	MIT License
  * @link	http://codeigniter.com
  * @since	Version 1.0.0
-- 
cgit v1.2.3-24-g4f1b


From 90726b8c769ea75aec34814ddfa91655d488e6c3 Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Tue, 20 Jan 2015 12:39:22 +0200
Subject: [ci skip] Change some log messages' level

'Class Loaded' type of messages flood log files when
log_threshold is set to 2 (debug). They're now logged
as 'info' level.

This is manually applying PR #1528, which was created
to do the same thing, but became outdated.
---
 system/core/Output.php | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index beac6b377..6b9a33d31 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -141,7 +141,7 @@ class CI_Output {
 		// Get mime types for later
 		$this->mimes =& get_mimes();
 
-		log_message('debug', 'Output Class Initialized');
+		log_message('info', 'Output Class Initialized');
 	}
 
 	// --------------------------------------------------------------------
@@ -491,7 +491,7 @@ class CI_Output {
 			}
 
 			echo $output;
-			log_message('debug', 'Final output sent to browser');
+			log_message('info', 'Final output sent to browser');
 			log_message('debug', 'Total execution time: '.$elapsed);
 			return;
 		}
@@ -528,7 +528,7 @@ class CI_Output {
 			echo $output; // Send it to the browser!
 		}
 
-		log_message('debug', 'Final output sent to browser');
+		log_message('info', 'Final output sent to browser');
 		log_message('debug', 'Total execution time: '.$elapsed);
 	}
 
-- 
cgit v1.2.3-24-g4f1b


From 4cbe463b4c442e0e2dae2f43565e77f7ac5ecb86 Mon Sep 17 00:00:00 2001
From: vlakoff 
Date: Wed, 21 Jan 2015 22:56:22 +0100
Subject: Remove closing blocks at end of PHP files

---
 system/core/Output.php | 3 ---
 1 file changed, 3 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 6b9a33d31..b8c6dc02e 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -777,6 +777,3 @@ class CI_Output {
 	}
 
 }
-
-/* End of file Output.php */
-/* Location: ./system/core/Output.php */
\ No newline at end of file
-- 
cgit v1.2.3-24-g4f1b


From 21432ab323bfb35133a1b725289b435b55db9c6a Mon Sep 17 00:00:00 2001
From: natepizzle 
Date: Tue, 3 Feb 2015 16:25:42 -0600
Subject: Documentation Fix

Signed-off-by: natepizzle 
---
 system/core/Output.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index b8c6dc02e..02f66936c 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -391,7 +391,7 @@ class CI_Output {
 	/**
 	 * Display Output
 	 *
-	 * Processes sends the sends finalized output data to the browser along
+	 * 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.
 	 *
-- 
cgit v1.2.3-24-g4f1b


From fd1bc2213f158ae9368a3d85dc108f641dd566bf Mon Sep 17 00:00:00 2001
From: Ivan Tcholakov 
Date: Thu, 23 Apr 2015 23:21:08 +0300
Subject: Output cache: Fixing a wrong timestamp. Credits to khoggatt
 (CodeIgniter forum).

---
 system/core/Output.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 02f66936c..e7d559a1d 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -674,7 +674,7 @@ class CI_Output {
 		$cache_info = unserialize($match[1]);
 		$expire = $cache_info['expire'];
 
-		$last_modified = filemtime($cache_path);
+		$last_modified = filemtime($filepath);
 
 		// Has the file expired?
 		if ($_SERVER['REQUEST_TIME'] >= $expire && is_really_writable($cache_path))
-- 
cgit v1.2.3-24-g4f1b


From 0b978ddf678281ad8c1ab263040fd108be6c926f Mon Sep 17 00:00:00 2001
From: w0den 
Date: Sat, 2 May 2015 17:53:33 +0300
Subject: Bug Fix manually delete caching method
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

According to documentation, to manually delete cache for page "/foo/bar" we should run $this->output->delete_cache('/foo/bar'), but in this case MD5 hash will be calculated for "http://site.com//foo/bar" and this is why, we should pass $uri without beginning slash (ie, "foo/bar"). But the problem is that there is no way to delete cache for home page because:
1) $this->output->delete_cache('/') — MD5 hash will be calculated for "http://site.com//" and cache file will not be deleted.
2) $this->output->delete_cache('') — MD5 hash will be calculated for "http://site.com/%CURRENT_PAGE%" and again, cache file will not be deleted.

Trimming the beginning slash, we enable ability to delete cache for home page by calling $this->output->delete_cache('/'). Also, this method will work as specified in the documentation.
---
 system/core/Output.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index e7d559a1d..f1859ccf6 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -735,7 +735,7 @@ class CI_Output {
 			}
 		}
 
-		$cache_path .= md5($CI->config->item('base_url').$CI->config->item('index_page').$uri);
+		$cache_path .= md5($CI->config->item('base_url').$CI->config->item('index_page').ltrim($uri, '/'));
 
 		if ( ! @unlink($cache_path))
 		{
-- 
cgit v1.2.3-24-g4f1b


From dc29c6dc9069650d69496635643f00ab5e52067e Mon Sep 17 00:00:00 2001
From: w0den 
Date: Mon, 11 May 2015 18:58:20 +0300
Subject: Improve Cache Query String behaviour
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Typically, in most cases, we do not need to cache all the Query String variables. That's why I suggest to improve `Cache Include Query String` behaviour — allow the developer to independently specify which variables should be cached.

For example, consider a query to the following URL address:
http://site.com/search?q=query&page=2&session=abcd&utm_source=web

In this case we don't need to build md5 hash for entire query string, because `session` or `utm_source` can be different for all users. The only variables which should be used for md5 hash should be `q` and `page`. Thus, in `config.php` we can use `$config['cache_query_string'] = array('page', 'q');`.

So:
`$config['cache_query_string'] = FALSE;` → Cache Include Query String is disabled
`$config['cache_query_string'] = TRUE;` → Cache Include Query String is enabled for all
`$config['cache_query_string'] = array('page', 'q');` → enabled only for specified variables
---
 system/core/Output.php | 33 +++++++++++++++++++++++++++------
 1 file changed, 27 insertions(+), 6 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index f1859ccf6..4aed62a86 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -556,9 +556,16 @@ class CI_Output {
 			.$CI->config->item('index_page')
 			.$CI->uri->uri_string();
 
-		if ($CI->config->item('cache_query_string') && ! empty($_SERVER['QUERY_STRING']))
+		if (($cache_query_string = $CI->config->item('cache_query_string')) && !empty($_SERVER['QUERY_STRING']))
 		{
-			$uri .= '?'.$_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);
@@ -646,9 +653,16 @@ class CI_Output {
 		// 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 ($CFG->item('cache_query_string') && ! empty($_SERVER['QUERY_STRING']))
+		if (($cache_query_string = $CFG->item('cache_query_string')) && !empty($_SERVER['QUERY_STRING']))
 		{
-			$uri .= '?'.$_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);
@@ -729,9 +743,16 @@ class CI_Output {
 		{
 			$uri = $CI->uri->uri_string();
 
-			if ($CI->config->item('cache_query_string') && ! empty($_SERVER['QUERY_STRING']))
+			if (($cache_query_string = $CI->config->item('cache_query_string')) && !empty($_SERVER['QUERY_STRING']))
 			{
-				$uri .= '?'.$_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'];
+				}
 			}
 		}
 
-- 
cgit v1.2.3-24-g4f1b


From 298e0058b9d8e576cb7f017ade57c794060c3e98 Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Wed, 15 Jul 2015 17:17:18 +0300
Subject: [ci skip] Revert styleguide violations from PR #3828

---
 system/core/Output.php | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 4aed62a86..76c1329d2 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -556,7 +556,7 @@ class CI_Output {
 			.$CI->config->item('index_page')
 			.$CI->uri->uri_string();
 
-		if (($cache_query_string = $CI->config->item('cache_query_string')) && !empty($_SERVER['QUERY_STRING']))
+		if (($cache_query_string = $CI->config->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))
 		{
 			if (is_array($cache_query_string))
 			{
@@ -653,7 +653,7 @@ class CI_Output {
 		// 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 (($cache_query_string = $CFG->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))
 		{
 			if (is_array($cache_query_string))
 			{
@@ -743,7 +743,7 @@ class CI_Output {
 		{
 			$uri = $CI->uri->uri_string();
 
-			if (($cache_query_string = $CI->config->item('cache_query_string')) && !empty($_SERVER['QUERY_STRING']))
+			if (($cache_query_string = $CI->config->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))
 			{
 				if (is_array($cache_query_string))
 				{
-- 
cgit v1.2.3-24-g4f1b


From 125ef4751080a2118cb203357d77687699e3eb25 Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Mon, 11 Jan 2016 12:33:00 +0200
Subject: [ci skip] Bump year to 2016

---
 system/core/Output.php | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 76c1329d2..75116b3a6 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -6,7 +6,7 @@
  *
  * This content is released under the MIT License (MIT)
  *
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * Copyright (c) 2014 - 2016, British Columbia Institute of Technology
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -29,7 +29,7 @@
  * @package	CodeIgniter
  * @author	EllisLab Dev Team
  * @copyright	Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright	Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @copyright	Copyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)
  * @license	http://opensource.org/licenses/MIT	MIT License
  * @link	http://codeigniter.com
  * @since	Version 1.0.0
-- 
cgit v1.2.3-24-g4f1b


From bd202c91b0e9cf0a8c93bcaa71df9574f5909346 Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Mon, 11 Jan 2016 12:50:18 +0200
Subject: [ci skip] Update codeigniter.com links to https

---
 system/core/Output.php | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 75116b3a6..faeb0ea97 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -31,7 +31,7 @@
  * @copyright	Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
  * @copyright	Copyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)
  * @license	http://opensource.org/licenses/MIT	MIT License
- * @link	http://codeigniter.com
+ * @link	https://codeigniter.com
  * @since	Version 1.0.0
  * @filesource
  */
@@ -46,7 +46,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
  * @subpackage	Libraries
  * @category	Output
  * @author		EllisLab Dev Team
- * @link		http://codeigniter.com/user_guide/libraries/output.html
+ * @link		https://codeigniter.com/user_guide/libraries/output.html
  */
 class CI_Output {
 
-- 
cgit v1.2.3-24-g4f1b


From 1924e879b165fb119847a49a7a5eab2f28295fa2 Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Mon, 11 Jan 2016 12:55:34 +0200
Subject: [ci skip] Update ellislab.com links to https too

---
 system/core/Output.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index faeb0ea97..ad87f8545 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -28,7 +28,7 @@
  *
  * @package	CodeIgniter
  * @author	EllisLab Dev Team
- * @copyright	Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
+ * @copyright	Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
  * @copyright	Copyright (c) 2014 - 2016, British Columbia Institute of Technology (http://bcit.ca/)
  * @license	http://opensource.org/licenses/MIT	MIT License
  * @link	https://codeigniter.com
-- 
cgit v1.2.3-24-g4f1b


From 22df06b544cb74b4a71c0e1b0d9fa0bc13c95469 Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Wed, 20 Jan 2016 12:10:08 +0200
Subject: [ci skip] Fix a documentation error on output cache times

---
 system/core/Output.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index ad87f8545..ec9c21b91 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -377,7 +377,7 @@ class CI_Output {
 	/**
 	 * Set Cache
 	 *
-	 * @param	int	$time	Cache expiration time in seconds
+	 * @param	int	$time	Cache expiration time in minutes
 	 * @return	CI_Output
 	 */
 	public function cache($time)
-- 
cgit v1.2.3-24-g4f1b


From e13fa9fdb3f2e311bd7331e49b26889f24bc81cb Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Fri, 20 May 2016 17:30:07 +0300
Subject: Merge pull request #4638 from kasimtan/phpdoc_fixes

[ci skip] Fixed PHPDoc parameter name and type discrepancies
---
 system/core/Output.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index ec9c21b91..06ff1011c 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -285,7 +285,7 @@ class CI_Output {
 	/**
 	 * Get Header
 	 *
-	 * @param	string	$header_name
+	 * @param	string	$header
 	 * @return	string
 	 */
 	public function get_header($header)
-- 
cgit v1.2.3-24-g4f1b


From 4e2cdec6ff4b4af5f994be4c348ad3b9a9a2942f Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Fri, 28 Oct 2016 14:19:08 +0300
Subject: Improve byte-safety

---
 system/core/Output.php | 62 ++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 55 insertions(+), 7 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 06ff1011c..cf6510ff1 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -122,6 +122,13 @@ class CI_Output {
 	 */
 	public $parse_exec_vars = TRUE;
 
+	/**
+	 * mbstring.func_override flag
+	 *
+	 * @var	bool
+	 */
+	protected static $func_override;
+
 	/**
 	 * Class constructor
 	 *
@@ -138,6 +145,8 @@ class CI_Output {
 			&& extension_loaded('zlib')
 		);
 
+		isset(self::$func_override) OR self::$func_override = (extension_loaded('mbstring') && ini_get('mbstring.func_override'));
+
 		// Get mime types for later
 		$this->mimes =& get_mimes();
 
@@ -304,9 +313,9 @@ class CI_Output {
 
 		for ($i = 0, $c = count($headers); $i < $c; $i++)
 		{
-			if (strncasecmp($header, $headers[$i], $l = strlen($header)) === 0)
+			if (strncasecmp($header, $headers[$i], $l = self::strlen($header)) === 0)
 			{
-				return trim(substr($headers[$i], $l+1));
+				return trim(self::substr($headers[$i], $l+1));
 			}
 		}
 
@@ -480,13 +489,13 @@ class CI_Output {
 				if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE)
 				{
 					header('Content-Encoding: gzip');
-					header('Content-Length: '.strlen($output));
+					header('Content-Length: '.self::strlen($output));
 				}
 				else
 				{
 					// User agent doesn't support gzip compression,
 					// so we'll have to decompress our cache
-					$output = gzinflate(substr($output, 10, -8));
+					$output = gzinflate(self::substr($output, 10, -8));
 				}
 			}
 
@@ -601,9 +610,9 @@ class CI_Output {
 
 			$output = $cache_info.'ENDCI--->'.$output;
 
-			for ($written = 0, $length = strlen($output); $written < $length; $written += $result)
+			for ($written = 0, $length = self::strlen($output); $written < $length; $written += $result)
 			{
-				if (($result = fwrite($fp, substr($output, $written))) === FALSE)
+				if (($result = fwrite($fp, self::substr($output, $written))) === FALSE)
 				{
 					break;
 				}
@@ -711,7 +720,7 @@ class CI_Output {
 		}
 
 		// Display the cache
-		$this->_display(substr($cache, strlen($match[0])));
+		$this->_display(self::substr($cache, self::strlen($match[0])));
 		log_message('debug', 'Cache file is current. Sending it to browser.');
 		return TRUE;
 	}
@@ -797,4 +806,43 @@ class CI_Output {
 		}
 	}
 
+	// --------------------------------------------------------------------
+
+	/**
+	 * Byte-safe strlen()
+	 *
+	 * @param	string	$str
+	 * @return	int
+	 */
+	protected static function strlen($str)
+	{
+		return (self::$func_override)
+			? mb_strlen($str, '8bit')
+			: strlen($str);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
+	 * Byte-safe substr()
+	 *
+	 * @param	string	$str
+	 * @param	int	$start
+	 * @param	int	$length
+	 * @return	string
+	 */
+	protected static function substr($str, $start, $length = NULL)
+	{
+		if (self::$func_override)
+		{
+			// mb_substr($str, $start, null, '8bit') returns an empty
+			// string on PHP 5.3
+			isset($length) OR $length = ($start >= 0 ? self::strlen($str) - $start : -$start);
+			return mb_substr($str, $start, $length, '8bit');
+		}
+
+		return isset($length)
+			? substr($str, $start, $length)
+			: substr($str, $start);
+	}
 }
-- 
cgit v1.2.3-24-g4f1b


From e377910ccf826b448203513bf63bd5721bbd1375 Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Thu, 1 Dec 2016 13:48:58 +0200
Subject: Fix #4927

---
 system/core/Output.php | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index cf6510ff1..57c78ab19 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -311,11 +311,12 @@ class CI_Output {
 			return NULL;
 		}
 
-		for ($i = 0, $c = count($headers); $i < $c; $i++)
+		// Count backwards, in order to get the last matching header
+		for ($c = count($headers) - 1; $c > -1; $c--)
 		{
-			if (strncasecmp($header, $headers[$i], $l = self::strlen($header)) === 0)
+			if (strncasecmp($header, $headers[$c], $l = self::strlen($header)) === 0)
 			{
-				return trim(self::substr($headers[$i], $l+1));
+				return trim(self::substr($headers[$c], $l+1));
 			}
 		}
 
-- 
cgit v1.2.3-24-g4f1b


From da60e9bc66ec90970fbd2dfd08b0a6e66b9f5f5f Mon Sep 17 00:00:00 2001
From: Master Yoda 
Date: Sat, 31 Dec 2016 08:46:18 -0800
Subject: Update copyright data to 2017

---
 system/core/Output.php | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 57c78ab19..349955cd2 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -6,7 +6,7 @@
  *
  * This content is released under the MIT License (MIT)
  *
- * Copyright (c) 2014 - 2016, British Columbia Institute of Technology
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -29,7 +29,7 @@
  * @package	CodeIgniter
  * @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/)
+ * @copyright	Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
  * @license	http://opensource.org/licenses/MIT	MIT License
  * @link	https://codeigniter.com
  * @since	Version 1.0.0
-- 
cgit v1.2.3-24-g4f1b


From c0c74d5201c171cd6d0cdc2133e63077ebe1a407 Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Thu, 19 Jan 2017 15:26:35 +0200
Subject: More byte-safety

---
 system/core/Output.php | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 349955cd2..6ddded22a 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -123,11 +123,11 @@ class CI_Output {
 	public $parse_exec_vars = TRUE;
 
 	/**
-	 * mbstring.func_override flag
+	 * mbstring.func_overload flag
 	 *
 	 * @var	bool
 	 */
-	protected static $func_override;
+	protected static $func_overload;
 
 	/**
 	 * Class constructor
@@ -145,7 +145,7 @@ class CI_Output {
 			&& extension_loaded('zlib')
 		);
 
-		isset(self::$func_override) OR self::$func_override = (extension_loaded('mbstring') && ini_get('mbstring.func_override'));
+		isset(self::$func_overload) OR self::$func_overload = (extension_loaded('mbstring') && ini_get('mbstring.func_overload'));
 
 		// Get mime types for later
 		$this->mimes =& get_mimes();
@@ -817,7 +817,7 @@ class CI_Output {
 	 */
 	protected static function strlen($str)
 	{
-		return (self::$func_override)
+		return (self::$func_overload)
 			? mb_strlen($str, '8bit')
 			: strlen($str);
 	}
@@ -834,7 +834,7 @@ class CI_Output {
 	 */
 	protected static function substr($str, $start, $length = NULL)
 	{
-		if (self::$func_override)
+		if (self::$func_overload)
 		{
 			// mb_substr($str, $start, null, '8bit') returns an empty
 			// string on PHP 5.3
-- 
cgit v1.2.3-24-g4f1b


From f8fba7bac1c69e619f504f9960133d9b0fecc34b Mon Sep 17 00:00:00 2001
From: Andrey Andreev 
Date: Tue, 18 Apr 2017 12:03:15 +0300
Subject: [ci skip] Reduce nesting levels in CI_Output

---
 system/core/Output.php | 95 +++++++++++++++++++++++---------------------------
 1 file changed, 44 insertions(+), 51 deletions(-)

(limited to 'system/core/Output.php')

diff --git a/system/core/Output.php b/system/core/Output.php
index 6ddded22a..a3155fece 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -586,62 +586,59 @@ class CI_Output {
 			return;
 		}
 
-		if (flock($fp, LOCK_EX))
+		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);
+			log_message('error', 'Unable to secure a file lock for file at: '.$cache_path);
+			fclose($fp);
+			return;
+		}
 
-				if ($this->get_header('content-type') === NULL)
-				{
-					$this->set_content_type($this->mime_type);
-				}
+		// 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);
+		$expire = time() + ($this->cache_expiration * 60);
 
-			// Put together our serialized info.
-			$cache_info = serialize(array(
-				'expire'	=> $expire,
-				'headers'	=> $this->headers
-			));
+		// Put together our serialized info.
+		$cache_info = serialize(array(
+			'expire'	=> $expire,
+			'headers'	=> $this->headers
+		));
 
-			$output = $cache_info.'ENDCI--->'.$output;
+		$output = $cache_info.'ENDCI--->'.$output;
 
-			for ($written = 0, $length = self::strlen($output); $written < $length; $written += $result)
+		for ($written = 0, $length = self::strlen($output); $written < $length; $written += $result)
+		{
+			if (($result = fwrite($fp, self::substr($output, $written))) === FALSE)
 			{
-				if (($result = fwrite($fp, self::substr($output, $written))) === FALSE)
-				{
-					break;
-				}
+				break;
 			}
-
-			flock($fp, LOCK_UN);
-		}
-		else
-		{
-			log_message('error', 'Unable to secure a file lock for file at: '.$cache_path);
-			return;
 		}
 
+		flock($fp, LOCK_UN);
 		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
+		if ( ! is_int($result))
 		{
 			@unlink($cache_path);
 			log_message('error', 'Unable to write the complete cache content at: '.$cache_path);
+			return;
 		}
+
+		chmod($cache_path, 0640);
+		log_message('debug', 'Cache file written: '.$cache_path);
+
+		// Send HTTP cache-control headers to browser to match file cache settings.
+		$this->set_cache_header($_SERVER['REQUEST_TIME'], $expire);
 	}
 
 	// --------------------------------------------------------------------
@@ -708,11 +705,9 @@ class CI_Output {
 			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);
-		}
+
+		// Send the HTTP cache control headers
+		$this->set_cache_header($last_modified, $expire);
 
 		// Add headers from cache file.
 		foreach ($cache_info['headers'] as $header)
@@ -798,13 +793,11 @@ class CI_Output {
 			$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');
-		}
+
+		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');
 	}
 
 	// --------------------------------------------------------------------
-- 
cgit v1.2.3-24-g4f1b