Installation

QFQ is coded to run on Linux hosts, preferable on Debian derivates like Ubuntu.

The following features are only tested / supported on linux hosts:

  • 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.

  • PDF decrypt (used for merge with pdfunite) - command gs - if qpdf is not successful.

  • PDF fix (used for merge with pdfunite) - command pdf2ps and ps2pdf - if qpdf is not successful.

  • Mime type detection for uploads - command file.

  • Split PDF into JPG - command convert.

  • Repair PDF - command pdftocairo.

  • Convert HEIC/HEIF to png - command heif-info and heif-convert.

Preparation

Report & Form

To normalize UTF8 input, php-intl package is needed by

  • normalizer::normalize()

For the Download function, the programs img2pdf, pdfunite, qpdf, gs, pdf2ps, ps2pdf and file are necessary to concatenate PDF files.

Preparation for Ubuntu:

# libargon2 is used for password hashing (FE & BE)
sudo apt install php-intl libargon2

# for file upload, PDF and 'HTML to PDF' (wkhtmltopdf), PDF split
sudo apt install poppler-utils libxrender1 file pdf2svg qpdf ghostscript img2pdf libheif-examples
sudo apt install inkscape imagemagick            # to render thumbnails

By using Apache as webserver: Apache headers should be enabled. Otherwise you might encounter effcts like saving a form does not show automatically the latest saved record:

a2enmod headers

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:

mkdir /opt/qfqpdf; cd /opt/qfqpdf
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 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 case of trouble with wkhtmltopdf, also install ‘libxrender1’.

    • The current version 0.12.4 might have trouble with https connections. Version 0.12.5-dev (github master branch) seems more reliable. Please contact the QFQ authors if you need a compiled Ubuntu version of wkhtmltopdf.

In Configuration specify:

config.cmdWkhtmltopdf:  /opt/wkhtmltox/bin/wkhtmltopdf
config.baseUrl: http://www.example.com/

If wkhtml has been compiled with dedicated libraries (not part of LD_LIBRARY_PATH), specify the LD_LIBRARY_PATH together with the path-filename:

config.cmdWkhtmltopdf: LD_LIBRARY_PATH=/opt/wkhtmltox/lib /opt/wkhtmltox/bin/wkhtmltopdf

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

[FE][lockIP] = 0 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 Typoscript) from specific IPs or if a FE-User is logged in.

If there are problems with converting/downloading FE_GROUP protected pages, check Configuration showDebugInfo = download to debug.

Note

Converting HTML to PDF gives no error message but RC=-1? Check carefully all includes of CSS, JS, images and so on! Typically some of them fails to load and wkhtml stops running! Verify the correct loading of all elements by calling the site via a regular browser and bypassing any browser cache (Ctrl F5).

Note

On Ubuntu, Apache is started by default with LANG=C. This is true even when the OS default locale is set to en_US.UTF-8. Furthermore, all child processes of Apache will inherit LANG=C. Some PHP functions (like ‘escapeshellarg()’) or wkhtml will strip all non-ASCII characters (e.g. commandline arguments).

Let Apache run with the system locale: /etc/apache/envvars, activate the line . /etc/default/locale and restart Apache.

Further tips on Checklist wkhtml problems.

Print

Different browser prints the same page in different variations. To prevent this, QFQ implements a small PHP wrapper print.php with uses wkhtmltopdf to convert HTML to PDF.

Provide a print this page-link (replace ‘current pageId’ ):

<a href="typo3conf/ext/qfq/Classes/Api/print.php?id={current pageId}">Print this page</a>

Any parameter specified after print.php will be delivered to wkhtmltopdf as part of the URL.

Typoscript code to implement a print link on every page:

10 = TEXT
10 {
  wrap = <a href="typo3conf/ext/qfq/Classes/Api/print.php?id=|&type=99"><span class="glyphicon glyphicon-print" aria-hidden="true"></span> Printview</a>
  data = page:uid
}

Send Email

  • QFQ sends mail via sendEmail http://caspian.dotconf.net/menu/Software/SendEmail/ - a small perl script without a central configuration.

  • sendEmail is part of the QFQ extension and installed by default.

  • The Typo3 sendmail eco-system is not used at all by QFQ.

  • Configuration parameter can be given via Settings > Configure extension > QFQ > Tools: tools.sendEMailOptions

  • By default, sendEmail uses the local installed MTA.

    • The use of a dedicated SMTP server/port/user can be specified via commandline arguments, defined in the QFQ config settings.

    • BTW: Only TLS (Port 587) is supported by sendEmail. If your provider suggests Port 465 (=SSL) only, try TLS/587, it might work.

    • Caution: if TLS makes problems, try to switch it off (do this only in LAN) - please check sendEmail: Error => TLS setup failed.

  • For the Email body, a basic HTML support (font sizes, colors, …) is implemented.

  • The latest sendEmail version is v1.56, which has at least one bug. That one is patched in the QFQ internal version v1.56p1 (see QFQ GIT sources in directory ‘patches/sendEmail.patch’).

Thumbnail

