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

Manual.rst: Add note about wkhtml only on linux boxes. More wkhtml explanations.

Add TestFormEditor.sql
parent d750eeec
......@@ -31,6 +31,12 @@ General
Installation
============
The following features are only tested on linux hosts:
* HTML to PDF conversion - command `wkhtmltopdf`.
* Concatenation of PDF files - command `pdftk`.
* Mime type detection for uploads - command `file`.
Preparation
-----------
......@@ -47,7 +53,7 @@ To normalize UTF8 input, the *php5-intl* resp. *php7.0-intl* package is needed b
* normalizer::normalize()
For the `download`_ function, the program `pdftk` is necessary to concatenate PDF files.
For the `download`_ function, the programs `pdftk` and `file` are necessary to concatenate PDF files.
Preparation for Ubuntu 14.04::
......@@ -66,24 +72,35 @@ Preparation steps for Ubuntu 16.04::
wkhtmltopdf
^^^^^^^^^^^
`wkhtmltopdf` `<http://wkhtmltopdf.org/>`_ will be used by QFQ to offer 'website print' and 'HTML to PDF' conversion.
The converter is not included in QFQ and has to be manually installed.
`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.
* The Ubuntu package `wkhtmltopdf` needs a running Xserver - this does not work on a headless webserver. Best is to
install the QT version from the named website above.
In `config-qfq-ini`_ specify the:
* installed `wkhtmltopdf` binary,
* the site base URL.
* installed `wkhtmltopdf` binary:
* `WKHTMLTOPDF = /.../wkhtmltopdf`
* the site base URL:
* `BASE_URL_PRINT = http://example.com/`
**Important**: To access FE_GROUP protected pages or content, it's necessary to disable the `[FE][lockIP]` check: `wkhtml`
will access the Typo3 page locally and that IP address is different from the client (=user) IP.
**Important**: To access FE_GROUP protected pages or content, it's necessary to disable the `[FE][lockIP]` check! `wkhtml`
will access the Typo3 page locally (localhost) and that IP address is different from the client (=user) IP.
Configure via Typo3 Installtool `All configuration > $TYPO3_CONF_VARS['FE']`: ::
[FE][lockIP] = 0
**Warning**: this disables an important anti-'session hijacking' protection. The security level of the whole installation
will be *lowered*! Again, this is only needed if `wkhtml` needs access to FE_GROUP protected pages & content. As an
alternative to lower the security level, create a separated page subtree which is only accessible (configured via
Typosript) from specific IPs **or** if a FE-User is logged in.
HTML to PDF conversion
''''''''''''''''''''''
......@@ -629,8 +646,11 @@ Honeypot
Every QFQ Form contains 'honeypot'-HTML input elements (HTML: hidden & readonly). Which of them to use is configured in
`config.qfq.ini`_ (default: 'username', 'password' and 'email'). On every start of QFQ (form, report, save, ...),
these variables are tested if they are non-empty. If any of the default configured are needed, an explicit variable name
list have to be unconfigured in `config.qfq.ini`_.
these variables are tested if they are non-empty. In such a case a probably malicous bot has send the request and the
request will not be processed.
If any of the default configured variable names are needed (which will never be the case for QFQ), an explicit variable name
list have to be configured in `config.qfq.ini`_.
**QFQ security restriction**:
......@@ -667,21 +687,27 @@ E.g. for Apache set a htaccess rule: ::
Require all denied
</Directory>
**Important**: all QFQ uploads should then save files in or below such a directory.
To offer download of those files, use the reserved columnname '_download':`download`_ or variants.
To protect the installation against executing of uploaded malicious script code, disable PHP for the final upload
**Important**: To protect the installation against executing of uploaded malicious script code, disable PHP for the final upload
directory. E.g. `fileadmin`: ::
<Directory "/var/www/html/fileadmin>
php_admin_flag engine Off
</Directory>
This is in general a good security improvement for directories with user supplied content.
File upload
-----------
By default the mime type of every uploaded file is checked against a whitelist of allowed mime types. The mime type of
a file can be faked by an attacker. This check is good for regular user to upload only allowed file types. To prevent
attacks against malicous code, the execution of files should be denied by the webserver config (`SecureDirectFileAccess`_).
a file can be (easily) faked by an attacker. This check is good to handle regular user file upload for specific file types. To
prevent attacks against uploading and executing malicous code this won't help.
Intstead prohibit the execution of user contributed files by the webserver config (`SecureDirectFileAccess`_).
Store
=====
......
DROP TABLE IF EXISTS `Form`;
CREATE TABLE IF NOT EXISTS `Form` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL DEFAULT '',
`title` VARCHAR(255) NOT NULL DEFAULT '',
`noteInternal` TEXT NOT NULL,
`tableName` VARCHAR(255) NOT NULL DEFAULT '',
`permitNew` ENUM('sip', 'logged_in', 'logged_out', 'always', 'never') NOT NULL DEFAULT 'sip',
`permitEdit` ENUM('sip', 'logged_in', 'logged_out', 'always', 'never') NOT NULL DEFAULT 'sip',
`escapeTypeDefault` VARCHAR(32) NOT NULL DEFAULT 'c',
`render` ENUM('plain', 'table', 'bootstrap') NOT NULL DEFAULT 'plain',
`requiredParameter` VARCHAR(255) NOT NULL DEFAULT '',
`showButton` SET('new', 'delete') NOT NULL DEFAULT 'new,delete',
`multiMode` ENUM('none', 'horizontal', 'vertical') NOT NULL DEFAULT 'none',
`multiSql` TEXT NOT NULL,
`multiDetailForm` VARCHAR(255) NOT NULL DEFAULT '',
`multiDetailFormParameter` VARCHAR(255) NOT NULL DEFAULT '',
`forwardMode` ENUM('client', 'no', 'page') NOT NULL DEFAULT 'client',
`forwardPage` VARCHAR(255) NOT NULL DEFAULT '',
`bsLabelColumns` VARCHAR(255) NOT NULL DEFAULT '',
`bsInputColumns` VARCHAR(255) NOT NULL DEFAULT '',
`bsNoteColumns` VARCHAR(255) NOT NULL DEFAULT '',
`parameter` TEXT NOT NULL,
`deleted` ENUM('yes', 'no') NOT NULL DEFAULT 'no',
`modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
KEY `name` (`name`),
KEY `name_deleted` (`name`, `deleted`)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8
AUTO_INCREMENT = 0;
# --
# -- Triggers `Form`
# --
# DROP TRIGGER IF EXISTS `on_Form_update_modified`;
# DELIMITER //
# CREATE TRIGGER `on_Form_update_modified` BEFORE UPDATE ON `Form`
# FOR EACH ROW SET NEW.modified =
# current_timestamp()
# //
# DELIMITER ;
# ----------------------------------------
# FormElement
DROP TABLE IF EXISTS `FormElement`;
CREATE TABLE IF NOT EXISTS `FormElement` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`formId` INT(11) NOT NULL,
`feIdContainer` INT(11) NOT NULL DEFAULT '0',
`dynamicUpdate` ENUM('yes', 'no') NOT NULL DEFAULT 'no',
`enabled` ENUM('yes', 'no') NOT NULL DEFAULT 'yes',
`name` VARCHAR(255) NOT NULL DEFAULT '',
`label` VARCHAR(255) NOT NULL DEFAULT '',
`mode` ENUM('show', 'readonly', 'required', 'lock', 'disabled') NOT NULL DEFAULT 'show',
`modeSql` TEXT NOT NULL,
`class` ENUM('native', 'action', 'container') NOT NULL DEFAULT 'native',
`type` ENUM('checkbox', 'date', 'datetime', 'dateJQW', 'datetimeJQW', 'extra', 'gridJQW', 'text', 'editor', 'time',
'note', 'password', 'radio', 'select', 'subrecord', 'upload', 'fieldset', 'pill',
'beforeLoad', 'beforeSave', 'beforeInsert', 'beforeUpdate', 'beforeDelete', 'afterLoad',
'afterSave', 'afterInsert', 'afterUpdate', 'afterDelete',
'sendmail') NOT NULL DEFAULT 'text',
`subrecordOption` SET('edit', 'delete', 'new') NOT NULL DEFAULT '',
`encode` ENUM('none', 'specialchar') NOT NULL DEFAULT 'specialchar',
`checkType` ENUM('alnumx', 'digit', 'numerical', 'email', 'min|max', 'min|max date', 'pattern', 'all') NOT NULL DEFAULT 'alnumx',
`checkPattern` VARCHAR(255) NOT NULL DEFAULT '',
`onChange` VARCHAR(255) NOT NULL DEFAULT '',
`ord` INT(11) NOT NULL DEFAULT '0',
`tabindex` INT(11) NOT NULL DEFAULT '0',
`size` VARCHAR(255) NOT NULL DEFAULT '',
`maxLength` VARCHAR(255) NOT NULL DEFAULT '',
`bsLabelColumns` VARCHAR(255) NOT NULL DEFAULT '',
`bsInputColumns` VARCHAR(255) NOT NULL DEFAULT '',
`bsNoteColumns` VARCHAR(255) NOT NULL DEFAULT '',
`rowLabelInputNote` SET('row', 'label', '/label', 'input', '/input', 'note', '/note', '/row') NOT NULL DEFAULT 'row,label,/label,input,/input,note,/note,/row',
`note` TEXT NOT NULL,
`tooltip` VARCHAR(255) NOT NULL DEFAULT '',
`placeholder` VARCHAR(255) NOT NULL DEFAULT '',
`value` TEXT NOT NULL,
`sql1` TEXT NOT NULL,
`sql2` TEXT NOT NULL,
`parameter` TEXT NOT NULL,
`clientJs` TEXT,
`feGroup` VARCHAR(255) NOT NULL DEFAULT '',
`debug` ENUM('yes', 'no') NOT NULL DEFAULT 'no',
`deleted` ENUM('yes', 'no') NOT NULL DEFAULT 'no',
`modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
KEY `formId` (`formId`),
KEY `formId_class_enabled_deleted` (`formId`, `class`, `enabled`, `deleted`)
)
ENGINE = InnoDB
DEFAULT CHARSET = utf8
AUTO_INCREMENT = 0;
# --
# -- Triggers `FormElement`
# --
# DROP TRIGGER IF EXISTS `on_FormEelement_update_modified`;
# DELIMITER //
# CREATE TRIGGER `on_FormEelement_update_modified` BEFORE UPDATE ON `FormElement`
# FOR EACH ROW SET NEW.modified =
# current_timestamp()
# //
# DELIMITER ;
#
# FormEditor: Form
INSERT INTO Form (name, title, noteInternal, tableName, permitNew, permitEdit, render, multiSql, parameter) VALUES
('form', 'Form Editor: {{SELECT id, " / ", title FROM Form WHERE id = {{recordId:S0}}}}', 'Please secure the form',
'Form', 'always', 'always', 'bootstrap', '', 'maxVisiblePill=3');
# FormEditor: FormElements
INSERT INTO FormElement (formId, name, label, mode, type, class, ord, size, maxLength, note, clientJs, value, sql1, sql2, parameter, feIdContainer, modeSql)
VALUES
(1, 'basic', 'Basic', 'show', 'pill', 'container', 10, 0, 0, '', '', '', '', '', '', 0, ''),
(1, 'permission', 'Permission', 'show', 'pill', 'container', 20, 0, 0, '', '', '', '', '', '', 0, ''),
(1, 'various', 'Various', 'show', 'pill', 'container', 30, 0, 0, '', '', '', '', '', '', 0, ''),
(1, 'formelement', 'Formelement', 'show', 'pill', 'container', 40, 0, 0, '', '', '', '', '', '', 0, ''),
(1, 'id', 'id', 'readonly', 'text', 'native', 100, 10, 11, '', '', '', '', '', '', 1, ''),
(1, 'name', 'Name', 'show', 'text', 'native', 120, 40, 255, '', '', '', '', '', 'autofocus=on', 1, ''),
(1, 'title', 'Title', 'show', 'text', 'native', 130, 40, 255, '', '', '', '', '', '', 1, ''),
(1, 'noteInternal', 'Note', 'show', 'text', 'native', 140, '40,3', 0, '', '', '', '', '', '', 1, ''),
(1, 'tableName', 'Table', 'required', 'select', 'native', 150, 0, 0, '', '', '', '{{!SHOW tables}}', '', 'emptyItemAtStart', 1, ''),
(1, 'permitNew', 'Permit New', 'show', 'radio', 'native', 160, 0, 0, '', '', '', '', '', '', 2, ''),
(1, 'permitEdit', 'Permit Edit', 'show', 'radio', 'native', 170, 0, 0, '', '', '', '', '', '', 2, ''),
(1, 'permitUrlParameter', 'Permit Url Parameter', 'show', 'text', 'native', 180, 40, 255, '', '', '', '', '', '', 2, ''),
(1, 'render', 'Render', 'show', 'radio', 'native', 190, 0, 0, '', '', '', '', '', '', 2, ''),
(1, 'multi', 'Multi', 'show', 'fieldset', 'native', 210, 0, 0, '', '', '', '', '', '', 3, ''),
(1, 'multiMode', 'Multi Mode', 'show', 'radio', 'native', 220, 0, 0, '', '', '', '', '', '', 3, ''),
(1, 'multiSql', 'Multi SQL', 'show', 'text', 'native', 230, '40,3', 0, '', '', '', '', '', '', 3, ''),
(1, 'multiDetailForm', 'Multi Detail Form', 'show', 'text', 'native', 240, 40, 255, '', '', '', '', '', '', 3, ''),
(1, 'multiDetailFormParameter', 'Multi Detail Form Parameter', 'show', 'text', 'native', 250, 40, 255, '', '', '', '', '', '', 3, ''),
(1, 'forwardMode', 'Forward', 'show', 'radio', 'native', 260, 0, 0, '', '', '', '', '', '', 3, ''),
(1, 'forwardPage', 'Forward Page', 'show', 'text', 'native', 270, 40, 255, '', '', '', '', '', '', 3, ''),
(1, 'bsLabelColumns', 'BS Label Columns', 'show', 'text', 'native', 280, 40, 250, '', '', '', '', '', '', 3, ''),
(1, 'bsInputColumns', 'BS Input Columns', 'show', 'text', 'native', 290, 40, 250, '', '', '', '', '', '', 3, ''),
(1, 'bsNoteColumns', 'BS Note Columns', 'show', 'text', 'native', 300, 40, 250, '', '', '', '', '', '', 3, ''),
(1, 'deleted', 'Deleted', 'show', 'checkbox', 'native', 400, 0, 0, '', '', '', '', '', '', 3, ''),
(1, 'modified', 'Modified', 'readonly', 'text', 'native', 410, 40, 20, '', '', '', '', '', '', 3, ''),
(1, 'created', 'Created', 'readonly', 'text', 'native', 420, 40, 20, '', '', '', '', '', '', 3, ''),
(1, '', 'FormElements', 'show', 'subrecord', 'native', 500, 0, 0, '', '', '',
'{{!SELECT * FROM FormElement WHERE formId={{id:R0}}}}',
'', 'form=formElement\npage=form.php', 4, '');
#
# FormEditor: FormElement
INSERT INTO Form (name, title, noteInternal, tableName, permitNew, permitEdit, render, multiSql, parameter) VALUES
('formElement', 'Form Element Editor : {{SELECT id, " / ", title FROM Form WHERE id = {{recordId:S0}}}}',
'Please secure the form',
'FormElement', 'always', 'always', 'bootstrap', '', 'maxVisiblePill=3');
# FormEditor: FormElements
INSERT INTO FormElement (id, formId, name, label, mode, type, class, ord, size, maxLength, note, clientJs, value, sql1, sql2, parameter, feIdContainer, debug, modeSql)
VALUES
(100, 2, 'basic', 'Basic', 'show', 'pill', 'container', 10, 0, 0, '', '', '', '', '', '', 0, 'no', ''),
(101, 2, 'check_order', 'Check & Order', 'show', 'pill', 'container', 20, 0, 0, '', '', '', '', '', '', 0, 'no', ''),
(102, 2, 'layout', 'Layout', 'show', 'pill', 'container', 20, 0, 0, '', '', '', '', '', '', 0, 'no', ''),
(103, 2, 'value', 'Value', 'show', 'pill', 'container', 20, 0, 0, '', '', '', '', '', '', 0, 'no', ''),
(104, 2, 'info', 'Info', 'show', 'pill', 'container', 20, 0, 0, '', '', '', '', '', '', 0, 'no', ''),
(110, 2, 'id', 'id', 'readonly', 'text', 'native', 100, 10, 11, '', '', '', '', '', '', 100, 'no', ''),
(111, 2, 'formId', 'formId', 'readonly', 'text', 'native', 120, 40, 255, '', '', '', '', '', '', 100, 'no', ''),
(112, 2, 'feIdContainer', 'Container', 'show', 'select', 'native', 150, 0, 0, '', '', '',
'{{!SELECT fe.id, CONCAT(fe.class, " / ", fe.label) FROM FormElement As fe WHERE fe.formId={{id}} AND fe.class="container" ORDER BY fe.ord }}',
'', 'emptyItemAtStart', 100, 'no', ''),
(113, 2, 'enabled', 'Enabled', 'show', 'checkbox', 'native', 120, 0, 0, '', '', '', '', '', '', 100, 'no', ''),
(114, 2, 'name', 'Name', 'show', 'text', 'native', 120, 40, 255, '', '', '', '', '', '', 100, 'no', ''),
(115, 2, 'label', 'Label', 'show', 'text', 'native', 130, 40, 255, '', '', '', '', '', '', 100, 'no', ''),
(116, 2, 'mode', 'Mode', 'show', 'select', 'native', 120, 0, 255, '', '', '', '', '', '', 100, 'no', ''),
(117, 2, 'class', 'Class', 'show', 'select', 'native', 120, 0, 255, '', '', '', '', '', '', 100, 'no', ''),
(118, 2, 'type', 'Type', 'show', 'select', 'native', 120, 0, 255, '', '', '', '', '', '', 100, 'no', ''),
(119, 2, 'checkType', 'Check Type', 'show', 'select', 'native', 120, 0, 255, '', '', '', '', '', '', 101, 'no', ''),
(120, 2, 'checkPattern', 'Check Pattern', 'show', 'text', 'native', 130, 40, 255, '', '', '', '', '', '', 101, 'no', ''),
(121, 2, 'onChange', 'JS onChange', 'show', 'text', 'native', 130, 40, 255, '', '', '', '', '', '', 101, 'no', ''),
(122, 2, 'ord', 'Order', 'show', 'text', 'native', 130, 40, 255, '', '', '', '', '', '', 101, 'no', ''),
(123, 2, 'tabindex', 'tabindex', 'show', 'text', 'native', 130, 40, 255, '', '', '', '', '', '', 101, 'no', ''),
(124, 2, 'size', 'Size', 'show', 'text', 'native', 130, 40, 255, '', '', '', '', '', '', 102, 'no', ''),
(125, 2, 'maxlenght', 'Maxlength', 'show', 'text', 'native', 130, 40, 255, '', '', '', '', '', '', 102, 'no', ''),
(126, 2, 'note', 'note', 'show', 'text', 'native', 130, 40, 255, '', '', '', '', '', '', 102, 'no', ''),
(127, 2, 'tooltip', 'Tooltip', 'show', 'text', 'native', 130, 40, 255, '', '', '', '', '', '', 102, 'no', ''),
(128, 2, 'placeholder', 'Placeholder', 'show', 'text', 'native', 130, 40, 255, '', '', '', '', '', '', 102, 'no', ''),
(129, 2, 'value', 'value', 'show', 'text', 'native', 130, 40, 255, '', '', '', '', '', '', 102, 'no', ''),
(130, 2, 'sql1', 'sql1', 'show', 'text', 'native', 130, '40,4', 255, '', '', '', '', '', '', 103, 'no', ''),
(131, 2, 'parameter', 'Parameter', 'show', 'text', 'native', 130, '40,4', 255, '', '', '', '', '', '', 103, 'no', ''),
(132, 2, 'clientJs', 'ClientJS', 'show', 'text', 'native', 130, 40, 255, '', '', '', '', '', '', 103, 'no', ''),
(133, 2, 'feGroup', 'feGroup', 'show', 'text', 'native', 130, 40, 255, '', '', '', '', '', '', 104, 'no', ''),
(134, 2, 'debug', 'Debug', 'show', 'checkbox', 'native', 130, 0, 0, '', '', '', '', '', '', 104, 'no', ''),
(135, 2, 'deleted', 'Deleted', 'show', 'checkbox', 'native', 400, 0, 0, '', '', '', '', '', '', 104, 'no', ''),
(136, 2, 'modified', 'Modified', 'readonly', 'text', 'native', 410, 40, 20, '', '', '', '', '', '', 104, 'no', ''),
(137, 2, 'created', 'Created', 'readonly', 'text', 'native', 420, 40, 20, '', '', '', '', '', '', 104, 'no', '');
# FormEditor: Small
INSERT INTO Form (id, name, title, noteInternal, tableName, permitNew, permitEdit, render, multiSql, parameter) VALUES
(3, 'phpunit_person',
'Person {{SELECT ": ", firstName, " ", name, " (", id, ")" FROM Person WHERE id = {{recordId:S0}}}}',
'Please secure the form',
'Person', 'always', 'always', 'bootstrap', '', '');
# FormEditor: FormElements
INSERT INTO FormElement (id, formId, name, label, mode, type, class, ord, size, maxLength, note, clientJs, value, sql1, sql2, parameter, feIdContainer, debug, modeSql)
VALUES
(200, 3, 'name', 'Name', 'show', 'text', 'native', 10, 50, 255, '', '', '', '', '', '', 0, 'no', ''),
(201, 3, 'firstName', 'Firstname', 'show', 'text', 'native', 10, 50, 255, '', '', '', '', '', '', 0, 'no', '');
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment