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

Merge branch 'develop' into 'master'

Merge dev to master

See merge request !375
parents 0f46b41f 7a551d98
Pipeline #6595 passed with stages
in 3 minutes and 18 seconds
......@@ -11,6 +11,7 @@
.project
.webprj
.vscode
.run
nbprojec
nohup.out
......
......@@ -1575,7 +1575,7 @@ Type: editor
* The default setting in *FormElement.parameter* is::
editor-plugins=code link lists searchreplace table textcolor textpattern visualchars
editor-toolbar=code searchreplace undo redo | styleselect link table | fontselect fontsizeselect | bullist numlist outdent indent | forecolor backcolor bold italic editor-menubar=false
editor-toolbar=code searchreplace undo redo | styleselect link table | bullist numlist outdent indent | forecolor backcolor bold italic editor-menubar=false
editor-statusbar=false
* To deactivate the surrouding `<p>` tag, configure in *FormElement.parameter*::
......@@ -2034,8 +2034,19 @@ FormElement.parameter
by an attacker. Therefore it's recommended to use a `fileDestination`-directory, which is secured against script
execution (even if the file has been uploaded, the webserver won't execute it) - see :ref:`SecureDirectFileAccess`.
* *sqlBefore*, *sqlAfter*: available in :ref:`Upload simple mode` and :ref:`Upload advanced mode`.
* *slaveId*, *sqlInsert*, *sqlUpdate*, *sqlDelete*, *sqlUpdate*: available only in :ref:`Upload advanced mode`.
* Keywords available in:
+-----------+----------------------------+-----------------------------+
| Available | :ref:`Upload simple mode` | :ref:`Upload advanced mode` |
+===========+============================+=============================+
| slaveId | - | yes |
| sqlBefore | yes | yes |
| sqlInsert | - | yes |
| sqlUpdate | - | yes |
| sqlDelete | - | yes |
| sqlAfter | yes | yes |
+-----------+----------------------------+-----------------------------+
* `fileSize` / `mimeType`
......@@ -2109,7 +2120,7 @@ FormElement.parameter
* *importRegion* = [tab],[startColumn],[startRow],[endColumn],[endRow]|... - All parts are optional (default:
entire 1st sheet). Tab can either be given as an index (1-based) or a name. start/endColumn can be given either
numerically (1, 2, ...) or by column name (A, B, ...). Note that you can specify several regions to import.
* *importMode* = `append` (default) | `replace` - The data is either appended or replace in the specified table.
* *importMode* = `append` (default) | `replace` - The data is either appended or replaced in the specified table.
* *importType* = `auto` (default) | `xls` | `xlsx` | `ods` | `csv` - Define what kind of data should be expected by the
Spreadsheet Reader.
* *importNamedSheetsOnly* = <comma separated list of sheet names>. Use this option if specific sheets cause problems
......@@ -2606,7 +2617,7 @@ record (defined by `multiSql`).
| multiMgsNoRecord | Default: No data | Message shown if `multiSql` selects no records |
+------------------+----------------------------------+------------------------------------------------+
.. note::
.. important::
Multi Form do not use 'record-locking' at all.
......@@ -2615,8 +2626,8 @@ The Form is shown as a HTML table.
* `multiSql`: Selects the records where the defined FormElements will work on each.
* A uniq column 'id' or '_id' (not shown) is mandatory and has to reflect an existing record id in table `primary table`.
* Additional columns, defined in `multiSql`, will be shown on the form in the same line, before the FormElements.
* A uniq column `id` or `_id` (not shown) is mandatory and has to reference an existing record in table `primary table`.
* Additional columns, defined in `multiSql`, will be shown on the form on the same line, before the FormElements.
* Per row, the STORE_PARENT is filled with the current record of the primary table.
The following definition of *Simple* and *Advanced* is just for explanation, there is no *flag* or *mode* which
......@@ -2635,7 +2646,7 @@ FormElement:
* The FormElement.name represents a column of the defined primary table.
* The existing values of such FormElements are automatically loaded.
* No further definition (sqlInsert, sqlUpdate, ...) is required.
* No further definition (`sqlInsert`, `sqlUpdate`, ...) is required.
Advanced
^^^^^^^^
......
......@@ -226,6 +226,11 @@ a more detailed message.
The error might occur if there are problematic characters in config.qfq.php, like single or double ticks inside strings,
wich are not enclosed (correctly).
Further T3 Logfile
^^^^^^^^^^^^^^^^^^
* `/var/www/html/typo3temp/var/log/...`
.. _`sendEmailProblem`:
sendEmail: Error => TLS setup failed
......
......@@ -41,7 +41,8 @@ Installation
The following features are only tested / supported on linux hosts:
* General: QFQ is coded to run on Linux hosts, preferable on Debian derivates like Ubuntu.
* HTML to PDF conversion - command `wkhtmltopdf`.
* PHP Module: curl
* HTML to PDF conversion - command `wkhtmltopdf` and `qfqpdf`.
* Concatenation of PDF files - command `pdfunite`.
* Convert of images to PDF files - command `img2pdf`.
* PDF decrypt (used for merge with pdfunite) - command `qpdf`.
......@@ -74,8 +75,23 @@ Preparation for Ubuntu::
.. _wkhtml:
wkhtmltopdf
^^^^^^^^^^^
HTML to PDF: qfqpdf
^^^^^^^^^^^^^^^^^^^
The below named `wkhtml` becomes more and more outdated (no further development). As a replacement, QFQ started to use
puppeteer (https://developers.google.com/web/tools/puppeteer/). The tool can't be used directly, a wrapper is neccessary
which is available under https://git.math.uzh.ch/bbaer/qfqpdf. The wrapper uses and installs always the latest version of
puppeteer. On first start and during updates, it might take longer to render a pdf.
Installation::
curl -L -o qfqpdf https://www.math.uzh.ch/repo/qfqpdf/current/qfqpdf-linux
chmod a+x qfqpdf
./qfqpdf --version
HTML to PDF: wkhtmltopdf
^^^^^^^^^^^^^^^^^^^^^^^^
`wkhtmltopdf <http://wkhtmltopdf.org/>`_ will be used by QFQ to offer 'website print' and 'HTML to PDF' conversion.
The program is not included in QFQ and has to be manually installed.
......@@ -142,11 +158,6 @@ Checklist wkhtml problems
* Check the `--cookie-jar '/tmp/qfq.cookie....'` file for the cookie.
* Call wkhtml manually on the webserver, with the same options as given in the :ref:`QFQ_LOG`.
HTML to PDF conversion
""""""""""""""""""""""
`wkhtmltopdf` converts a website (local or remote) to a (multi)-page PDF file. It's mainly used in :ref:`download`.
Print
"""""
......@@ -498,7 +509,8 @@ Extension Manager: QFQ Configuration
+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
| securityVarsHoneypot | email,username,password | If empty: no check. All named variables will rendered as INPUT elements. |
+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
| securityAttackDelay | 5 | If an attack is detected, sleep 'x' seconds and exit PHP process. |
| securityAttackDelay | 5 | If an attack is detected, sleep 'x' seconds and exit PHP process. '-1' |
| | | Reports the attack and returns normally - use this with care. |
+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
| securityShowMessage | true | If an attack is detected, show a message. |
+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
......
......@@ -155,7 +155,7 @@ GET Variables provided via URL are available via STORE_CLIENT as usual.
| Attribute | Description |
+===================+==================================================================================+
| restSqlData | Mandatory. SQL query selects content shown in data mode. |
| | | ``restSqlData={{!SELECT id, name, gender FROM Person WHERE id='{{r:T0}}'' }}`` |
| | | ``restSqlData={{!SELECT id, name, gender FROM Person WHERE id='{{r:T0}}' }} `` |
+-------------------+----------------------------------------------------------------------------------+
| restSqlList | Mandatory. SQL query selects content shown in data mode. |
| | | ``restSqlData={{!SELECT id, name FROM Person }}`` |
......
......@@ -707,7 +707,7 @@ Column: _link
+---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
|x | |Mail |m:<email> |m:info@example.com |Default link class: email |
+---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
|x | |Page |p:<pageId> |p:impressum |Prepend '?' or '?id=', no hostname qualifier (automatically set by browser) |
|x | |Page |p:<pageId> |p:impressum |Prepend '?' or '?id=', no hostname qualifier (automatically set by browser). If omitted, default is current page id. |
+---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
|x | |Download |d:[<exportFilename>] |d:complete.pdf |Link points to `.../typo3conf/ext/qfq/Api/download.php`. Additional parameter SIP encoded. 'Download' needs SIP. See :ref:`download`. |
+---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
......@@ -722,7 +722,7 @@ Column: _link
+---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
| | |Render |r:<mode> |r:3 |See: :ref:`render-mode`, Default: 0 |
+---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
| | |Button | b[:0|1|<btn class>] | b:0, b:1, b:success |'b', 'b:1': a bootstrap button is created. 'b:0' disable the button. <btn class>: default, primary, success, info, warning,danger |
| | |Button | b[:0|1|<btn class>] | b:0, b:1, b:success |'b', 'b:1': with Bootstrap class 'btn btn-...'. 'b:0' no Bootstrap class. <btn class>: default, primary, success, info, warning,danger |
+---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
| |x |Picture |P:<filename> |P:bullet-red.gif |Picture '<img src="bullet-red.gif"alt="....">'. |
+---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
......@@ -768,7 +768,8 @@ Column: _link
+---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
| | |SIP |s[:0|1] |s, s:0, s:1 |If 's' or 's:1' a SIP entry is generated with all non Typo 3 Parameters. The URL contains only parameter 's' and Typo 3 parameter |
+---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
| | |Mode |M:file|pdf|zip |M:file, M:pdf, M:zip |Mode. Used to specify type of download. One or more element sources needs to be configured. See :ref:`download`. |
| | |Mode |M:file|pdf|qfqpdf|zip |M:file, M:pdf, M:qfqpdf, |Mode. Used to specify type of download. One or more element sources needs to be configured. See :ref:`download`. |
| | | | |M:zip | |
+---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
| | |File |F:<filename> |F:fileadmin/file.pdf |Element source for download mode file|pdf|zip. See :ref:`download`. |
+---+---+--------------+-----------------------------------+---------------------------+----------------------------------------------------------------------------------------------------------------------------------------+
......@@ -1761,8 +1762,9 @@ REST Client
POST and GET data to external REST interfaces or other API services.
Access to external services via HTTP / HTTPS is triggered via special column name *restClient*. The received data might
be processed in subsequent calls.
Access to external services via HTTP / HTTPS is triggered via special column name *restClient*.
QFQ uses the php stream interface for the API calls. Because of that, allow_url_fopen needs to be set to 1 on the installation.
The received data can be processed in subsequent calls.
Example::
......@@ -1782,6 +1784,9 @@ Example::
+-------------------+----------------------------------------------------+--------------------------------------------------------+
| content | content:{"name":"John";"surname":"Doe"} | Depending on the REST server JSON might be expected |
+-------------------+----------------------------------------------------+--------------------------------------------------------+
| contentFile | contentFile:fileadmin/_temp_/data.txt | Replaces content, if given. Recommended for large data |
| | | sections, such as binary data for files. |
+-------------------+----------------------------------------------------+--------------------------------------------------------+
| header | *see below* | |
+-------------------+----------------------------------------------------+--------------------------------------------------------+
| timeout | timeout:5 | Default: 5 seconds. |
......@@ -1797,13 +1802,19 @@ Example::
* *content-type: text/plain* - if *content* does not start with a ``{``.
* *connection: close* - Necessary for HTTP 1.1.
* Basic Authorization Example
Warning: Only use base64 for SSL encrypted connections::
10.sql = SELECT CONCAT('n:https://sample.com/id/1234|header:Authorization: Basic ', TO_BASE64('{{username}}:{{password}}') )
**Result received**
* After a *REST client* call is fired, QFQ will wait up to *timeout* seconds for the answer.
* By default, the whole received answer will be shown. To suppress the output: ``... AS '_restClient|_hide'``
* The variable ``{{http-status:C}}`` shows the `HTTP status code<https://en.wikipedia.org/wiki/List_of_HTTP_status_codes>`_.
A value starting with '2..' shows success.
* In case of an error, ``{{error-message:C:allbut}}`` shows some details.
* In case of an error, the HTTP status code is set to 0 and ``{{error-message:C:allbut}}`` shows some details.
* In case the returned answer is a valid JSON string, it is flattened and automatically copied to STORE_CLIENT with corresponding key names.
* NOTE: The CLIENT store is emptied beforehand!
......@@ -2120,11 +2131,11 @@ By using the ``_link`` column name:
* in ``persistent link`` mode: path download script (optional) and key(s) to identify the record with the PathFilename
information (see below).
* the optional ``M:...`` (Mode) specifies the export type (file, pdf, zip, export),
* the optional ``M:...`` (Mode) specifies the export type (file, pdf, qfqpdf, zip, export),
* the alttext ``a:...`` specifies a message in the download popup.
By using ``_pdf``, ``_Pdf``, ``_file``, ``_File``, ``_zip``, ``_Zip``, ``_excel`` as column name, the options `d`, `M` and `s`
will be set.
By using ``_pdf``, ``_Pdf``, ``_file``, ``_File``, ``_zip``, ``_Zip``, ``_excel`` as column name, the options `d`,
`M` (pdf: wkhtml) and `s` will be set.
All files will be read by PHP - therefore the directory might be protected against direct web access. This is the
preferred option to offer secure downloads via QFQ. Check `secure-direct-file-access`_.
......@@ -2191,7 +2202,10 @@ Parameter and (element) sources
* *mode*: ``M:<mode>``
* *mode* = <file | pdf | zip | excel>
* *mode* = <file | pdf | qfqpdf | zip | excel>
* pdf: `wkhtml` will be used to render the pdf.
* qfqpdf: `qfqpdf` will be used to render the pdf.
* If ``M:file``, the mime type is derived dynamically from the specified file. In this mode, only one element source
is allowed per download link (no concatenation).
......@@ -2204,7 +2218,7 @@ Parameter and (element) sources
* If only one `file` is specified, the default is `file`.
* If there is a) a page defined or b) multiple elements, the default is `pdf`.
* *element sources* - for ``M:pdf`` or ``M:zip``, all of the following element sources may be specified multiple times.
* *element sources* - for ``M:pdf``, ``M:qfqpdf`` or ``M:zip``, all of the following element sources may be specified multiple times.
Any combination and order of these options are allowed.
* *file*: ``F:<pathFileName>`` - relative or absolute pathFileName offered for a) download (single), or to be concatenated
......@@ -2249,7 +2263,7 @@ Parameter and (element) sources
* Tip: For more obviously structuring, put the additional tt-content record on the same Typo3 page (where the QFQ
tt-content record is located which produces the link) and specify ``render = api`` (`report-render`_).
* *WKHTML Options* for `page`, `urlParam` or `url`:
* 'M:pdf' - *WKHTML Options* for `page`, `urlParam` or `url`:
* The 'HTML to PDF' will be done via `wkhtmltopdf`.
* All possible options, suitable for `wkhtmltopdf`, can be submitted in the `p:...`, `u:...` or `U:...` element source.
......@@ -2258,6 +2272,17 @@ Parameter and (element) sources
the key/value tuple in `p:...`, `u:...` or `U:...` has to be separated by '='. Please see last example below.
* If an option contains an '&' it must be escaped with double \\ . See example.
* 'M:qfqpdf' - *qfqpdf Options* for `page`, `urlParam` or `url`:
* The 'HTML to PDF' will be done via `qfqpdf`.
* Check https://puppeteer.github.io/puppeteer and https://git.math.uzh.ch/bbaer/qfqpdf/-/tree/master
* All possible options, suitable for `qfqpdf`, can be submitted in the `p:...`, `u:...` or `U:...` element source.
Be aware that
key/value tuple in the documentation is separated by a space, but to respect the QFQ key/value notation of URLs,
the key/value tuple in `p:...`, `u:...` or `U:...` has to be separated by '='. Please see last example below.
* If an option contains an '&' it must be escaped with double \\ . See example.
* Page numbering is done via HTML templating / CSS classes: ``--header-template '<div style="font-size:5mm;" class="pageNumber"></div>'``
Most of the other Link-Class attributes can be used to customize the link as well.
Example `_link`: ::
......@@ -2271,6 +2296,9 @@ Example `_link`: ::
# three sources: two pages and one file
SELECT "d:complete.pdf|s|t:Complete PDF|p:id=detail&r=1|p:id=detail2&r=1|F:fileadmin/pdf/test.pdf" AS _link
# qfqpdf - three sources: two pages and one file
SELECT "d:complete.pdf|M:qfqpdf|s|t:Complete PDF|p:id=detail&r=1|p:id=detail2&r=1|F:fileadmin/pdf/test.pdf" AS _link
# three sources: two pages and one file
SELECT "d:complete.pdf|s|t:Complete PDF|p:id=detail&r=1|p:id=detail2&r=1|F:fileadmin/pdf/test.pdf" AS _link
......@@ -2286,8 +2314,8 @@ Example `_link`: ::
# One indirect source reference
SELECT "d:complete.pdf|s|t:Complete PDF|source:centralPdf&pId=1234" AS _link
An additional tt-content record is defined with `sub header: centralPdf`. One or multiple attachments might be concatenated.
10.sql = SELECT '|F:', a.pathFileName FROM Attachments AS a WHERE a.pId={{pId:S}}
An additional tt-content record is defined with `sub header: centralPdf`. One or multiple attachments might be concatenated.
10.sql = SELECT '|F:', a.pathFileName FROM Attachments AS a WHERE a.pId={{pId:S}}
..
......@@ -2925,8 +2953,8 @@ The *tablesorter* options:
* 'Views' can be saved as:
* public: every user will see the `view` and can modify it.
* private: only the user who created the `view` will see/modify it.
* group: every user will see the `view` and can modify it.
* personal: only the user who created the `view` will see/modify it.
* readonly: manually mark a `view` as readonly (no FE User can change it) by setting column `readonly='true'` in table
`Setting` of the corresponding view (identified by `name`).
......
......@@ -217,37 +217,47 @@ Store: *TYPO3* (Bodytext) - T
* Sanitized: *no*
+-------------------------+-------------------------------------------------------------------+----------+
| Name | Explanation | Note |
+=========================+===================================================================+==========+
| form | | Formname defined in ttcontent record bodytext | see note |
| | | * Fix. E.g. *form = person* | |
| | | * via SIP. E.g. *form = {{form:SE}}* | |
+-------------------------+-------------------------------------------------------------------+----------+
| pageId | Record id of current Typo3 page | see note |
+-------------------------+-------------------------------------------------------------------+----------+
| pageAlias | Alias of current Typo3 page. If empty, take pageId. | see note |
+-------------------------+-------------------------------------------------------------------+----------+
| pageTitle | Title of current Typo3 page | see note |
+-------------------------+-------------------------------------------------------------------+----------+
| pageType | Current selected page type (typically URL parameter 'type') | see note |
+-------------------------+-------------------------------------------------------------------+----------+
| pageLanguage | Current selected page language (typically URL parameter 'L') | see note |
+-------------------------+-------------------------------------------------------------------+----------+
| ttcontentUid | Record id of current Typo3 content element | see note |
+-------------------------+-------------------------------------------------------------------+----------+
| feUser | Logged in Typo3 FE User | |
+-------------------------+-------------------------------------------------------------------+----------+
| feUserUid | Logged in Typo3 FE User uid | |
+-------------------------+-------------------------------------------------------------------+----------+
| feUserGroup | FE groups of logged in Typo3 FE User | |
+-------------------------+-------------------------------------------------------------------+----------+
| beUser | Logged in Typo3 BE User | |
+-------------------------+-------------------------------------------------------------------+----------+
| beUserLoggedIn | 'yes' | 'no' - Status if a BE-User is logged in | |
+-------------------------+-------------------------------------------------------------------+----------+
* **note**: not available:
+-------------------------+-------------------------------------------------------------------+-----+
| Name | Explanation | API |
+=========================+===================================================================+=====+
| form | | Formname defined in ttcontent record bodytext | no |
| | | * Fix. E.g. *form = person* | |
| | | * via SIP. E.g. *form = {{form:SE}}* | |
+-------------------------+-------------------------------------------------------------------+-----+
| pageId | Record id of current Typo3 page | no |
+-------------------------+-------------------------------------------------------------------+-----+
| pageAbstract | Abstract of current Typo3 page | no |
+-------------------------+-------------------------------------------------------------------+-----+
| pageAlias | Alias of current Typo3 page. If empty, take pageId. | no |
+-------------------------+-------------------------------------------------------------------+-----+
| pageDescription | Description of current Typo3 page | no |
+-------------------------+-------------------------------------------------------------------+-----+
| pageKeywords | Keywords of current Typo3 page | no |
+-------------------------+-------------------------------------------------------------------+-----+
| pageLanguage | Current selected page language (typically URL parameter 'L') | no |
+-------------------------+-------------------------------------------------------------------+-----+
| pageNavTitle | Alternative navigation title of current Typo3 page | no |
+-------------------------+-------------------------------------------------------------------+-----+
| pageTitle | Title of current Typo3 page | no |
+-------------------------+-------------------------------------------------------------------+-----+
| pageType | Current selected page type (typically URL parameter 'type') | no |
+-------------------------+-------------------------------------------------------------------+-----+
| ttcontentSubheader | Subheader of the current ttcontent record | no |
+-------------------------+-------------------------------------------------------------------+-----+
| ttcontentUid | Record id of current Typo3 content element | no |
+-------------------------+-------------------------------------------------------------------+-----+
| feUser | Logged in Typo3 FE User | yes |
+-------------------------+-------------------------------------------------------------------+-----+
| feUserGroup | FE groups of logged in Typo3 FE User | yes |
+-------------------------+-------------------------------------------------------------------+-----+
| feUserUid | Logged in Typo3 FE User uid | yes |
+-------------------------+-------------------------------------------------------------------+-----+
| beUser | Logged in Typo3 BE User | yes |
+-------------------------+-------------------------------------------------------------------+-----+
| beUserLoggedIn | 'yes' | 'no' - Status if a BE-User is logged in | yes |
+-------------------------+-------------------------------------------------------------------+-----+
* **API**: available:
* in :ref:`dynamic-update` or
* by *FormElement* class 'action' with type 'beforeSave', 'afterSave', 'beforeDelete', 'afterDelete'.
......
......@@ -141,7 +141,7 @@ Sanitize class
{{name:store:**sanitize**:escape:default:message}}
Values in STORE_CLIENT *C* (Client=Browser) and STORE_FORM *F* (Form, HTTP 'post') are checked against a
sanitize class. Values from other stores are *not* checked against any sanitize class, even if a sanitize class is specified.
sanitize class. Values from other stores are *not* checked against any sanitize class, unless a sanitize class is specified.
* Variables get by default the sanitize class defined in the corresponding `FormElement`. If not defined,
the default class is ``digit``.
......
......@@ -18,10 +18,10 @@ use IMATHUZH\Qfq\Core\Helper\KeyValueStringParser;
use IMATHUZH\Qfq\Core\Helper\Ldap;
use IMATHUZH\Qfq\Core\Helper\Logger;
use IMATHUZH\Qfq\Core\Helper\OnArray;
use IMATHUZH\Qfq\Core\Helper\OnString;
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;
......@@ -257,7 +257,8 @@ 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_EXPECT_1, [$row[$idName]]);
$record = $this->dbArray[$this->dbIndexData]->sql('SELECT * FROM `' . $this->formSpec[F_TABLE_NAME] . '` WHERE `id`= ?',
ROW_EXPECT_1, [$row[$idName]], 'If you get 0 records: check that the primary table is the one used in multi SQL');
$this->store->setStore($record, STORE_RECORD, true);
$jsonTmp = array();
......@@ -513,12 +514,9 @@ abstract class AbstractBuildForm {
* @throws \UserFormException
*/
public function getFormTag() {
$md5 = '';
$attribute = $this->getFormTagAttributes();
$honeypot = $this->getHoneypotVars();
$md5 = $this->buildInputRecordHashMd5();
return '<form ' . OnArray::toString($attribute, '=', ' ', "'") . '>' . $honeypot . $md5;
......@@ -1342,12 +1340,19 @@ abstract class AbstractBuildForm {
$elementCharacterCount = '';
if (isset($formElement[FE_INPUT_CLEAR_ME]) && $formElement[FE_INPUT_CLEAR_ME] != '0') {
$class .= ' qfq-clear-me';
if (isset($this->formSpec["multiMode"]) && $this->formSpec["multiMode"] == 'vertical'){
$class .= ' qfq-clear-me-multiform';
}else {
$class .= ' qfq-clear-me';
}
}
if ($formElement[FE_MAX_LENGTH] > 0 && $value !== '') {
// Check if there are \r\n > those should be counted as one char, not two. #13030
$crlf = substr_count($value, "\r\n");
$max = $formElement[FE_MAX_LENGTH] + $crlf;
// crop string only if it's not empty (substr returns false on empty strings)
$value = mb_substr($value, 0, $formElement[FE_MAX_LENGTH]);
$value = mb_substr($value, 0, $max);
}
if ($formElement[FE_HIDE_ZERO] != '0' && $value == '0') {
......@@ -2403,8 +2408,14 @@ abstract class AbstractBuildForm {
}
}
if ($this->showDebugInfoFlag)
// Check if detail contains Typo3 reserved keywords
if(isset($queryStringArray[CLIENT_PAGE_ID]) || isset($queryStringArray[CLIENT_PAGE_TYPE]) ||isset($queryStringArray[CLIENT_PAGE_LANGUAGE])){
throw new \UserFormException("Reserved Typo3 keyword (id, type, L) in formElement.parameter.detail - please use something else.");
}
if ($this->showDebugInfoFlag) {
$toolTip .= PHP_EOL . OnArray::toString($queryStringArray, ' = ', PHP_EOL, "'");
}
Support::appendTypo3ParameterToArray($queryStringArray);
// If there is a specific targetpage defined, take it.
......@@ -2465,7 +2476,7 @@ abstract class AbstractBuildForm {
private function getSubrecordColumnControl(array $titleRaw) {
$control = array();
foreach ($titleRaw AS $columnName) {
foreach ($titleRaw as $columnName) {
switch ($columnName) {
case SUBRECORD_COLUMN_ROW_CLASS:
......@@ -3391,7 +3402,7 @@ abstract class AbstractBuildForm {
// toolbar: https://www.tinymce.com/docs/advanced/editor-control-identifiers/#toolbarcontrols
if (!isset($formElement[FE_EDITOR_PREFIX . 'toolbar'])) {
$formElement[FE_EDITOR_PREFIX . 'toolbar'] = 'code searchreplace undo redo | ' .
'styleselect link table | fontselect fontsizeselect | ' .
'styleselect link table | ' .
'bullist numlist outdent indent | forecolor backcolor bold italic';
}
......
......@@ -42,7 +42,7 @@ const FORM_DRAG_AND_DROP = 'form_drag_and_drop';
const FORM_REST = 'form_rest';
const FORM_PERMISSION_SIP = 'sip';
const FORM_PERMISSION_LOGGED_IN = 'logged_id';
const FORM_PERMISSION_LOGGED_IN = 'logged_in';
const FORM_PERMISSION_LOGGED_OUT = 'logged_out';
const FORM_PERMISSION_ALWAYS = 'always';
const FORM_PERMISSION_NEVER = 'never';
......@@ -78,38 +78,6 @@ const SQL_FORM_ELEMENT_NATIVE_TG_COUNT = "SELECT `fe`.*, IFNULL(`feTg`.`maxLengt
const NAME_TG_COPIES = '_tgCopies'; // Number of templatesGroup copies to create on the fly. Also used in SQL_FORM_ELEMENT_NATIVE_TG_COUNT.
const FE_TG_INDEX = '_tgIndex'; // Index of the current copy of a templateGroup FE.
// SANITIZE Classifier
const SANITIZE_ALLOW_AUTO = "auto"; // Default for FormElements
const SANITIZE_ALLOW_ALNUMX = "alnumx";
const SANITIZE_ALLOW_DIGIT = "digit";
const SANITIZE_ALLOW_NUMERICAL = "numerical";
const SANITIZE_ALLOW_EMAIL = "email";
const SANITIZE_ALLOW_PATTERN = "pattern";
const SANITIZE_ALLOW_ALLBUT = "allbut";
const SANITIZE_ALLOW_ALL = "all";
const SANITIZE_DEFAULT = SANITIZE_ALLOW_DIGIT; // for {{variable}} expressions without checkType
const SANITIZE_EXCEPTION = 'exception';
const SANITIZE_EMPTY_STRING = 'empty string';
const SANITIZE_VIOLATE = '!!';
const SANITIZE_ALLOW_ALNUMX_MESSAGE = 'Allowed characters: 0...9, [latin character], @-_.m;: /()';
const SANITIZE_ALLOW_DIGIT_MESSAGE = 'Allowed characters: 0...9';
const SANITIZE_ALLOW_NUMERICAL_MESSAGE = 'Allowed characters: 0...9 and .+-';
const SANITIZE_ALLOW_EMAIL_MESSAGE = 'Requested format: string@domain.tld';
const SANITIZE_ALLOW_ALLBUT_MESSAGE = 'Forbidden characters: ^[]{}%\#';
const SANITIZE_TYPE_MESSAGE_VIOLATE_EMPTY = 'e';
const SANITIZE_TYPE_MESSAGE_VIOLATE_ZERO = '0';
const SANITIZE_TYPE_MESSAGE_VIOLATE_CLASS = 'c';
const PATTERN_ALNUMX = '^[@\-_\.,;: \/\(\)a-zA-Z0-9ÀÈÌÒÙàèìòùÁÉÍÓÚÝáéíóúýÂÊÎÔÛâêîôûÃÑÕãñõÄËÏÖÜŸäëïöüÿçß]*$';
const PATTERN_DIGIT = '^[\d]*$';
const PATTERN_NUMERICAL = '^[\d.+-]*$';
const PATTERN_EMAIL = '^([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})?$';
const PATTERN_ALLBUT = '^[^\[\]{}%\\\\#]*$';
const PATTERN_ALL = '.*';
// Index wrap setup table
......@@ -379,6 +347,7 @@ const ERROR_IMPORT_LIST_SHEET_NAMES = 2901;
const ERROR_FORM_REST = 3000;
const ERROR_REST_AUTHORIZATION = 3001;
const ERROR_REST_INVALID_ID = 3002;
const ERROR_REST_API_CALL = 3010;
// Tablesorter
const ERROR_TABLESORTER_SIP_NOT_FOUND = 3100;
......@@ -411,6 +380,59 @@ const STORE_ZERO = "0"; // value: 0, might helpfull if variable is empty but use
const STORE_USE_DEFAULT = "FSRVD";
// SANITIZE Classifier
const SANITIZE_ALLOW_AUTO = "auto"; // Default for FormElements
const SANITIZE_ALLOW_ALNUMX = "alnumx";
const SANITIZE_ALLOW_DIGIT = "digit";
const SANITIZE_ALLOW_NUMERICAL = "numerical";
const SANITIZE_ALLOW_EMAIL = "email";
const SANITIZE_ALLOW_PATTERN = "pattern";
const SANITIZE_ALLOW_ALLBUT = "allbut";
const SANITIZE_ALLOW_ALL = "all";
const SANITIZE_DEFAULT = SANITIZE_ALLOW_DIGIT; // for {{variable}} expressions without checkType
const SANITIZE_DEFAULT_OF_STORE = [
STORE_FORM => SANITIZE_ALLOW_DIGIT,
STORE_SIP => SANITIZE_ALLOW_ALL,
STORE_RECORD => SANITIZE_ALLOW_ALL,
STORE_BEFORE => SANITIZE_ALLOW_ALL,
STORE_PARENT_RECORD => SANITIZE_ALLOW_ALL,
STORE_TABLE_DEFAULT => SANITIZE_ALLOW_ALL,
STORE_TABLE_COLUMN_TYPES => SANITIZE_ALLOW_ALL,
STORE_CLIENT => SANITIZE_ALLOW_DIGIT,
STORE_TYPO3 => SANITIZE_ALLOW_ALL,
STORE_VAR => SANITIZE_ALLOW_ALL,
STORE_ZERO => SANITIZE_ALLOW_ALL,
STORE_EMPTY => SANITIZE_ALLOW_ALL,
STORE_SYSTEM => SANITIZE_ALLOW_ALL,
STORE_EXTRA => SANITIZE_ALLOW_ALL,
STORE_USER => SANITIZE_ALLOW_ALL,
STORE_LDAP => SANITIZE_ALLOW_ALL,
STORE_ADDITIONAL_FORM_ELEMENTS => SANITIZE_ALLOW_ALL,
];
const SANITIZE_EXCEPTION = 'exception';
const SANITIZE_EMPTY_STRING = 'empty string';
const SANITIZE_VIOLATE = '!!';
const SANITIZE_ALLOW_ALNUMX_MESSAGE = 'Allowed characters: 0...9, [latin character], @-_.m;: /()';
const SANITIZE_ALLOW_DIGIT_MESSAGE = 'Allowed characters: 0...9';
const SANITIZE_ALLOW_NUMERICAL_MESSAGE = 'Allowed characters: 0...9 and .+-';
const SANITIZE_ALLOW_EMAIL_MESSAGE = 'Requested format: string@domain.tld';
const SANITIZE_ALLOW_ALLBUT_MESSAGE = 'Forbidden characters: ^[]{}%\#';
const SANITIZE_TYPE_MESSAGE_VIOLATE_EMPTY = 'e';
const SANITIZE_TYPE_MESSAGE_VIOLATE_ZERO = '0';
const SANITIZE_TYPE_MESSAGE_VIOLATE_CLASS = 'c';
const PATTERN_ALNUMX = '^[@\-_\.,;: \/\(\)a-zA-Z0-9ÀÈÌÒÙàèìòùÁÉÍÓÚÝáéíóúýÂÊÎÔÛâêîôûÃÑÕãñõÄËÏÖÜŸäëïöüÿçß]*$';
const PATTERN_DIGIT = '^[\d]*$';
const PATTERN_NUMERICAL = '^[\d.+-]*$';
const PATTERN_EMAIL = '^([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})?$';
const PATTERN_ALLBUT = '^[^\[\]{}%\\\\#]*$';
const PATTERN_ALL = '.*';
//
// Store: Definitions / Members
//
......@@ -464,10 +486,16 @@ const TYPO3_FE_USER = 'feUser';
const TYPO3_FE_USER_UID = 'feUserUid';
const TYPO3_FE_USER_GROUP = 'feUserGroup';
const TYPO3_TT_CONTENT_UID = 'ttcontentUid';
const TYPO3_TT_CONTENT_SUBHEADER = 'ttcontentSubheader';
const TYPO3_PAGE_ID = 'pageId';
const TYPO3_PAGE_ALIAS = 'pageAlias';
const TYPO3_PAGE_TITLE = 'pageTitle';
const TYPO3_PAGE_TYPE = 'pageType';
const TYPO3_PAGE_ABSTRACT = 'pageAbstract';
const TYPO3_PAGE_DESCRIPTION = 'pageDescription';