Thumbnails will be rendered via ImageMagick (https://www.imagemagick.org/) ‘convert’ and ‘inkscape’ (https://inkscape.org). ‘inkscape’ is only used for ‘.svg’ files.

The Typo3 graphic eco-system is not used at all by QFQ.

Usage: Column: _thumbnail.

If there are no thumbnails and you see convert-im6.q16: no images defined in syslog: Check file /etc/ImageMagick-6/policy.xml and update:

old: <policy domain="coder" rights="none" pattern="PDF" />

New: <policy domain="coder" rights="read | write" pattern="PDF" />

Setup

  • Install the extension via the Extension Manager.

    • If you install the extension by manual download/upload and get an error message “can’t activate extension”: rename the downloaded zip file to qfq.zip or qfq_<version>.zip (e.g. version: 18.12.0).

    • If the Extension Manager stops after importing: check your memory limit in php.ini.

  • Copy/rename the file <site path>/fileadmin/protected/qfqProject/conf/example.qfq.json to <site path>/fileadmin/protected/qfqProject/conf/qfq.json. Configure the necessary settings Configuration The configuration file is outside of the extension directory, to not loose it during de-install and install again.

  • When the QFQ Extension is called the first time on the Typo3 frontend, the file <ext_dir>/Classes/Sql/qfqDefaultTables.sql will played and fills the database with the QFQ system tables.

  • Configure Typoscript to include Bootstrap, jQuery, QFQ javascript and CSS files.

Setup CSS & JS

page.meta {
    X-UA-Compatible = IE=edge
    X-UA-Compatible.attribute = http-equiv
    viewport=width=device-width, initial-scale=1
}

page.includeCSS {
    file01 = typo3conf/ext/qfq/Resources/Public/Css/bootstrap.min.css
    file02 = typo3conf/ext/qfq/Resources/Public/Css/bootstrap-theme.min.css
    file03 = typo3conf/ext/qfq/Resources/Public/Css/qfq-bs.css
    file04 = typo3conf/ext/qfq/Resources/Public/Css/tablesorter-bootstrap.css
    file05 = typo3conf/ext/qfq/Resources/Public/Css/font-awesome.min.css
    file06 = typo3conf/ext/qfq/Resources/Public/Css/bootstrap-datetimepicker.min.css
    file07 = typo3conf/ext/qfq/Resources/Public/Css/codemirror.css

    # Only needed if FullCalendar is used
    file10 = typo3conf/ext/qfq/Resources/Public/Css/fullcalendar.min.css

    # Only needed if FormElement 'upload' filepond is used
    file11 = typo3conf/ext/qfq/Resources/Public/Css/filepond.min.css
}

page.includeJS {
    file01 = typo3conf/ext/qfq/Resources/Public/JavaScript/jquery.min.js
    file02 = typo3conf/ext/qfq/Resources/Public/JavaScript/bootstrap.min.js
    file03 = typo3conf/ext/qfq/Resources/Public/JavaScript/validator.min.js
    file04 = typo3conf/ext/qfq/Resources/Public/JavaScript/tinymce.min.js
    file05 = typo3conf/ext/qfq/Resources/Public/JavaScript/EventEmitter.min.js
    file06 = typo3conf/ext/qfq/Resources/Public/JavaScript/qfq.min.js
    file07 = typo3conf/ext/qfq/Resources/Public/JavaScript/typeahead.bundle.min.js
    file08 = typo3conf/ext/qfq/Resources/Public/JavaScript/jquery.tablesorter.combined.min.js
    file09 = typo3conf/ext/qfq/Resources/Public/JavaScript/jquery.tablesorter.pager.min.js
    file10 = typo3conf/ext/qfq/Resources/Public/JavaScript/widget-columnSelector.min.js
    file11 = typo3conf/ext/qfq/Resources/Public/JavaScript/moment.min.js
    file12 = typo3conf/ext/qfq/Resources/Public/JavaScript/bootstrap-datetimepicker.min.js
    file13 = typo3conf/ext/qfq/Resources/Public/JavaScript/codemirror/codemirror-qfq.min.js

    # Only needed if FormElement 'annotate' is used.
    file20 = typo3conf/ext/qfq/Resources/Public/JavaScript/fabric.min.js
    file21 = typo3conf/ext/qfq/Resources/Public/JavaScript/qfq.fabric.min.js

    # Only needed if FullCalendar is used.
    file22 = typo3conf/ext/qfq/Resources/Public/JavaScript/fullcalendar.min.js

    # Only needed if widget-output is used.
    file23 = typo3conf/ext/qfq/Resources/Public/JavaScript/widget-output.min.js

    # Only needed if FormElement 'upload' filepond is used.
    file24 = typo3conf/ext/qfq/Resources/Public/JavaScript/filepond.min.js
    file25 = typo3conf/ext/qfq/Resources/Public/JavaScript/filepond-plugin-file-validate-size.min.js
    file25 = typo3conf/ext/qfq/Resources/Public/JavaScript/filepond-plugin-file-validate-type.min.js

    # Needed for FormElement 'chat'
    file26 = typo3conf/ext/qfq/Resources/Public/JavaScript/popper.min.js
}

Datetimepicker

There are three types of datetimepicker available which can be set over QFQ-Configuration, Form.parameter and FormElement.parameter.:

dateTimePickerType = qfq
dateTimePickerType = browser
dateTimePickerType = no

qfq

Is set as default and gives best experience. For this type following steps are needed to do at first time:

Include these JS and CSS Files to get datetimepicker work:

  • bootstrap-datetimepicker.min.css

  • bootstrap-datetimepicker.min.js

As first option both can be inserted to the setup of the main Template like the other scripts shown above.

Second option is to use the UZH CD template.

Following configurations can be set over FormElement.parameter:

dateFormat = DD.MM.YYYY | MM-DD-YYYY -> DD:day of month,MM:month value,YYYY:year value dateDaysOfWeekEnabled = 0,1,6 -> 0:sunday,1:monday,2:tuesday,3:wednesday,4:thursday,5:friday,6:saturday dateLocale = en | de -> Set language min = 03.05.2022 | 03.05.2022 14:00:00 -> minDate that can be set for date or datetime max = 23.07.2022 | 23.07.2022 13:00:00 -> maxDate that can be set for date or datetime dateViewModeDefault = days | months | years clearMe = 0 | 1 -> show clear button dateShowCalendarWeeks = false | true dateUseCurrentDatetime = false | true datetimeSideBySide = false | true -> Show time right to date

browser

For this datetimepicker most options are given from browser and there only can be set max and min date as own parameters. Date format can not be changed, means dateFormat settings and parameters dont have impact on this type of datetimepicker. It will be used for datetime, date and time.

no

This option deactivates the datetimepicker and allows a normal user input. Input still will be checked for correct format and following parameters are available too:

  • dateFormat

  • min

  • max

  • clearMe

Support for QFQ syntax

FormEditor

Setup a report to manage all forms:

  • Create a Typo3 page.

  • Set the ‘URL slug’ to /form (recommended) or the individual defined value in parameter editFormPage (configuration).

  • Insert a content record of type qfq.

  • In the bodytext insert the following code (see explanation of code: Report As File):

    file={{file:SU:::_formEditor}}
    
  • Twig version of FormEditor:

    file=_formEditorTwig
    

Intitialization

During the first run (or on QFQ update), the forms defined in Resources/Private/Form/* are imported. These are system forms and might be overwritten through QFQ when during QFQ updates.

Installation: Check List

  • Protect the directory <T3 installation>/fileadmin/protected in Apache against direct file access.

    • <T3 installation>/fileadmin/protected/ should be used for confidential (uploaded / generated) data.

    • <T3 installation>/fileadmin/protected/qfqProject/log/… is the default place for QFQ log files.

  • Protect the directory <T3 installation>/fileadmin in Apache to not execute PHP Scripts - malicious uploads won’t be executed.

  • Correctly set the QFQ extension setting “base url” in the typo3 backend.

  • Setup a log rotation rule for sqlLog.

  • Check that sqlLogMode is set to modify on productive sites. With none you have no chance to find out who changed which data and all really logs a mass of data.

  • Enable Extension Editor with syntax highlighting to get QFQ syntax support in backend tt-content records. See tt-content Report editing.

Encryption key and default method

To set up the encryption feature first thing to do is to append the encryption key in the qfq.json file. This can be done with writing a new line at the end of the file which looks like this:

"ENCRYPTION_KEY": "myTestKey"

It is possible to define your own default as encryption method. AES-128 is set from the beginning. Place to set the default is the QFQ-Configuration in Extension Manager. See: Extension Manager: QFQ Configuration

Important:

  • Keyword ‘ENCRYPTION_KEY’ is given and need to be written correctly.

  • For security reasons please use keys with a length of 8 chars or more.

  • If the encryption feature was used before and a key change is needed, check first for with actually key encrypted data. With one key encrypted data can not be decrypted with another key.

Websocket implementation

As an optional feature the qfq extension offers a websocket implementation. This feature allows a chat communication in real-time while the FormElement Chat is open in the form. The new messages are shown immediately to the receiving clients without reloading the page.

Requirements:

  • PHP 8.1 (used: Ubuntu 22.04)

  • Typo3 V11

  • Caution: Other Typo3 third-party Extensions needs to be compatible with php 8.1

Installation without Docker:

1. Clarify that your currently used webserver is running with php 8.1 (Ubuntu 22.04) or higher

2. nginx config file adjustments, add following proxy:
   location /ws {
     proxy_pass http://localhost:8090;
     proxy_http_version 1.1;
     proxy_set_header Upgrade $http_upgrade;
     proxy_set_header Connection "upgrade";
     proxy_set_header Host $host;
   }

3. Restart the nginx server

4. Set websocket port and websocket url in QFQ Config, examples:
websocketPort: 8090
websocketUrl: wss://mydomain.com/ws         (wss=ssl/tls, ws=http)

5. If websocketPort is set in qfq config, the websocket server should start automatically the first time a web page with qfq content is loaded.

Installation with Docker:

1. At least Ubuntu 22.04 needs to be installed in docker container. (Usually done inside Dockerfile.nginx):
FROM ubuntu:22.04

1.1 Add the following to the top of your docker file (after FROM ubuntu:22.04) if it does not already exist. It defines the timezone configurations for the ubuntu 22.04 installation:
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
    apt-get install -y tzdata && \
    ln -fs /usr/share/zoneinfo/Europe/Zurich /etc/localtime && \
    dpkg-reconfigure --frontend noninteractive tzdata


1.2(optional) If you are using wkhtmltopdf, you will need to manually install libssl1.1 in the docker file before wkhtmltopdf is installed. Reason: libssl1.1 is no longer included in Ubuntu 22.04. Add:
# Manually install libssl1.1
RUN wget http://archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.0g-2ubuntu4_amd64.deb
RUN dpkg -i libssl1.1_1.1.0g-2ubuntu4_amd64.deb

2. Expose the websocket port in the dockerfile (Dockerfile.nginx), it should be added before the services start, example:
EXPOSE 8090
CMD service php8.1-fpm start && service ssh start && nginx


3. Add new websocket port (8090) to nginx webserver in Dockerfile (docker-compose.yml), example:
  nginx:
    image: webserver
    build:
      dockerfile: Dockerfile.nginx
    ports:
      - "46301:46301"
      - "51301:51301"
      - "44909:22"
      - "8090:8090"         <------ Websocket port

4. nginx config file adjustments, add following proxy:
   location /ws {
        proxy_pass http://mydomain:8090;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
    }

5. Start/Restart (Build first time) the docker container.

6. Set the configured websocket port and websocket url in QFQ Config, examples:
websocketPort: 8090
websocketUrl: ws://mydomain:46301/ws

7. If websocketPort is set in qfq config, the websocket server should start automatically the first time a web page with qfq content is loaded.

If you are upgrading the qfq extension (new with FE Chat) in an already existing project, then you need to add the new enum value chat to the column type from the FormElement table.

Configuration

qfq.project.path.php

The file qfq.project.path.php provides the path to the qfqProject directory.

  • The qfqProject directory contains the qfq configuration file (see qfq.json) as well as forms and reports which are saved as files. See Form As File and Report As File.

  • The file qfq.project.path.php is located/created in the root directory of the application. (Where index.php is located)

  • This file only returns the path to the qfq project directory where logs, config (qfq.json), report files and form files are located.

  • If the file does not exist, it is created and the project path is set as follows:

    • Does the deprecated config file typo3conf/config.qfq.php exist? Then set the qfq project path to fileadmin/protected/qfqProject (config is migrated automatically to qfqProject).

    • If not, does fileadmin/protected exist? Then set the qfq project path to fileadmin/protected/qfqProject.

    • If not, then set qfq project path to ../ (i.e. outside the app directory where index.php is located)

Example: typo3conf/config.qfq.php:

<?php

/**
QFQ project path configuration
!! ATTENTION !!: The files in the project directory should NOT be served by your http server!
Only exception: The app directory inside the project directory may be served.
*/

return 'fileadmin/protected/qfqProject'; // path relative to app directory (i.e. location of this file).

qfq.json

  • Additionally to the keywords bellow one can also override the configuration values defined in the Typo3 extension manager: Extension Manager: QFQ Configuration

    • e.g. if qfq.json contains “flagProduction”:”no” then this value is taken instead of the one set in the extension manager.

Keyword

Example

Description

DB_<n>_USER

“DB_1_USER”=”qfqUser”

Credentials configured in MySQL

DB_<n>_PASSWORD

“DB_1_PASSWORD”=”1234567890”

Credentials configured in MySQL

DB_<n>_SERVER

“DB_1_SERVER”=”localhost”

Hostname of MySQL Server

DB_<n>_NAME

“DB_1_NAME”=”qfq_db”

Database name

LDAP_1_RDN LDAP_1_PASSWORD

“LDAP_1_RDN”=”ou=Admin,ou=example,dc=com ” “LDAP_1_PASSWORD”=”mySecurePassword”

Credentials for non-anonymous LDAP access. Only one set supported.

PASSWORD_HASH_TYPE

“PASSWORD_HASH_TYPE”=”PASSWORD_BCRYPT”

Password hashing algorithm used for “p” action class. See: Escape/Action class Possible values: “PASSWORD_ARGON2I” (QFQ default), “PASSWORD_BCRYPT”, “PASSWORD_DEFAULT” (PHP default)

ENCRYPTION_KEY

“ENCRYPTION_KEY”=”myTestKey”

Key for encryption and decryption of data.

Example: fileadmin/protected/qfqProject/qfq.json:

{
  "DB_1_USER": "<DBUSER>",
  "DB_1_SERVER": "<DBSERVER>",
  "DB_1_PASSWORD": "<DBPW>",
  "DB_1_NAME": "<DB>",

  "DB_2_USER": "<OPTIONAL DBUSER>",
  "DB_2_SERVER": "<OPTIONAL DBSERVER>",
  "DB_2_PASSWORD": "<OPTIONAL DBPW>",
  "DB_2_NAME": "<OPTIONAL DB>",

  "LDAP_1_RDN": "<OPTIONAL> ou=Admin,ou=example,dc=com",
  "LDAP_1_PASSWORD": "<OPTIONAL> mySecurePassword",

  "ENCRYPTION_KEY": "<SECRET KEY>"
}

config.qfq.php

DEPRECATED : use qfq.json as described above.

Extension Manager: QFQ Configuration

  • These configuration values can be overwritten by qfq.json

Keyword

Default / Example

Description

Config

flagProduction

yes

yes|no: used to differentiate production and development site.

render

single

both|single: QFQ will show form and/or report. In most cases only one at a time is needed. Options: ‘single’ (default) or ‘both’ (legacy). In mode ‘single’ prefer ‘form’ over ‘report’.

baseUrl

http://example.com or multiple like ‘http://localhost, https://proxy.example.com,http://example.com

URL where wkhtmltopdf will fetch the HTML (no parameter, those comes later)

dateFormat

yyyy-mm-dd

Possible options: yyyy-mm-dd, dd.mm.yyyy.

editInlineReports

checked/unchecked

Shows an edit symbol in the frontend to directly edit a QFQ Report record.

reportAsFileAutoExport

no

Auto export of qfq reports to files. See Report As File

websocketPort

empty

If not empty: Websocket server starts automatically with given port. Empty: Websocket server shuts down if it’s running. See WebSocket

websocketUrl

empty

Websocket url for client communication with server. See WebSocket

Graphics

cmdInkscape

inkscape

If inkscape is not available, specify an empty string.

cmdConvert

convert

Image-/GraphicsMagics ‘convert’ is recommended.

cmdPdf2svg

pdf2svg

Convert PDF to SVG.

cmdPdftocairo

pdftocairo

Poppler based.

cmdWkhtmltopdf

/usr/bin/wkhtmltopdf

PathFilename of wkhtmltopdf. Optional variables like LD_LIBRARY_PATH=…

cmdQpdf

qpdf

PathFilename of qpdf. Optional variables like LD_LIBRARY_PATH=…

cmdGs

gs

PathFilename of gs. Optional variables like LD_LIBRARY_PATH=…

cmdPdfunite

pdfunite

PathFilename of pdfunite. Optional variables like LD_LIBRARY_PATH=…

cmdImg2pdf

img2pdf

PathFilename of img2pdf. Optional variables like LD_LIBRARY_PATH=…

cmdHeifConvert

heif-convert

PathFilename of heif-convert. Optional variables like LD_LIBRARY_PATH=… . During upload, HEIF/HEIC images will be silently converted to PNG. To disable the conversion, leave the field blank.

cmdPdf2ps

pdf2ps

Will be used to convert images from PDF to PS.

cmdPs2pdf

ps2pdf

Will be used to convert images from PS to PDF.

Debug

throwExceptionGeneralError

auto

yes: ‘general errors’ in QFQ (PHP) will throw an exception.
auto: becomes ‘yes’, if ‘flagProduction’!=’yes’, else ‘no’.
no: ‘general errors’ in QFQ (PHP) will be silently ignored.

formSubmitLogMode

all

all: every form submission will be logged.
none: no logging.
modify: prevent logging tables: FormSubmitLog and Dirty.
See Form Submit Log page for example QFQ code to display the log.

redirectAllMailTo

john@doe.com

If set, redirect all QFQ generated mails (Form, Report) to the specified.

sqlLogMode

modify

all: every statement will be logged - this might be a lot.
modifyAll: log all statements which might change data, even if 0 rows
affected.
modify: log only statements which change data (affected rows > 0).
error: log only DB errors.
none: no SQL log at all.

sqlLogModeAutoCron

error

Applies only to AutoCron Jobs. For production ‘error’ should be fine.

sqlLog

fileadmin/protected/qfqProject/log/sql.log

Filename to log SQL commands: relative to <site path> or absolute. If the directory does not exist, create it.

qfqLog

fileadmin/protected/qfqProject/log/qfq.log

Filename to log general QFQ events:relative to <site path> or absolute. If the directory does not exist, create it.

mailLog

fileadmin/protected/qfqProject/log/mail.log

Filename to log sendEmail commands: relative to <site path> or absolute. If the directory does not exist, create it.

showDebugInfo

auto

FE - Possible values: yes|no|auto|download. For ‘auto’: If a BE User is logged in, a debug information will be shown on the FE.

reportMinPhpVersion

auto

Possible values: yes|no|auto. For ‘auto’: If a BE User is logged in, it becomes ‘yes’. If installed PHP version is too low, report and stop QFQ.

Database

init

init=SET names utf8; SET sql_mode = “NO_ENGINE_SUBSTITUTION”

Global init for using the database. For ‘sql_mode=”NO_ENGINE_SUBSTITUTION”’ see #7407.

update

auto

General: QFQ will only do a DB update during an active T3 BE User session
auto: apply DB Updates only if there is a newer version.
always: apply DB Updates always, time QFQ is called - not recommended!
never: never apply DB Updates.

indexData

1

Optional. Default: 1. Retrieve the current setting via {{dbNameData:Y}}.

indexQfq

1

Optional. Default: 1. Retrieve the current setting via {{dbNameQfq:Y}}.

Security

sessionTimeoutSeconds

empty

Default is empty to take the php.ini system value (minimum of ‘session.cookie_lifetime’ and ‘session.gc_maxlifetime’).

escapeTypeDefault

m

All variables {{…}} get this escape class by default. See Escape/Action class.

securityVarsHoneypot

email,username,password

If empty: no check. All named variables will rendered as INPUT elements.

securityAttackDelay

5

If an attack is detected: a) clear SIP Store b) wait number of seconds, c) quit PHP process. -1: Switch off attack detection.

