diff --git a/extension/Documentation/Manual.rst b/extension/Documentation/Manual.rst index d87b8dba08fb07c5f0698e7ec59c53253a784cf1..d018c16233ab87c4af5d0015450fcee95182d34f 100644 --- a/extension/Documentation/Manual.rst +++ b/extension/Documentation/Manual.rst @@ -1258,25 +1258,42 @@ QFQ offers different ways of escaping. Which of them to use, depends on the situ Especially variables used in SQL Statements might cause trouble when using: NUL (ASCII 0), \\n, \\r, \\, ', ", or Control-Z. -Additional there is the escape class 'p' (password hash) which is not 'escape' but hashing. It transforms the value of +Additional there function classes like 'p' (password hash) which is not 'escape' but hashing. It transforms the value of the variable into a hash. The hash function is the one used by Typo3 to encrypt and salt a password. This is useful to manipulate FE user passwords via QFQ. See `setFeUserPassword`_ -The following `escape` and `hashing` types are available: +The following `escape`, `hashing`, `action` types are available: + + ++-------+----------------------------------------------------------------------------------------------------------------------------------+ +| Token | Description | ++=======+==================================================================================================================================+ +| m | `real_escape_string() <http://php.net/manual/en/mysqli.real-escape-string.php>`_ (m = mysql) | ++-------+----------------------------------------------------------------------------------------------------------------------------------+ +| l | LDAP search filter values: `ldap-escape() <http://php.net/manual/en/function.ldap-escape.php>`_ (LDAP_ESCAPE_FILTER). | ++-------+----------------------------------------------------------------------------------------------------------------------------------+ +| L | LDAP DN values. `ldap-escape() <http://php.net/manual/en/function.ldap-escape.php>`_ (LDAP_ESCAPE_DN). | ++-------+----------------------------------------------------------------------------------------------------------------------------------+ +| s | Single ticks ' will be escaped against \\'. | ++-------+----------------------------------------------------------------------------------------------------------------------------------+ +| d | Double ticks " will be escaped against \\". | ++-------+----------------------------------------------------------------------------------------------------------------------------------+ +| C | Colon ':' will be escaped against \\:. | ++-------+----------------------------------------------------------------------------------------------------------------------------------+ +| c | Config - the escape type configured in `configuration`_. | ++-------+----------------------------------------------------------------------------------------------------------------------------------+ +| p | Password hashing: depends on the hashing type in the Typo3 installation, includes salting if configured. | ++-------+----------------------------------------------------------------------------------------------------------------------------------+ +| '' | Nothing defined - the escape type configured in `configuration`_. | ++-------+----------------------------------------------------------------------------------------------------------------------------------+ +| - | No escaping. | ++-------+----------------------------------------------------------------------------------------------------------------------------------+ +| S | Stop replace. If the replaced value contains variables, they won't be replaced. | ++-------+----------------------------------------------------------------------------------------------------------------------------------+ - * 'm' - `real_escape_string() <http://php.net/manual/en/mysqli.real-escape-string.php>`_ (m = mysql) - * 'l' - LDAP search filter values: `ldap-escape() <http://php.net/manual/en/function.ldap-escape.php>`_ (LDAP_ESCAPE_FILTER). - * 'L' - LDAP DN values. `ldap-escape() <http://php.net/manual/en/function.ldap-escape.php>`_ (LDAP_ESCAPE_DN). - * 's' - Single ticks ' will be escaped against \\'. - * 'd' - double ticks " will be escaped against \\". - * 'C' - colon ':' will be escaped against \\:. - * 'c' - config - the escape type configured in `configuration`_. - * 'p' - password hashing: depends on the hashing type in the Typo3 installation, includes salting if configured. - * '' - the escape type configured in `configuration`_. - * '-' - no escaping. * The `escape` type is defined by the fourth parameter of the variable. E.g.: `{{name:FE:alnumx:m}}` (m = mysql). -* It's possible to combine different `escape` types, they will be processed in the order given. E.g. `{{name:FE:alnumx:Ls}}` (L, s). +* It's possible to combine multiple `escape` types, they will be processed in the order given. E.g. `{{name:FE:alnumx:Ls}}` (L, s). * Escaping is typically necessary for all user supplied content, especially if they are processed via SQL or LDAP queries. * Be careful when escaping nested variables. Best is to escape **only** the most outer variable. * In configuration_ a global `escapeTypeDefault` can be defined. The configured escape type applies to all substituted diff --git a/extension/Source/core/Constants.php b/extension/Source/core/Constants.php index 3cfc88a69809ce020fc5da10e2b3ec8b7d7f67f3..228a0068e6137901ddfe81be2647032d2422d024 100644 --- a/extension/Source/core/Constants.php +++ b/extension/Source/core/Constants.php @@ -731,6 +731,10 @@ const TOKEN_ESCAPE_MYSQL = 'm'; const TOKEN_ESCAPE_PASSWORD_T3FE = 'p'; const TOKEN_ESCAPE_NONE = '-'; +const TOKEN_ESCAPE_STOP_REPLACE = 'S'; +#const TOKEN_ESCAPE_ACTION = 'A'; +#const TOKEN_ESCAPE_EXCEPTION = 'X'; + // Workaround for PHP < 5.6.0 if (!function_exists('ldap_escape')) { define('LDAP_ESCAPE_FILTER', 0x01); diff --git a/extension/Source/core/Evaluate.php b/extension/Source/core/Evaluate.php index 5285751bcfa9829e5686b8dc42180c1117c44094..2b0f8933faae51320c39a51b60d18f196337dc54 100644 --- a/extension/Source/core/Evaluate.php +++ b/extension/Source/core/Evaluate.php @@ -349,7 +349,6 @@ class Evaluate { if ($type == DND_DATA_DND_API) { return ($this->inlineDataDndApi($arrToken, $dbIndex, $foundInStore)); - } } @@ -394,6 +393,9 @@ class Evaluate { case TOKEN_ESCAPE_PASSWORD_T3FE: $value = Password::getHash($value); break; + case TOKEN_ESCAPE_STOP_REPLACE: + $value = Support::encryptDoubleCurlyBraces($value); + break; default: throw new UserFormException("Unknown escape qualifier: $escape", UNKNOWN_TYPE); break; diff --git a/extension/Tests/unit/core/EvaluateTest.php b/extension/Tests/unit/core/EvaluateTest.php index 9397e54f617a64e77dfc9be8f2f91ad8e21dfd06..bbcaf5882a594589ab5f44b419657f09ac3e5dd7 100644 --- a/extension/Tests/unit/core/EvaluateTest.php +++ b/extension/Tests/unit/core/EvaluateTest.php @@ -465,10 +465,18 @@ class EvaluateTest extends AbstractDatabaseTest { $this->store->setVar('a', 'h\e,l=l+o< >w;o"r#ld', STORE_FORM, true); $this->assertEquals('h\5ce\2cl\3dl\2bo\3c \3ew\3bo\22r\23ld', $eval->substitute('a:F:all:L', $foundInStore)); - $this->store->setVar('a', ' hel;lo world ', STORE_FORM, true); // $this->assertEquals('\20hel\3blo world\20', $eval->substitute('a:F:all:sL', $foundInStore)); + + // The test needs a T3 installation to call the T3 password hash function - this is not available on alfred16 + // The password contains a dynamic salt - we can't force the salt and we can't force the hash +// $this->store->setVar('a', 'password', STORE_FORM, true); +// $result = $eval->substitute('a:F::p', $foundInStore); +// +// $this->assertEquals(34, strlen($result)); +// $this->assertEquals('$P$', substr($result, 0, 3)); + } /** @@ -547,6 +555,26 @@ class EvaluateTest extends AbstractDatabaseTest { $this->assertEquals("$store - start violate with \\\" in string end", $eval->parse("$store - start {{value:$store::::violate with \" in string}} end")); } + /** + * @throws CodeException + * @throws DbException + * @throws UserFormException + * @throws UserReportException + */ + public function testParseActionEscape() { + $eval = new Evaluate($this->store, $this->dbArray[DB_INDEX_DEFAULT]); + + $this->store->setVar('hidden', 'magic value', STORE_FORM, true); + $this->store->setVar('a', 'start {{hidden:F:alnumx}} end', STORE_FORM, true); + + // Recursive replace (already tested) + $this->assertEquals('go start magic value end stop', $eval->parse('go {{a:F:all}} stop')); + + // Stop Recursive replace + $this->assertEquals('go start {{hidden:F:alnumx}} end stop', $eval->parse('go {{a:F:all:S}} stop')); + + } + /** * @throws CodeException * @throws DbException