[!!!][TASK] Remove RDCT redirect functionality 25/54225/5
authorBenni Mack <benni@typo3.org>
Thu, 28 Sep 2017 07:51:09 +0000 (09:51 +0200)
committerFrank Naegler <frank.naegler@typo3.org>
Fri, 29 Sep 2017 14:34:43 +0000 (16:34 +0200)
The very legacy RDCT code and the corresponding DB table
"cache_md5params" has been long superseeded and is be
completely moved into its own extension "RDCT" published
on GitHub https://github.com/FriendsOfTYPO3/rdct and in TER.

An upgrade wizard checks if the DB table is filled,
and then installs EXT:rdct.

Note #1: I decided to trigger the hard breaking way,
instead of deprecation as the whole logic (evalution,
static method call in GeneralUtility removed) is interconnected
and only makes sense if all places are there.

Note #2: This functionality has not been in use in the
TYPO3 Core since 4.x - at all, but is in place for
other extensions.

Resolves: #82572
Releases: master
Change-Id: I1514293500c385f7b8c1fff440cca3ab3845615b
Reviewed-on: https://review.typo3.org/54225
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
Reviewed-by: Frank Naegler <frank.naegler@typo3.org>
Tested-by: Frank Naegler <frank.naegler@typo3.org>
14 files changed:
typo3/sysext/core/Classes/DataHandling/DataHandler.php
typo3/sysext/core/Classes/Utility/GeneralUtility.php
typo3/sysext/core/Documentation/Changelog/master/Breaking-82572-RDCTFunctionalityRemoved.rst [new file with mode: 0644]
typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php
typo3/sysext/frontend/Classes/Http/RequestHandler.php
typo3/sysext/frontend/ext_tables.sql
typo3/sysext/install/Classes/Service/ClearTableService.php
typo3/sysext/install/Classes/Updates/RedirectExtractionUpdate.php [new file with mode: 0644]
typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodArgumentDroppedMatcher.php
typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallMatcher.php
typo3/sysext/install/Configuration/ExtensionScanner/Php/MethodCallStaticMatcher.php
typo3/sysext/install/Configuration/ExtensionScanner/Php/PropertyPublicMatcher.php
typo3/sysext/install/ext_localconf.php
typo3/sysext/workspaces/Classes/Hook/PreviewHook.php

index 6ad39f6..abf57ca 100644 (file)
@@ -8577,7 +8577,6 @@ class DataHandler
      *
      * The following cache_* are intentionally not cleared by 'all'
      *
-     * - cache_md5params:      RDCT redirects.
      * - cache_imagesizes:     Clearing this table would cause a lot of unneeded
      * Imagemagick calls because the size informations have
      * to be fetched again after clearing.
index d3d7031..71287c4 100644 (file)
@@ -19,7 +19,6 @@ use Psr\Log\LoggerAwareInterface;
 use Psr\Log\LoggerInterface;
 use TYPO3\CMS\Core\Core\ApplicationContext;
 use TYPO3\CMS\Core\Core\ClassLoadingInformation;
-use TYPO3\CMS\Core\Database\ConnectionPool;
 use TYPO3\CMS\Core\Http\RequestFactory;
 use TYPO3\CMS\Core\Log\LogLevel;
 use TYPO3\CMS\Core\Log\LogManager;
