diff --git a/Documentation-develop/F_FE_PARAMETER.md b/Documentation-develop/F_FE_PARAMETER.md new file mode 100644 index 0000000000000000000000000000000000000000..2b8fd7a8b19b6ad9be10a310f5b5b19fe9756a3c --- /dev/null +++ b/Documentation-develop/F_FE_PARAMETER.md @@ -0,0 +1,74 @@ +# Config, Form & FormElement parameter + +## QFQ Config > Form > FormElement + +* QFQ Config: Add to ext_conf_template.txt + + * Update PHP Unittest + * Define a default in case there is no T3 Localconf file. + +* Form + + * Inherit from QFQ config + * Add in ... (Form) init. + +* FormElement + + * Inherit from Form + * Add in Formelrment init + +## Check parameter + +To add a new Form/FormElement parameter, include it in the constant array `$FE_PARAMETER_RULES` in `HelperFormElement`. +Adding rules for the parameter is optional but recommended. This array is used to verify whether a parameter in +the Form Element is recognized by QFQ. If a parameter is not listed in the array, a `UserFormException` will be thrown. + +Location: `Qfq\Core\HelperFormElement->$FE_PARAMETER_RULES[]` + +The `$FE_PARAMETER_RULES` array should contain all parameters along with their corresponding wrapping rules. To add a +new parameter, simply insert a key-value pair into the array. + +Example: + +```php +FE_AUTOFOCUS => [NO_BRACE] +``` +Note: Empty values are skipped during wrapping validation but are still checked for existence in `$FE_PARAMETER_RULES`. + +## Rule + +When configuring a new rule array, you can choose from the following options (multiple options allowed). +At least one of the selected options must be satisfied for the input to be considered valid. +If no rules are configured ([]), no wrapping checks will be performed. + +### Option + +* NO_BRACE: no wrap +* DOUBLE_OPEN_BRACE: wrap by `{{ }}`. +* DOUBLE_OPEN_BRACE_WITH_EXCLAMATION: wrap by `{{! }}`. + + +## Things to Keep in Mind + +* Dynamic Parameter Values + If a parameter's value needs to be dynamically set and should only allow `{{VAR:STORE}}`, use the rule + `DOUBLE_OPEN_BRACE` in the configuration. This ensures proper validation and dynamic value handling. + + Example: + + ```php + FE_DYNAMIC_PARAMETER => [DOUBLE_OPEN_BRACE] + ``` + +* Static Text with Dynamic Replacements + If the parameter contains static text with placeholders for dynamic values (e.g., `Hi {{name:F}}`), there is no need to include the `DOUBLE_OPEN_BRACE` rule in the configuration. Such cases are implicitly handled by the system. + + Example: + + ```plaintext + paramName = Hi {{name:F}} + ``` + +* Consistency + + Regularly review and update the `$FE_PARAMETER_RULES` array to ensure it remains aligned with actually implemented parameters. diff --git a/Documentation/Installation.rst b/Documentation/Installation.rst index 4ffb1a120bbae6f1e3649189cc818515001d8092..4cc732bdcffaf0f4a68a2b5b4834a366631c6c3e 100644 --- a/Documentation/Installation.rst +++ b/Documentation/Installation.rst @@ -685,28 +685,6 @@ Extension Manager: QFQ Configuration +-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ | renderer | Bootstrap3Renderer | Name of the class used for rendering | +-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ -| **Authentication** (see :ref:`column-authenticate`) | -+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ -| authCreateAccount | false | Controls if user accounts can be created on the fly. | -+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ -| authUnlockAccount | false | Controls if a disabled user accounts can be unlocked. | -+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ -| authActivateAccount | false | Controls if an expired or inactive user accounts can be activated. | -+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ -| authExtendByDays | 7 (positive integer) | The number of days for which an expired account is extended. | -+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ -| authUpdateAccount | false | When true, then accounts can be updated on a successful authentication. | -+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ -| authEnable | true | The false value disables the qfq-based authentication service. | -+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ -| authPriority | 82 (positive integer) | Consult :ref:`typo3-service-precedence` | -+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ -| authQuality | 80 (positive integer) | Consult :ref:`typo3-service-precedence` | -+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ -| authUserStorage | comma-separated list of integers | The list of IDs of pages on which FE accounts are stored. | -+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ -| authUserGroups | comma-separated list of integers | The list of IDs of FE user groups to be assigned to newly created accounts.| -+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ | **Graphics** | +-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ | cmdInkscape | inkscape | If inkscape is not available, specify an empty string. | @@ -841,6 +819,9 @@ Extension Manager: QFQ Configuration | showHistory | 0 (off), 1 (on), SqlQuery (auto) | Show history button in form. SQL query can be used for dynamic value. | | | | Default: 0 | +-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ +| validateFormElementParameter | 0 (off), 1 (on) |Checks if parameters known by qfq and are wrapped correctly where necessary.| +| | | Default: 1 | ++-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ | recentLog | 0 (off), 1 (on) | For each user form open, create a record in table `Recent`. | | | | Default: 1 | +-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ @@ -1030,6 +1011,28 @@ Extension Manager: QFQ Configuration | cmdWget | wget >/dev/null 2>&1 | Command is used for trying to download content from protected folder. | | | | To accept self signed certificate, add option '--no-check-certificate' | +-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ +| **Authentication** (see :ref:`column-authenticate`) | ++-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ +| authEnable | true | The false value disables the qfq-based authentication service. | ++-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ +| authPriority | 82 (positive integer) | Consult :ref:`typo3-service-precedence` | ++-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ +| authQuality | 80 (positive integer) | Consult :ref:`typo3-service-precedence` | ++-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ +| authUserStorage | comma-separated list of integers | The list of IDs of pages on which FE accounts are stored. | ++-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ +| authUserGroups | comma-separated list of integers | The list of IDs of FE user groups to be assigned to newly created accounts.| ++-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ +| authCreateAccount | false | Controls if user accounts can be created on the fly. | ++-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ +| authUnlockAccount | false | Controls if a disabled user accounts can be unlocked. | ++-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ +| authActivateAccount | false | Controls if an expired or inactive user accounts can be activated. | ++-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ +| authExtendByDays | 7 (positive integer) | The number of days for which an expired account is extended. | ++-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ +| authUpdateAccount | false | When true, then accounts can be updated on a successful authentication. | ++-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+ .. _`typo3-service-precedence`: diff --git a/extension/Classes/Core/Constants.php b/extension/Classes/Core/Constants.php index 34f38414afdd2ed52300dfdf5ecd846600f444ac..d131e8de2671ec463991127b1dbcf3bc5298cd68 100644 --- a/extension/Classes/Core/Constants.php +++ b/extension/Classes/Core/Constants.php @@ -805,6 +805,7 @@ const SYSTEM_SHOW_ID_IN_FORM_TITLE = 'showIdInFormTitle'; const SYSTEM_INPUT_CLEAR_ME = 'clearMe'; const SYSTEM_REMEMBER_LAST_PILL = 'rememberLastPill'; const SYSTEM_SHOW_HISTORY = 'showHistory'; +const SYSTEM_VALIDATE_FORM_ELEMENT = 'validateFormElementParameter'; const SYSTEM_CMD_WKHTMLTOPDF = 'cmdWkhtmltopdf'; const SYSTEM_CMD_QFQPDF = 'cmdQfqpdf'; const SYSTEM_CMD_INKSCAPE = 'cmdInkscape'; diff --git a/extension/Classes/Core/Helper/HelperFormElement.php b/extension/Classes/Core/Helper/HelperFormElement.php index a4c9637878a3dd06fa1084bc4f37a29c2fc4bdb2..617768db56ed0a23e979b4a5d29582d0db06ec4e 100644 --- a/extension/Classes/Core/Helper/HelperFormElement.php +++ b/extension/Classes/Core/Helper/HelperFormElement.php @@ -25,6 +25,12 @@ class HelperFormElement { private static $store = null; /** + * Array containing all FE parameter and rules that they should follow. + * Rule options + * 1. NO_BRACE => The parameter value should not be wrapped by ether '{{!' or '{{' + * 2. DOUBLE_OPEN_BRACE => The parameter value must be wrapped by '{{' + * 3. DOUBLE_OPEN_BRACE_WITH_EXCLAMATION => The parameter value must be wrapped by '{{' + * @see Documentation-develop/NEW_PARAMETER.md * @var array */ private static array $FE_PARAMETER_RULES = [ @@ -60,8 +66,8 @@ class HelperFormElement { FE_IMPORT_LIST_SHEET_NAMES => [NO_BRACE], FE_CHECKBOX_MODE => [NO_BRACE], FE_ITEM_LIST => [NO_BRACE], - FE_EMPTY_ITEM_AT_START => [], - FE_EMPTY_ITEM_AT_END => [], + FE_EMPTY_ITEM_AT_START => [NO_BRACE, DOUBLE_OPEN_BRACE], + FE_EMPTY_ITEM_AT_END => [NO_BRACE, DOUBLE_OPEN_BRACE], FE_BUTTON_CLASS => [NO_BRACE], FE_DATE_FORMAT => [NO_BRACE], F_FE_DATA_PATTERN_ERROR => [NO_BRACE], @@ -195,7 +201,73 @@ class HelperFormElement { FE_FILE_SPLIT_OPTIONS => [NO_BRACE], FE_FILE_SPLIT => [NO_BRACE], F_CLASS_BODY => [NO_BRACE], - F_DB_INDEX => [NO_BRACE, DOUBLE_OPEN_BRACE] + F_DB_INDEX => [NO_BRACE, DOUBLE_OPEN_BRACE], + FE_TYPEAHEAD_LDAP => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_LDAP_SERVER => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_TYPEAHEAD_LDAP_SEARCH => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_TYPEAHEAD_LDAP_VALUE_PRINTF => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_TYPEAHEAD_LDAP_ID_PRINTF => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_TYPEAHEAD_LDAP_SEARCH_PER_TOKEN => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_TYPEAHEAD_LDAP_SEARCH_PREFETCH => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_LDAP_USE_BIND_CREDENTIALS => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_LDAP_ATTRIBUTES => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_LDAP_SEARCH => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_LDAP_TIME_LIMIT => [NO_BRACE], + FE_FILL_STORE_LDAP => [NO_BRACE], + F_LDAP_BASE_DN => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_MULTI_MODE => [], + F_MULTIFORM_DELETE_ROW => [NO_BRACE], + F_PROCESS_ROW => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_BTN_TOP_LEFT => [], + F_BTN_TOP_RIGHT => [], + F_BTN_TOP_WRAP => [NO_BRACE], + F_BTN_TOP_LEFT_WRAP => [NO_BRACE], + F_BTN_TOP_RIGHT_WRAP => [NO_BRACE], + F_BTN_TOP_LEFT_ORDER => [NO_BRACE], + F_BTN_TOP_RIGHT_ORDER => [NO_BRACE], + F_BTN_FOOTER_WRAP => [NO_BRACE], + F_BTN_FOOTER_LEFT_WRAP => [NO_BRACE], + F_BTN_FOOTER_LEFT_ORDER => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_BTN_FOOTER_RIGHT_ORDER => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_BS_COLUMNS => [NO_BRACE], + FE_CLASS => [NO_BRACE], + F_CLASS_TITLE => [NO_BRACE], + F_CLASS_PILL => [NO_BRACE], + F_BUTTON_ON_CHANGE_CLASS => [NO_BRACE], + F_ACTIVATE_FIRST_REQUIRED_TAB => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_ENTER_AS_SUBMIT => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_SUBMIT_BUTTON_TEXT => [NO_BRACE], + F_SAVE_BUTTON_ACTIVE => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_SAVE_BUTTON_TEXT => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_SAVE_BUTTON_TOOLTIP => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_SAVE_BUTTON_CLASS => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_SAVE_BUTTON_GLYPH_ICON => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_SUBMIT_BUTTON_CLASS => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_SUBMIT_BUTTON_GLYPH_ICON => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_SUBMIT_BUTTON_TOOLTIP => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_CLOSE_BUTTON_TEXT => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_CLOSE_BUTTON_TOOLTIP => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_CLOSE_BUTTON_CLASS => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_CLOSE_BUTTON_GLYPH_ICON => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_DELETE_BUTTON_TEXT => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_DELETE_BUTTON_TOOLTIP => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_DELETE_BUTTON_GLYPH_ICON => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_NEW_BUTTON_TEXT => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_NEW_BUTTON_TOOLTIP => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_NEW_BUTTON_CLASS => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_NEW_BUTTON_GLYPH_ICON => [NO_BRACE, DOUBLE_OPEN_BRACE], + SYSTEM_SHOW_ID_IN_FORM_TITLE => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_FORM_SUBMIT_LOG_MODE => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_SESSION_TIMEOUT_SECONDS => [NO_BRACE], + F_REMEMBER_LAST_PILL => [NO_BRACE], + F_DO_NOT_LOG_COLUMN => [NO_BRACE], + F_SHOW_HISTORY => [NO_BRACE], + F_SHOW_HISTORY_TITLE => [NO_BRACE, DOUBLE_OPEN_BRACE], + F_SHOW_HISTORY_FE_USER_SET => [NO_BRACE, DOUBLE_OPEN_BRACE, DOUBLE_OPEN_BRACE_WITH_EXCLAMATION], + F_BTN_PREVIOUS_NEXT_SQL => [DOUBLE_OPEN_BRACE_WITH_EXCLAMATION], + F_BTN_PREVIOUS_NEXT_LOOP => [NO_BRACE], + F_BTN_PREVIOUS_NEXT_WRAP => [NO_BRACE], + FE_SUBRECORD_EMPTY => [NO_BRACE, DOUBLE_OPEN_BRACE], ]; /** @@ -257,7 +329,7 @@ class HelperFormElement { * @throws \UserFormException * @throws \UserReportException */ - public static function explodeParameter(array &$element, $keyName, $flagAllowOverwrite = false, $flagValidateParameter = false) { + public static function explodeParameter(array &$element, $keyName, $flagAllowOverwrite = false) { // Something to explode? if (isset($element[$keyName]) && $element[$keyName] !== '') { @@ -281,18 +353,6 @@ class HelperFormElement { } } } - if ($flagValidateParameter && $keyName === FE_PARAMETER) { - // Check if FE.Parameter exists in $FE_PARAMETER_RULES - $parameterKeys = array_keys($arr); - $feParameterRulesKeys = array_keys(self::$FE_PARAMETER_RULES); - $missingKeys = array_diff($parameterKeys, $feParameterRulesKeys); - - // If there are missing keys, throw an exception - if ($missingKeys) { - $missingKeysList = implode(', ', $missingKeys); - throw new \CodeException("The following parameters are unknown: {$missingKeysList}. Please check for spelling mistakes or ensure the parameters are correctly defined or contact Developer :)"); - } - } $element = array_merge($element, $arr); // For retype elements: copy the language specific value. @@ -1434,54 +1494,74 @@ EOF; /** * Checks a formElement against a list of requirements and throws a error if they are not met. - * + * @see Documentation-develop/NEW_PARAMETER.md * @param array $element * @return void * @throws \UserFormException * @throws \CodeException + * @throws \UserReportException */ public static function validateFormRules(array $element): void { // self::$FE_PARAMETER_RULES defines the validation rules for each parameter. // Each parameter must adhere to at least one of the specified rules to be valid. // The rules specify whether the value must be wrapped in {{ }}, {{! }}, or have no wrapper at all. + $initialElementState = $element; + $generalErrorState = Store::getVar(SYSTEM_THROW_GENERAL_ERROR, STORE_SYSTEM); Store::setVar(SYSTEM_THROW_GENERAL_ERROR, 'no', STORE_SYSTEM); - self::explodeParameter($element, FE_PARAMETER, flagValidateParameter: true); + self::explodeParameter($element, FE_PARAMETER); Store::setVar(SYSTEM_THROW_GENERAL_ERROR, $generalErrorState, STORE_SYSTEM); - // Loop through each parameter rule and validate against the element's value. - foreach (self::$FE_PARAMETER_RULES as $paramKey => $paramRuleArray) { - // If the parameter is not set or is empty, skip validation. + // Identify keys that exist in the processed element but are not part of the initial state or allowed rules + $missingKeys = array_diff(array_keys($element), array_keys($initialElementState), array_keys(self::$FE_PARAMETER_RULES)); + + // If there are missing keys then they are not defined in the $FE_PARAMETER_RULES + if (!empty($missingKeys)) { + throw new \CodeException("The following parameters are unknown: " . implode(', ', $missingKeys) . ". Please check for spelling mistakes or contact the developer."); + } + + foreach (self::$FE_PARAMETER_RULES as $paramKey => $rules) { + if (!isset($element[$paramKey])) { continue; } - if ($element[$paramKey] == '') { + + $value = $element[$paramKey]; + + if ($value === '') { continue; } - $value = trim($element[$paramKey]); + $value = trim($value); $escapedValue = OnString::trimQuote($value); $isValid = false; - // A rule is either: - // - '' (no wrapper allowed), - // - '{{' (value must start and end with {{ }}), - // - '{{!' (value must start with {{! and end with }}). - foreach ($paramRuleArray as $rule) { - // IF Rule is '' also regex match to check that the value is not wrapped by {{ }} - if ($rule === '' && !preg_match('/^\{\{.*}}$/', $escapedValue)) { - $isValid = true; - } elseif ($rule && preg_match('/^' . preg_quote($rule, '/') . '.*}}$/', $escapedValue)) { + foreach ($rules as $rule) { + // Rule: '' (No wrapper allowed) + // If the rule is '', ensure the value is not wrapped by {{ }} + // Example: 'value' is valid; '{{value}}' is invalid if NO_WRAPPER is the only rule in $rules + if ($rule === '' && (!preg_match('/^\{\{[^{}]*}}$/s', $escapedValue) || count($rules) > 1)) { $isValid = true; } + + // Rule: '{{' or '{{!' (Specific wrappers allowed) + // Check if the value starts with the rule and ends with }} + // Example for '{{': '{{value}}' is valid; '{{!value}}' is invalid + // Example for '{{!': '{{!value}}' is valid; '{{value}}' is invalid + elseif ($rule && preg_match('/^' . preg_quote($rule, '/') . '.*}}$/s', $escapedValue)) { + // Additional brace balance validation + $innerContent = substr($escapedValue, strlen($rule), -2); // Extract content inside the wrapper + if (OnString::validateBraceBalance($innerContent)) { + $isValid = true; + } + } } if (!$isValid) { // turn '' into 'no wrapper' to make the exception less confusing - $readableRules = array_map(fn($rule) => $rule === '' ? 'no wrapper' : $rule, $paramRuleArray); + $readableRules = array_map(fn($rule) => $rule === '' ? 'no wrapper' : $rule, $rules); throw new \UserFormException("{$paramKey} is not wrapped correctly. Allowed wrapper(s): " . implode(', ', $readableRules)); } - } } } \ No newline at end of file diff --git a/extension/Classes/Core/Helper/OnString.php b/extension/Classes/Core/Helper/OnString.php index 9d5feb5493f6921617287b37cc0b181d500e272e..cc4652df0ba1403f021a94dafa5d8e778edfd292 100644 --- a/extension/Classes/Core/Helper/OnString.php +++ b/extension/Classes/Core/Helper/OnString.php @@ -897,5 +897,29 @@ class OnString { } return $str; } + + public static function validateBraceBalance(string $content): bool { + $stack = []; + $len = strlen($content); + + for ($i = 0; $i < $len; $i++) { + if ($content[$i] === '{' && isset($content[$i + 1]) && $content[$i + 1] === '{') { + // Push an opening brace onto the stack + $stack[] = '{{'; + $i++; + } elseif ($content[$i] === '}' && isset($content[$i + 1]) && $content[$i + 1] === '}') { + // Pop a closing brace from the stack + if (empty($stack) || array_pop($stack) !== '{{') { + // Unmatched closing brace + return false; + } + $i++; + } + } + + // If the stack is empty, all braces are balanced + return empty($stack); + } + } diff --git a/extension/Classes/Core/Save.php b/extension/Classes/Core/Save.php index e4cc6225282482e70b16849feadb10ff5f478ed7..b6b286865894ea6152566a5094c32f6dac1ebf61 100644 --- a/extension/Classes/Core/Save.php +++ b/extension/Classes/Core/Save.php @@ -115,9 +115,9 @@ class Save { if ($formName === FORM_NAME_FORM_ELEMENT) { // Check formElement - - // disaable tmp 20388 - //HelperFormElement::validateFormRules($this->store->getStore(STORE_FORM)); + if ($this->store->getVar(SYSTEM_VALIDATE_FORM_ELEMENT, STORE_SYSTEM)) { + HelperFormElement::validateFormRules($this->store->getStore(STORE_FORM)); + } $encryptionState = $this->store->getVar(FE_ENCRYPTION, STORE_FORM, SANITIZE_ALLOW_ALL); $databaseFieldType = 'No real column'; diff --git a/extension/Tests/Unit/Core/Helper/HelperFormElementTest.php b/extension/Tests/Unit/Core/Helper/HelperFormElementTest.php index 080ce060ed862a630e63d76746dc3c496a75290a..344bf7ee1218d9cb8549f8a3f643a891175a0708 100644 --- a/extension/Tests/Unit/Core/Helper/HelperFormElementTest.php +++ b/extension/Tests/Unit/Core/Helper/HelperFormElementTest.php @@ -410,4 +410,145 @@ class HelperFormElementTest extends TestCase { // [FE_NAME => 'nameB', FE_LABEL => 'labelB', FE_VALUE => '11']]; // $this->assertEquals($formElements, $result, "Both arrays should be equal"); // } + + /** + * @throws \UserFormException + * @throws \CodeException + * @throws \UserReportException + */ + public function testValidateParameterPassingCases() { + + $element = [ + FE_ID => 1, + FE_PARAMETER => + FE_SQL_BEFORE . '={{TEST}}' . "\n" . // RULES ['{{'] + FE_ITEM_LIST . '=item:1' . "\n" . // RULES [''] + FE_FILL_STORE_VAR . '={{!TEST}}' // RULES ['{{!'] + ]; + HelperFormElement::validateFormRules($element); + $this->assertTrue(true); + + $element = [ + FE_ID => 1, + FE_PARAMETER => + FE_SQL1 . '={{! TEST {{VAR}} }} ' . "\n" . // RULES ['{{!', ''] + FE_TYPEAHEAD_SQL . '=TEST' // RULES ['{{', ''] + ]; + + HelperFormElement::validateFormRules($element); + $this->assertTrue(true); + + + $element = [ + FE_ID => 1, + FE_PARAMETER => + FE_SQL1 . "={{! Test \n {{VAR}} \n }}" . "\n" . // RULES ['{{!'] + FE_WRAP_NOTE . "=TEST {{VAR}} \n " // RULES [''] + ]; + + HelperFormElement::validateFormRules($element); + $this->assertTrue(true); + + $element = [ + FE_ID => 1, + FE_PARAMETER => + FE_SQL1 . '=' . "\n" . // RULES ['{{!'] + FE_WRAP_NOTE . "={{VAR}} {{VAR}}" // RULES [''] + ]; + + HelperFormElement::validateFormRules($element); + $this->assertTrue(true); + + $element = [ + FE_ID => 1, + FE_PARAMETER => + FE_SQL1 . "={{! \n Multiline Content \n }}", // Valid as per '{{!' + ]; + HelperFormElement::validateFormRules($element); + $this->assertTrue(true); + + $element = [ + FE_ID => 1, + FE_PARAMETER => + FE_SQL1 . '={{! Complex Content {{Nested}} Extra }}' . "\n" . // Valid as per '{{!' + FE_TYPEAHEAD_SQL . "={{Outer}}" . "\n" . // Valid as per '{{' + FE_WRAP_ROW . "=plainValue", // Valid as per '' + ]; + HelperFormElement::validateFormRules($element); + $this->assertTrue(true); + + } + + /** + * @throws \CodeException + * @throws \UserReportException + */ + public function testValidateFormRulesInvalidCases() { + // Case: Partial Wrapping + try { + $element = [ + FE_ID => 1, + FE_PARAMETER => + FE_SQL1 . '={{! TEST {{VAR}} }} {{EXTRA}} ' . "\n" . // Invalid: content outside `{{! ... }}` + FE_WRAP_NOTE . "=plainValue" // Valid as per '' + ]; + HelperFormElement::validateFormRules($element); + $this->fail('Expected UserFormException was not thrown for partial wrapping.'); + } catch (\UserFormException $e) { + $this->assertStringContainsString('is not wrapped correctly', $e->getMessage()); + } + + // Case: Unwrapped Value for `{{` + try { + $element = [ + FE_ID => 1, + FE_PARAMETER => + FE_SQL1 . '=plainValue', // Invalid: should be wrapped as `{{ ... }}` + ]; + HelperFormElement::validateFormRules($element); + $this->fail('Expected UserFormException was not thrown for unwrapped value.'); + } catch (\UserFormException $e) { + $this->assertStringContainsString('is not wrapped correctly', $e->getMessage()); + } + + // Case: Missing Closing Braces + try { + $element = [ + FE_ID => 1, + FE_PARAMETER => + FE_SQL1 . '={{! TEST {{VAR}}', // Invalid: missing closing `}}` + ]; + HelperFormElement::validateFormRules($element); + $this->fail('Expected UserFormException was not thrown for missing closing braces.'); + } catch (\UserFormException $e) { + $this->assertStringContainsString('Missing close delimiter', $e->getMessage()); + } + + // Case: Extra Content After Wrapper + try { + $element = [ + FE_ID => 1, + FE_PARAMETER => + FE_SQL1 . '={{! TEST }} ExtraContent', // Invalid: extra content outside wrapper + ]; + HelperFormElement::validateFormRules($element); + $this->fail('Expected UserFormException was not thrown for extra content after wrapper.'); + } catch (\UserFormException $e) { + $this->assertStringContainsString('is not wrapped correctly', $e->getMessage()); + } + + // Case: Completely Missing Wrapping + try { + $element = [ + FE_ID => 1, + FE_PARAMETER => + FE_SQL1 . '=TEST', // Invalid: does not meet the wrapping requirement + ]; + HelperFormElement::validateFormRules($element); + $this->fail('Expected UserFormException was not thrown for completely missing wrapping.'); + } catch (\UserFormException $e) { + $this->assertStringContainsString('is not wrapped correctly', $e->getMessage()); + } + + } } diff --git a/extension/ext_conf_template.txt b/extension/ext_conf_template.txt index ef02efb9de6c1fd321fe764505a1223a6df769c8..f4fa9d1bc78b75793f406bc67578157e2b3c4c05 100644 --- a/extension/ext_conf_template.txt +++ b/extension/ext_conf_template.txt @@ -1,4 +1,4 @@ -# cat=config/config; type=options[yes,no]; label=Flag Production: Retrieve via '{{flagProduction:Y}}''. Default is 'yes'. Used to differentiate between development & production systems. +# cat=config/config; type=options[yes,no]; label=Flag Production:Default is 'yes'. Retrieve via '{{flagProduction:Y}}''. Used to differentiate between development & production systems. flagProduction = yes # cat=config/config; type=options[single,both]; label=QFQ shows Form and Report at the same time or only one: a) 'single' (default) - only form or report (depending of if a form is given via SIP), b) 'both' at the same time. @@ -7,13 +7,13 @@ render = single # cat=config/config; type=string; label=Base URL of the current Typo3 installation:Use '{{baseUrl:Y}}' to reference own URL. Important for API calls (load, save, dirty, delete), downloads and PDF conversion. Example: https://your.base.url/including/sub/dir. Separate multiple URLs with comma. Final one will detected dynamically. Skip the scheme if the website needs to be accessible with http and https. Advanced example: first.base.url/sub1,second.example.url baseUrl = -# cat=config/date; type=string; label=Date format:Default is 'dd.mm.yyyy'. Possible options: 'yyyy-mm-dd', 'dd.mm.yyyy' +# cat=config/config; type=string; label=Date format:Default is 'dd.mm.yyyy'. Possible options: 'yyyy-mm-dd', 'dd.mm.yyyy' dateFormat = dd.mm.yyyy # cat=config/config; type=boolean; label=Show edit inline reports: In the frontend, for every QFQ Report record an edit symbol is shown. Click on it will open a window to edit the QFQ report. editInlineReports = 1 -# cat=config/config; type=boolean; label=Dark mode for edit inline report editor: Default is off=light mode. +# cat=config/config; type=boolean; label=Dark mode for edit inline report editor:Default is off=light mode. editInlineReportDarkTheme = 0 # cat=config/config; type=string; label=Report as File Auto Export:Default is 'no'. If set to 'yes': When a QFQ tt-content record is rendered which does not contain the "file=" keyword, then its body is exported to a file in the qfq-project directory and the tt-content body is replaced by "file=<path_to_file>". @@ -29,37 +29,6 @@ websocketUrl = renderer = Bootstrap3Renderer -# cat=authentication/service/11; type=boolean; label=Enable authentication: If selected, then QFQ can authenticate a Typo3 user -authEnable = 0 - -# cat=authentication/service/12; type=int+; label=Service priority: This defines the order of the QFQ authentication service in relation to other authentication services. Higher number wins. -authPriority = 82 - -# cat=authentication/service/13; type=int+; label=Service quality: This value is used by TYPO3 if two authentication services have the same priority. Higher number wins. -authQuality = 80 - -# cat=authentication/service/14; type=string; label=User storage: The UID of the page where local users are located. The first UID is used to store new users. -authUserStorage = - -# cat=authentication/service/15; type=string; label=User groups: The comma-separated list of UIDs of user groups to be assigned to new users. -authUserGroups = - -# cat=authentication/enable/21; type=boolean; label=Create accounts: If selected, then a local account is created if non exists when a user is authenticated by QFQ -authCreateAccount = 0 - -# cat=authentication/enable/22; type=boolean; label=Unlock accounts: If selected, then a disabled local account is unlocked when a user is authenticated by QFQ -authUnlockAccount = 0 - -# cat=authentication/enable/23; type=boolean; label=Activate accounts: If selected, then an inactive or expired account is activated when a user is authenticated by QFQ -authActivateAccount = 0 - -# cat=authentication/enable/24; type=int+; label=Account extension time: The number of days after which an account activated during authentication will expire -authExtendByDays = 7 - -# cat=authentication/enable/25; type=boolean; label=Update accounts: If selected, then accounts are updated when a user is authenticated by QFQ with provided user data -authUpdateAccount = 0 - - # cat=graphics/config; type=string; label=Command 'inkscape':Default is 'inkscape'. Will be used to convert SVG to images (png). An empty string disables `inkscape`. If it is not available, `convert` will be used instead. cmdInkscape = inkscape @@ -100,40 +69,40 @@ cmdPdf2ps = pdf2ps cmdPs2pdf = ps2pdf -# cat=debug/debug; type=options[auto,yes,no]; label=Throw exception General Error: Default is 'auto'. If a) 'yes' or b) 'auto' and 'flagProduction!=yes', throw an exception in case of a 'General Error'. +# cat=debug/debug; type=options[auto,yes,no]; label=Throw exception General Error:Default is 'auto'. If a) 'yes' or b) 'auto' and 'flagProduction!=yes', throw an exception in case of a 'General Error'. throwExceptionGeneralError = auto -# cat=debug/form; type=options[all,none]; label=Form submit log mode:Default is 'all'. Form submit requests will be logged in the table FormSubmitLog. 'all' - every form save will be logged. 'none' - no logging. This setting can also be changed per form. +# cat=debug/debug; type=options[all,none]; label=Form submit log mode:Default is 'all'. Form submit requests will be logged in the table FormSubmitLog. 'all' - every form save will be logged. 'none' - no logging. This setting can also be changed per form. formSubmitLogMode = all -# cat=debug/mail; type=string; label=Redirect all mail to ...:Default is empty. If set, redirect all QFQ generated mails (Form, Report) to the specified email address. +# cat=debug/debug; type=string; label=Redirect all mail to ...:Default is empty. If set, redirect all QFQ generated mails (Form, Report) to the specified email address. redirectAllMailTo = -# cat=debug/sql; type=options[modify,all,error,none]; label=SQL log mode:Default is 'modify'. A logfile of QFQ fired SQL statements will be written. 'all' - every statement will be logged (this might a lot). 'modify' - log only statements who change data. 'error' - log only DB errors. 'none' - log never. +# cat=debug/debug; type=options[modify,all,error,none]; label=SQL log mode:Default is 'modify'. A logfile of QFQ fired SQL statements will be written. 'all' - every statement will be logged (this might a lot). 'modify' - log only statements who change data. 'error' - log only DB errors. 'none' - log never. sqlLogMode = modify -# cat=debug/sql; type=options[modify,all,error,none]; label=SQL log mode for AutoCron:Default is 'error'. Modes see 'sqlLogMode'. +# cat=debug/debug; type=options[modify,all,error,none]; label=SQL log mode for AutoCron:Default is 'error'. Modes see 'sqlLogMode'. sqlLogModeAutoCron = error -# cat=debug/sql; type=string; label=SQL log file:By default fileadmin/protected/qfqProject/log/sql.log. A logfile of fired SQL statements. PathFile is absolute or relative to '<site path>'. +# cat=debug/debug; type=string; label=SQL log file:Default 'fileadmin/protected/qfqProject/log/sql.log'. A logfile of fired SQL statements. PathFile is absolute or relative to '<site path>'. sqlLog = -# cat=debug/qfq; type=string; label=QFQ log file:By default fileadmin/protected/qfqProject/log/qfq.log directory. A logfile of fired SQL statements. PathFile is absolute or relative to '<site path>'. +# cat=debug/debug; type=string; label=QFQ log file:Default 'fileadmin/protected/qfqProject/log/qfq.log'. A logfile of QFQ errors. PathFile is absolute or relative to '<site path>'. qfqLog = -# cat=debug/mail; type=string; label=Mail log file:By default fileadmin/protected/qfqProject/log/mail.log. A logfile of sent mail. PathFile is absolute or relative to '<site path>'. +# cat=debug/debug; type=string; label=Mail log file:Default 'fileadmin/protected/qfqProject/log/mail.log'. A logfile of sent mail. PathFile is absolute or relative to '<site path>'. mailLog = -# cat=debug/merge; type=string; label=Merge log file:By default fileadmin/protected/qfqProject/log/merge.log. A logfile of all data merge actions. PathFile is absolute or relative to '<site path>'. +# cat=debug/debug; type=string; label=Merge log file:Default 'fileadmin/protected/qfqProject/log/merge.log'. A logfile of all data merge actions. PathFile is absolute or relative to '<site path>'. mergeLog = -# cat=debug/info; type=string; label=Show debug info:Default is 'auto'. Possible values: [yes|no|auto][,download]. For 'auto': If a BE User is logged in, a debug information will be shown on the FE. +# cat=debug/debug; type=string; label=Show debug info:Default is 'auto'. Possible values: [yes|no|auto][,download]. For 'auto': If a BE User is logged in, a debug information will be shown on the FE. showDebugInfo = auto -# cat=debug/reportMinPhpVersion; type=options[auto,yes,no]; label=Report too low PHP Version:Default is 'auto'. 'auto': If a BE User is logged in, qfq shows message and terminate. +# cat=debug/debug; type=options[auto,yes,no]; label=Report too low PHP Version:Default is 'auto'. 'auto': If a BE User is logged in, qfq shows message and terminate. reportMinPhpVersion = auto -# cat=database/db1; type=string; label=Init database:Default is 'set names utf8'. Optional. Might set specific settings. +# cat=database/db; type=string; label=Init database:Default is 'set names utf8'. Optional. Might set specific settings. init = SET names utf8; SET sql_mode = "NO_ENGINE_SUBSTITUTION"; # cat=database/db; type=options[auto,always,once,never]; label=Update QFQ database structures,functions & system forms:Default is 'auto'. After installing a new QFQ version it might be necessary to apply DB updates. 'auto' - apply DB updates only if there is a newer version. 'always' - apply DB updates every time QFQ is called - *not* recommended - slow! 'once' - on next QFQ start, do updates and switch back to 'auto'. 'never' - never apply DB updates. @@ -174,7 +143,7 @@ securityFailedAuthDelay = 3 # cat=security/security; type=string; label=Default encryption method:Options: 'AES-128' (default) or 'AES-256'. If value is not valid then error will be shown on page. encryptionMethod = -# cat=security/security; type=boolean; label=Check for protected folder access from outside +# cat=security/security; type=boolean; label=Check for protected folder access from outside: Default is 'on'. protectedFolderCheck = 1 # cat=security/security; type=string; label=Auth token for endpoint QFQ Version check:Default is empty and no qfq information can be fetched. @@ -184,19 +153,16 @@ qfqVersionApiToken = # cat=form-config/config; type=string; label=Dirty record lock timeout (seconds):Default is '900'. Time in seconds to lock a record, starting from the first modification. If lock expires, it is acquired again on the next modification. recordLockTimeoutSeconds = 900 -# cat=form-config/config; type=boolean; label=Enter as submit:Default is on. Pressing 'enter' on an input, means 'save form and close' (exception: 'textarea' and 'editor' elements). +# cat=form-config/config; type=boolean; label=Enter as submit:Default is 'on'. Pressing 'enter' on an input, means 'save form and close' (exception: 'textarea' and 'editor' elements). enterAsSubmit = 1 - # cat=form-config/config; type=string; label=Form page alias:Default is 'form'. T3 Page slug to edit a form. editFormPage = form -# cat=form-config/; type=string; label=Datetimepicker type:Default is 'qfq'. Type of date-time-picker in form. Options: 'no', 'browser', 'qfq'. +# cat=form-config/config; type=string; label=Datetimepicker type:Default is 'qfq'. Type of date-time-picker in form. Options: 'no', 'browser', 'qfq'. dateTimePickerType = qfq - - -# cat=form-config/config; type=string; label=Form data pattern error message: default is 'Pattern mismatch' for all custom pattern. Customizable message used in validator.js. 'pattern' violation. +# cat=form-config/config; type=string; label=Form data pattern error message:Default is 'Pattern mismatch' for all custom pattern. Customizable message used in validator.js. 'pattern' violation. formDataPatternError = # cat=form-config/config; type=string; label=Form data required error message:Default is 'Required'. Customizable error message used in validator.js. 'required' violation. @@ -208,29 +174,30 @@ formDataMatchError = # cat=form-config/config; type=string; label=Form data error message:Default is 'Error'. Customizable error message used in validator.js. generic violation. formDataError = -# cat=form-config/config; type=boolean; label=Show record-id in form title:Default is off (0). If on (1), append the current record id on the title. New records get '(new)'. +# cat=form-config/config; type=boolean; label=Show record-id in form title:Default is 'off' (0). If on (1), append the current record id on the title. New records get '(new)'. showIdInFormTitle = 0 -# cat=form-config/config; type=boolean; label=On form load, bring last used pill to front +# cat=form-config/config; type=boolean; label=On form load, bring last used pill to front:Default is 'on'. rememberLastPill = 1 # cat=form-config/config; type=string; label=Do not log column:Default is 'password'. Comma separated more than one column possible. doNotLogColumn = password -# cat=form-config/config; type=string; label=History in forms: Options - "0" (off / Default), "1" (on), "SELECT ...". Example for sql query (empty result set means 0=off) - "SELECT IF(ISNULL(r.id), 0, 1) FROM Person AS p LEFT JOIN Role AS r ON r.pId = p.id AND r.name = 'admin' WHERE p.id='{{pIdUser:Y}}' LIMIT 1" +# cat=form-config/config; type=string; label=History in forms: Options - "0" (off / default), "1" (on), "SELECT ...". Example for sql query (empty result set means 0=off) - "SELECT IF(ISNULL(r.id), 0, 1) FROM Person AS p LEFT JOIN Role AS r ON r.pId = p.id AND r.name = 'admin' WHERE p.id='{{pIdUser:Y}}' LIMIT 1" showHistory = 0 -# cat=form-config/config; type=boolean; label=Recent Log: Each 'form open' by a user will be logged in table Recent, incl. all SIP parameter. Default: on -recentLog = 1 - +# cat=form-config/config; type=boolean; label=Validate F & FE.parameter:Default is 'on'. Checks if parameters known by qfq and are wrapped correctly where necessary. EXAMPLE => FE.parameter.sqlAfter have to be wrapped by {{ }}. Each parameter uses its own configuration. +validateFormElementParameter = 1 +# cat=form-config/config; type=boolean; label=Recent Log:Default is 'on'. Each 'form open' by a user will be logged in table Recent, incl. all SIP parameter. +recentLog = 1 # cat=form-layout/layout; type=string; label=CSS class QFQ container:Default is empty. Empty, if the page content is already wrapped in a Bootstrap container. Else 'container'. cssClassQfqContainer = -# cat=form-layout/layout; type=string; label=CSS class QFQ form:Default is 'qfq-notify''. If given wrap around QFQ-Form. E.g. 'qfq-color-base'. +# cat=form-layout/layout; type=string; label=CSS class QFQ form:Default is 'qfq-notify'. If given wrap around QFQ-Form. E.g. 'qfq-color-base'. cssClassQfqForm = # cat=form-layout/layout; type=string; label=CSS class of pills on the HTML form:Default is 'qfq-color-grey-1'. Wrap around title bar for pills: CSS Class, typically a background color. @@ -239,7 +206,6 @@ cssClassQfqFormPill =qfq-color-grey-1 # cat=form-layout/layout; type=string; label=CSS class of the body of the HTML form:Default is 'qfq-color-grey-2'. Wrap around FormElements: CSS Class, typically a background color. cssClassQfqFormBody = qfq-color-grey-2 - # cat=form-layout/layout; type=string; label=Bootstrap CSS column class(es) to wrap the 'whole form':Default is 'col-md-12 col-lg-10'. formBsColumns = col-md-12 col-lg-10 @@ -281,6 +247,7 @@ formLanguageDId = # cat=form-language/config; type=string; label=Language D label:Default is empty. Label shown in *Form editor*, on the 'basic' tab. formLanguageDLabel = + # cat=form-button/layout; type=string; label=Button Top Wrap 'class':Default '<div class="row"><div class="col-md-12">' - Wraps the entire row above the form. It is used to group any elements you want to place on the top part of the form. btnTopWrap = @@ -347,36 +314,34 @@ saveButtonGlyphIcon = # cat=form-button/layout; type=string; label=Close button 'text':Default empty - Text for the close button (top of the form). closeButtonText = -# cat=form-button/layout; type=string; label=Close button 'tooltip':Default 'Close' +# cat=form-button/layout; type=string; label=Close button 'tooltip':Default 'Close'. closeButtonTooltip = Close -# cat=form-button/layout; type=string; label=Close button 'CSS Class':Default 'btn btn-default navbar-btn' +# cat=form-button/layout; type=string; label=Close button 'CSS Class':Default 'btn btn-default navbar-btn'. closeButtonClass = btn btn-default navbar-btn # cat=form-button/layout; type=string; label=close button 'glyph icon':Default 'glyphicon-remove'. Glyph icon shown on the close button. closeButtonGlyphIcon = - # cat=form-button/layout; type=string; label=Delete button 'text':Default empty - Text for the delete button (top of the form). deleteButtonText = -# cat=form-button/layout; type=string; label=Delete button 'tooltip':Default 'Delete' +# cat=form-button/layout; type=string; label=Delete button 'tooltip':Default 'Delete'. deleteButtonTooltip = Delete -# cat=form-button/layout; type=string; label=Delete button 'CSS Class':Default 'btn btn-default navbar-btn' +# cat=form-button/layout; type=string; label=Delete button 'CSS Class':Default 'btn btn-default navbar-btn'. deleteButtonClass = btn btn-default navbar-btn # cat=form-button/layout; type=string; label=Delete button 'glyph icon':Default 'glyphicon-trash'. Glyph icon shown on the delete button. deleteButtonGlyphIcon = - # cat=form-button/layout; type=string; label=New button 'text':Default empty - Text for the new button (top of the form). newButtonText = -# cat=form-button/layout; type=string; label=New button 'tooltip':Default 'New' +# cat=form-button/layout; type=string; label=New button 'tooltip':Default 'New'. newButtonTooltip = New -# cat=form-button/layout; type=string; label=New button 'CSS Class':Default 'btn btn-default navbar-btn' +# cat=form-button/layout; type=string; label=New button 'CSS Class':Default 'btn btn-default navbar-btn'. newButtonClass = btn btn-default navbar-btn # cat=form-button/layout; type=string; label=New button 'glyph icon':Default 'glyphicon-plus'. Glyph icon shown on the new button. @@ -392,7 +357,7 @@ emptySubrecord = show # cat=form-Element/formelement; type=options[dnd,button]; label=Upload type:Default is 'dnd'. 'dnd' - file chooser or drag'n'drop of files. 'button' - the regular file chooser button. uploadType = dnd -# cat=form-Element/formelement; type=string; label=Form data pattern error message: default is 'Pattern mismatch' for all custom pattern. Customizable message used in validator.js. 'pattern' violation. +# cat=form-Element/formelement; type=string; label=Form data pattern error message:Default is 'Pattern mismatch' for all custom pattern. Customizable message used in validator.js. 'pattern' violation. formDataPatternError = # cat=form-Element/formelement; type=string; label=Form data required error message:Default is 'Required'. Customizable error message used in validator.js. 'required' violation. @@ -427,14 +392,6 @@ extraButtonInfoClass = - - - - - - - - # cat=custom/layout; type=string; label=Custom variable 01:Default empty. Can be used the centrally define variables. E.g. "CONTACT_EMAIL = 'john@doe.com'". Retrieve them via '{{CONTACT_EMAIL:Y}}'. custom1 = @@ -557,7 +514,7 @@ fillStoreSystemBySql3 = fillStoreSystemBySqlErrorMsg3 = -# cat=file/missingFile; type=options[error,dummy]; label=Action on missing PDF in PDF concat:Default is 'error' - show an error if a file is missing. :'dummy' an empty PDF dummy file is inserted (typo3conf/ext/qfq/Resources/Public/pdf/dummy.pdf) +# cat=file/file; type=options[error,dummy]; label=Action on missing PDF in PDF concat:Default is 'error' - show an error if a file is missing. :'dummy' an empty PDF dummy file is inserted (typo3conf/ext/qfq/Resources/Public/pdf/dummy.pdf) missingFile = error # cat=file/file; type=string; label=Cache directory 'secure':Default is 'fileadmin/protected/cache'. Directory to optionally save on-the-fly rendered PDF, Excel, ZIP files. Important: secure the directory against direct access. @@ -607,8 +564,40 @@ sqlDirectdl3phperror = # cat=tools/config; type=string; label=Force fixed sender email address:Default is empty. Set this ONLY if your SMTP needs one fix sender address. QFQ will then set Reply-To to the initial sender. Realname is optional. E.g.: 'realname <mail@example.com>' forceSmtpSender = -# cat=tools/email; type=string; label=Options for SendEMail:Default is empty. General options. Check: http://caspian.dotconf.net/menu/Software/SendEmail. E.g.: 'sendEMail=-o tls=yes' +# cat=tools/config; type=string; label=Options for SendEMail:Default is empty. General options. Check: http://caspian.dotconf.net/menu/Software/SendEmail. E.g.: 'sendEMail=-o tls=yes' sendEMailOptions = -# cat=tools/tools; type=string; label=Command 'wget':Default is 'wget >/dev/null 2>&1'. Will be used for trying to get content from protected server. +# cat=tools/config; type=string; label=Command 'wget':Default is 'wget >/dev/null 2>&1'. Will be used for trying to get content from protected server. cmdWget = wget >/dev/null 2>&1 + + + +# cat=authentication/service; type=boolean; label=Enable authentication: If selected, then QFQ can authenticate a Typo3 user +authEnable = 0 + +# cat=authentication/service; type=int+; label=Service priority: This defines the order of the QFQ authentication service in relation to other authentication services. Higher number wins. +authPriority = 82 + +# cat=authentication/service; type=int+; label=Service quality: This value is used by TYPO3 if two authentication services have the same priority. Higher number wins. +authQuality = 80 + +# cat=authentication/service; type=string; label=User storage: The UID of the page where local users are located. The first UID is used to store new users. +authUserStorage = + +# cat=authentication/service; type=string; label=User groups: The comma-separated list of UIDs of user groups to be assigned to new users. +authUserGroups = + +# cat=authentication/service; type=boolean; label=Create accounts: If selected, then a local account is created if non exists when a user is authenticated by QFQ +authCreateAccount = 0 + +# cat=authentication/service; type=boolean; label=Unlock accounts: If selected, then a disabled local account is unlocked when a user is authenticated by QFQ +authUnlockAccount = 0 + +# cat=authentication/service; type=boolean; label=Activate accounts: If selected, then an inactive or expired account is activated when a user is authenticated by QFQ +authActivateAccount = 0 + +# cat=authentication/service; type=int+; label=Account extension time: The number of days after which an account activated during authentication will expire +authExtendByDays = 7 + +# cat=authentication/service; type=boolean; label=Update accounts: If selected, then accounts are updated when a user is authenticated by QFQ with provided user data +authUpdateAccount = 0