securityShowMessage

on/off

on: If an attack is detected, show a message.

securityGetMaxLength

50

GET vars longer than ‘x’ chars triggers an attack-recognized. Exception for SECURITY_GET_MAX_LENGTH.

securityFailedAuthDelay

3

If REST authorization fails, sleep ‘x’ seconds before answering.

encryptionMethod

AES-128

Options: ‘AES-128’ (default) or ‘AES-256’. Invalid option will be shown on page.

protectedFolderCheck

on/off

on (default): check if fileadmin/protected is really protected.

Form-Config

recordLockTimeoutSeconds

900

Timeout for record locking. After this time, a record will be replaced.

enterAsSubmit

enterAsSubmit = 1

0: off, 1: Pressing enter in a form means save and close.

editFormPage

form

T3 page slug to edit a form.

dateTimePickerType

qfq

Type of date-time-picker in form. Options: ‘no’, ‘browser’, ‘qfq’

formDataPatternError

please check pattern error

Customizable error message used in validator.js. ‘pattern’ violation.

formDataRequiredError

missing value

Customizable error message used in validator.js. ‘required’ fields.

formDataMatchError

type error

Customizable error message used in validator.js. ‘match’ retype mismatch.

formDataError

generic error

Customizable error message used in validator.js. ‘no specific’ given.

