Commit 52643069 authored by Carsten  Rose's avatar Carsten Rose
Browse files

Merge branch 'develop' into 'master'

Refs #12615. Implements silent HEIC/HEIF conversion to png. Write a note in...

See merge request !355
parents 768c8a93 ae52d966
Pipeline #5376 passed with stages
in 3 minutes and 22 seconds
......@@ -16,7 +16,7 @@
.. Bold **bold**
.. Code ``text``
.. External Links: `Bootstrap <http://getbootstrap.com/>`_
.. Internal Link: :ref:downloadButton (default url text) or :ref:`download Button<downloadButton>` (explicit url text)
.. Internal Link: :ref:`downloadButton` (default url text) or :ref:`download Button<downloadButton>` (explicit url text)
.. Add Images: .. image:: ../Images/a4.jpg
..
..
......
......@@ -16,7 +16,7 @@
.. Bold **bold**
.. Code ``text``
.. External Links: `Bootstrap <http://getbootstrap.com/>`_
.. Internal Link: :ref:downloadButton (default url text) or :ref:`download Button<downloadButton>` (explicit url text)
.. Internal Link: :ref:`downloadButton` (default url text) or :ref:`download Button<downloadButton>` (explicit url text)
.. Add Images: .. image:: ../Images/a4.jpg
..
..
......
......@@ -16,7 +16,7 @@
.. Bold **bold**
.. Code ``text``
.. External Links: `Bootstrap <http://getbootstrap.com/>`_
.. Internal Link: :ref:downloadButton (default url text) or :ref:`download Button<downloadButton>` (explicit url text)
.. Internal Link: :ref:`downloadButton` (default url text) or :ref:`download Button<downloadButton>` (explicit url text)
.. Add Images: .. image:: ../Images/a4.jpg
..
..
......
.. ==================================================
.. ==================================================
.. ==================================================
.. Header hierarchy
.. ==
.. --
.. ^^
.. ""
.. ;;
.. ,,
..
.. --------------------------------------------used to the update the records specified ------
.. Best Practice T3 reST: https://docs.typo3.org/m/typo3/docs-how-to-document/master/en-us/WritingReST/CheatSheet.html
.. Reference: https://docs.typo3.org/m/typo3/docs-how-to-document/master/en-us/WritingReST/Index.html
.. Italic *italic*
.. Bold **bold**
.. Code ``text``
.. External Links: `Bootstrap <http://getbootstrap.com/>`_
.. Internal Link: :ref:`downloadButton` (default url text) or :ref:`download Button<downloadButton>` (explicit url text)
.. Add Images: .. image:: ../Images/a4.jpg
..
..
.. Admonitions
.. .. note:: .. important:: .. tip:: .. warning::
.. Color: (blue) (orange) (green) (red)
..
.. Definition:
.. some text becomes strong (only one line)
.. description has to indented
.. -*- coding: utf-8 -*- with BOM.
.. include:: Includes.txt
.. _`use-case`:
Use Case
========
To install the following use cases, please:
* Create the page and tt-content records.
* Copy the JSON form code to a new empty form (open Form in JSON mode).
.. _`self-registration`:
Self Registration
-----------------
**Concept:**
* The T3 FE User record will be created on the fly in the *last* step, when the user set's the password.
* Form *Registration*
* Input: *last name, first name, email*.
* Create record in table `Person`, if no name or email sibling is found. Else give a hint to do a password reset.
* Set a new ``Person.auth`` token.
* Set ``Person.authExpired = NOW() + INTERVAL 1 DAY``.
* Send an email to the given email address with a password reset link (incl. the token) which is time limited.
* Further steps: See *Set password*.
* Form *Request password reset link*
* This is optional, but useful to offer the opportunity to reset the own password.
* Input: *email address*.
* Send an email to the given email address with a password reset link (incl. a token) which is time limited.
* Only send email if the email address is known!
* If email is not found, the user should not be noticed. This prohibits misusing the form to validate email adresses.
* Set a new ``Person.auth`` token.
* Set ``Person.authExpired = NOW() + INTERVAL 1 DAY``.
* Form *Set password*
* The user types in the new password.
* On save:
* If the FE account does not exist, it will be created.
* Set the FE user password.
* Clear ``Person.authExpired``.
Table: Person
^^^^^^^^^^^^^
::
CREATE TABLE `Person` (
`id` int(11) UNSIGNED NOT NULL,
`lastName` varchar(64) NOT NULL DEFAULT '',
`firstName` varchar(64) NOT NULL DEFAULT '',
`email` varchar(128) NOT NULL,
`account` varchar(128) NOT NULL,
`auth` varchar(32) NOT NULL,
`authExpire` datetime NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8 PACK_KEYS=1;
Registration
^^^^^^^^^^^^
Page: Registration
""""""""""""""""""
* Page Alias: registration
QFQ content record::
#
# {{action:SE}}: thanksRegistration
#
form={{SELECT IF('{{action:SE}}' = '','registration','') }}
20.sql = SELECT "<p>Thank you for your registration.</p><p>An email with further instructions has been sent to you.</p>"
, "<p>You should receive the mail during the next 5 minutes. If not, please check your SPAM folder.</p>"
FROM (SELECT '') AS fake
WHERE '{{action:SE}}' = 'thanksRegistration'
AND '{{form:SE}}'=''
Form: registration
""""""""""""""""""
::
{
"title": "Registration",
"tableName": "Person",
"permitNew": "always",
"permitEdit": "never",
"showButton": "close,save",
"forwardMode": "url-sip-skip-history",
"forwardPage": "?id=registration&action=thanksRegistration",
"parameter": "submitButtonText=Register",
"FormElement_ff": [
{
"enabled": "yes",
"name": "firstName",
"label": "First name",
"mode": "required",
"type": "text"
},
{
"enabled": "yes",
"name": "lastName",
"label": "Last name",
"mode": "required",
"type": "text"
},
{
"enabled": "yes",
"name": "email",
"label": "Email",
"mode": "required",
"class": "native",
"type": "text",
"checkType": "email",
"parameter": "retype\r\nretypeLabel=Retype email"
},
{
"enabled": "yes",
"label": "Check for double registration",
"mode": "show",
"modeSql": "",
"class": "action",
"type": "beforeSave",
"parameter": "sqlValidate={{!SELECT p.id FROM Person AS p WHERE p.email='{{email:F:alnumx}}' OR ('{{firstName:F:allbut}}'=p.firstName AND '{{lastName:F:allbut}}'=p.lastName ) LIMIT 1 }}\r\n expectRecords=0\r\nmessageFail=Sorry, person already registered by name or email. Please just reset the password under <a href='?id=reset'>reset</a>"
},
{
"enabled": "yes",
"label": "auth, deadline",
"class": "action",
"type": "afterSave",
"parameter": "# Set token & expiration\r\nsqlBefore={{UPDATE Person SET auth='{{random:V}}', authExpire=DATE_ADD(NOW(), INTERVAL 1 DAY) WHERE id={{id:R}} }}"
},
{
"enabled": "yes",
"label": "a) sendEmail, b) fe user",
"mode": "show",
"class": "action",
"type": "sendMail",
"value": "Dear new user\r\nPlease set a new password under {{baseUrl:Y}}?id=set&auth={{auth:R}}\r\nRegards.",
"parameter": "sendMailTo={{email:R}}\r\nsendMailSubject=Registration confirmation\r\nsendMailFrom={{ADMINISTRATIVE_EMAIL:Y}}\r\n\r\n# Create User in T3\r\nsqlAfter={{INSERT INTO {{dbNameT3:Y}}.fe_users (pid, usergroup, username, password, first_name, last_name, name, email) VALUES (6, '1', '{{email:F:alnumx}}','$p$initial invalid hash', '{{firstName:R}}', '{{lastName:R}}', '{{firstName:R}} {{lastName:R}}', '{{email:F:alnumx}}') }}"
}
]
}
Request password reset link
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Page: reset
"""""""""""
* Page Alias: reset
QFQ content record::
#
# {{action:SE}}: passwordReset
#
# Empty: {{action:SE}}='' > shows the form angezeigt 'passwordReset'.
# Given: {{action:SE}}='confirmation' > show confirmation.
#
form={{SELECT IF('{{action:SE}}' = '','passwordReset','') }}
r=1
10 {
sql = SELECT '' FROM (SELECT '') AS fake WHERE '{{action:SE}}'='confirmation'
head = <div class="alert alert-success">
<p>Thank you.</p>
<p>If the email address is known in our database, we sent a password reset link to it.</p>
<p>The mail should be received during the next minutes. If not, please check you junk folder.</p>
<p>To set a new password, please click on the link provided in the email.</p>
</div>
}
Form: passwordReset
"""""""""""""""""""
.. note::
Take care that there is one dummy person record with person.id=1
Form 'passwordReset'::
{
"title": "Password reset",
"tableName": "Person",
"permitNew": "never",
"permitEdit": "always",
"escapeTypeDefault": "c",
"render": "bootstrap",
"dirtyMode": "exclusive",
"showButton": "save",
"multiMode": "none",
"forwardMode": "url-sip-skip-history",
"forwardPage": "?id={{pageAlias:T}}&action=confirmation",
"labelAlign": "default",
"parameter": "submitButtonText = Send password reset email",
"deleted": "no",
"FormElement_ff": [
{
"enabled": "yes",
"name": "emailValue",
"label": "Email",
"mode": "show",
"class": "native",
"type": "text",
"encode": "specialchar",
"checkType": "email",
"ord": 10
},
{
"enabled": "yes",
"label": "Check for *example.com email",
"mode": "show",
"class": "action",
"type": "beforeSave",
"ord": 20,
"parameter": "sqlValidate={{!SELECT 'fake' FROM (SELECT '') AS fake WHERE '{{emailValue:F:alnumx}}' LIKE '%example.com' }}\r\n expectRecords=0\r\nmessageFail=Sorry, Password reset is not possible for *example.com."
},
{
"enabled": "yes",
"label": "a) set auth, expire, b) send email",
"mode": "show",
"class": "action",
"type": "sendMail",
"encode": "specialchar",
"checkType": "auto",
"ord": 50,
"value": "Dear new user\r\nPlease set a new password under {{baseUrl:Y}}?id=set&auth={{auth:V}}\r\nRegards.",
"parameter": "fillStoreVar={{!SELECT CONCAT(p.firstName , ' ', p.lastName) AS name, p.id AS _pId, @expire:=DATE_ADD(NOW(), INTERVAL 4 DAY) AS expireTs, QDATE_FORMAT(@expire) AS expire, p.email, '{{random:V}}' AS auth FROM Person AS p WHERE p.email='{{emailValue:F:alnumx}}' AND p.email!='' LIMIT 1}}\r\n\r\nsendMailTo={{email:VE}}\r\nsendMailSubject=Password Reset\r\nsendMailFrom=webmaster@example.com\r\nsendMailGrId=123\r\nsendMailXId=456\r\n\r\n# Set token & expiration\r\nsqlAfter = {{UPDATE Person SET auth='{{auth:V}}', authExpire='{{expireTs:V}}' WHERE email='{{emailValue:F:alnumx}}' AND email!='' LIMIT 1}}"
}
]
}
Set new password
^^^^^^^^^^^^^^^^
Page: set
"""""""""
* Page
* Alias: set
* Hide in menu: yes
QFQ content record::
#
# {{auth:CE}} - empty >> Form 'setPassword'
# {{auth:CE}} - unknown | expired >> Error message
# {{auth:SE}} - valid >> Set Password
#
# {{action:CE}} - 'thanks'
form={{SELECT IF( ISNULL(p.id), '', 'passwordSet' )
FROM (SELECT '') AS fake
LEFT JOIN Person AS p
ON p.auth='{{auth:C:alnumx}}'
AND p.auth!=''
AND NOW()<p.authExpire }}
r={{SELECT IFNULL(p.id, 0) FROM (SELECT '') AS fake LEFT JOIN Person AS p ON p.auth='{{auth:C:alnumx}}' AND p.auth!='' AND NOW()<p.authExpire}}
10 {
sql = SELECT IF( ISNULL(p.id)
, 'Token invalid'
, IF( NOW()<p.authExpire
,''
, IF( p.authExpire=0, 'Password already set', 'Token expired') )
)
FROM (SELECT '') AS fake
LEFT JOIN Person AS p
ON p.auth='{{auth:C:alnumx}}'
AND p.auth!=''
WHERE '{{action:SE}}'=''
AND (ISNULL(p.id) OR NOW()>=p.authExpire)
head = <div class="alert alert-warning" role="alert">
tail = </div>
}
20.sql = SELECT 'Thanks for setting the password. Please <a href="?id=login">log in</a> now.'
FROM (SELECT '') AS fake
WHERE '{{action:SE}}'='thanks'
Form: passwordSet
"""""""""""""""""
.. note::
Please adjust the numbers for ``usergroup`` and ``pid`` in FormElement `Update fe_user.password > parameter > sqlInsert`
to your needs. Remember that every FE-User needs at least one FE-Group to log in successfully.
Form 'passwordSet'::
{
"title": "Set password",
"tableName": "Person",
"permitNew": "never",
"permitEdit": "always",
"escapeTypeDefault": "c",
"render": "bootstrap",
"dirtyMode": "exclusive",
"showButton": "save",
"multiMode": "none",
"forwardMode": "url-sip-skip-history",
"forwardPage": "?{{pageAlias:T}}&action=thanks",
"parameter": "submitButtonText='Set password'",
"FormElement_ff": [
{
"enabled": "yes",
"name": "myValue",
"label": "Password",
"mode": "show",
"class": "native",
"type": "password",
"checkType": "pattern",
"checkPattern": "[a-zA-Z0-9-_+ *\\\/.,:;]{10,}",
"ord": 10,
"parameter": "retype\r\nretypeLabel=Retype password\r\ndata-pattern-error=At least 10 characters are required. Valid characters: a-z A-Z 0-9 -_+*\/.,:;\r\nextraButtonPassword"
},
{
"enabled": "yes",
"label": "Update fe_user.password",
"mode": "show",
"class": "action",
"type": "afterSave",
"encode": "specialchar",
"ord": 20,
"parameter": "slaveId={{SELECT fe.uid FROM {{dbNameT3:Y}}.fe_users AS fe WHERE fe.username='{{email:RE}}' AND fe.username!='' AND fe.deleted=0 LIMIT 1}}\r\n\r\n# Create FE User. Please update values of `pid`, `usergroup` to your setup.\r\nsqlInsert = {{INSERT INTO {{dbNameT3:Y}}.fe_users ( `pid`, `usergroup`, `username`, `email`, `name`, `password`,`crdate`) VALUES ( 5 , 1 , '{{email:RE}}', '{{email:RE}}', '{{lastName:RE}}, {{firstName:RE}}', '{{myValue:FE:all:p}}', UNIX_TIMESTAMP() ) }}\r\n\r\nsqlUpdate = {{UPDATE {{dbNameT3:Y}}.fe_users SET password='{{myValue:FE:all:p}}' WHERE uid={{slaveId:V0}} }}\r\n\r\nsqlAfter={{UPDATE Person SET authExpire=0 WHERE id={{id:R}} }}"
}
]
}
\ No newline at end of file
......@@ -16,7 +16,7 @@
.. Bold **bold**
.. Code ``text``
.. External Links: `Bootstrap <http://getbootstrap.com/>`_
.. Internal Link: :ref:downloadButton (default url text) or :ref:`download Button<downloadButton>` (explicit url text)
.. Internal Link: :ref:`downloadButton` (default url text) or :ref:`download Button<downloadButton>` (explicit url text)
.. Add Images: .. image:: ../Images/a4.jpg
..
..
......
......@@ -54,7 +54,7 @@ master_doc = 'index'
# General information about the project.
project = 'QFQ'
copyright = '2020, Carsten Rose, Benjamin Baer, Marc Egger'
copyright = '2021, Carsten Rose, Benjamin Baer, Marc Egger'
author = 'Carsten Rose, Benjamin Baer, Marc Egger'
# The version info for the project you're documenting, acts as replacement for
......
......@@ -87,6 +87,7 @@ This documentation is for the TYPO3 extension **qfq**.
ApplicationTest
GeneralTips
CodingGuideline
UseCase
License
Sitemap
SearchDocs
......
......@@ -21,6 +21,7 @@ use IMATHUZH\Qfq\Core\Helper\OnArray;
use IMATHUZH\Qfq\Core\Helper\Path;
use IMATHUZH\Qfq\Core\Helper\Sanitize;
use IMATHUZH\Qfq\Core\Helper\Support;
use IMATHUZH\Qfq\Core\Helper\OnString;
use IMATHUZH\Qfq\Core\Report\Link;
use IMATHUZH\Qfq\Core\Report\Report;
use IMATHUZH\Qfq\Core\Store\Sip;
......@@ -256,7 +257,7 @@ abstract class AbstractBuildForm {
$this->store->setStore($row, STORE_PARENT_RECORD, true);
$this->store->setVar(F_MULTI_COL_ID, $row[$idName], STORE_PARENT_RECORD); // In case '_id' is used, both '_id' and 'id' should be accessible.
$record = $this->dbArray[$this->dbIndexData]->sql('SELECT * FROM `' . $this->formSpec[F_TABLE_NAME] . '` WHERE `id`=' . $row[F_MULTI_COL_ID], ROW_EXPECT_1);
$record = $this->dbArray[$this->dbIndexData]->sql('SELECT * FROM `' . $this->formSpec[F_TABLE_NAME] . '` WHERE `id`= ?', ROW_EXPECT_1, [$row[$idName]]);
$this->store->setStore($record, STORE_RECORD, true);
$jsonTmp = array();
......@@ -862,6 +863,8 @@ abstract class AbstractBuildForm {
if ($formElement[FE_ENCODE] === FE_ENCODE_SPECIALCHAR) {
// $value = htmlspecialchars_decode($value, ENT_QUOTES);
$value = Support::htmlEntityEncodeDecode(MODE_DECODE, $value);
} elseif ($formElement[FE_ENCODE] === FE_ENCODE_SINGLE_TICK) {
$value = OnString::escapeSingleTickInHtml($value);
}
// Typically: $htmlElementNameIdZero = true
......
......@@ -419,8 +419,6 @@ const STORE_USE_DEFAULT = "FSRVD";
const CLIENT_FORM = 'form';
const CLIENT_SIP = 's';
const CLIENT_RECORD_ID = 'r';
const CLIENT_KEY_SEM_ID = 'keySemId';
const CLIENT_KEY_SEM_ID_USER = 'keySemIdUser';
const CLIENT_PAGE_ID = 'id';
const CLIENT_PAGE_TYPE = 'type';
const CLIENT_PAGE_LANGUAGE = 'L';
......@@ -652,6 +650,7 @@ const SYSTEM_CMD_QPDF = 'cmdQpdf';
const SYSTEM_CMD_GS = 'cmdGs';
const SYSTEM_CMD_PDFUNITE = 'cmdPdfunite';
const SYSTEM_CMD_IMG2PDF = 'cmdImg2pdf';
const SYSTEM_CMD_HEIF_CONVERT = 'cmdHeifConvert';
// Thumbnail
const SYSTEM_THUMBNAIL_DIR_SECURE_REL_TO_APP = 'thumbnailDirSecure';
......@@ -1333,6 +1332,7 @@ const TYPEAHEAD_PLACEHOLDER = '?';
// Values
const FE_ENCODE_SPECIALCHAR = 'specialchar';
const FE_ENCODE_SINGLE_TICK = 'single tick';
const FE_ENCODE_NONE = 'none';
const FE_FILE_CAPTURE_CAMERA = 'camera';
......
......@@ -1133,7 +1133,7 @@ class Database {
$column = (is_numeric($uid)) ? 'uid' : 'subheader';
$dbT3 = $this->store->getVar(SYSTEM_DB_NAME_T3, STORE_SYSTEM);
$sql = "SELECT * FROM `$dbT3`.`tt_content` WHERE `$column` = ?";
$sql = "SELECT * FROM `$dbT3`.`tt_content` WHERE `$column` = ? AND `deleted` = 0 AND `hidden` = 0 ";
$arr = $this->sql($sql, ROW_EXPECT_1, [$uid], 'Function "' . $column . '=' . $uid . '" not found or more than one found.');
return ($arr);
......
......@@ -204,6 +204,11 @@ $UPDATE_ARRAY = array(
"ALTER TABLE `FormSubmitLog` ADD `formName` VARCHAR(255) NOT NULL DEFAULT '' AFTER `formId`;",
],
'21.6.0' => [
"ALTER TABLE `FormElement` CHANGE `encode` `encode` ENUM('none','specialchar','single tick') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'specialchar';",
],
);
......
......@@ -249,7 +249,7 @@ class Evaluate {
* @throws \UserFormException
* @throws \UserReportException
*/
private function inlineLink($arrToken, $dbIndex, &$foundInStore) {
private function inlineLink($arrToken, $dbIndex, &$foundInStore): string {
$token = OnString::trimQuote(trim(implode(' ', $arrToken)));
......@@ -262,31 +262,6 @@ class Evaluate {
return $this->link->renderLink($token);
}
/**
* Get the CET/CEST Timezone for a given date, or if date is '' based on the current date.
*
* @param string $dateStr
* @return string // CET, CEST or GMT+?/GMT-?
*/
public function getEuropeanTimezone($dateStr = '') {
$ts = ($dateStr == '') ? time() : strtotime($dateStr);
$offset = date("Z", $ts) / 3600;
switch ($offset) {
case 1:
$tz = "CET";
break;
case 2:
$tz = "CEST";
break;
default:
$tz = 'GMT' . sprintf("%+d", $offset);
}
return $tz;
}
/**
* @param $arrToken
* @param $dbIndex
......@@ -296,7 +271,7 @@ class Evaluate {
* @throws \UserFormException
* @throws \UserReportException
*/
private function inlineDataDndApi($arrToken, $dbIndex, &$foundInStore) {
private function inlineDataDndApi($arrToken, $dbIndex, &$foundInStore): string {
$token = OnString::trimQuote(trim(implode(' ', $arrToken)));
......@@ -344,7 +319,7 @@ class Evaluate {
$token = trim($token);
$dbIndex = $this->dbIndex;
$flagWipe = false;
$rcFlagWipe = false;
// Check if the $token starts with '[<int>]...' - yes: open the necessary database.
if (strlen($token) > 2 && $token[0] === '[') {
......@@ -421,64 +396,7 @@ class Evaluate {
$value = $this->store::getVar($arrToken[VAR_INDEX_VALUE], $arrToken[VAR_INDEX_STORE], $arrToken[VAR_INDEX_SANITIZE],
$foundInStore, $typeMessageViolate, $arrToken[VAR_INDEX_DEFAULT]);
// escape ticks
if (is_string($value)) {
// Process all escape requests in the given order.
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);
break;
case TOKEN_ESCAPE_DOUBLE_TICK:
$value = str_replace('"', '\\"', $value);
break;
case TOKEN_ESCAPE_COLON:
$value = str_replace(':', '\\:', $value);
break;
case TOKEN_ESCAPE_LDAP_FILTER:
$value = Support::ldap_escape($value, null, LDAP_ESCAPE_FILTER);
break;
case TOKEN_ESCAPE_LDAP_DN:
$value = Support::ldap_escape($value, null, LDAP_ESCAPE_DN);
break;
case TOKEN_ESCAPE_MYSQL:
$value = $this->dbArray[$dbIndex]->realEscapeString($value);
break;
case TOKEN_ESCAPE_NONE: // do nothing
break;
case TOKEN_ESCAPE_PASSWORD_T3FE:
$value = T3Handler::getHash($value);
break;
case TOKEN_ESCAPE_STOP_REPLACE:
$value = Support::encryptDoubleCurlyBraces($value);
break;
case TOKEN_ESCAPE_EXCEPTION:
// empty values will be handled later.
break;
case TOKEN_ESCAPE_WIPE:
$flagWipe = true;
break;
case TOKEN_ESCAPE_TIMEZONE:
$value = $this->getEuropeanTimezone($value);
break;
case TOKEN_ESCAPE_HTML_SPECIAL_CHAR:
$value = Support::htmlEntityEncodeDecode(MODE_ENCODE, $value);
break;
default:
throw new \UserFormException("Unknown escape qualifier: $escape", ERROR_UNKNOW_SANITIZE_CLASS);
break;
}
}
} else {
// In case the value is not found and the escape class forces a full stop
if (strpos($escapeTypes, TOKEN_ESCAPE_EXCEPTION) !== false) {
throw new \UserFormException($arrToken[VAR_INDEX_MESSAGE] ?? '', ERROR_QUIT_QFQ_REGULAR);
}
}
$value = OnString::escape($escapeTypes, $value, $rcFlagWipe);
// Not found and a default is given: take the default.
if ($foundInStore == '' && $arrToken[VAR_INDEX_DEFAULT] != '') {
......@@ -486,7 +404,7 @@ class Evaluate {
$value = str_replace('\\:', ':', $arrToken[VAR_INDEX_DEFAULT]);