Commit 0de87089 authored by Carsten  Rose's avatar Carsten Rose
Browse files

Merge branch '4049_variable_default_value'

parents 4fdaa7c1 2332294e
......@@ -411,7 +411,7 @@ Example: *typo3conf/config.qfq.ini*
; LDAP_1_RDN='ou=Admin,dc=example,dc=com'
; LDAP_1_PASSWORD=mySecurePassword
; ESCAPE_TYPE_DEFAULT=s
; ESCAPE_TYPE_DEFAULT=m
; SECURITY_VARS_HONEYPOT=email,username,password
; SECURITY_ATTACK_DELAY=5
; SECURITY_SHOW_MESSAGE=true
......@@ -445,7 +445,7 @@ Example: *typo3conf/config.qfq.ini*
; Local Documentation (doc fits to installed version): typo3conf/ext/qfq/Documentation/html/Manual.html
;DOCUMENTATION_QFQ = https://docs.typo3.org/typo3cms/drafts/github/T3DocumentationStarter/Public-Info-053/Manual.html
;VAR_ADD_BY_SQL = {{!SELECT s.id AS _periodId FROM Period AS s WHERE s.start<=NOW() ORDER BY s.start DESC LIMIT 1}}
;VAR_ADD_BY_SQL = 'SELECT s.id AS _periodId FROM Period AS s WHERE s.start<=NOW() ORDER BY s.start DESC LIMIT 1'
;FORM_LANGUAGE_A_ID = 1
;FORM_LANGUAGE_A_LABEL = english
......@@ -509,7 +509,7 @@ The QFQ approach works without a marker and without manual intervention: the whi
In `config.qfq.ini`: ::
VAR_ADD_BY_SQL = SELECT id AS periodId FROM Period WHERE start<=NOW() ORDER BY start DESC LIMIT 1
VAR_ADD_BY_SQL = 'SELECT id AS periodId FROM Period WHERE start<=NOW() ORDER BY start DESC LIMIT 1'
a variable 'periodId' will automatically computed and filled in STORE SYSTEM. Access it via `{{periodId:Y0}}`.
To get the name and current period: ::
......@@ -824,7 +824,7 @@ Types
Store variables
^^^^^^^^^^^^^^^
Syntax: *{{VarName[:<store / prio>[:<sanitize class>[:<escape>]]]}}*
Syntax: *{{VarName[:<store / prio>[:<sanitize class>[:<escape>[:<default>]]]]}}*
* Example::
......@@ -832,11 +832,13 @@ Syntax: *{{VarName[:<store / prio>[:<sanitize class>[:<escape>]]]}}*
{{pId:FSE}}
{{pId:FSE:digit}}
{{name:FSE:alnumx:m}}
{{name:FSE:alnumx:m:John Doe}}
* Zero or more stores might be specified to be searched for the given VarName.
* If no store is specified, the by default searched stores are: **FSRVD** (=FORM > SIP > RECORD > VARS > DEFAULT).
* If the VarName is not found in one store, the next store is searched, up to the last specified store.
* If the VarName is not found in any store, nothing is replaced - the string '{{<VarName>}}' remains.
* If the VarName is not found and a default value is given, the default is returned.
* If no value is found, nothing is replaced - the string '{{<VarName>}}' remains.
* If anywhere along the line an empty string is found, this **is** a value: therefore, the search will stop.
See also:
......@@ -953,6 +955,8 @@ To protect the web application the following `escape` types are available:
* 'L' - LDAP DN values will be escaped. `ldap-escape() <http://php.net/manual/en/function.ldap-escape.php>`_ (LDAP_ESCAPE_DN).
* 's' - single ticks will be escaped. str_replace() of ' against \\'.
* 'd' - double ticks will be escaped: str_replace() of " against \\".
* 'c' - config - the escape type configured in `config.qfq.ini`_.
* '' - the escape type configured in `config.qfq.ini`_.
* '-' - no escaping.
* The `escape` type is defined by the fourth parameter of the variable. E.g.: `{{name:FE:alnumx:m}}` (m = mysql).
......
......@@ -561,6 +561,7 @@ if (!function_exists('ldap_escape')) {
}
const TOKEN_FOUND_IN_STORE_QUERY = 'query';
const TOKEN_FOUND_AS_DEFAULT = 'default';
const RANDOM_LENGTH = 32;
......
......@@ -52,6 +52,9 @@ class Evaluate {
$this->endDelimiter = $endDelimiter;
$this->endDelimiterLength = strlen($endDelimiter);
$this->escapeTypeDefault = $this->store->getVar(F_ESCAPE_TYPE_DEFAULT, STORE_SYSTEM);
if (empty($this->escapeTypeDefault) || $this->escapeTypeDefault == TOKEN_ESCAPE_CONFIG) {
$this->escapeTypeDefault = $this->store->getVar(SYSTEM_ESCAPE_TYPE_DEFAULT, STORE_SYSTEM);
}
}
/**
......@@ -174,9 +177,9 @@ class Evaluate {
* Tries to substitute $token.
* Token might be:
* a) a SQL statement to fire
* b) fetch from a store. Syntax: 'form', 'form:C', 'form:SC0', 'form:S:alnumx', 'form:F:all:s'
* b) fetch from a store. Syntax: 'form', 'form:C', 'form:SC0', 'form:S:alnumx', 'form:F:all:s','form:F:all:s:default'
*
* The token have to be _without_ Delimiter '{{' / '}}'
* The token have to be _without_ Delimiter '{{' , '}}'
* If neither a) or b) match, return the token itself.
*
* @param string $token
......@@ -209,9 +212,9 @@ class Evaluate {
return $this->db->sql($token, $sqlMode);
}
// explode for: <key>:<store priority>:<sanitize class>:<escape>
$arr = explode(':', $token, 4);
$arr = array_merge($arr, [null, null, null, null]); // fake isset()
// explode for: <key>:<store priority>:<sanitize class>:<escape>:<default>
$arr = explode(':', $token, 5);
$arr = array_merge($arr, [null, null, null, null, null]); // fake isset()
$escapeTypes = $arr[3];
if ($escapeTypes == '') {
$escapeTypes = $this->escapeTypeDefault;
......@@ -223,8 +226,11 @@ class Evaluate {
// escape ticks
if (is_string($value)) {
// Process all escape requests in the given order.
for ($ii = 0; $ii < strlen($arr[3]); $ii++) {
for ($ii = 0; $ii < strlen($escapeTypes); $ii++) {
$escape = $escapeTypes[$ii];
if ($escape == TOKEN_ESCAPE_CONFIG) {
$escape = $this->escapeTypeDefault;
}
switch ($escape) {
case TOKEN_ESCAPE_SINGLE_TICK:
$value = str_replace("'", "\\'", $value);
......@@ -250,10 +256,12 @@ class Evaluate {
}
}
// OLD: nothing replaced: put ticks around, to sanitize strings for SQL statements. Nothing to substitute is not a wished situation.
// return ($value === false) ? "'" . $token . "'" : $value;
// Not found and a default is given: take the default.
if ($foundInStore == '' && !empty($arr[4])) {
$foundInStore = TOKEN_FOUND_AS_DEFAULT;
$value = str_replace('\\:', ':', $arr[4]);
}
// NEW: nothing replaced: higher level should decide what to do
return $value;
}
......
......@@ -860,6 +860,10 @@ class QuickFormQuery {
break;
}
if (isset($form[F_ESCAPE_TYPE_DEFAULT]) && $form[F_ESCAPE_TYPE_DEFAULT] == TOKEN_ESCAPE_CONFIG) {
$form[F_ESCAPE_TYPE_DEFAULT] = $this->store->getVar(SYSTEM_ESCAPE_TYPE_DEFAULT, STORE_SYSTEM);
}
return $form;
}
......
......@@ -85,6 +85,7 @@ $UPDATE_ARRAY = array(
'0.25.0' => [
"ALTER TABLE `FormElement` CHANGE `type` `type` ENUM( 'checkbox', 'date', 'datetime', 'dateJQW', 'datetimeJQW', 'extra', 'gridJQW', 'text', 'editor', 'annotate', 'time', 'note', 'password', 'radio', 'select', 'subrecord', 'upload', 'annotate', 'fieldset', 'pill', 'templateGroup', 'beforeLoad', 'beforeSave', 'beforeInsert', 'beforeUpdate', 'beforeDelete', 'afterLoad', 'afterSave', 'afterInsert', 'afterUpdate', 'afterDelete', 'sendMail', 'paste' ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'text';",
],
);
......
......@@ -416,10 +416,6 @@ class Report {
continue;
}
// Set dbAlias if one is specified. Else keep the parent one.
//TODO dbAlias
// $this->dbAlias = $this->getValueParentDefault("db", $full_super_level, $full_level, $cur_level, DB);
// Set debug, if one is specified else keep the parent one.
$lineDebug = $this->getValueParentDefault(TOKEN_DEBUG, $full_super_level, $full_level, $cur_level, 0);
......
......@@ -177,7 +177,7 @@ class Config {
Support::setIfNotSet($config, SYSTEM_SECURITY_ATTACK_DELAY, SYSTEM_SECURITY_ATTACK_DELAY_DEFAULT);
Support::setIfNotSet($config, SYSTEM_SECURITY_SHOW_MESSAGE, '0');
Support::setIfNotSet($config, SYSTEM_SECURITY_GET_MAX_LENGTH, SYSTEM_SECURITY_GET_MAX_LENGTH_DEFAULT);
Support::setIfNotSet($config, SYSTEM_ESCAPE_TYPE_DEFAULT, TOKEN_ESCAPE_SINGLE_TICK);
Support::setIfNotSet($config, SYSTEM_ESCAPE_TYPE_DEFAULT, TOKEN_ESCAPE_MYSQL);
Support::setIfNotSet($config, SYSTEM_GFX_EXTRA_BUTTON_INFO_INLINE, '<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>');
Support::setIfNotSet($config, SYSTEM_GFX_EXTRA_BUTTON_INFO_BELOW, '<span class="glyphicon glyphicon-info-sign text-info" aria-hidden="true"></span>');
Support::setIfNotSet($config, SYSTEM_EXTRA_BUTTON_INFO_CLASS, '');
......
......@@ -11,8 +11,8 @@ CREATE TABLE IF NOT EXISTS `Form` (
`permitEdit` ENUM('sip', 'logged_in', 'logged_out', 'always', 'never') NOT NULL DEFAULT 'sip',
`escapeTypeDefault` VARCHAR(32) NOT NULL DEFAULT 'c',
`render` ENUM('bootstrap', 'table', 'plain') NOT NULL DEFAULT 'bootstrap',
`requiredParameterNew` VARCHAR(255) NOT NULL DEFAULT '',
`requiredParameterEdit` VARCHAR(255) NOT NULL DEFAULT '',
`requiredParameterNew` VARCHAR(255) NOT NULL DEFAULT '',
`requiredParameterEdit` VARCHAR(255) NOT NULL DEFAULT '',
`dirtyMode` ENUM('exclusive', 'advisory', 'none') NOT NULL DEFAULT 'exclusive',
`showButton` SET('new', 'delete', 'close', 'save') NOT NULL DEFAULT 'new,delete,close,save',
`multiMode` ENUM('none', 'horizontal', 'vertical') NOT NULL DEFAULT 'none',
......@@ -28,10 +28,10 @@ CREATE TABLE IF NOT EXISTS `Form` (
`bsNoteColumns` VARCHAR(255) NOT NULL DEFAULT '',
`parameter` TEXT NOT NULL,
`parameterLanguageA` TEXT NOT NULL,
`parameterLanguageB` TEXT NOT NULL,
`parameterLanguageC` TEXT NOT NULL,
`parameterLanguageD` TEXT NOT NULL,
`parameterLanguageA` TEXT NOT NULL,
`parameterLanguageB` TEXT NOT NULL,
`parameterLanguageC` TEXT NOT NULL,
`parameterLanguageD` TEXT NOT NULL,
`recordLockTimeoutSeconds` INT(11) NOT NULL DEFAULT 900,
`deleted` ENUM('yes', 'no') NOT NULL DEFAULT 'no',
......@@ -441,7 +441,7 @@ CREATE TABLE IF NOT EXISTS `Cron` (
`frequency` VARCHAR(32) NOT NULL,
`inProgress` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
`status` ENUM('enable', 'disable') NOT NULL DEFAULT 'enable',
`sql1` TEXT NOT NULL,
`sql1` TEXT NOT NULL,
`content` TEXT NOT NULL,
`comment` TEXT NOT NULL,
`modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
......
......@@ -360,6 +360,25 @@ class EvaluateTest extends \AbstractDatabaseTest {
}
public function testSubstituteDefault() {
$eval = new \qfq\Evaluate($this->store, $this->dbArray[DB_INDEX_DATA_DEFAULT]);
// No escape
$this->store->setVar('a', 'hello', STORE_FORM, true);
$this->assertEquals('hello', $eval->substitute('a:F:all::world', $foundInStore));
$this->assertEquals(STORE_FORM, $foundInStore);
$this->assertEquals('world', $eval->substitute('a-notused:F:all::world', $foundInStore));
$this->assertEquals(TOKEN_FOUND_AS_DEFAULT, $foundInStore);
$this->assertEquals('hello:world', $eval->substitute('a-notused:F:all::hello\\:world', $foundInStore));
$this->assertEquals(TOKEN_FOUND_AS_DEFAULT, $foundInStore);
$this->assertEquals(false, $eval->substitute('a-notused:F:all::', $foundInStore));
$this->assertEquals('', $foundInStore);
}
protected function setUp() {
$this->store = Store::getInstance('form=TestFormName', true);
......
......@@ -290,7 +290,7 @@ EOT;
SYSTEM_SECURITY_ATTACK_DELAY => '5',
SYSTEM_SECURITY_SHOW_MESSAGE => '0',
SYSTEM_SECURITY_GET_MAX_LENGTH => '50',
SYSTEM_ESCAPE_TYPE_DEFAULT => 's',
SYSTEM_ESCAPE_TYPE_DEFAULT => 'm',
SYSTEM_GFX_EXTRA_BUTTON_INFO_INLINE => '<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>',
SYSTEM_GFX_EXTRA_BUTTON_INFO_BELOW => '<span class="glyphicon glyphicon-info-sign text-info" aria-hidden="true"></span>',
SYSTEM_EXTRA_BUTTON_INFO_CLASS => '',
......
......@@ -9,7 +9,7 @@ CREATE TABLE IF NOT EXISTS `Form` (
`permitNew` ENUM('sip', 'logged_in', 'logged_out', 'always', 'never') NOT NULL DEFAULT 'sip',
`permitEdit` ENUM('sip', 'logged_in', 'logged_out', 'always', 'never') NOT NULL DEFAULT 'sip',
`escapeTypeDefault` VARCHAR(32) NOT NULL DEFAULT 'c',
`escapeTypeDefault` VARCHAR(32) NOT NULL DEFAULT 'c',
`render` ENUM('plain', 'table', 'bootstrap') NOT NULL DEFAULT 'plain',
`requiredParameter` VARCHAR(255) NOT NULL DEFAULT '',
`dirtyMode` ENUM('exclusive', 'advisory', 'none') NOT NULL DEFAULT 'exclusive',
......@@ -27,7 +27,7 @@ CREATE TABLE IF NOT EXISTS `Form` (
`bsNoteColumns` VARCHAR(255) NOT NULL DEFAULT '',
`parameter` TEXT NOT NULL,
`recordLockTimeoutSeconds` INT(11) NOT NULL DEFAULT 900,
`recordLockTimeoutSeconds` INT(11) NOT NULL DEFAULT 900,
`deleted` ENUM('yes', 'no') NOT NULL DEFAULT 'no',
`modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment