Empty &cHash
If there is a cHash value in the URL, TYPO3 will take care of all validation and if parameters are forged caching will be disabled. The plugin using the parameters doesn't have to worry a thing.
However if there is no cHash value is found TYPO3 has no way of knowing that the additional parameters are used by a plugin which expects its output to be cached based on these values and thus no evaluation will take place! This problem does open up for spamming the caching table but results in something even worse in the eyes of a website user: Unexpected page content!
The result of this error can be that the specific plugin output of "?id=566&tx_myext[uid]=44" showing a news article will be cached using only "?id=566" as identification for the cached page. Thus, when someone requests "?id=566" they will get to see the news article and not the expected article archive list which would normally be on "?id=566"! It is not only confusing but altogether impossible to see the archive list because its place in the cache is taken by the article until someone clears the cache! Further, the occurrence of this error is puzzling and "occasional" to developers because it depends on whether the page "?id=566" or "?id=566&tx_myext[uid]=44" was viewed first after a cache-clearing; the first one viewed will be the one to fill the cache of "?id=566".
Solving the empty &cHash problem
The reason for spending 4 hours writing this article is that this problem cannot be solved on system level like the validation of a non-empty &cHash value; it has to be implemented inside the plugins!
Basically a plugin author has to ask himself; "Is my plugin running as a USER cObject?" If so, then "where am I creating cached output depending on external variables" and at those locations you should check if the &cHash value is set and if not, disable caching.
In order to make this easy for plugin developers TYPO3 version 3.8.0 will feature an API which makes this easy to fix for plugins made by the standards. The basic assumptions are that a plugin will only display specific information based on parameters in the internal "->piVars" array which are initialized during instantiation of the plugin class. So, we can simply check if this array contains values (meaning parameters are sent) and if so run a check whether the cHash value exists and if it does not, disable caching. As soon as caching is disabled we are on safe ground and even with forged or otherwise obsolete input variables we can generate output from the plugin without compromising the integrity of the cache.
So, to make it short:
If your plugin is running as a USER cObject being cached with pages, set this internal variable (highlighted) in the the plugin class (example with "mininews" extension):
class tx_mininews_pi1 extends tslib_pibase {
// Default plugin variables:
var $prefixId = 'tx_mininews_pi1';
var $scriptRelPath = 'pi1/class.tx_mininews_pi1.php';
var $extKey = 'mininews';
var $pi_checkCHash = TRUE;
// TemplaVoila specific:
var $TA='';
var $TMPLobj='';
....
This API is implemented in the base class, tslib_pibase:
function tslib_pibase() {
...
$this->piVars = t3lib_div::GParrayMerged($this->prefixId);
if ($this->pi_checkCHash && count($this->piVars)) {
$GLOBALS['TSFE']->reqCHash();
}
...
The function TSFE->reqCHash() will simply disable caching if the &cHash value was not found in the URL:
function reqCHash() {
if (!$this->cHash) {
$this->set_no_cache();
}
}
Pre-3.8.0 solutions
Since this API is not implemented for TYPO3 versions prior to 3.8.0 you can of course create a custom implementation where you check directly on TSFE->cHash and call TSFE->set_no_cache() if needed. However, it should suffice if you set the internal variable pi_checkCHash to true since that does not spoil backwards compatibility; So the feature is enabled for 3.8.0 but not fixed when the plugin runs under older versions of TYPO3.
Notice that this internal variables has to be set in the class definition hardcoded and not dynamically during execution; the reason is that the use of it is done during instantiation of the object!
Error-prone setups
One might ask; When will a URL ever contain a blank cHash value since the combination of parameters and cHash is automatically created by TYPO3 anyway?
An obvious answer is when the enemy forges URLs on you website! It will be very easy for the enemy to tease you with this confusing bug. This alone should be motivation enough to fix the problem.
However a much more likely scenario is that it happens when using the "realurl" extension or some other extension manipulating the URL and its parameters:
With realurl the problem simply is that the value of "cHash" is not "speakable" under any circumstances and since the realurl extension is trying to translate parameter strings into something human readable the cHash value of URLs will typically be the only left-over that cannot be a part of the URL. The solution chosen for realurl is to store the cHash value in a table linked to the complete URL it was associated with. This works very well until something changes the values of the URL. In reality what happens is that when translating the URL back, realurl might
- either retrieve a wrong cHash value from the database; no problem, caching will be disabled since cHash-strings didn't match.
- or retrieve nothing; big problem, because parameters will be set but cHash empty!
This is the reason why "realurl" has sparked some fancy situations where the frontpage of the documentation library of TYPO3.org has been a particular page deep inside the documentation library instead of the frontend page - because something has resulted in no returned value from the cHash-table in realurl!