showIdInFormTitle

0 (off), 1 (on)

Append at the form title the current record id.

cssClassColumnId

text-muted

A column in a subrecord with the name id|ID|Id gets this class.

clearMe

0 (off), 1 (on)

Default to show a small ‘x’ in every input or textarea to clear field.

rememberLastPill

0 (off), 1 (on)

On form load, bring last used pill to front. Default is on.

doNotLogColumn

password

Do not log named FE-Elements during form save in table FormSubmitLog. Default: password

Form-Layout

labelAlign

left

Label align (left/center/right)/ Default: left. Will be inherited to Form.

cssClassQfqContainer

container

QFQ with own Bootstrap: ‘container’.
QFQ already nested in Bootstrap of mainpage: <empty>.

cssClassQfqForm

qfq-color-base

Wrap around QFQ ‘Form’.

cssClassQfqFormPill

qfq-color-grey-1

Wrap around title bar for pills: CSS Class, typically a background color.

cssClassQfqFormBody

qfq-color-grey-2

Wrap around FormElements: CSS Class, typically a background color.

formBsColumns

col-md-12 col-lg-10

The whole form will be wrapped. See Custom field width

formBsLabelColumns

col-md-3 col-lg-3

The column get the width. See Custom field width

formBsInputColumns

col-md-6 col-lg-6