@@ -3761,40 +3760,6 @@ class GeneralUtility
     }
 
     /**
-     * Create a shortened "redirect" URL with specified length from an incoming URL
-     *
-     * @param string $inUrl Input URL
-     * @param int $l URL string length limit
-     * @param string $index_script_url URL of "index script" - the prefix of the "?RDCT=..." parameter. If not supplied it will default to \TYPO3\CMS\Core\Utility\GeneralUtility::getIndpEnv('TYPO3_REQUEST_DIR').'index.php'
-     * @return string Processed URL
-     */
-    public static function makeRedirectUrl($inUrl, $l = 0, $index_script_url = '')
-    {
-        if (strlen($inUrl) > $l) {
-            $md5 = substr(md5($inUrl), 0, 20);
-            $connection = self::makeInstance(ConnectionPool::class)->getConnectionForTable('cache_md5params');
-            $count = $connection->count(
-                '*',
-                'cache_md5params',
-                ['md5hash' => $md5]
-            );
-            if (!$count) {
-                $connection->insert(
-                    'cache_md5params',
-                    [
-                        'md5hash' => $md5,
-                        'tstamp'  => $GLOBALS['EXEC_TIME'],
-                        'type'    => 2,
-                        'params'  => $inUrl
-                    ]
-                );
-            }
-            $inUrl = ($index_script_url ?: self::getIndpEnv('TYPO3_REQUEST_DIR') . 'index.php') . '?RDCT=' . $md5;
-        }
-        return $inUrl;
-    }
-
-    /**
      * Initialize the system log.
      *
      * @see sysLog()
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-82572-RDCTFunctionalityRemoved.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-82572-RDCTFunctionalityRemoved.rst
new file mode 100644 (file)
index 0000000..eb01844
--- /dev/null
@@ -0,0 +1,63 @@
+.. include:: ../../Includes.txt
+
+=============================================
+Breaking: #82572 - RDCT functionality removed
+=============================================
+
+See :issue:`82572`
+
+Description
+===========
+
+The short-link / redirect functionality based on the GET parameter `RDCT` of TYPO3 Frontend requests
+has been removed from TYPO3.
+
+Along, all functionality related to evaluating `RDCT` is not evaluated anymore.
+
+The following PHP methods have been removed:
+* TypoScriptFrontendController->sendRedirect()
+* TypoScriptFrontendController->updateMD5paramsRecord()
+* GeneralUtility::makeRedirectUrl()
+
+The eighth property of the constructor of TypoScriptFrontendController is not evaluated anymore,
+also the public property `TSFE->RDCT` is removed as it is not set anymore.
+
+The corresponding database table `cache_md5params` has been dropped.
+
+Substitution logic can be found in the TER extension `rdct`.
+
+
+Impact
+======
+
+When calling TYPO3 Frontend via `index.php&RDCT=myhash` the RDCT GET parameter is not evaluated
+anymore.
+
+Calling :php:`$TSFE->sendRedirect()`, :php:`$TSFE->updateMD5paramsRecord()` and
+:php:`GeneralUtility::makeRedirectUrl()` will result in a fatal PHP error.
+
+Accessing the now non-existent property :php:`$TSFE->RDCT` will trigger a PHP notice, as well
+as setting up a new instance of `TypoScriptFrontendController` with a eighth parameter.
+
+Accessing the database table `cache_md5params` will also lead to unexpected results as this table
+does not exist in new installations anymore.
+
+
+Affected Installations
+======================
+
+Any TYPO3 instance handling data via the `cache_md5params` database table or creating short links
+via `&RDCT` hashes.
+
+
+Migration
+=========
+
+The TER extension `rdct` contains all previous functionality handled via a simple hook. An upgrade
+wizard within the Install Tool will check if the database table is filled and downloads the extension
+from TER.
+
+It is recommended to use a third-party short-url or redirect extension which provides a richer feature
+set.
+
+.. index:: Frontend, PHP-API, PartiallyScanned
\ No newline at end of file
index 6c5acf1..2b5753c 100644 (file)
@@ -177,11 +177,6 @@ class TypoScriptFrontendController implements LoggerAwareInterface
     public $MP = '';
 
     /**
-     * @var string
-     */
-    public $RDCT = '';
-
-    /**
      * This can be set from applications as a way to tag cached versions of a page
      * and later perform some external cache management, like clearing only a part
      * of the cache of a page...
@@ -801,10 +796,9 @@ class TypoScriptFrontendController implements LoggerAwareInterface
      * @param string $cHash The value of GeneralUtility::_GP('cHash')
      * @param string $_2 previously was used to define the jumpURL
      * @param string $MP The value of GeneralUtility::_GP('MP')
-     * @param string $RDCT The value of GeneralUtility::_GP('RDCT')
      * @see \TYPO3\CMS\Frontend\Http\RequestHandler
      */
