Fixed bug #9974: Use PHP built-in gzip/deflate compression in Frontend
authorDmitry Dulepov <dmitry.dulepov@gmail.com>
Wed, 4 Mar 2009 08:21:41 +0000 (08:21 +0000)
committerDmitry Dulepov <dmitry.dulepov@gmail.com>
Wed, 4 Mar 2009 08:21:41 +0000 (08:21 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/Core/trunk@5118 709f56b5-9817-0410-a4d7-c38de5d9e867

ChangeLog
t3lib/config_default.php
typo3/sysext/cms/tslib/class.tslib_fecompression.php [new file with mode: 0644]
typo3/sysext/cms/tslib/index_ts.php

index c7e3858..5417005 100755 (executable)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2009-03-04  Dmitry Dulepov  <dmitry@typo3.org>
+
+       * Fixed bug #9974: Use PHP built-in gzip/deflate compression in Frontend
+
 2009-03-03  Ingo Renner  <ingo@typo3.org>
 
        * Fixed bug #9779: t3lib_div::trimExplode limit parameter leads to wrong result with non-empty requirement
index 26a97f9..e40979c 100755 (executable)
@@ -268,8 +268,7 @@ $TYPO3_CONF_VARS = Array(
                'strictFormmail' => TRUE,                               // Boolean. If set, the internal "formmail" feature in TYPO3 will send mail ONLY to recipients which has been encoded by the system itself. This protects against spammers misusing the formmailer.
                'secureFormmail' => TRUE,                               // Boolean. If set, the internal "formmail" feature in TYPO3 will send mail ONLY to the recipients that are defined in the form CE record. This protects against spammers misusing the formmailer.
                'formmailMaxAttachmentSize' => 250000,          // Integer. Sets the maximum allowed size (in bytes) of attachments for the internal "formmail" feature.
-               'compressionLevel' => 0,                                // Determines output compression of FE output. Makes output smaller but slows down the page generation depending on the compression level. Requires zlib in your PHP4 installation. Range 1-9, where 1 is least compression (approx. 50%) and 9 is greatest compression (approx 33%). 'true' as value will set the compression based on the system load (works with Linux, FreeBSD). Suggested value is 3. For more info, see class in t3lib/class.gzip_encode.php written by Sandy McArthur, Jr. <Leknor@Leknor.com>
-               'compressionDebugInfo' => 0,                    // Boolean. If set, then in the end of the pages, the sizes of the compressed and non-compressed document is output. This should be used ONLY as a test, because the content is compressed twice in order to output this statistics!
+               'compressionLevel' => 0,                                // Determines output compression of FE output. Makes output smaller but slows down the page generation depending on the compression level. Requires zlib in your PHP installation. Range 1-9, where 1 is least compression and 9 is greatest compression. 'true' as value will set the compression based on the PHP default settings (usually 5). Suggested and most optimal value is 5.
                'pageNotFound_handling' => '',                  // How TYPO3 should handle requests for non-existing/accessible pages. false (default): The 'nearest' page is shown. TRUE or '1': An TYPO3 error box is displayed. Strings: page to show (reads content and outputs with correct headers), eg. 'notfound.html' or 'http://www.domain.org/errors/notfound.html'. If prefixed "REDIRECT:" it will redirect to the URL/script after the prefix (original behaviour). If prefixed with "READFILE:" then it will expect the remaining string to be a HTML file which will be read and outputted directly after having the marker "###CURRENT_URL###" substituted with REQUEST_URI and ###REASON### with reason text, for example: "READFILE:fileadmin/notfound.html". Another option is the prefix "USER_FUNCTION:" which will call a user function, eg. "USER_FUNCTION:typo3conf/pageNotFoundHandling.php:user_pageNotFound->pageNotFound" where the file must contain a class "user_pageNotFound" with a method "pageNotFound" inside with two parameters, $param and $ref
                'pageNotFound_handling_statheader' => 'HTTP/1.0 404 Not Found',                 // If 'pageNotFound_handling' is enabled, this string will always be sent as header before the actual handling.
                'pageNotFoundOnCHashError' => 0,                // Boolean. If true, a page not found call is made when cHash evaluation error occurs. By default they will just disable caching but still display page output.
diff --git a/typo3/sysext/cms/tslib/class.tslib_fecompression.php b/typo3/sysext/cms/tslib/class.tslib_fecompression.php
new file mode 100644 (file)
index 0000000..e8c3d97
--- /dev/null
@@ -0,0 +1,84 @@
+<?php
+/***************************************************************
+*  Copyright notice
+*
+*  (c) 2009 Dmitry Dulepov <dmitry@typo3.org>
+*  All rights reserved
+*
+*  This script is part of the TYPO3 project. The TYPO3 project is
+*  free software; you can redistribute it and/or modify
+*  it under the terms of the GNU General Public License as published by
+*  the Free Software Foundation; either version 2 of the License, or
+*  (at your option) any later version.
+*
+*  The GNU General Public License can be found at
+*  http://www.gnu.org/copyleft/gpl.html.
+*
+*  This script is distributed in the hope that it will be useful,
+*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*  GNU General Public License for more details.
+*
+*  This copyright notice MUST APPEAR in all copies of the script!
+***************************************************************/
+
+require_once(PATH_t3lib . 'interfaces/interface.t3lib_singleton.php');
+
+/**
+ * This class contains compression functions for the TYPO3 Frontend. It can be
+ * used only in EXT:cms/tslib/index_ts.php
+ *
+ * $Id: $
+ *
+ * @author     Dmitry Dulepov <dmitry@typo3.org>
+ * @package    TYPO3
+ * @subpackage tx_cms
+ */
+class tslib_fecompression implements t3lib_Singleton {
+
+       /**
+        * Accumulates content length for the compressed content. It is necessary to
+        * replace the Content-length HTTP header after compression if it was added
+        * by TYPO3 before compression.
+        *
+        * @var int
+        */
+       protected       $contentLength = 0;
+
+       /**
+        * Corrects HTTP "Content-length" header if it was sent by TYPO3 and compression
+        * is enabled.
+        *
+        * @param       string  $outputBuffer   Output buffer to compress
+        * @param       int     $mode   One of PHP_OUTPUT_HANDLER_xxx contants
+        * @return      string  Compressed string
+        * @see ob_start()
+        * @see ob_gzhandler()
+        */
+       function compressionOutputHandler($outputBuffer, $mode) {
+               // Compress the content
+               $outputBuffer = ob_gzhandler($outputBuffer, $mode);
+               if ($outputBuffer !== false) {
+                       // Save compressed size
+                       $this->contentLength += strlen($outputBuffer);
+
+                       // Check if this was the last content chunk
+                       if (0 != ($mode & PHP_OUTPUT_HANDLER_END)) {
+                               // Check if we have content-length header
+                               foreach (headers_list() as $header) {
+                                       if (0 == strncasecmp('Content-length:', $header, 15)) {
+                                               header('Content-length: ' . $this->contentLength);
+                                               break;
+                                       }
+                               }
+                       }
+               }
+               return $outputBuffer;
+       }
+}
+
+if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/cms/tslib/class.tslib_fecompression.php'])    {
+       include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['ext/cms/tslib/class.tslib_fecompression.php']);
+}
+
+?>
\ No newline at end of file
index 8c29b9d..f63482a 100755 (executable)
@@ -75,6 +75,12 @@ if (!defined('PATH_tslib')) {
 if (!@is_dir(PATH_typo3conf))  die('Cannot find configuration. This file is probably executed from the wrong location.');
 
 // *********************
+// Prevent any output until AJAX/compression is initialized to stop
+// AJAX/compression data corruption
+// *********************
+ob_start();
+
+// *********************
 // Timetracking started
 // *********************
 require_once(PATH_t3lib.'class.t3lib_timetrack.php');
@@ -132,6 +138,9 @@ if (!get_magic_quotes_gpc())        {
 // *********************
 if ($temp_extId = t3lib_div::_GP('eID'))       {
        if ($classPath = t3lib_div::getFileAbsFileName($TYPO3_CONF_VARS['FE']['eID_include'][$temp_extId]))     {
+               // Remove any output produced until now
+               ob_clean();
+
                require_once(PATH_tslib.'class.tslib_eidtools.php');
                require($classPath);
        }
@@ -193,11 +202,17 @@ if ($TSFE->RDCT)  {$TSFE->sendRedirect();}
 
 
 // *******************
-// output compression
+// Output compression
 // *******************
-if ($TYPO3_CONF_VARS['FE']['compressionLevel'])        {
-       ob_start();
-       require_once(PATH_t3lib.'class.gzip_encode.php');
+// Remove any output produced until now
+ob_clean();
+if ($TYPO3_CONF_VARS['FE']['compressionLevel'] && extension_loaded('zlib'))    {
+       if (t3lib_div::testInt($TYPO3_CONF_VARS['FE']['compressionLevel'])) {
+               // Prevent errors if ini_set() is unavailable (safe mode)
+               @ini_set('zlib.output_compression_level', $TYPO3_CONF_VARS['FE']['compressionLevel']);
+       }
+       require_once(PATH_tslib . 'class.tslib_fecompression.php');
+       ob_start(array(t3lib_div::makeInstance('tslib_fecompression'), 'compressionOutputHandler'));
 }
 
 // *********
@@ -545,12 +560,4 @@ if (TYPO3_DLOG) {
        t3lib_div::devLog('END of FRONTEND session', 'cms', 0, array('_FLUSH' => TRUE));
 }
 
-
-// *************
-// Compressions
-// *************
-if ($TYPO3_CONF_VARS['FE']['compressionLevel'])        {
-       new gzip_encode($TYPO3_CONF_VARS['FE']['compressionLevel'], false, $TYPO3_CONF_VARS['FE']['compressionDebugInfo']);
-}
-
 ?>
\ No newline at end of file