formBsNoteColumns

col-md-3 col-lg-3

extraButtonInfoInline

<img src=”info.png”>

Image for extraButtonInfo (inline).

extraButtonInfoBelow

<img src=”info.png”>

Image for extraButtonInfo (below).

extraButtonInfoPosition

below

‘auto’ (default) or ‘below’. See extraButtonInfo.

extraButtonInfoClass

pull-right

‘’ (default) or ‘pull-right’. See extraButtonInfo.

fieldsetClass

qfq-fieldset

Alternative: qfq-fieldset-borderless

Form-Language

formLanguage[ABCD]Id

E.g.: 1

In Typo3 configured pageLanguage id. The number after the ‘L’ parameter.

formLanguage[ABCD]Label

E.G.: english

Label shown in Form editor, on the ‘basic’ tab.

Form-Button

saveButtonText

Text on the form save button. Typically none.

saveButtonTooltip

Save

Tooltip on the form save button.

saveButtonClass

btn btn-default navbar-btn

Bootstrap CSS class for save button on top of the form.

buttonOnChangeClass

alert-info btn-info

Bootstrap CSS class for save button showing ‘data changed’.

saveButtonGlyphIcon

glyphicon-ok

Icon for the form save button.

closeButtonText

Text on the form close button. Typically none.