-    public function __construct($_ = null, $id, $type, $no_cache = '', $cHash = '', $_2 = null, $MP = '', $RDCT = '')
+    public function __construct($_ = null, $id, $type, $no_cache = '', $cHash = '', $_2 = null, $MP = '')
     {
         // Setting some variables:
         $this->id = $id;
@@ -822,7 +816,6 @@ class TypoScriptFrontendController implements LoggerAwareInterface
         }
         $this->cHash = $cHash;
         $this->MP = $GLOBALS['TYPO3_CONF_VARS']['FE']['enable_mount_pids'] ? (string)$MP : '';
-        $this->RDCT = $RDCT;
         $this->uniqueString = md5(microtime());
         $this->initPageRenderer();
         // Call post processing function for constructor:
@@ -888,38 +881,6 @@ class TypoScriptFrontendController implements LoggerAwareInterface
         }
     }
 
-    /**
-     * Looks up the value of $this->RDCT in the database and if it is
-     * found to be associated with a redirect URL then the redirection
-     * is carried out with a 'Location:' header
-     * May exit after sending a location-header.
-     */
-    public function sendRedirect()
-    {
-        if ($this->RDCT) {
-            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
-                ->getQueryBuilderForTable('cache_md5params');
-
-            $row = $queryBuilder
-                ->select('params')
-                ->from('cache_md5params')
-                ->where(
-                    $queryBuilder->expr()->eq(
-                        'md5hash',
-                        $queryBuilder->createNamedParameter($this->RDCT, \PDO::PARAM_STR)
-                    )
-                )
-                ->execute()
-                ->fetch();
-
-            if ($row) {
-                $this->updateMD5paramsRecord($this->RDCT);
-                header('Location: ' . $row['params']);
-                die;
-            }
-        }
-    }
-
     /********************************************
      *
      * Initializing, resolving page id
@@ -3792,27 +3753,6 @@ class TypoScriptFrontendController implements LoggerAwareInterface
         GeneralUtility::deprecationLog('TypoScript ' . $typoScriptProperty . ' is deprecated' . $explanationText);
     }
 
-    /**
-     * Updates the tstamp field of a cache_md5params record to the current time.
-     *
-     * @param string $hash The hash string identifying the cache_md5params record for which to update the "tstamp" field to the current time.
-     * @access private
-     */
-    public function updateMD5paramsRecord($hash)
-    {
-        $connection = GeneralUtility::makeInstance(ConnectionPool::class)
-            ->getConnectionForTable('cache_md5params');
-        $connection->update(
-            'cache_md5params',
-            [
-                'tstamp' => $GLOBALS['EXEC_TIME']
-            ],
-            [
-                'md5hash' => $hash
-            ]
-        );
-    }
-
     /********************************************
      * PUBLIC ACCESSIBLE WORKSPACES FUNCTIONS
      *******************************************/
index cb87a6d..f5ea643 100644 (file)
@@ -106,7 +106,6 @@ class RequestHandler implements RequestHandlerInterface
         }
 
         $this->controller->connectToDB();
-        $this->controller->sendRedirect();
 
         // Output compression
         // Remove any output produced until now
@@ -332,8 +331,7 @@ class RequestHandler implements RequestHandlerInterface
             GeneralUtility::_GP('no_cache'),
             GeneralUtility::_GP('cHash'),
             null,
-            GeneralUtility::_GP('MP'),
-            GeneralUtility::_GP('RDCT')
+            GeneralUtility::_GP('MP')
         );
         // setting the global variable for the controller
         // We have to define this as reference here, because there is code around
index 43e7e2b..ec08969 100644 (file)
@@ -1,16 +1,4 @@
 #
-# Table structure for table 'cache_md5params'
-#
-CREATE TABLE cache_md5params (
-       md5hash varchar(20) DEFAULT '' NOT NULL,
-       tstamp int(11) DEFAULT '0' NOT NULL,
-       type tinyint(3) DEFAULT '0' NOT NULL,
-       params text,
-
-       PRIMARY KEY (md5hash)
-) ENGINE=InnoDB;
-
-#
 # Table structure for table 'cache_treelist'
 #
 CREATE TABLE cache_treelist (
index 6857efd..4f5da85 100644 (file)
@@ -33,10 +33,6 @@ class ClearTableService
             'description' => 'Backend user sessions'
         ],
         [
-            'name' => 'cache_md5params',
-            'description' => 'Frontend redirects',
-        ],
-        [
             'name' => 'fe_sessions',
             'description' => 'Frontend user sessions',
         ],
diff --git a/typo3/sysext/install/Classes/Updates/RedirectExtractionUpdate.php b/typo3/sysext/install/Classes/Updates/RedirectExtractionUpdate.php
new file mode 100644 (file)
index 0000000..ceb0ac7
--- /dev/null
@@ -0,0 +1,146 @@
+<?php
+namespace TYPO3\CMS\Install\Updates;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Core\Database\ConnectionPool;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * Installs and downloads EXT:rdct if cache_md5params is filled
+ */
+class RedirectExtractionUpdate extends AbstractDownloadExtensionUpdate
+{
+    /**
+     * @var string
+     */
+    protected $title = 'Install extension "rdct" from TER if DB table cache_md5params is filled';
+
+    /**
+     * @var string
+     */
+    protected $extensionKey = 'rdct';
+
+    /**
+     * @var array
+     */
+    protected $extensionDetails = [
+        'rdct' => [
+            'title' => 'Redirects based on &RDCT parameter',
+            'description' => 'Provides redirects based on "cache_md5params" and the GET parameter &RDCT for extensions that still rely on it.',
+            'versionString' => '1.0.0',
+        ]
+    ];
+
+    /**
+     * Checks if an update is needed
+     *
+     * @param string $description The description for the update
+     * @return bool Whether an update is needed (true) or not (false)
+     */
+    public function checkForUpdate(&$description)
+    {
+        $description = 'The extension "rdct" includes redirects based on the GET parameter &RDCT. The functionality has been extracted to'
+            . ' the TYPO3 Extension Repository. This update downloads the TYPO3 extension from the TER.'
+            . ' Use this if you are dealing with extensions in the instance that rely on this kind of redirects.';
+
+        $updateNeeded = false;
+
+        // Check if table exists and table is not empty, and the wizard has not been run already
+        if ($this->checkIfWizardIsRequired() && !$this->isWizardDone()) {
+            $updateNeeded = true;
+        }
+
+        return $updateNeeded;
+    }
+
+    /**
+     * Second step: Ask user to install the extension
+     *
+     * @param string $inputPrefix input prefix, all names of form fields have to start with this. Append custom name in [ ... ]
+     * @return string HTML output
+     */
+    public function getUserInput($inputPrefix)
+    {
+        return '
+            <div class="panel panel-danger">
+                <div class="panel-heading">Are you really sure?</div>
+                <div class="panel-body">
+                    <p>You should install EXT:rdct only if you really need it.</p>
+                    <p>If you have never heard of index.php?RDCT then we are 99% confident that you don\'t need to install this extension.</p>
+                    <p>Are you really sure, you want to install EXT:rdct?</p>
+                    <div class="btn-group clearfix" data-toggle="buttons">
+                        <label class="btn btn-default active">
+                            <input type="radio" name="' . $inputPrefix . '[install]" value="0" checked="checked" /> no, don\'t install
+                        </label>
+                        <label class="btn btn-default">
+                            <input type="radio" name="' . $inputPrefix . '[install]" value="1" /> yes, please install
+                        </label>
+                    </div>
+                </div>
+            </div>
+        ';
+    }
+
+    /**
+     * Performs the update if EXT:rdct should be installed.
+     *
+     * @param array $databaseQueries Queries done in this update
+     * @param string $customMessage Custom message
+     * @return bool
+     */
+    public function performUpdate(array &$databaseQueries, &$customMessage)
+    {
+        $requestParams = GeneralUtility::_GP('install');
+        if (!isset($requestParams['values']['rdctExtension']['install'])) {
+            return false;
+        }
+        $install = (int)$requestParams['values']['rdctExtension']['install'];
+
+        $updateSuccessful = true;
+        if ($install === 1) {
+            // user decided to install extension, install and mark wizard as done
+            $updateSuccessful = $this->installExtension($this->extensionKey, $customMessage);
+        }
+        if ($updateSuccessful) {
+            $this->markWizardAsDone();
+        }
+        return $updateSuccessful;
+    }
+
+    /**
+     * Check if the database table "cache_md5params" exists and if so, if there are entries in the DB table.
+     *
+     * @return bool
+     * @throws \InvalidArgumentException
+     */
+    protected function checkIfWizardIsRequired(): bool
+    {
+        $connectionPool = GeneralUtility::makeInstance(ConnectionPool::class);
+        $connection = $connectionPool->getConnectionByName('Default');
+        $tableNames = $connection->getSchemaManager()->listTableNames();
+        if (in_array('cache_md5params', $tableNames, true)) {
+            // table is available, now check if there are entries in it
+            $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
+                ->getQueryBuilderForTable('cache_md5params');
+            $numberOfEntries = $queryBuilder->count('*')
+                ->from('cache_md5params')
+                ->execute()
+                ->fetchColumn();
+            return (bool)$numberOfEntries;
+        }
+
+        return false;
+    }
+}
index f16b3c3..5236f36 100644 (file)
@@ -111,4 +111,10 @@ return [
             'Breaking-55298-DecoupledHistoryFunctionality.rst',
         ],
     ],