closeButtonTooltip

close

Tooltip on the form close button.

closeButtonClass

btn btn-default navbar-btn

Bootstrap CSS class for close button on top of the form.

closeButtonGlyphIcon

glyphicon-remove

Icon for the form close button.

deleteButtonText

Text on the form delete button. Typically none.

deleteButtonTooltip

delete

Tooltip on the form delete button.

deleteButtonClass

btn btn-default navbar-btn

Bootstrap CSS class for delete button on top of the form.

deleteButtonGlyphIcon

glyphicon-trash

Icon for the form delete button.

newButtonText

Text on the form new button. Typically none.

newButtonTooltip

new

Tooltip on the form new button.

newButtonClass

btn btn-default navbar-btn

Bootstrap CSS class for new button on top of the form.

newButtonGlyphIcon

glyphicon-plus

Icon for the form new button.

Custom

custom1…30

Empty. Example: PHONE=6355847

Custom Variable

Dynamic

fillStoreSystemBySqlRow

SELECT gr.reference AS name, gr.id AS value FROM

Ggroup AS gr WHERE gr.loadConfig=’yes’

Specific values read from the database to fill STORE_SYSTEM. Fired at the beginning of loading STORE_SYSTEM. No support of QFQ-Variables. See Fill STORE SYSTEM by Sql Row for a usecase.