+    'TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->__construct' => [
+        'maximumNumberOfArguments' => 7,
+        'restFiles' => [
+            'Breaking-82572-RDCTFunctionalityRemoved.rst',
+        ],
+    ],
 ];
index ef82d39..8e2170f 100644 (file)
@@ -1240,4 +1240,18 @@ return [
             'Deprecation-52694-DeprecatedGeneralUtilitydevLog.rst',
         ],
     ],
+    'TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->sendRedirect' => [
+        'numberOfMandatoryArguments' => 0,
+        'maximumNumberOfArguments' => 0,
+        'restFiles' => [
+            'Breaking-82572-RDCTFunctionalityRemoved.rst',
+        ],
+    ],
+    'TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->updateMD5paramsRecord' => [
+        'numberOfMandatoryArguments' => 1,
+        'maximumNumberOfArguments' => 1,
+        'restFiles' => [
+            'Breaking-82572-RDCTFunctionalityRemoved.rst',
+        ],
+    ],
 ];
index 6cb0ce1..3d04f48 100644 (file)
@@ -421,4 +421,11 @@ return [
             'Deprecation-81534-BackendUtilitygetListGroupNamesDeprecated.rst',
         ],
     ],
+    'TYPO3\CMS\Core\Utility\GeneralUtility::makeRedirectUrl' => [
+        'numberOfMandatoryArguments' => 1,
+        'maximumNumberOfArguments' => 3,
+        'restFiles' => [
+            'Breaking-82572-RDCTFunctionalityRemoved.rst',
+        ],
+    ],
 ];
index b32b4e8..211a63d 100644 (file)
@@ -189,6 +189,11 @@ return [
             'Breaking-82425-RemoveOldTyposcriptConstantsEditorOptionMOD_TSEDITABLE_CONSTANTS.rst',
         ],
     ],
+    'TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController->RDCT' => [
+        'restFiles' => [
+            'Breaking-82572-RDCTFunctionalityRemoved.rst',
+        ],
+    ],
 
     // Deprecated public properties
 ];
index 8bed37a..229f515 100644 (file)
@@ -46,6 +46,8 @@ $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['pagesUrltype
     = \TYPO3\CMS\Install\Updates\MigrateUrlTypesInPagesUpdate::class;
 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['separateSysHistoryFromLog']
     = \TYPO3\CMS\Install\Updates\SeparateSysHistoryFromSysLogUpdate::class;
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/install']['update']['rdctExtension']
+    = \TYPO3\CMS\Install\Updates\RedirectExtractionUpdate::class;
 
 $iconRegistry = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Imaging\IconRegistry::class);
 $icons = [
index 6fe3718..b06dacc 100644 (file)
@@ -81,8 +81,7 @@ class PreviewHook implements \TYPO3\CMS\Core\SingletonInterface
                 GeneralUtility::_GP('no_cache'),
                 GeneralUtility::_GP('cHash'),
                 null,
-                GeneralUtility::_GP('MP'),
-                GeneralUtility::_GP('RDCT')
+                GeneralUtility::_GP('MP')
             );
             $GLOBALS['TSFE'] = $this->tsfeObj;
             // Configuration after initialization of TSFE object.