fillStoreSystemBySqlRowErrorMsg

No record found

Only define an error message, if QFQ should stop running in case of an SQL error or not at least one record.

fillStoreSystemBySqlRowVariable

SELECT ‘pIdUser’ AS name, p.id AS value

FROM Person AS p WHERE p.account = ‘{{feUser:T}}’

Specific values read from the database to fill STORE_SYSTEM. Fired at the end of loading STORE_SYSTEM. Supports QFQ-Variables from STORE_SYSTEM. See Fill STORE SYSTEM by Sql Row for a usecase.

fillStoreSystemBySqlRowVariable- ErrorMsg

No record found

Only define an error message, if QFQ should stop running in case of an SQL error or not at least one record.

fillStoreSystemBySql1/2/3

SELECT s.id AS …

Specific values read from the database to fill the system store during QFQ load. See Fill STORE_SYSTEM by SQL for a usecase.

fillStoreSystemBySqlErrorMsg1/2/3

No current period found

Only define an error message, if QFQ should stop running in case of an SQL error or not exact one record.

File

cacheDirSecure

fileadmin/protected/cache

Important: secure the directory (recursive) against direct access.

cachePurgeFilesOlderDays

365

Purge files in $cacheDirSecure older than $cachePurgeFilesOlderDays.

maxFileSize

10M

If empty, take minimum of ‘post_max_size’ and ‘upload_max_filesize’.

imageUploadDir

fileadmin/imageUploadDir

Used for TinyMCE Image Upload.

thumbnailDirSecure

fileadmin/protected/qfqThumbnail

Important: secure the directory (recursive) against direct access. Used by special columnname ‘_thumbnail’.

thumbnailDirPublic

typo3temp/qfqThumbnail

Will be used by a special columnname ‘_thumbnail’.

sqlDirectdownloadphp/dl…dl3

no default

Access via download.php. Example: SELECT CONCAT(‘d:output.pdf|F:’, n.pathFileName) FROM notiz AS n WHERE n.id=? AND NOW()<n.expire

sqlDirectdownloadphperror/dl…3

no default

Message shown to the user if record isn’t found.

Tools

forceSmtpSender

<empty>

Set this ONLY if your SMTP needs a static ‘from’ address (weired setup). ‘reply-to’ will be used to offer simple ‘Reply’ functionality to user. To hide static ‘from’ address to the reciever, a realname is set for the ‘from’ address. Take realname from ‘Reply-To’, ‘From’, ‘forceSmtpSender’ or misuse the ‘From’ email as realname (take first in the named priority).

sendEMailOptions

-o tls=yes

General options. Check: http://caspian.dotconf.net/menu/Software/SendEmail

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’

After parsing the configuration, the following variables will be set automatically in STORE_SYSTEM:

Keyword

Description

dbNameData

Name of the ‘data’-database. ‘{{dbNameData:Y}}

dbNameQfq

Name of the ‘QFQ’-database. ‘{{dbNameQfq:Y}}

dbNameT3

Name of the ‘T3’-database. ‘{{dbNameT3:Y}}

sitePath

Absolute path of the current T3 instance. ‘{{sitePath:Y}}

extPath

Absolute path of the QFQ extension. ‘{{extPath:Y}}

Custom variables

Up to 30 custom variables can be defined in Configuration.

E.g. to setup a contact address and reuse the information inside your installation do:

custom1: ADMINISTRATIVE_CONTACT = john@doe.com
custom2: ADMINISTRATIVE_ADDRESS = John Doe, Hollywood Blvd. 1, L.A.
custom3: ADMINISTRATIVE_NAME = John Doe
  • Somewhere in a Form or in Report:

    {{ADMINISTRATIVE_CONTACT:Y}}, {{ADMINISTRATIVE_ADDRESS:Y}}, {{ADMINISTRATIVE_NAME}}
    

Change your custom variables in the T3 Extension Configuration window under Custom.

Fill STORE_SYSTEM by SQL

A specified SELECT statement in Configuration in variable fillStoreSystemBySql1 (or 2, or 3) will be fired. The query should have 0 (nothing happens) or 1 row. All columns will be added to the existing STORE_SYSTEM. Existing variables will be overwritten. Be careful not to overwrite system values.

This option is useful to make generic custom values, saved in the database, accessible to all QFQ Report and Forms. Access such variables via {{<varname>:Y}}.

In case QFQ should stop working if a given query does not select exact one record (e.g. a missing period), define an error message:

fillStoreSystemBySql1: SELECT name FROM Person WHERE name='Doe'
fillStoreSystemBySqlErrorMsg1: Too many or to few "Doe's" in our database

periodId

This is

  • a usecase, implemented via Fill STORE_SYSTEM by SQL,

  • a way to access Period.id with respect to the current period (the period itself is custom defined).

After a full QFQ installation:

  • a table Period (extend / change it to your needs, fill them with your periods),

  • one sample record in table Period,

Websites, delivering semester data, school year schedules, or any other type or periods, often need an index to the current period.

In Configuration:

fillStoreSystemBySql1: SELECT id AS periodId FROM Period WHERE start<=NOW() ORDER BY start DESC LIMIT 1

a variable ‘periodId’ will automatically computed and filled in STORE SYSTEM. Access it via {{periodId:Y0}}. To get the name and current period:

SELECT name, ' / ', start FROM Period WHERE id={{periodId:Y0}}

Typically, it’s necessary to offer a ‘previous’ / ‘next’ link. In this example, the STORE SIP holds the new periodId:

SELECT CONCAT('p:{{pageSlug:T}}?periodId=', {{periodId:SY0}}-1, '|Next') AS _page, ' ', name, ' ',
  CONCAT('p:{{pageSlug:T}}?periodId=', {{periodId:SY0}}+1, '|Next') AS _page FROM Period AS s WHERE s.id={{periodId:SY0}}

Take care for minimum and maximum indexes (do not render the links if out of range).

Fill STORE SYSTEM by Sql Row

Similar to the fillStoreSystemBySql1/2/3 a specified SELECT statement in Configuration in variable fillStoreSystemBySqlRow will be fired. This option gives the opportunity to define a key name and assigning a value to that key for multiple rows. It makes UNION usable too. The ‘fillStoreSystemBySqlRowVariable’ is like fillStoreSystemBySqlRow but it can parse variables from T|S|Y|C Store.

Best practice is to create a new column ‘storeSystem’ for the specific table from which the query is executed. A type ENUM with yes and no could then be used to filter the desired values.

Exactly two columns are expected as aliases: name, value Example:

fillStoreSystemBySqlRow: SELECT gr.reference AS name, IF('{{pageLanguage:T}}'=0 OR gr.value2='', gr.value, gr.value2) AS value FROM Ggroup AS gr WHERE gr.storeSystem='yes'

To retrieve the value, name is used as variable name. For example if the column reference from one record is named ‘id_accepted’ and related column value has the value ‘22’:

{{id_accepted:Y}}

This returns the value ‘22’.

Giving more or less than two columns will lead to an error. Also not allowed are the use of other aliases than ‘name’ and ‘value’. In case QFQ should stop working if a given query does not select at least one record or more, define an error message:

fillStoreSystemBySqlRowErrorMsg: No rows found with given query.

Best practice is to make a Person table with column account and then use the typo3 store variable ‘{{feUser:T}}’ to get the person id. Example:

fillStoreSystemBySqlRowVariable: SELECT 'pIdUser' AS name, p.id AS value FROM Person AS p.account = '{{feUser:T}}'

To retrieve the person id use {{pIdUser:Y}}.

In case QFQ should stop working if a given query does not select at least one record or more, define an error message:

fillStoreSystemBySqlRowVariableErrorMsg: No rows found with given query.

DB USER privileges

The specified DB User needs privileges

  • to the QFQ database of at least: SELECT / INSERT / UPDATE / DELETE / SHOW.

  • to the Typo3 database of at least table tt_content with SELECT.

To apply automatically QFQ-‘DB UPDATE’ the following rights are mandatory too: CREATE / ALTER

To get access to the Typo3 installation, ‘dbuser’ should also have access to the Typo3 Database with at least SELECT / INSERT / UPDATE / DELETE.

Exception for SECURITY_GET_MAX_LENGTH

If it is necessary to use a GET variable which exceeds securityGetMaxLength limit, name the variable with ‘_<num>’ at the end. E.g. my_long_variable_130. Such a variable has an allowed length of 130 chars. Access the variable as usual with the variable name: {{my_long_variable_130:C:…}}.

FE-User: Session timeout seconds

There is no timeout for website users who are not logged in (but typically those users don’t have access to protected content).

For logged in users, the default timeout is the php.ini settings for session.cookie_lifetime and session.gc_maxlifetime (minimum of both). These timeout only affects QFQ related content and can be specified a) globally (QFQ configuration) and b) specific per Form.

The maximum timeout depends on the minimal value of php.ini session.cookie_lifetime and session.gc_maxlifetime. Specifying a higher value produces an error in the front end.

Every access to QFQ related content resets the timeout.

After FE login, the next access to QFQ related content starts the timeout counter.

Cron Job: Remove Form Backup Files

The following cron job may be used to automatically remove form backup files (see Form As File) which are older than 31 days. Be sure to adjust the path accordingly:

0 19 * * * find /var/www/html/fileadmin/protected/qfqProject/form/.backup/ -type f -mtime +31  -exec rm {} \;