diff --git a/.gitignore b/.gitignore
index 702495ab8b7d5cd2604e049f548d36ba84a28b5b..1503198894a2228e7b286b043815772d560cb92d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,7 +6,6 @@
 /.plantuml
 /doc/plantuml
 /extension/Documentation/_make/build
-/qfq.ini
 /doc/phpdoc
 /.idea
 /node_modules
@@ -20,7 +19,7 @@
 /css
 /fonts
 /qfq.flowchart.dia.autosave
-/extension/config.ini
+/qfq*.zip
 /support
 /extension/Resources/Public/fonts
 /extension/Resources/Public/JavaScript
diff --git a/Makefile b/Makefile
index c6ed615c18c0549bc96b695d38b5ac308d141073..a3fd4e6215d69fcd38815f00a82f408c40abbdc1 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ PHPDOC ?= support/pear/phpdoc
 JSDOC ?= jsdoc
 PKG_VERSION = $(shell awk '/version/ { print $$3 }' extension/ext_emconf.php  | sed "s/'//g")
 NIGHTLY_DATE = $(shell date '+%Y%m%d')
-EXTENSION_CONTENT = Classes Configuration Documentation qfq Resources ext_emconf.php ext_localconf.php ext_tables.php config.example.ini
+EXTENSION_CONTENT = Classes Configuration Documentation qfq Resources ext_emconf.php ext_localconf.php ext_tables.php ext_icon.png config.example.ini
 
 all: archive t3sphinx
 
@@ -12,10 +12,10 @@ maintainer-clean:
 	rm -f .bowerpackages .doc_plantuml .npmpackages .phpdocinstall .plantuml_install .support .support_plantuml
 	rm -rf doc support
 
-archive: clean qfq_$(PKG_VERSION).zip
+archive: clean qfq.zip
 
-qfq_$(PKG_VERSION).zip:  
-	cd extension; zip -r ../$@ $(EXTENSION_CONTENT) -x config.ini
+qfq.zip:
+	cd extension; zip -r ../$@ $(EXTENSION_CONTENT)
 
 clean:
 	rm -f qfq_$(PKG_VERSION).zip
diff --git a/doc/CODING.md b/doc/CODING.md
index 6724b2e642ed09385792398d5171fb2c39a72866..620d93aa851d466a799acc5c64aed95998096b7d 100644
--- a/doc/CODING.md
+++ b/doc/CODING.md
@@ -23,7 +23,7 @@ LOAD
 * When qfq starts, 
   * (Form) Looking for a formname at: 
     1. Typo3 Bodytext Element,
-    2. For the 'SIP' ($_GET['s'])
+    2. For the 'SIP' ($_GET['s'] => $S_SESSION['qfq'][$_GET['s']]="form=person&r=123")
     3. $_GET variables 'form' and 'r' (=recordId) - the parameter 'form' has to be allowed in 'Permit URL Parameter' of 
        the specified form. This means: load the form to check, if it is allowed to load the form!?
     * If a formname is found, the search stops and the specified form will be processed.
@@ -36,12 +36,20 @@ LOAD
   * All parameters from active SIP:  [$this->store->getStore(STORE_SIP)]
   * Check Contstants.php for known Store members
   
-* In QuickFormQuery.php the whole Form will be copied to $this->formSpec and depending on further processing, the elements are
-available in $this->feNative and $this->feAction.
+* In QuickFormQuery.php the whole Form will be copied to `$this->formSpec` and depending on further processing, the 
+  elements are available in `$this->feNative` and `$this->feAction`.
   * The Form specificaton (table form) will be evaluated direct after loading.
   * The FormElement specification will be evaluated later on in BuildForm*.php
 
-
+* If a form is called without a SIP (form.permitNew='always'), than a SIP is created on the fly (as a 
+  parameter in the form).
+* Depending on `r=0` or `r>0` a form submit will do an MySQL `insert` or `update` later during save.
+* For new records (r=0), clicking on 'save' without closing the form is a tricky situation. Additionally the user might have open multiple
+  tabs (same form, all r=0) and after saving the record (wihtout closing the form) the user expects that it's ok to edit 
+  the record again and again. Unfortunately, the initial created SIP (before 'form load') is not uniqe anymore (multiple 
+  tabs might  contain a saved 'new record'). To guarantee correct saving of r=0 records, a unique on the fly generated SIP 
+  is creatd during form load - individually per browser tab.  
+   
 SAVE
 ----
 * Via wrapper api/save.php
@@ -51,6 +59,18 @@ SAVE
   * Client will handle the response of save.php.
   * Optional redirection initiated by client.
   
+New records
+...........
+* r=0 (missing 'r' means r=0)
+* After saving the SIP content will be updated with the new record. 
+  Remember that the SIP in the URL is *not* the SIP used in the form to identify the form/record. The form use a 
+  individual 'new record' SIP.
+
+Existing records
+................
+* r>0 ('r' have to exist)
+
+  
 DELETE
 ------
 * Via wrapper api/delete.php
@@ -226,8 +246,8 @@ SIP
 ===
 Page loaded: www.example.com?index.php&id=start&s=badcaffee1234&type=2&L=3, with $_SESSION['badcaffee1234'] => 'form=Person&r=1'
 
-* $_SESSION[$sip] => <urlparam>  >> $_SESSION['badcaffee1234'] => 'form=Person&r=1'
-* $_SESSION[$urlparam] => <sip>  >> $_SESSION['form=Person&r=1'] => 'badcaffee1234'
+* $_SESSION['qfq'][$sip] => <urlparam>  >> $_SESSION['qfq']['badcaffee1234'] => 'form=Person&r=1'
+* $_SESSION['qfq'][$urlparam] => <sip>  >> $_SESSION['qfq']['form=Person&r=1'] => 'badcaffee1234'
 
 
 FormElement
diff --git a/doc/NewVersion.md b/doc/NewVersion.md
index 12207fd70cc4823df5d12a473d84239b19ecef6f..80f117d057cd77bae06b6126dc3c259232a5dfda 100644
--- a/doc/NewVersion.md
+++ b/doc/NewVersion.md
@@ -10,13 +10,16 @@ Neue Versionsnummer
 2) Im Projectverzeichnis:
   make t3sphinx   (nicht sicher ob das noetig ist)
   
-3) Neuen Tag vergeben: git tag v0.5  
+3) Merge auf master Branch
+  
+4) Neuen Tag vergeben: git tag 0.8
 
-4) Alle Files, inkl. Tags, in GIT einchecken.
+5) Alle Files, inkl. Tags, in GIT einchecken.
 
-5) Per PhpStorm Sync aller Files auf VM qfq
+6) Per PhpStorm Sync aller Files auf VM qfq
 
-6) In T3 Instanz Dokumentation rendern lassen.
+7) In T3 Instanz Dokumentation rendern lassen.
   
  T3 6.2:  Admin Tools > Extension Manager > QFQ > Doku HTML: rechts oben 'Render Documentation'
   
+Note
\ No newline at end of file
diff --git a/extension/Classes/Controller/QfqController.php b/extension/Classes/Controller/QfqController.php
index 82463dc7113b5543e211faa3fbdb7a5543d3a525..2601a46e3389e1452000823040c945c4b786495c 100644
--- a/extension/Classes/Controller/QfqController.php
+++ b/extension/Classes/Controller/QfqController.php
@@ -17,6 +17,8 @@ class QfqController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController {
 
     public function showAction() {
 
+        $origErrorReporting = '';
+
         try {
             $contentObject = $this->configurationManager->getContentObject();
 
diff --git a/extension/Configuration/PageTSconfig/PageTSconfig.ts b/extension/Configuration/PageTSconfig/PageTSconfig.ts
index 2383aefc58f91b9aa2a17d9f042b67ffbb400d83..9da2d2f6b7777844aa4a84094e499927c637d534 100644
--- a/extension/Configuration/PageTSconfig/PageTSconfig.ts
+++ b/extension/Configuration/PageTSconfig/PageTSconfig.ts
@@ -4,27 +4,26 @@ mod.wizards.newContentElement
     {
         special.elements
         {
-            sampleextension_element
+            qfq_element
             {
                 icon = icon
                 goes
                 here
-                title = Sample
+                title = QFQ Content Element
                 Content
                 Element
-                description = More
+                description = Quick Form Query (QFQ) offers a Form Editor and a SQL based Report Language.
                 info
                 goes
                 here
                 tt_content_defValues
                 {
-                    CType = sampleextension_samplepluginname
+                    CType = qfq_qfq
                 }
             }
         }
         special.show
     :
-        = addToList(sampleextension_element)
+        = addToList(qfq_element)
     }
 }
-
diff --git a/extension/Documentation/AdministratorManual/Index.rst b/extension/Documentation/AdministratorManual/Index.rst
index 26927c868ad55d8cfd86f8aa63c376c383dac8e2..48d3237012ca49c63882b70dd0f967d9875cc55f 100644
--- a/extension/Documentation/AdministratorManual/Index.rst
+++ b/extension/Documentation/AdministratorManual/Index.rst
@@ -20,19 +20,30 @@ native driver (see also: http://dev.mysql.com/downloads/connector/php-mysqlnd/):
 * mysqli::get_result (important),
 * mysqli::fetch_all (nice to use)
 
-Installation for Ubuntu::
+Preparation for Ubuntu 14.04::
 
 	sudo apt-get install php5-mysqlnd
 	sudo php5enmod mysqlnd
 	sudo service apache2 restart
 
+Preparation steps for Ubuntu 16.04::
+
+	none
+
 Setup
 -----
 
 * Install the extension via the Extensionmanager.
-* Rename the file *<ext_dir>/config.example.ini* to *<ext_dir>/config.ini* and configure the necessary values: `<ext_dir>/config.ini`_
+
+  * 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`.
+
+  * If the Extensionmanager stops after importing: check your memory limit in php.ini.
+
+* Enable the online Documentation_.
+* Copy/rename the file *<ext_dir>/config.example.qfq.ini* to *typo3conf/config.qfq.ini* and configure the necessary values: `config.qfq.ini`_
 * Play the SQL File *<ext_dir>/qfq/sql/formEditor.sql* to fill the database with the *FormEditor* records.
-* Configure Typoscript to include Bootstrap, jQuery and QFQ javascript and CSS files.
+* Configure Typoscript to include Bootstrap, jQuery, QFQ javascript and CSS files.
 
 ::
 
@@ -62,9 +73,9 @@ Setup a *report* to manage all *forms*: Create a Typo3 page and insert a content
 
 ::
 
-  form = {{form}}
+  form = {{form:T}}
   10 {
-    sql = SELECT CONCAT('{{pageId}}&form=Form&r=', f.id) as Pagee, f.id, f.name, f.title, f.tableName FROM FormEditor As f ORDER BY f.name
+    sql = SELECT CONCAT('{{pageId}}&form=Form&r=', f.id) as Pagee, f.id, f.name, f.title, f.tableName FROM Form AS f ORDER BY f.name
     head = <br><table class="table">
     tail = </table>
     rbeg = <tr class="table-hover">
@@ -73,8 +84,9 @@ Setup a *report* to manage all *forms*: Create a Typo3 page and insert a content
     fend = </td>
   }
 
-<ext_dir>/config.ini
---------------------
+
+config.qfq.ini
+--------------
 
 +------------------------+----------------------------------+----------------------------------------------------------------------------+
 | Keyword                | Example                          | Description                                                                |
@@ -106,7 +118,7 @@ Setup a *report* to manage all *forms*: Create a Typo3 page and insert a content
 | DATE_FORMAT            | DATE_FORMAT= yyyy-mm-dd          | Possible options: yyyy-mm-dd, dd.mm.yyyy                                   |
 +------------------------+----------------------------------+----------------------------------------------------------------------------+
 
-Example: *<ext_dir>/config.ini*
+Example: *typo3conf/config.qfq.ini*
 
 ::
 
@@ -119,4 +131,24 @@ Example: *<ext_dir>/config.ini*
 	SQL_LOG = sql.log
 	SHOW_DEBUG_INFO = auto
 	CSS_LINK_CLASS_INTERNAL = internal
-	CSS_LINK_CLASS_EXT = external
\ No newline at end of file
+	CSS_LINK_CLASS_EXT = external
+
+Documentation
+-------------
+
+To render the QFQ reST documentation:
+
+* Take care to have 'unzip' and 'Python setuptools' installed (necessary to run ).
+
+Preparation for Ubuntu 16.04::
+
+	sudo apt install unzip python-setuptools
+
+* Install the extension "Sphinx Python Documentation Generator and Viewer" (sphinx).
+
+  * Execute the update script (symbol 'two arrows as a circle' behind the extension name)
+  * Choose 'Sphinx 1.4.4' - click on 'Import'.
+
+* In the Exension Manager open the configuration dialog of the extension 'sphinx'. Activate the 'Sphinx 1.4.4' option and save it.
+* On top of the browser window click on the 'question mark' to open the menu, choose 'Sphinx'.
+* Show doumentation 'QFQ Extension'
diff --git a/extension/Documentation/Settings.yml b/extension/Documentation/Settings.yml
index 8d6f6a839a8430c75424a81867d659546936779c..0033e03ae500b91de02807b884c63bb1ab5a6ef3 100644
--- a/extension/Documentation/Settings.yml
+++ b/extension/Documentation/Settings.yml
@@ -4,10 +4,10 @@
 
 ---
 conf.py:
-  copyright: 2016
+  copyright: 2017
   project: QFQ Extension
-  version: 0.5
-  release: 0.5.0
+  version: 0.8
+  release: 0.8.0
   latex_documents:
   - - Index
     - qfq.tex
diff --git a/extension/Documentation/UsersManual/Index.rst b/extension/Documentation/UsersManual/Index.rst
index 8fda8c73999e82a20fdd3358fd3ed33653e3c2da..c8251e0e043926b3923e6a9382e74f8a28cf5c30 100644
--- a/extension/Documentation/UsersManual/Index.rst
+++ b/extension/Documentation/UsersManual/Index.rst
@@ -191,14 +191,26 @@ Sanitize class
   the default class is 'digit'.
 * A default sanitize class can be overwritten by individual definition: *{{a:C:all}}*
 
-  * **alnumx**: [A-Za-z][0-9]@-_.,;: /()
-  * **digit**: [0-9].-+
-  * **email**: [a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}
-  * **min|max**: only usable in forms. Compares the value against an lower and upper limit (numeric or string).
-  * **min|max date**:  only usable in forms. Compares the value against an lower and upper date or datetime.
-  * **pattern**:  only usable in forms. Compares the value against a regexp.
-  * **allbut**: all characters allowed, but not [ ]  { } % & \ #. The used regexp: '^[^\[\]{}%&\\#]+$',
-  * **all**: no sanitizing
++------------------+------+-------+-----------------------------------------------------------------------------------------+
+| Name             | Form | Query | Pattern                                                                                 |
++==================+======+=======+=========================================================================================+
+| **alnumx**       | Form | Query | [A-Za-z][0-9]@-_.,;: /()                                                                |
++------------------+------+-------+-----------------------------------------------------------------------------------------+
+| **digit**        | Form | Query | [0-9].-+                                                                                |
++------------------+------+-------+-----------------------------------------------------------------------------------------+
+| **email**        | Form | Query | [a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}                                          |
++------------------+------+-------+-----------------------------------------------------------------------------------------+
+| **min|max**      | Form |       | Compares the value against an lower and upper limit (numeric or string).                |
++------------------+------+-------+-----------------------------------------------------------------------------------------+
+| **min|max date** | Form |       | Compares the value against an lower and upper date or datetime.                         |
++------------------+------+-------+-----------------------------------------------------------------------------------------+
+| **pattern**      | Form |       | Compares the value against a regexp.                                                    |
++------------------+------+-------+-----------------------------------------------------------------------------------------+
+| **allbut**       | Form | Query | All characters allowed, but not [ ]  { } % & \ #. The used regexp: '^[^\[\]{}%&\\#]+$', |
++------------------+------+-------+-----------------------------------------------------------------------------------------+
+| **all**          | Form | Query | no sanitizing                                                                           |
++------------------+------+-------+-----------------------------------------------------------------------------------------+
+
 
 
 Store / prio
@@ -449,7 +461,7 @@ SQL Statement
 
 * Special case for SELECT input fields. To deliver a result array specify an '!' before the SELECT: ::
 
-   *{{!SELECT ...}}*
+   {{!SELECT ...}}
 
   * This is only possible for the outermost SELECT.
 
@@ -1680,12 +1692,14 @@ Records will be deleted via `typo3conf/ext/qfq/qfq/api/delete.php` and needs the
 
 * _targetUrl=<url>  , typically, this is the $_SERVER['REQUEST_URI'] available via {{REQUEST_URI:Y}}.
 * _answerMode=html
+* _table=<table name>
+* r=<record id>
 
 Example:
 
 ::
 
-    SELECT 'u:typo3conf/ext/qfq/qfq/api/delete.php|U:table=Person&r=123&_targetUrl={{REQUEST_URI:Y}}&_answerMode=html|q:Do you want delete John Doe?|s|c:n' AS _link
+    SELECT 'u:typo3conf/ext/qfq/qfq/api/delete.php|U:_table=Person&r=123&_targetUrl={{REQUEST_URI:Y}}&_answerMode=html|q:Do you want delete John Doe?|s|c:n' AS _link
 
 It's easier to use the shortcut via special columnname `_paged`.
 
@@ -1718,7 +1732,7 @@ The colum name is composed of the string *page* and a trailing character to spec
 +---------------+-----------------------------------------------+-------------------------------------+----------------------------------------------+
 |_pagec         |Internal link without a grafic, with question  |*Please confirm!*                    |p:<pageId>[&param]                            |
 +---------------+-----------------------------------------------+-------------------------------------+----------------------------------------------+
-|_paged         |Internal link with delete icon (trash)         |*Delete record ?*                    |p:<pageId>[&param]                            |
+|_paged         |Internal link with delete icon (trash)         |*Delete record ?*                    |p:<pageId>[&param]????                        |
 +---------------+-----------------------------------------------+-------------------------------------+----------------------------------------------+
 |_pagee         |Internal link with edit icon (pencil)          |empty                                |p:<pageId>[&param]                            |
 +---------------+-----------------------------------------------+-------------------------------------+----------------------------------------------+
@@ -1770,7 +1784,7 @@ Necessary parameter:
 
 ::
 
-    SELECT "p:delete?table=<tablename>&r=<recordId|q:<question>|..." AS _paged
+    SELECT "p:delete?_table=<tablename>&r=<recordId>|q:<question>|..." AS _paged
 
 ..
 
@@ -1782,7 +1796,7 @@ Columns: _Page[X]
 
 ::
 
-    [<page id|alias>[&param=value&...]] | [text] | [tooltip] | [question parameter] | [class] | [target] | [render mode] | [create sip] "" as _pagee.
+    [<page id|alias>[&param=value&...]] | [text] | [tooltip] | [question parameter] | [class] | [target] | [render mode] | [create sip] "" as _Pagee.
 
 ..
 
diff --git a/extension/Documentation/_make/conf.py b/extension/Documentation/_make/conf.py
index bfd2f683279a68ab8a4635f3ca1974c40991e472..dd359d00eecc98adeb9fcf582da4a6379a10d7a5 100644
--- a/extension/Documentation/_make/conf.py
+++ b/extension/Documentation/_make/conf.py
@@ -50,16 +50,16 @@ master_doc = 'Index'
 
 # General information about the project.
 project = u'QFQ Extension'
-copyright = u'2016, Carsten Rose'
+copyright = u'2017, Carsten Rose'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
 # built documents.
 #
 # The short X.Y version.
-version = '0.5'
+version = '0.8'
 # The full version, including alpha/beta/rc tags.
-release = '0.5.0'
+release = '0.8.0'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/extension/config.example.ini b/extension/config.qfq.example.ini
similarity index 100%
rename from extension/config.example.ini
rename to extension/config.qfq.example.ini
diff --git a/extension/ext_emconf.php b/extension/ext_emconf.php
index 8ae832fa2ccac1b97d2dabcec0cbdf9ecfb09a31..e002a8a057c8a5ae5dc3113e9824c37f9ce2645d 100644
--- a/extension/ext_emconf.php
+++ b/extension/ext_emconf.php
@@ -10,5 +10,5 @@ $EM_CONF[$_EXTKEY] = array(
     'dependencies' => 'fluid,extbase',
     'clearcacheonload' => true,
     'state' => 'alpha',
-    'version' => '0.5'
+    'version' => '0.8'
 );
\ No newline at end of file
diff --git a/extension/qfq/api/delete.php b/extension/qfq/api/delete.php
index 6491942bbc7edd4a0daf3d40f96288444878b6e7..f2488a3f9d413b886fc52f0f4fe80a72c7bfb957 100644
--- a/extension/qfq/api/delete.php
+++ b/extension/qfq/api/delete.php
@@ -72,8 +72,9 @@ if (!isset($result[MSG_HEADER]) && !isset($result[MSG_CONTENT])) {
     $result[MSG_CONTENT] = json_encode($answer);
 }
 
-if (isset($result[MSG_HEADER]) && $result[MSG_HEADER] !== '')
+if (isset($result[MSG_HEADER]) && $result[MSG_HEADER] !== '') {
     header($result[MSG_HEADER]);
+}
 
 echo $result[MSG_CONTENT];
 
diff --git a/extension/qfq/qfq/AbstractBuildForm.php b/extension/qfq/qfq/AbstractBuildForm.php
index 48622b410f3e760d717dbafbd20cbcb5625afb45..836ec76323c096112250cddf3c8e2d1573535a5b 100644
--- a/extension/qfq/qfq/AbstractBuildForm.php
+++ b/extension/qfq/qfq/AbstractBuildForm.php
@@ -281,6 +281,8 @@ abstract class AbstractBuildForm {
     }
 
     /**
+     * Return a uniq form id
+     *
      * @return string
      */
     public function getFormId() {
@@ -343,7 +345,7 @@ abstract class AbstractBuildForm {
 
         // get current data record
         if ($recordId > 0 && $this->store->getVar('id', STORE_RECORD) === false) {
-            $row = $this->db->sql("SELECT * FROM " . $this->formSpec[F_TABLE_NAME] . " WHERE id = ?", ROW_EXPECT_1, array($recordId));
+            $row = $this->db->sql("SELECT * FROM " . $this->formSpec[F_TABLE_NAME] . " WHERE id = ?", ROW_EXPECT_1, array($recordId), "Form '" . $this->formSpec[F_NAME] . "' failed to load record '$recordId' from table '" . $this->formSpec[F_TABLE_NAME] . "'.");
             $this->store->setVarArray($row, STORE_RECORD);
         }
 
@@ -467,6 +469,8 @@ abstract class AbstractBuildForm {
     }
 
     /**
+     * Create an array with standard elements and add 'form-element', 'value'.
+     *
      * @param $htmlFormElementId
      * @param string|array $value
      * @param string $feMode disabled|readonly|''
@@ -497,6 +501,8 @@ abstract class AbstractBuildForm {
     }
 
     /**
+     * Depending of $feMode set variables $hidden, $disabled, $required to 'yes' or 'no'.
+     *
      * @param $feMode
      * @param $hidden
      * @param $disabled
@@ -648,6 +654,8 @@ abstract class AbstractBuildForm {
     }
 
     /**
+     * Calculates the maxlength of an input field, based on formElement type, formElement user definition and table.field definition.
+     *
      * @param array $formElement
      */
     private function adjustMaxLength(array &$formElement) {
@@ -848,6 +856,8 @@ abstract class AbstractBuildForm {
     }
 
     /**
+     * Build HelpBlock
+     *
      * @return string
      */
     private function getHelpBlock() {
@@ -1255,6 +1265,7 @@ abstract class AbstractBuildForm {
         $br = '';
 
         $html = $this->buildNativeHidden($htmlFormElementId, $value);
+
         for ($ii = 0; $ii < count($itemValue); $ii++) {
             $jj++;
             $attribute = $attributeBase; //
@@ -1433,7 +1444,6 @@ abstract class AbstractBuildForm {
             }
 
             if ($flagDelete) {
-//                $s = $this->createDeleteUrl($targetTableName, $row[$nameColumnId], RETURN_SIP);
                 $s = $this->createDeleteUrl($targetTableName, $row[$nameColumnId], RETURN_SIP);
                 $rowHtml .= Support::wrapTag('<td>', Support::wrapTag("<button type='button' class='record-delete btn btn-default' data-sip='$s'>", '<span class="glyphicon ' . GLYPH_ICON_DELETE . '"></span>'));
             }
@@ -1469,7 +1479,7 @@ abstract class AbstractBuildForm {
     private function prepareSubrecod(array $formElement, array $primaryRecord, &$rcText, &$nameColumnId) {
 
         if (!isset($primaryRecord['id'])) {
-            $rcText = 'Please save record first.';
+            $rcText = 'Please save and close record and reopen it.';
             return false;
         }
 
@@ -1772,7 +1782,7 @@ abstract class AbstractBuildForm {
         $attribute .= Support::doAttribute('data-load', ($formElement['dynamicUpdate'] === 'yes') ? 'data-load' : '');
         $attribute .= Support::doAttribute('data-sip', $sipUpload);
 
-        if ($value === '') {
+        if ($value === '' || $value === false) {
             $textDeleteClass = 'hidden';
             $uploadClass = '';
         } else {
@@ -2029,6 +2039,8 @@ abstract class AbstractBuildForm {
     }
 
     /**
+     * Parse $formElement[FE_EDITOR_*] settings and build editor settings.
+     *
      * @param array $formElement
      * @param $htmlFormElementId
      * @return array
@@ -2206,6 +2218,8 @@ abstract class AbstractBuildForm {
     }
 
     /**
+     * Create a delete link.
+     *
      * @param $table
      * @param $recordId
      * @param $symbol
diff --git a/extension/qfq/qfq/BuildFormBootstrap.php b/extension/qfq/qfq/BuildFormBootstrap.php
index a07bad4bea73095353eb19de7657c655d84f48c9..5346876756f5a70f8806b7ee9efe25311559cd55 100644
--- a/extension/qfq/qfq/BuildFormBootstrap.php
+++ b/extension/qfq/qfq/BuildFormBootstrap.php
@@ -59,8 +59,8 @@ class BuildFormBootstrap extends AbstractBuildForm {
         $this->wrap[WRAP_SETUP_SUBRECORD][WRAP_SETUP_START] = "<div class='col-md-12'>";
         $this->wrap[WRAP_SETUP_SUBRECORD][WRAP_SETUP_END] = "</div>";
 
-        $this->wrap[WRAP_SETUP_IN_FIELDSET][WRAP_SETUP_START] = "<p>";
-        $this->wrap[WRAP_SETUP_IN_FIELDSET][WRAP_SETUP_END] = "</p>";
+        $this->wrap[WRAP_SETUP_IN_FIELDSET][WRAP_SETUP_START] = "";
+        $this->wrap[WRAP_SETUP_IN_FIELDSET][WRAP_SETUP_END] = "";
 
 //        $this->feDivClass['radio'] = 'radio';
 //        $this->feDivClass['checkbox'] = 'checkbox';
@@ -434,10 +434,15 @@ EOF;
     }
 
     /**
+     * Builds a fieldset
+     *
      * @param $formElement
      * @param $elementHtml
      */
     public function buildRowFieldset(array $formElement, $elementHtml) {
+        $html = $elementHtml;
+
+        return $html;
     }
 
     /**
diff --git a/extension/qfq/qfq/Constants.php b/extension/qfq/qfq/Constants.php
index d8d4c6de42b019df4be0c924cd663ab06559bc34..72f704b589ee81c9b8858510a158d64eece36b5b 100644
--- a/extension/qfq/qfq/Constants.php
+++ b/extension/qfq/qfq/Constants.php
@@ -7,7 +7,7 @@
  */
 
 const EXT_KEY = 'qfq';
-const CONFIG_INI = "config.ini";  // QFQ configuration file: db access
+const CONFIG_INI = "config.qfq.ini";  // QFQ configuration file: db access
 
 const GFX_INFO = 'typo3conf/ext/qfq/Resources/Public/icons/note.gif';
 const API_DIR = 'typo3conf/ext/qfq/qfq/api';
@@ -153,6 +153,7 @@ const ERROR_UNKNOWN_ESCAPE_MODE = 1068;
 const ERROR_MISSING_CONFIG_INI_VALUE = 1069;
 const ERROR_SENDMAIL = 1070;
 const ERROR_SENDMAIL_MISSING_VALUE = 1071;
+const ERROR_OVERWRITE_RECORD_ID = 1072;
 
 // Subrecord
 const ERROR_SUBRECORD_MISSING_COLUMN_ID = 1100;
@@ -323,17 +324,21 @@ const MSG_HEADER = 'header';
 const MSG_CONTENT = 'content';
 const MSG_ERROR_CODE = 'errorCode';
 
+const SIP_TOKEN_LENGTH = 13; // length of string returned by `uniqid()`
 const SIP_SIP = CLIENT_SIP;  // s
 const SIP_RECORD_ID = CLIENT_RECORD_ID; // r
 const SIP_TARGET_URL= '_targetUrl'; // URL where to jump after delete()
 const SIP_MODE_ANSWER = '_modeAnswer'; // Mode how delete() will answer to client: MODE_HTML, MODE_JSON
 const SIP_FORM = CLIENT_FORM;
-const SIP_TABLE = 'table'; // delete a record from 'table'
+const SIP_TABLE = '_table'; // delete a record from 'table'
 const SIP_URLPARAM = 'urlparam';
+const SIP_MAKE_URLPARAM_UNIQ = '_makeUrlParamUniq'; // SIPs for 'new records' needs to be uniq per TAB! Therefore add a uniq parameter
 // FURTHER: all extracted params from 'urlparam
 
 const VAR_RANDOM = 'random';
 
+//const RECORD_ID_NEW = -1;
+
 // TOKEN evaluate
 const TOKEN_ESCAPE_SINGLE_TICK = 's';
 const TOKEN_ESCAPE_DOUBLE_TICK = 'd';
@@ -431,6 +436,7 @@ const GLYPH_ICON_CHECK = 'glyphicon-ok';
 const GLYPH_ICON_CLOSE = 'glyphicon-remove';
 
 // FORM
+const F_NAME = 'name';
 const F_TABLE_NAME = 'tableName';
 const F_REQUIRED_PARAMETER = 'requiredParameter';
 
diff --git a/extension/qfq/qfq/Database.php b/extension/qfq/qfq/Database.php
index 31a16a2fb283c62e73aae5c3d85cc319aaf83e86..53e9e11d20eefc1466cd8266e08dc65a1fbf89d7 100644
--- a/extension/qfq/qfq/Database.php
+++ b/extension/qfq/qfq/Database.php
@@ -282,7 +282,7 @@ class Database {
                 $stat[DB_INSERT_ID] = $this->mysqli->insert_id;
                 $stat[DB_AFFECTED_ROWS] = $this->mysqli->affected_rows;
                 $count = $stat[DB_AFFECTED_ROWS];
-                $msg = 'ID: ' . $count;
+            $msg = 'ID: ' . $this->mysqli->insert_id;
                 break;
             case 'UPDATE':
             case 'DELETE':
diff --git a/extension/qfq/qfq/Delete.php b/extension/qfq/qfq/Delete.php
index 415674e916ad84faec4e5b141b8589d65b0d6fc7..606332ff88981d8ba50a197124f1e652a3ab8db8 100644
--- a/extension/qfq/qfq/Delete.php
+++ b/extension/qfq/qfq/Delete.php
@@ -34,7 +34,7 @@ class Delete {
 
     /**
      * Deletes the record id=$recordId from table $form[F_TABLE_NAME].
-     * If the tables has a column named COLUMN_PATH_FILE_NAME and the value of that specific record column points
+     * If the table has a column named COLUMN_PATH_FILE_NAME and the value of that specific record column points
      * to a file: delete such a file if their are no other records in the same table which also have a reference to that file.
      *
      * @param array $form
@@ -49,7 +49,7 @@ class Delete {
         $rc = false;
         $msg = array();
 
-        if (!isset($form[F_TABLE_NAME]) || $form[F_TABLE_NAME] === '') {
+        if (!isset($form[F_TABLE_NAME]) || $form[F_TABLE_NAME] === '' || $form[F_TABLE_NAME] === false ) {
             throw new CodeException('Missing table name', ERROR_MISSING_TABLE_NAME);
         }
 
@@ -86,11 +86,8 @@ class Delete {
                         }
                     }
                 }
-
-
             }
 
-
             $this->db->sql("DELETE FROM " . $form[F_TABLE_NAME] . " WHERE id =? LIMIT 1", ROW_REGULAR, [$recordId]);
             $rc = true;
         } else {
diff --git a/extension/qfq/qfq/Evaluate.php b/extension/qfq/qfq/Evaluate.php
index 9c84068d54005d977bce954c82de812bfe572f76..0f9296223450c5facf9c5500a8ab7190f5746aa6 100644
--- a/extension/qfq/qfq/Evaluate.php
+++ b/extension/qfq/qfq/Evaluate.php
@@ -211,7 +211,7 @@ class Evaluate {
     /**
      * @return string
      */
-    public function getDebug() {
-        return '<pre>' . implode("\n", $this->debugStack) . '</pre>';
-    }
+//    public function getDebug() {
+//        return '<pre>' . implode("\n", $this->debugStack) . '</pre>';
+//    }
 }
\ No newline at end of file
diff --git a/extension/qfq/qfq/QuickFormQuery.php b/extension/qfq/qfq/QuickFormQuery.php
index 54fcf67fb79096e0ded728cb150df78bb38aaa3d..66777e1d6592b9dee71454ba98236f05dee65944 100644
--- a/extension/qfq/qfq/QuickFormQuery.php
+++ b/extension/qfq/qfq/QuickFormQuery.php
@@ -163,7 +163,7 @@ class QuickFormQuery {
     }
 
     /**
-     * Returns the defined forwardMode and set, if necessary, $forwardPage
+     * Returns the defined forwardMode and set $forwardPage (call be reference)
      *
      * @param $forwardPage
      * @return mixed
@@ -174,7 +174,7 @@ class QuickFormQuery {
     }
 
     /**
-     * Main entrypoint for display content: form or report
+     * Main entrypoint for display content: a) form and/or b) report
      *
      * @return string
      */
@@ -226,12 +226,13 @@ class QuickFormQuery {
         }
 
         $sipFound = $this->validateForm($foundInStore);
-        if (!$sipFound) {
+        $recordId = $this->store->getVar(SIP_RECORD_ID, STORE_SIP . STORE_TYPO3 . STORE_CLIENT);
+        // For 'new' record always create a new TAB-uniq (for this current form, nowhere else used) SIP.
+        // With such a TAB-uniq SIP, multiple TABs and following repeated NEWs are easily implemented.
+        if (!$sipFound || ($mode == FORM_LOAD && $recordId == 0)) {
             $this->store->createSipAfterFormLoad($formName);
         }
 
-        $formAction = new FormAction($this->formSpec, $this->db, $this->phpUnit);
-
         $this->store->fillStoreTableDefaultColumnType($this->formSpec[F_TABLE_NAME]);
 
         switch ($this->formSpec['render']) {
@@ -248,10 +249,10 @@ class QuickFormQuery {
                 throw new CodeException("This statement should never be reached", ERROR_CODE_SHOULD_NOT_HAPPEN);
         }
 
+        $formAction = new FormAction($this->formSpec, $this->db, $this->phpUnit);
         switch ($mode) {
             case FORM_LOAD:
             case FORM_UPDATE:
-                $recordId = $this->store->getVar(SIP_RECORD_ID, STORE_SIP . STORE_TYPO3 . STORE_CLIENT);
                 $formAction->elements($recordId, $this->feSpecAction, FE_TYPE_BEFORE_LOAD);
 
                 $data = $build->process($mode);
@@ -277,19 +278,19 @@ class QuickFormQuery {
                 $save->processAllUploads($rc);
 
                 // Action: After
-                $formAction->elements($recordId, $this->feSpecAction, FE_TYPE_AFTER_INSERT . ',' . FE_TYPE_AFTER_UPDATE . ',' . FE_TYPE_AFTER_SAVE);
+                $formAction->elements($rc, $this->feSpecAction, FE_TYPE_AFTER_INSERT . ',' . FE_TYPE_AFTER_UPDATE . ',' . FE_TYPE_AFTER_SAVE);
 
                 $htmlElementNameIdZero = false;
                 // Retrieve current STORE_SIP.
                 $sipArray = $this->store->getStore(STORE_SIP);
                 if ($sipArray[SIP_RECORD_ID] == 0) {
                     // After insert: a new SIP for the new record id is required.
-                    $this->newRecordCreateSip($sipArray, $rc);
+                    $this->newRecordUpdateSip($rc);
                     $htmlElementNameIdZero = true;
                 }
 
                 // Action: Sendmail
-                $formAction->elements($recordId, $this->feSpecAction, FE_TYPE_SENDMAIL);
+                $formAction->elements($rc, $this->feSpecAction, FE_TYPE_SENDMAIL);
 
                 // Retrieve FE Values as JSON
                 $data = $build->process($mode, $htmlElementNameIdZero);
@@ -339,7 +340,7 @@ class QuickFormQuery {
         }
 
         // Load form
-        $form = $this->db->sql("SELECT * FROM Form AS f WHERE f.name LIKE ? AND f.deleted='no'", ROW_EXPECT_1,
+        $form = $this->db->sql("SELECT * FROM Form AS f WHERE f." . F_NAME . " LIKE ? AND f.deleted='no'", ROW_EXPECT_1,
             [$formName], 'Form not found or multiple forms with the same name.');
 
         $this->formSpec = $this->eval->parseArray($form);
@@ -449,7 +450,7 @@ class QuickFormQuery {
         // Retrieve record_id either from SIP (prefered) or via URL
         $r = $this->store->getVar(SIP_RECORD_ID, STORE_SIP . STORE_TYPO3 . STORE_CLIENT, '', $recordIdFoundInStore);
 
-        // Missing 'r' is in general an error
+        // Set missing 'r'.
         if ($r === false) {
             $r = 0;
             $this->store->setVar(TYPO3_RECORD_ID, $r, STORE_TYPO3);
@@ -519,6 +520,8 @@ class QuickFormQuery {
     }
 
     /**
+     * Load record $id from $table.
+     *
      * @param string $table
      * @param string $recordId
      * @throws CodeException
@@ -533,40 +536,26 @@ class QuickFormQuery {
     }
 
     /**
-     * @param $sipArray
+     * Update current SIP Store with new $recordId and update SESSION store.
+     *
      * @param $recordId
+     * @throws CodeException
+     * @throws UserFormException
      */
-    private function newRecordCreateSip($sipArray, $recordId) {
-
-        $tmpParam = array();
-
-        foreach ($sipArray as $key => $value) {
-            switch ($key) {
-                case SIP_SIP:
-                case SIP_URLPARAM:
-                case SIP_TABLE:
-                    continue;
+    private function newRecordUpdateSip($recordId) {
+        // Update current SIP store with new RecordID
+        $sipArray = $this->store->getStore(STORE_SIP);
 
-                case SIP_RECORD_ID:
-                    $tmpParam[SIP_RECORD_ID] = $recordId;
-                    break;
-                default:
-                    // further vars stored in old SIP (form, maybe default values)
-                    $tmpParam[$key] = $value;
-                    break;
-            }
+        if (isset($sipArray[SIP_RECORD_ID]) && $sipArray[SIP_RECORD_ID] > 0) {
+            throw new CodeException('Attemp to overwrite existing record id: SIP(otf)=' . $sipArray[SIP_SIP] . " existing_r=" . $sipArray[SIP_RECORD_ID] . " new_r=" . $recordId, ERROR_OVERWRITE_RECORD_ID);
         }
 
-        // Construct fake urlparam
-        $tmpUrlparam = OnArray::toString($tmpParam);
+        $sipArray[SIP_RECORD_ID] = $recordId;
+        $this->store->setVarArray($sipArray, STORE_SIP, true);
 
-        // Create a SIP which has never been passed by URL - further processing might expect this to exist.
-        $sip = store::getSipInstance()->queryStringToSip($tmpUrlparam, RETURN_SIP);
-        $this->store->setVar(CLIENT_SIP, $sip, STORE_CLIENT);
+        // Update SIP urlparam
+        store::getSipInstance()->updateSipToSession($sipArray);
 
-        // Overwrite SIP Store
-        $tmpParam[SIP_SIP] = $sip;
-        $this->store->setVarArray($tmpParam, STORE_SIP, true);
     }
 
     /**
@@ -653,6 +642,8 @@ class QuickFormQuery {
             case MODE_HTML:
                 if ($targetUrl === false || $targetUrl === '') {
                     $result[MSG_CONTENT] = 'Missing target URL. ' . ERROR_MISSING_VALUE;
+                    //TODO: vermutlich muss hier $rc=false gesetzt werden. Habe zur Zeit keine Moeglichkeit das zu testen.
+//                    $rc = false;
                 }
 
                 if ($rc === true) {
@@ -672,4 +663,44 @@ class QuickFormQuery {
         return $result;
     }
 
+    /**
+     * Based on the given SIP, create a new uniqe SIP by copying the relevant old params and taking the new recordId..
+     *
+     * @param $sipArray
+     * @param $recordId
+     */
+    private function newRecordCreateSip($sipArray, $recordId) {
+
+        $tmpParam = array();
+
+        foreach ($sipArray as $key => $value) {
+            switch ($key) {
+                case SIP_SIP:
+                case SIP_URLPARAM:
+                case SIP_TABLE:
+                continue; // do not copy these params to the new SIP
+
+                case SIP_RECORD_ID:
+                    // set the new recordId
+                    $tmpParam[SIP_RECORD_ID] = $recordId;
+                    break;
+                default:
+                    // copy further vars stored in old SIP (form, maybe default values)
+                    $tmpParam[$key] = $value;
+                    break;
+            }
+        }
+
+        // Construct fake urlparam
+        $tmpUrlparam = OnArray::toString($tmpParam);
+
+        // Create a SIP which has never been passed by URL - further processing might expect this to exist.
+        $sip = store::getSipInstance()->queryStringToSip($tmpUrlparam, RETURN_SIP);
+        $this->store->setVar(CLIENT_SIP, $sip, STORE_CLIENT);
+
+        // Overwrite SIP Store
+        $tmpParam[SIP_SIP] = $sip;
+        $this->store->setVarArray($tmpParam, STORE_SIP, true);
+    }
+
 }
\ No newline at end of file
diff --git a/extension/qfq/qfq/form/FormAction.php b/extension/qfq/qfq/form/FormAction.php
index 8da84e28879624c1c763e0ef5b42e9c467e197e1..2702f7ae2bc9ad8a0f3c4e7288a0a01dacc96400 100644
--- a/extension/qfq/qfq/form/FormAction.php
+++ b/extension/qfq/qfq/form/FormAction.php
@@ -76,6 +76,9 @@ class FormAction {
                 continue;
             }
 
+            // Preparation for Log, Debug
+            $this->store->setVar(SYSTEM_FORM_ELEMENT, Logger::formatFormElementName($fe), STORE_SYSTEM);
+
             if ($fe[FE_TYPE] !== FE_TYPE_BEFORE_LOAD && $fe[FE_TYPE] !== FE_TYPE_AFTER_LOAD) {
                 // Always work on recent data: previous actions might have modified the data.
                 $this->fillStoreRecord($this->primaryTableName, $recordId);
@@ -90,8 +93,6 @@ class FormAction {
                 //no further processing of current element necessary.
                 continue;
             }
-            // Preparation for Log, Debug
-            $this->store->setVar(SYSTEM_FORM_ELEMENT, Logger::formatFormElementName($fe), STORE_SYSTEM);
 
             $this->validate($fe);
 
diff --git a/extension/qfq/qfq/helper/Sanitize.php b/extension/qfq/qfq/helper/Sanitize.php
index 67e48f248daf370e6048defade3d8ae1b0493ebf..9995910dc74edfcb61ba3e1ce36bd6d5ff277baa 100644
--- a/extension/qfq/qfq/helper/Sanitize.php
+++ b/extension/qfq/qfq/helper/Sanitize.php
@@ -143,7 +143,7 @@ class Sanitize {
             SANITIZE_ALLOW_MIN_MAX => '',
             SANITIZE_ALLOW_MIN_MAX_DATE => '',
             SANITIZE_ALLOW_PATTERN => '',
-            SANITIZE_ALLOW_ALLBUT => '^[^\[\]{}%&\\#]+$',
+            SANITIZE_ALLOW_ALLBUT => '^[^\[\]{}%&\\\\#]*$',
             SANITIZE_ALLOW_ALL => '.*'
         ];
     }
diff --git a/extension/qfq/qfq/report/Db.php b/extension/qfq/qfq/report/Db.php
deleted file mode 100644
index 530f854a9345038b52d7a28fdda44885bfdaf0b9..0000000000000000000000000000000000000000
--- a/extension/qfq/qfq/report/Db.php
+++ /dev/null
@@ -1,373 +0,0 @@
-<?php
-/***************************************************************
- *  Copyright notice
- *
- *  (c) 2010 Glowbase GmbH <support@glowbase.com>
- *  All rights reserved
- *
- *  This script is part of the TYPO3 project. The TYPO3 project is
- *  free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  The GNU General Public License can be found at
- *  http://www.gnu.org/copyleft/gpl.html.
- *
- *  This script is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  This copyright notice MUST APPEAR in all copies of the script!
- ***************************************************************/
-
-namespace qfq;
-
-//use qfq;
-
-require_once(__DIR__ . '/Define.php');
-require_once(__DIR__ . '/Error.php');
-require_once(__DIR__ . '/Log.php');
-
-
-class Db {
-
-    public $t3_typo_db_host = "";
-    /**
-     * @var string
-     */
-    private $lastUsedDB = "";
-    /**
-     * @var array
-     */
-    private $arrDB = array();
-    /**
-     * @var
-     */
-    private $t3_typo_db_username, $t3_typo_db, $t3_typo_db_password;
-    /**
-     * @var Log
-     */
-    private $log;
-
-    // Emulate global variable: will be set much earlier in other functions. Will be shown in error messages.
-    private $fr_error;
-
-
-    /**
-     * Constructor:
-     *
-     * @param    Log   fully created for logging.
-     *
-     */
-
-    public function __construct($log) {
-        // CR 25.4.11: require_once does not work here. No idea why
-        require(PATH_typo3conf . 'localconf.php');
-        $this->t3_typo_db_host = $typo_db_host;
-        $this->t3_typo_db_username = $typo_db_username;
-        $this->t3_typo_db = $typo_db;
-        $this->t3_typo_db_password = $typo_db_password;
-
-        $this->log = $log;
-    }
-
-    /**
-     * Set Array fr_error: setter function to set most recent values, especially fr_erro['row'].
-     * Will be shown in error messages.
-     *
-     * @param array $fr_error uid, pid, row, column_idx, full_level
-     */
-    public function set_fr_error(array $fr_error) {
-        $this->fr_error = $fr_error;
-    }
-
-    /**
-     * doQueryKeys: See doQuery
-     *                Difference: fake Array for $keys
-     *
-     * @param string $dbAlias
-     * @param string $sql
-     * @param array $result
-     * @param string string $expect
-     * @param string $merge
-     * @return bool
-     * @throws CodeReportException
-     * @throws SqlReportException
-     * @throws SyntaxReportException
-     */
-    public function doQuery($dbAlias, $sql, array &$result, $expect = ROW_REGULAR, $merge = MERGE_NONE) {
-        return ($this->doQueryKeys($dbAlias, $sql, $result, $fake, $expect, $merge, MYSQL_ASSOC));
-    }
-
-    /**
-     * doQueryKeys: fires a show, select, insert, update or delete and collects result.
-     *            insert, update and delete will produce a log entry.
-     *            If: $expect==EXPECT_SQL_OR_STRING, '$sql' can be anything which won't be fired if it's not a SQL statement.
-     *
-     * @param string $dbAlias Name of Database to be used.
-     * @param string $sql Select Query
-     * @param array $result content depends on $sql.
-     *                                    $sql='insert ...': mysql_last_insert_id will be returned in $result.
-     *                                    $sql='update ...' or 'delete ----': mysql_affected_rows will be returned in $result.
-     *                                $sql='select ...': all selected rows will be returned in $result.
-     *                                $result will be formatted like specified in $merge.
-     *                                    Attention: with EXPECT_1|EXPECT_0_1 '$result' is a one dimensional array, else a two dimensional array.
-     * @param array $keys
-     * @param string $expect
-     * @param string $merge Applies different modes of merging - MERGE_NONE, MERGE_ROW, MERGE_ALL
-     * @param int $arrayMode
-     * @return bool                     true: all ok
-     *                                  false:    a) Number of rows don't match $expect
-     *                                        b) $expect==EXPECT_SQL_OR_STRING and $sql is not an SQL expression (instead it's a regular string) - this is not bad, just to indicate that there was no query.
-     * @throws CodeReportException
-     * @throws SqlReportException
-     * @throws SyntaxReportException
-     */
-    public function doQueryKeys($dbAlias, $sql, array &$result, array &$keys, $expect = ROW_REGULAR, $merge = MERGE_NONE, $arrayMode = MYSQL_NUM) {
-        $result = "";
-        $tmp = "";
-        $action = "";
-
-        $this->selectDB($dbAlias);
-
-        if ($this->fr_error["debug_level"] >= DEBUG_SQL) {
-            // T3 function: debug()
-//            debug(array('SQL' => $sql));
-        }
-
-        // Extract first parameter to check if it is a SQL statement
-        $tmp = explode(" ", trim($sql), 2);
-        $action = strtolower($tmp[0]);
-        switch ($action) {
-            case "show"  :
-            case "select":
-            case "insert":
-            case "update":
-            case "delete":
-                break;  // SQL Statement: go further
-            default:
-                if ($expect == EXPECT_SQL_OR_STRING) {
-                    $result = $sql;
-                    return (false);    // nothing bad, just to indicate $sql was not a SQL statement.
-                } else
-                    throw new SyntaxReportException ("Unexpected SQL Statement: '$action'", "", __FILE__, __LINE__, array("DB:$dbAlias", "SQL:$sql"), $this->fr_error);
-        }
-
-        // Fire SQL statement
-        if (!($res = mysql_query($sql))) {
-            // Escape query if in AJAX mode
-            $sql = (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') ? addslashes($sql) : $sql;
-            throw new SqlReportException ("Did not get result for query.", $sql, __FILE__, __LINE__, $this->fr_error);
-        }
-
-
-        switch ($action) {
-            case "show"  :
-            case "select":
-                $action = QUERY; // aggregate 'SLELECT' and 'SHOW' and ...
-                $num_rows = mysql_num_rows($res);
-                break;
-
-            case "insert":
-                $num_rows = mysql_affected_rows();
-                $result = mysql_insert_id();
-                break;
-            case "update":
-            case "delete":
-                $num_rows = mysql_affected_rows();
-                $result = $num_rows;
-                break;
-
-            default:
-                throw new CodeReportException ("This error should be catched 20 lines above.", __FILE__, __LINE__);  // can't be happen, should already be detected earlier.
-        }
-
-        // Logging
-        if ($action != QUERY) {
-            // Not a query: write log and go home.
-            $this->log->log_sql('db', '', $num_rows, $result, $sql);
-            return (TRUE);
-        } else {
-            // Logging if localconf log_level >=D2
-            $this->log->log_do('error', 'D2', '-', $sql);
-        }
-
-        // Check $expect against real result.
-        switch ($expect) {
-            case ROW_EXPECT_0:
-                return ($num_rows == 0);
-                break;
-            case ROW_EXPECT_1:
-                if ($num_rows != 1) return (false);
-                break;
-            case ROW_EXPECT_0_1:
-                if ($num_rows > 1) return (false);
-                break;
-//            case ROW_EXPECT_GE_0:
-//                break;
-            case ROW_EXPECT_GE_1:
-                if ($num_rows == 0) return (false);
-                break;
-            case EXPECT_SQL_OR_STRING:
-                break;
-            default:
-                throw new CodeReportException ("Unknown 'expect' qualifier: $expect", __FILE__, __LINE__);
-                break;
-        }
-
-        // Preparation to fetch all rows
-        $tmp = "";
-        $fieldCount = 0;
-
-        // Fetch all rows:
-        while ($row = mysql_fetch_array($res, $arrayMode)) {
-            foreach ($row as $key => $value) {
-                $row[$key] = stripslashes($value);
-            }
-
-            switch ($merge) {
-                case MERGE_NONE:
-                    $tmp[] = $row;
-                    break;
-                case MERGE_ROW:
-                    $tmp[] = implode($row);
-                    break;
-                case MERGE_ALL:
-                    $tmp .= implode($row);
-                    break;
-                default:
-                    throw new CodeReportException ("Unknown 'merge' qualifier: $merge", __FILE__, __LINE__);
-                    break;
-            }
-        }
-
-        // Collect 'keys'
-        if ($merge == MERGE_NONE) {
-            $keys = array();
-            $numberfields = mysql_num_fields($res);
-
-            for ($i = 0; $i < $numberfields; $i++) {
-                $keys[] = mysql_field_name($res, $i);
-            }
-        }
-
-        // adjust Result Array: one or two dimensions.
-        switch ($expect) {
-            case ROW_EXPECT_0:
-                break;
-            case ROW_EXPECT_1:
-            case ROW_EXPECT_0_1:
-            case EXPECT_SQL_OR_STRING:
-                $result = $tmp[0];
-                break;
-            default:
-                $result = $tmp;
-        }
-
-        if ($merge == MERGE_ALL)
-            $result = $tmp;
-
-        mysql_free_result($res);
-
-        return (TRUE);
-    } // doQueryKeys()
-
-    /**
-     * select DB
-     *
-     * @param    string $dbAlias : Name of the dbname
-     *
-     * @return    bool        TRUE if ok, else exception.
-     */
-    public function selectDB($dbAlias) {
-
-        if (!$dbAlias)
-            throw new CodeReportException ("Failed: empty dbAlias", __FILE__, __LINE__);
-
-        // If the db is still selected: do nothing.
-        if ($dbAlias == $this->lastUsedDB)
-            return true;
-
-        // if the db is already open - just select it.
-        if (isset($this->arrDB[$dbAlias]['link'])) {
-            if (!mysql_select_db($this->arrDB[$dbAlias]['db']))
-                throw new SqlReportException ("Failed: mysql_select_db($this->arrDB[$dbAlias]['db'])", "", __FILE__, __LINE__, $this->fr_error);
-            return true;
-        }
-
-        $this->openDB($dbAlias);
-
-        return true;
-    } // openDB()
-
-    /**
-     * Open specified DB
-     *
-     * @param string $dbAlias Name of database to be opened
-     * @throws SqlReportException
-     */
-    public function openDB($dbAlias) {
-        // TYPO3 globale Variablen
-// 		global $typo_db_host,$typo_db_username,$typo_db,$typo_db_password;
-//		Du sollst kein global verwenden!!
-
-        if ($dbAlias == T3) {
-            $host = $this->t3_typo_db_host;
-            $username = $this->t3_typo_db_username;
-            $db = $this->t3_typo_db;
-            $password = $this->t3_typo_db_password;
-        } else {
-//			require(PATH_typo3conf.'ext/formreport/ext_localconf.php');
-            $host = $GLOBALS['TYPO3_CONF_VARS'][FORMREPORT][$dbAlias]['host'];
-            $username = $GLOBALS['TYPO3_CONF_VARS'][FORMREPORT][$dbAlias]['username'];
-            $db = $GLOBALS['TYPO3_CONF_VARS'][FORMREPORT][$dbAlias]['name'];
-            $password = $GLOBALS['TYPO3_CONF_VARS'][FORMREPORT][$dbAlias]['password'];
-
-        }
-
-        // If 't3' is specified or the custom DB is not fully specified, take credentials from localconf.php
-#		$host     = $host     ? $host 		: $typo_db_host;
-#		$username = $username ? $username	: $typo_db_username;
-#		$db       = $db       ? $db 		: $typo_db;
-#		$password = $password ? $password 	: $typo_db_password;
-
-
-        // MySQL Connect
-        if (!($link = mysql_connect($host, $username, $password)))
-            throw new SqlReportException ("mysql_connect($host, $username)", "", __FILE__, __LINE__, $this->fr_error);
-
-        // Set connection charset
-        if (!mysql_set_charset('utf8', $link))
-            throw new SqlReportException ("mysql_set_charset('utf8', $link)", "", __FILE__, __LINE__, $this->fr_error);
-
-        // MySQL select
-        if (!mysql_select_db($db, $link))
-            throw new SqlReportException ("mysql_select_db($db)", "", __FILE__, __LINE__, $this->fr_error);
-
-        // Remember that this DB has been opened.
-        $this->arrDB[$dbAlias]['link'] = $link;
-        $this->arrDB[$dbAlias]['db'] = $db;
-
-        // Remember the new DB as 'last used'
-        $this->lastUsedDB = $dbAlias;
-
-    } // selectDB()
-
-    /**
-     * closeAllDB
-     *
-     * @return    void
-     */
-    public function closeAllDB() {
-
-        foreach ($this->arrDB as $key => $value) {
-            if ($key != T3) {
-                mysql_close($value);
-                $arrDB[$key] = null;
-            }
-        }
-
-    } // closeAllDB()
-}
diff --git a/extension/qfq/qfq/report/Link.php b/extension/qfq/qfq/report/Link.php
index e7a799da780db9f1cc127b5e5b197ced6272e331..1c21b66ad1c462ea9b1df27812235dc66fb2818e 100644
--- a/extension/qfq/qfq/report/Link.php
+++ b/extension/qfq/qfq/report/Link.php
@@ -27,7 +27,6 @@ namespace qfq;
 //use qfq;
 
 require_once(__DIR__ . '/Define.php');
-require_once(__DIR__ . '/Utils.php');
 require_once(__DIR__ . '/../store/Store.php');
 require_once(__DIR__ . '/../store/Sip.php');
 require_once(__DIR__ . '/../exceptions/UserReportExtension.php');
@@ -168,10 +167,6 @@ class Link {
      * @var Utils
      */
 
-    private $utils;
-    /**
-     * @var array
-     */
     private $renderControl = array();
     private $linkClassSelector = array(TOKEN_CLASS_INTERNAL => "internal ", TOKEN_CLASS_EXTERNAL => "external ");
     private $cssLinkClassInternal = '';
@@ -246,7 +241,6 @@ class Link {
         $this->store = Store::getInstance('', $phpUnit);
         $this->cssLinkClassInternal = $this->store->getVar(SYSTEM_CSS_LINK_CLASS_INTERNAL, STORE_SYSTEM);
         $this->cssLinkClassExternal = $this->store->getVar(SYSTEM_CSS_LINK_CLASS_EXTERNAL, STORE_SYSTEM);
-        $this->utils = new Utils();
 
         /*
          * mode:
@@ -535,7 +529,7 @@ class Link {
             case TOKEN_ENCRYPTION:
             case TOKEN_SIP:
                 if ($value !== '0' && $value !== '1') {
-                    throw new UserReportException ("Invalied value for token '$key': '$value''", ERROR_INVALID_VALUE);
+                    throw new UserReportException ("Invalid value for token '$key': '$value''", ERROR_INVALID_VALUE);
                 }
                 break;
             default:
diff --git a/extension/qfq/qfq/report/Log.php b/extension/qfq/qfq/report/Log.php
deleted file mode 100644
index 21accfd77b2a0e542ec2340229d18ed70a31a3d9..0000000000000000000000000000000000000000
--- a/extension/qfq/qfq/report/Log.php
+++ /dev/null
@@ -1,214 +0,0 @@
-<?php
-/***************************************************************
- *  Copyright notice
- *
- *  (c) 2010 Glowbase GmbH <support@glowbase.com>
- *  All rights reserved
- *
- *  This script is part of the TYPO3 project. The TYPO3 project is
- *  free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  The GNU General Public License can be found at
- *  http://www.gnu.org/copyleft/gpl.html.
- *
- *  This script is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  This copyright notice MUST APPEAR in all copies of the script!
- ***************************************************************/
-
-/*
- * Howto
- * 
- * 1) Specify Logfiles (incl. path) in ext_localconf.php in $TYPO3_CONF_VARS[$_EXTKEY]['log'][<name>].
- *    <name> means a class of 'error', 'mail', 'sql', 'browser', ...
- * 2) Call 'log_do($class, $status, $origin, $message)' to write one entry. 
- *    Every entry will start with: [<status>|<origin>|<date/time>|<IP>|<fe.uid>|<fe.username>|<URL>].
- *    Specify $message string or $message array.
- * 3) For 'sql' and 'mail' log entries, use the wrapper log_sql() or log_mail().   
- */
-
-namespace qfq;
-
-//use qfq;
-
-class Log {
-    /**
-     * @var array
-     */
-    private $config;    // filled in __construct, Definition: tx_fr_variables->collectGlobalVariables
-
-    /**
-     * @var array   order to compare loglevel
-     */
-    private $config_level = array('E' => 0, 'W' => 1, 'I' => 2, 'D1' => 3, 'D2' => 4, 'D3' => 5);
-
-    /**
-     * @var array Emulate global variable: will be set much earlier in other functions. Will be shown in error messages.
-     */
-    private $fr_error = array();
-
-    /**
-     * Initializes class
-     *
-     * @param    array $tmp_config :    Part of array 'fr_array': 'global.'
-     *
-     * @throws \Exception
-     */
-    public function __construct(array $tmp_config) {
-//        global $TYPO3_CONF_VARS;
-//        $this->prepare_log_file_dir($TYPO3_CONF_VARS[EXTKEY]['log']['sql']);
-//        $this->prepare_log_file_dir($TYPO3_CONF_VARS[EXTKEY]['log']['mail']);
-//        $this->prepare_log_file_dir($TYPO3_CONF_VARS[EXTKEY]['log']['error']);
-//        $this->prepare_log_file_dir($TYPO3_CONF_VARS[EXTKEY]['log']['browser']);
-
-        $this->config = $tmp_config;
-
-    } // __construct()
-
-    /**
-     * Set Array fr_error: setter function to set most recent values.
-     * Will be shown in log messages.
-     *
-     * @param    array $fr_error :   uid, pid, row, column_idx, full_level
-     *
-     * @return    void
-     */
-    public function set_fr_error(array $fr_error) {
-        $this->fr_error = $fr_error;
-    }
-
-    /**
-     * log_sql: wrapper for log_do() for sql logging
-     *
-     * @param    string $origin :    Sender of the logmessage. F.e.: 'form', 'save', 'report', 'extjs', ...
-     * @param    string $msg : Only filled if there was an error
-     * @param    int $affected_rows : Number of rows inserted, updated or deleted.
-     * @param    int $new_id : last_insert_id()
-     * @param    string $sql : SQL statement fired
-     *
-     * @return    void
-     */
-    public function log_sql($origin, $msg, $affected_rows, $new_id, $sql) {
-
-        if ($msg) {
-            $status = 'E';
-        } else {
-            $status = 'I';
-            $msg = 'OK';
-        }
-
-        $text = "[$msg]";
-        $text .= "[$affected_rows]";
-        $text .= "[$new_id]";
-        $text .= "[$sql]";
-
-        $this->log_do('sql', $status, $origin, $text);
-    } // prepare_log_file_dir()
-
-    /**
-     * log_do: format log entries, build fix part, append dynamic part, write.
-     *
-     * @param    string $class :        'error', 'mail', 'sql', 'browser'. New classes has to be defined in ext_localconf.php
-     * @param    string $status :    'E' (0:error), 'W' (1:warning), 'I' (2:information), 'D1' (3:debug verbose), 'D2' (4:debug very verbose), 'D3' (5:debug very very verbose)
-     * @param    string $orign :        Sender of the logmessage. F.e.: 'form', 'save', 'report', 'extjs', ...
-     * @param  string /array        $message:    skalar or one dimensal array with logmessage(s).
-     * @throws CodeReportException
-     * @throws SyntaxReportException
-     */
-    public function log_do($class, $status, $origin, $message) {
-        global $TYPO3_CONF_VARS;
-        $tmp = '';
-
-        // Check if loglevel should be respected and if 'yes' if loglevel is greater than this message: break
-        if (($class == 'error' || $class == 'browser') && $this->config_level[$status] > $TYPO3_CONF_VARS[EXTKEY]['log']['level'])
-            return;
-
-        // Get filename
-        $filename = $TYPO3_CONF_VARS[EXTKEY]['log'][$class];
-        if (!$filename)
-            throw new SyntaxReportException ("Missing logfile definition: Undefind TYPO3_CONF_VARS[" . EXTKEY . "]['log']['$class']", "", __FILE__, __LINE__);
-
-        if ($this->fr_error['pid']) $tmp = '|' . $this->fr_error['pid'];
-        if ($this->fr_error['uid']) $tmp .= '|' . $this->fr_error['uid'];
-        if ($this->fr_error['full_level']) $tmp .= '|' . $this->fr_error['full_level'];
-
-        // F.e.: [I|Form|2012.01.31-19:59:33|IP|fe.uid|fe.username|URL]
-        $text = '[' . $status . '|' . $origin . '|' . date('Y.m.d-H:i:s') . '|' . $this->config["REMOTE_ADDR"] . '|' . $this->config["fe_user_uid"] . '|' . $this->config["fe_user"] . $tmp . '|' . $this->config["url"] . ']';
-
-        // If 'message' is an array, wrap every element (but not the last) with '[', ']'.
-        if ($message && is_array($message)) {
-            $last = array_pop($message);
-            if ($last && $message) {
-                $text .= '[' . implode('][', $message) . ']';
-            }
-            $message = $last;
-        }
-        $text .= $message;
-
-        // Write whole entry
-        $this->log_write($filename, $text);
-    } // log_do()
-
-    /**
-     *    Logs every email (failed or successfull)
-     *
-     * @param    string $orign :        Sender of the logmessage. F.e.: 'form', 'save', 'report', 'extjs', ...
-     * @param    string $status :    'E' (0:error), 'W' (1:warning), 'I' (2:information), 'D1' (3:debug verbose), 'D2' (4:debug very verbose), 'D3' (5:debug very very verbose)
-     * @param    string $msg :        Message
-     * @param    array $mailarr :    Details of the mail
-     *
-     * $mailarr['sender']      Absender
-     * $mailarr['receiver']    Empfaenger, mehrere mit Komma getrennt
-     * $mailarr['subject']     Betreff
-     * $mailarr['body']        Mailinhalt
-     * $mailarr['src']         level oder form_element.id um herauszufinden wer die Mail gesendet hat
-     *
-     * @param    string $mailarr : data to log
-     * @return    The content that is displayed on the website
-     */
-
-    public function log_mail($origin, $status, $msg, $mailarr) {
-
-        $text = '[' . $msg . "]";
-        $text .= '[' . $mailarr["sender"] . ']';
-        $text .= '[' . $mailarr["receiver"] . ']';
-        $text .= '[' . $mailarr["subject"] . ']';
-        $text .= '[' . $mailarr["body"] . ']';
-
-        $this->log_do('mail', $status, $origin, $text);
-
-    } // log_sql()
-
-    /**
-     * Check if path of logfile exists. No: create it.
-     * Check if path of logfile is writeable.
-     *
-     * @param string $filename Name of logfile
-     * @throws \Exception
-     */
-    private function prepare_log_file_dir($filename) {
-        $this->logFile = $filename;
-
-        // extract optional path component
-        $path = dirname($filename);
-
-        // If there is a path: check if directories really exist and are writeable.
-        if ($path) {
-            if (file_exists($path)) {
-                // Directory already exists: check if it is writeable.
-                if (!is_writable($path)) throw new \Exception ("Failed: directory '$path' of Logfile '$filename' is not writeable.");
-            } else {
-                // Directoy doesn't exist: create it.
-                if (!mkdir($path, 0775, true))
-                    throw new \Exception ("Failed to create directory '$path' for Logfile '$filename'");
-            }
-        }
-    } // log_mail()
-
-}
diff --git a/extension/qfq/qfq/report/Report.php b/extension/qfq/qfq/report/Report.php
index b8dcb4e7bb7bb31141a8415baf17ffacc4b6e3cc..3492ba07678fd57c743d04ea5f1838be22b5f454 100644
--- a/extension/qfq/qfq/report/Report.php
+++ b/extension/qfq/qfq/report/Report.php
@@ -12,7 +12,6 @@ namespace qfq;
 //use qfq;
 
 require_once(__DIR__ . '/Define.php');
-require_once(__DIR__ . '/Utils.php');
 require_once(__DIR__ . '/Variables.php');
 require_once(__DIR__ . '/Error.php');
 require_once(__DIR__ . '/../Database.php');
@@ -64,12 +63,7 @@ class Report {
     private $variables = null;
 
     /**
-     * @var Utils
-     */
-    private $utils = null;
-
-    /**
-     * @var Db
+     * @var Database
      */
     private $db = null;
 
@@ -124,7 +118,6 @@ class Report {
         $this->pageDefaults[DEFAULT_ICON]["pages"] = TOKEN_SHOW;
 
         $this->db = new Database();
-        $this->utils = new Utils();
         $this->variables = new Variables($eval, $t3data["uid"]);
 
         // Set static values, which won't change during this run.
@@ -407,7 +400,7 @@ class Report {
 
             //Execute SQL. All errors have been already catched.
             unset($result);
-            $result = $this->db->sqlKeys($sql, $keys, $stat);
+            $result = $this->db->sql($sql, ROW_KEYS, array(), '', $keys, $stat);
 
             // If an array is returned, $sql was a query, otherwise an 'insert', 'update', 'delete', ...
             // Query: total nummber of rows
diff --git a/extension/qfq/qfq/report/Utils.php b/extension/qfq/qfq/report/Utils.php
deleted file mode 100644
index e2fe65e05d55111eae03c436d6bb7741ba28b976..0000000000000000000000000000000000000000
--- a/extension/qfq/qfq/report/Utils.php
+++ /dev/null
@@ -1,132 +0,0 @@
-<?php
-/***************************************************************
- *  Copyright notice
- *
- *  (c) 2010 Glowbase GmbH <support@glowbase.com>
- *  All rights reserved
- *
- ***************************************************************/
-
-namespace qfq;
-
-//use qfq;
-
-require_once(__DIR__ . '/Define.php');
-require_once(__DIR__ . '/Db.php');
-
-
-class Utils {
-    /**
-     * @var Db
-     */
-    private $db = null;
-
-    /**
-     * @param $db
-     */
-    public function __construct($db = null) {
-        //TODO: Im Original nachschauen woher die globale Variable $Db kommt??? Ubergangsweise hier im Konstruktor plaziert. Wird aber aktuell nicht initialisiert!!!
-        $this->db = null;
-    }
-
-    /**
-     * If record locking has been enabled in ext_localconf.php, create a record in the lock table
-     *
-     * @param string $form
-     * @param int $record_id
-     * @param string $tablename
-     * @param string $dbalias
-     * @param $tx_db_pi1
-     */
-    function setLockRecord($form, $record_id, $tablename, $dbalias, &$tx_db_pi1) {
-        $result = '';
-        $mode = $GLOBALS['TYPO3_CONF_VARS'][FORMREPORT]['lock_records']['mode'];
-        if ($mode == "warn" || $mode == "lock") {
-            $query = "INSERT INTO `" . FR_LOCK . "` (`phpsession_id`, `fe_user_uid`, `form`, `record_id`, `tablename`, `dbalias`) VALUES ('" . session_id() . "', '" . $GLOBALS["TSFE"]->fe_user->user["uid"] . "', '" . $form . "', '" . $record_id . "', '" . $tablename . "', '" . $dbalias . "')";
-            $this->db->doQuery(DB, $query, $result, ROW_EXPECT_0);
-        } // if
-    } // randomAlphaNumUnique()
-
-    /**
-     * If record locking has been enabled in ext_localconf.php,
-     *    delete all expired locking records
-     *    check if a record exists in the lock table for the currently edited record
-     *
-     * @param int $form form_id
-     * @param int $record_id record_id
-     * @param string $tablename tablename
-     * @param Db $dbalias Db class object
-     * @param $tx_db_pi1
-     * @return array|bool           information on locking mode, locking user and timestamp. false if not locked
-     */
-    function checkLockRecord($form, $record_id, $tablename, $dbalias, &$tx_db_pi1) {
-        // Get config values from localconf or use default from define.php
-        $mode = $GLOBALS['TYPO3_CONF_VARS'][FORMREPORT]['lock_records']['mode'];
-        $interval = ($GLOBALS['TYPO3_CONF_VARS'][FORMREPORT]['lock_records']['interval']) ?: LOCK_RECORDS_INTERVAL;
-
-        if ($mode == "warn" || $mode == "lock") {
-            // Delete all expired locking records
-            $query = "DELETE FROM `" . FR_LOCK . "` WHERE timestamp + INTERVAL " . $GLOBALS['TYPO3_CONF_VARS'][FORMREPORT]['lock_records']['interval'] . " SECOND < NOW()";
-            $this->db->doQuery(DB, $query, $result, ROW_EXPECT_0);
-
-            // Check if locking records exist
-            $query = "SELECT fe_user_uid, phpsession_id, date_format(timestamp + INTERVAL " . $interval . " SECOND, \"%H:%i %d.%m.%Y\") as lock_endtime FROM `" . FR_LOCK . "` WHERE `record_id`='" . $record_id . "' and `tablename`='" . $tablename . "' and `dbalias`='" . $dbalias . "' LIMIT 1";
-            $this->db->doQuery(DB, $query, $result, ROW_REGULAR);
-
-            // If result is empty, return false
-            if (empty($result))
-                return false;
-
-            // If user is the same as the current one, return false
-            // Compare fe_user_uid and session-id
-            if ($result[0]['phpsession_id'] == session_id())
-                return false;
-
-            // Build array with locking information - will be used to create a warning/error message etc.
-            $arr = array();
-            $arr['mode'] = $mode;
-            $arr['fe_user_uid'] = $result[0]['fe_user_uid'];
-            $arr['lock_endtime'] = $result[0]['lock_endtime'];
-            return $arr;
-
-        } // if
-        // no locking configured
-        return false;
-    } // eo setLockRecord
-
-    /**
-     * Returns username for a fe_user_uid
-     *
-     * @param int $uid fe_user_uid
-     * @param $tx_db_pi1
-     * @return string       username
-     */
-    function getFEUserName($uid, &$tx_db_pi1) {
-        $query = "SELECT username FROM `fe_users` WHERE `uid`='" . $uid . "'";
-        $this->db->doQuery(T3, $query, $result, ROW_EXPECT_1);
-        $username = ($result['username']) ?: "anonymous";
-        return $username;
-    } // eo setLockRecord
-
-    /**
-     * Create a unique directory in $path
-     *
-     * @param $path
-     * @return string
-     * @throws CodeReportException
-     */
-    function createUniqueDir($path) {
-        // Try max. 20 times
-        for ($i = 0; $i < 20; $i++) {
-            $dirname = Support::randomAlphaNum(5);
-            $dirpath = $path . "/" . $dirname;
-
-            if (!file_exists($dirpath)) {
-                mkdir($dirpath, 0700, true);
-                return $dirpath;
-            }
-        }
-        // Too many tries without success
-        throw new CodeReportException ("Could not create unique directory.", __FILE__, __LINE__);
-    }
-}
diff --git a/extension/qfq/qfq/store/FillStoreForm.php b/extension/qfq/qfq/store/FillStoreForm.php
index 52e7b4a616a55ded76344a711562d3e23aa599cc..604f15ec3195c94819c11e1c32c982933b5ed909 100644
--- a/extension/qfq/qfq/store/FillStoreForm.php
+++ b/extension/qfq/qfq/store/FillStoreForm.php
@@ -104,6 +104,11 @@ class FillStoreForm {
             }
         }
 
+        // Check if there is a 'new record already saved' situation:
+        // yes: the names of the input fields are submitted with '<fieldname>:0' instead of '<fieldname>:<id>'
+        // no: regular situation, take real 'recordid'
+        $fakeRecordId = isset($sipValues[SIP_MAKE_URLPARAM_UNIQ]) ? 0 : $sipValues[SIP_RECORD_ID];
+
         // Iterate over all formelements. Sanatize values. Built an assoc array $newValues.
         foreach ($this->feSpecNative AS $formElement) {
 
@@ -118,7 +123,7 @@ class FillStoreForm {
             $formElement = $this->evaluate->parseArray($formElement, $debugStack);
 
             // Get related formElement. Construct the field name used in the form.
-            $clientFieldName = HelperFormElement::buildFormElementName($formElement['name'], $sipValues[SIP_RECORD_ID]);
+            $clientFieldName = HelperFormElement::buildFormElementName($formElement['name'], $fakeRecordId);
 
             // Some Defaults
             $formElement = Support::setFeDefaults($formElement);
@@ -155,8 +160,13 @@ class FillStoreForm {
                                 $newValues[$formElement['name']] = $this->doDateTime($formElement, $clientValues[$clientFieldName]);
                             break;
                         default:
-                            $newValues[$formElement['name']] = Sanitize::sanitize($clientValues[$clientFieldName],
-                                $formElement['checkType'], $formElement['checkPattern'], SANATIZE_EXCEPTION);
+                            // Check only if their is something
+                            if($clientValues[$clientFieldName] !== '') {
+                                $newValues[$formElement['name']] = Sanitize::sanitize($clientValues[$clientFieldName],
+                                    $formElement['checkType'], $formElement['checkPattern'], SANATIZE_EXCEPTION);
+                            } else {
+                                $newValues[$formElement['name']] ='';
+                            }
                             break;
                     }
                 }
diff --git a/extension/qfq/qfq/store/Session.php b/extension/qfq/qfq/store/Session.php
index d1be743631b66dc3c3609bfc755a60ba5ea628dd..9d0634de9c955b53ad5e6db9ffd54406f0d52e4f 100644
--- a/extension/qfq/qfq/store/Session.php
+++ b/extension/qfq/qfq/store/Session.php
@@ -47,6 +47,7 @@ class Session {
 
         $feUserUidSession = Session::get(SESSION_FE_USER_UID);
         $feUserSession = Session::get(SESSION_FE_USER);
+        $feUserGroup = false;
 
         if (isset($GLOBALS["TSFE"])) {
             // if noone is logged in: 0
@@ -60,7 +61,7 @@ class Session {
 
         if ($feUidLoggedIn !== $feUserUidSession) {
             // destroy existing session store
-            Session::clear();
+            Session::clearAll();
 
             // save new feUserUid, feUserName
             Session::set(SESSION_FE_USER_UID, $feUidLoggedIn);
@@ -97,7 +98,7 @@ class Session {
     /**
      *
      */
-    public static function clear() {
+    public static function clearAll() {
 
         if (self::$phpUnit) {
             self::$sessionLocal = array();
@@ -119,6 +120,19 @@ class Session {
         }
     }
 
+    /**
+     * Unset the given $key
+     *
+     * @param $key
+     */
+    public static function unsetItem($key) {
+
+        if (isset($_SESSION[SESSION_NAME][$key])) {
+            unset($_SESSION[SESSION_NAME][$key]);
+        }
+
+    }
+
     /**
      * @param bool|false $phpUnit
      * @return Session class
diff --git a/extension/qfq/qfq/store/Sip.php b/extension/qfq/qfq/store/Sip.php
index 24f9e7ffa34d755797ed240d16bde1e8783e72df..5051499f5a1d0caabfb877ef71aa9fc2b249a54e 100644
--- a/extension/qfq/qfq/store/Sip.php
+++ b/extension/qfq/qfq/store/Sip.php
@@ -67,11 +67,8 @@ class Sip {
         // Split parameter between Script, Client and SIP
         $script = $this->splitParamClientSip($paramArray, $clientArray, $sipArray);
 
-        // sort array to guarantee identical respresentation in $_SESSION. Param 'a, r, b, ...' should be saved as 'a, b, r, ..'
-        OnArray::sortKey($sipArray);
-
         // Generate keyname for $_SESSION[]
-        $sipParamString = OnArray::toString($sipArray);
+        $sipParamString = $this->buildParamStringFromArray($sipArray);
 
         $sessionParamSip = Session::get($sipParamString);
         if ($sessionParamSip === false) {
@@ -184,6 +181,34 @@ class Sip {
         return $script;
     }
 
+    /**
+     * Takes the values form an array and creates a urlparamstring. Skip values which should no passed to the urlparamstring.
+     *
+     * @param array $sipArray
+     * @return string
+     */
+    private function buildParamStringFromArray(array $sipArray) {
+        $tmpArray = array();
+
+        foreach ($sipArray as $key => $value) {
+            switch ($key) {
+                case SIP_SIP:
+                case SIP_TARGET_URL:
+//                case SIP_MODE_ANSWER:
+//                case SIP_TABLE:
+                case SIP_URLPARAM:
+                    break;
+                default:
+                    $tmpArray[$key] = $value;
+                    break;
+            }
+        }
+
+        OnArray::sortKey($tmpArray);
+
+        return OnArray::toString($tmpArray);
+    }
+
     /**
      * Returns a new uniqid, which will be used as a SIP identifier
      *
@@ -201,6 +226,25 @@ class Sip {
         return uniqid();
     }
 
+    /**
+     * Update the SIP in the Session according $sipArray.
+     *
+     * @param array $sipArray
+     */
+    public function updateSipToSession(array $sipArray) {
+        $sip = $sipArray[SIP_SIP];
+
+        // Remove old entry, cause the the 'key' will change.
+        $sipParamStringOld = Session::get($sipArray[SIP_SIP]);
+        Session::unsetItem($sipParamStringOld);
+
+        // Generate keyname for $_SESSION[]
+        $sipParamStringNew = $this->buildParamStringFromArray($sipArray);
+
+        Session::set($sip, $sipParamStringNew);
+        Session::set($sipParamStringNew, $sip);
+    }
+
     /**
      * Retrieve Params stored in $_SESSION[$s]
      *
@@ -212,7 +256,7 @@ class Sip {
     public function getVarsFromSip($s) {
 
         # Check if parameter is manipulated
-        if (strlen($s) != 13) {
+        if (strlen($s) != SIP_TOKEN_LENGTH) {
             throw new UserFormException("Broken Parameter", ERROR_BROKEN_PARAMETER);
         }
 
diff --git a/extension/qfq/qfq/store/Store.php b/extension/qfq/qfq/store/Store.php
index 055b471c459688848e395bb67d5df359fa1cf258..cffcd4cd5cdd956845e30345894a9b93b911539e 100644
--- a/extension/qfq/qfq/store/Store.php
+++ b/extension/qfq/qfq/store/Store.php
@@ -167,14 +167,29 @@ class Store {
     }
 
     /**
+     * Fills the system store.
+     *
      * @throws CodeException
      * @throws qfq\UserFormException
      */
     private static function fillSystemStore() {
+
+        // PHPUnit Path to CONFIG_INI
+        $configIni = __DIR__ . '/../../../' . CONFIG_INI;
+        if (!file_exists($configIni)) {
+            // Production Path to CONFIG_INI
+            $configIni = __DIR__ . '/../../../../../' . CONFIG_INI;
+
+            if (!file_exists($configIni)) {
+                throw new qfq\UserFormException ("Config not found: " . getcwd() . "/" . $configIni, ERROR_IO_READ_FILE);
+            }
+        }
+
         try {
             //TODO: Vernuenftige Fehlermeldung falls nicht auf qfq.ini zugegriffen werden kann.
             //TODO: sinnvollen Platz fuer qfq.ini bestimmen. In der Installationsdoku erwaehnen.
-            $config = parse_ini_file(__DIR__ . '/../../../' . CONFIG_INI, false);
+//            $config = parse_ini_file(__DIR__ . '/../../../' . CONFIG_INI, false);
+            $config = parse_ini_file($configIni, false);
 
             //TODO: auskommentiert weil dann die Unittests nicht mehr laufen. Sollte eigentlich wieder aktiviert werden.
 //            $config['SQLLOG'] = Support::ifRelativePathPrependExtensionPath($config['SQLLOG']);
@@ -232,6 +247,8 @@ class Store {
     }
 
     /**
+     * Set or overwrite a complete store.
+     *
      * @param array $dataArray
      * @param $store
      * @param bool|false $flagOverwrite
@@ -311,6 +328,8 @@ class Store {
     }
 
     /**
+     * Fills the STORE_CLIENT
+     *
      * @throws CodeException
      */
     private static function fillStoreClient() {
@@ -329,6 +348,8 @@ class Store {
     }
 
     /**
+     * Fills the STORE_SIP. Reads therefore specified SIP, decode the values and stores them in STORE_SIP.
+     *
      * @throws CodeException
      * @throws UserFormException
      */
@@ -413,6 +434,8 @@ class Store {
     }
 
     /**
+     * Fills the STORE_EXTRA.
+     *
      * @throws UserFormException
      * @throws \qfq\CodeException
      */
@@ -432,6 +455,8 @@ class Store {
     }
 
     /**
+     * Returns a pointer to this Class.
+     *
      * @param string $bodytext
      * @param bool|false $phpUnit
      * @return null|\qfq\Store
@@ -471,6 +496,8 @@ class Store {
     }
 
     /**
+     * Deletes a store assigning a new empty array to it.
+     *
      * @param $store
      * @throws UserFormException
      * @throws \qfq\CodeException
@@ -490,6 +517,8 @@ class Store {
     }
 
     /**
+     * Set's a single $key/$value pair $store.
+     *
      * @param string $key
      * @param string|array $value
      * @param string $store
@@ -527,6 +556,8 @@ class Store {
     }
 
     /**
+     * Create a SIP after a form load. This is necessary on forms without a sip and on forms with r=0 (new record).
+     *
      * @param $formName
      * @throws CodeException
      */
@@ -537,7 +568,16 @@ class Store {
             $recordId = 0;
         }
 
-        $tmpParam = [SIP_RECORD_ID => $recordId, SIP_FORM => $formName];
+        // If there are existing SIP param, keep them by copying to the new SIP Param Array
+        $tmpParam = self::getNonSystemSipParam();
+
+        $tmpParam[SIP_RECORD_ID] = $recordId;
+        $tmpParam[SIP_FORM] = $formName;
+
+        if ($recordId == 0) {
+            // SIPs for 'new records' needs to be uniq per TAB! Therefore add a uniq parameter
+            $tmpParam[SIP_MAKE_URLPARAM_UNIQ] = uniqid();
+        }
 
         // Construct fake urlparam
         $tmpUrlparam = OnArray::toString($tmpParam);
@@ -553,13 +593,37 @@ class Store {
     }
 
     /**
-     * @return null|Sip
+     * Return an array with non system SIP parameter. Take the whole STORE_SIP and search for non system parameter.
+     * @return array
+     * @throws UserFormException
+     * @throws \qfq\CodeException
      */
-    public static function getSipInstance() {
-        return self::$sip;
+    private static function getNonSystemSipParam() {
+        $tmpParam = array();
+
+        $sipArray = self::getStore(STORE_SIP);
+
+        foreach ($sipArray as $key => $value) {
+            if ($key[0] === '_') {
+                continue;
+            }
+            switch ($key) {
+                case SIP_SIP:
+                case SIP_RECORD_ID:
+                case SIP_FORM;
+                case SIP_URLPARAM:
+                    continue;
+                default:
+                    $tmpParam[$key] = $value;
+            }
+        }
+
+        return $tmpParam;
     }
 
     /**
+     * Returns a complete $store.
+     *
      * @param $store
      * @return array
      * @throws UserFormException
@@ -580,6 +644,14 @@ class Store {
         return array();
     }
 
+    /**
+     * Returns a pointer to this class.
+     *
+     * @return null|Sip
+     */
+    public static function getSipInstance() {
+        return self::$sip;
+    }
 
     /**
      * Fills STORE_TABLE_DEFAULT and STORE_TABLE_COLUMN_TYPES
diff --git a/extension/qfq/sql/formEditor.sql b/extension/qfq/sql/formEditor.sql
index 22ccc0e5eed3aa0725ea078145493b8c24d7fc4d..ff4724af80fe502be8bcc5cf3383ee4dde81837f 100644
--- a/extension/qfq/sql/formEditor.sql
+++ b/extension/qfq/sql/formEditor.sql
@@ -1,4 +1,4 @@
-DROP TABLE IF EXISTS `Form`;
+#DROP TABLE IF EXISTS `Form`;
 CREATE TABLE IF NOT EXISTS `Form` (
   `id`                       INT(11)                                                   NOT NULL  AUTO_INCREMENT,
   `name`                     VARCHAR(255)                                              NOT NULL  DEFAULT '',
@@ -53,7 +53,7 @@ CREATE TABLE IF NOT EXISTS `Form` (
 # ----------------------------------------
 # FormElement
 
-DROP TABLE IF EXISTS `FormElement`;
+#DROP TABLE IF EXISTS `FormElement`;
 CREATE TABLE IF NOT EXISTS `FormElement` (
   `id`              INT(11)                                                                                 NOT NULL  AUTO_INCREMENT,
   `formId`          INT(11)                                                                                 NOT NULL,
@@ -120,6 +120,13 @@ CREATE TABLE IF NOT EXISTS `FormElement` (
 #//
 #DELIMITER ;
 
+# Delete previous FormElements (if exist)
+DELETE FormElement FROM FormElement, Form
+WHERE Form.name LIKE 'form' OR Form.name LIKE 'formElement' AND Form.id = FormElement.formId;
+
+# Delete previous Forms (if exist)
+DELETE FROM Form
+WHERE name LIKE 'form' OR name LIKE 'formElement';
 
 #
 # FormEditor: Form
@@ -167,7 +174,7 @@ VALUES
    '', '', '', '', 4, '', ''),
 
   (1, '', 'FormElements', 'show', 'subrecord', 'all', 'native', 500, 0, 0, '', '', '',
-   '{{!SELECT IF( fe.enabled="yes", IF( fe.enabled="yes" AND fe.feIdContainer=0 AND !ISNULL(feCX.id) AND fe.class="native", "danger", IF( fe.class="container", "text-info",  IF( fe.class="action", "text-success", ""))), "text-muted") AS _rowClass, IF( fe.enabled="yes", IF(fe.feIdContainer=0 AND !ISNULL(feCX.id) AND fe.class="native", "Please choose a container for this formelement", fe.class), "Disabled") AS _rowTitle, fe.id, CONCAT( IFNULL( CONCAT( feC.name, " (", fe.feIdContainer, ")"),"")) AS Container, fe.name, fe.label, fe.mode, fe.class,	fe.type, fe.ord, fe.size, fe.sql1, fe.parameter FROM FormElement AS fe LEFT JOIN FormElement AS feC ON feC.id=fe.feIdContainer AND feC.formId=fe.formId LEFT JOIN FormElement AS feCX ON feCX.class="container" AND feCX.enabled="yes" AND feCX.formId=fe.formId WHERE fe.formId={{id:R0}} GROUP BY fe.id ORDER BY fe.class DESC, fe.feIdContainer, fe.ord, fe.id}}',
+   '{{!SELECT IF( fe.enabled="yes", IF( fe.enabled="yes" AND fe.feIdContainer=0 AND !ISNULL(feCX.id) AND fe.class="native", "danger", IF( fe.class="container", "text-info",  IF( fe.class="action", "text-success", ""))), "text-muted") AS _rowClass, IF( fe.enabled="yes", IF(fe.feIdContainer=0 AND !ISNULL(feCX.id) AND fe.class="native", "Please choose a container for this formelement", fe.class), "Disabled") AS _rowTitle, fe.id, CONCAT( IFNULL( CONCAT( feC.name, " (", fe.feIdContainer, ")"),"")) AS Container, fe.name, fe.label, fe.mode, fe.class,	fe.type, fe.ord, fe.size, fe.sql1, fe.parameter FROM FormElement AS fe LEFT JOIN FormElement AS feC ON feC.id=fe.feIdContainer AND feC.formId=fe.formId LEFT JOIN FormElement AS feCX ON feCX.class="container" AND feCX.enabled="yes" AND feCX.formId=fe.formId WHERE fe.formId={{id:R0}} GROUP BY fe.id ORDER BY fe.class DESC, feC.ord, fe.ord, fe.id}}',
    '', 'form=formElement\ndetail=id:formId', 5, 'new,edit,delete', '');
 
 #
@@ -199,7 +206,7 @@ VALUES
    ''),
   (2, 'formId', 'formId', 'readonly', 'text', 'all', 'native', 110, 0, 255, '', '', '', '', '', '', 100, '', 'no', '', '', '', ''),
   (2, 'feIdContainer', 'Container', 'show', 'select', 'all', 'native', 120, 0, 0, '', '', '',
-   '{{!SELECT fe.id, CONCAT(fe.class, " / ", fe.label) FROM FormElement As fe WHERE fe.formId={{formId}} AND fe.class="container" ORDER BY fe.ord }}',
+   '{{!SELECT fe.id, CONCAT(fe.class, " / ", fe.label) FROM FormElement As fe WHERE fe.formId={{formId:S0}} AND fe.class="container" ORDER BY fe.ord }}',
    '', 'emptyItemAtStart', 100, '', 'no', '', '', '', ''),
   (2, 'enabled', 'Enabled', 'show', 'checkbox', 'all', 'native', 130, 0, 0, '', '', '', '', '', '', 100, '', 'no', '', '', '', ''),
   (2, 'dynamicUpdate', 'Dynamic Update', 'show', 'checkbox', 'all', 'native', 135, 0, 0, 'On change, this element will be updated and trigger other.', '', '', '', '', '', 100, '', 'no', '3', '2', '7', ''),
diff --git a/extension/qfq/tests/phpunit/SanitizeTest.php b/extension/qfq/tests/phpunit/SanitizeTest.php
index 21526314e6e07c77b7f7cea670e71c5a830ab004..24f02a2a076f386fd8a1dad3c15f5e9033e91b45 100644
--- a/extension/qfq/tests/phpunit/SanitizeTest.php
+++ b/extension/qfq/tests/phpunit/SanitizeTest.php
@@ -30,6 +30,7 @@ class SanitizeTest extends \PHPUnit_Framework_TestCase {
         $this->assertEquals('', Sanitize::sanitize('', SANITIZE_ALLOW_EMAIL), "SANITIZE_EMAIL fails");
         $this->assertEquals('', Sanitize::sanitize('', SANITIZE_ALLOW_PATTERN, '.*'), "SANITIZE_PATTERN fails");
         $this->assertEquals('', Sanitize::sanitize('', SANITIZE_ALLOW_ALL), "SANITIZE_ALL fails");
+        $this->assertEquals('', Sanitize::sanitize('', SANITIZE_ALLOW_ALLBUT), "SANITIZE_ALLBUT fails");
 
         # Check '1'
         $this->assertEquals('1', Sanitize::sanitize('1', SANITIZE_ALLOW_ALNUMX), "SANITIZE_ALNUMX fails");
@@ -38,6 +39,7 @@ class SanitizeTest extends \PHPUnit_Framework_TestCase {
         $this->assertEquals('', Sanitize::sanitize('1', SANITIZE_ALLOW_EMAIL), "SANITIZE_EMAIL fails");
         $this->assertEquals('1', Sanitize::sanitize('1', SANITIZE_ALLOW_PATTERN, '.*'), "SANITIZE_PATTERN fails");
         $this->assertEquals('1', Sanitize::sanitize('1', SANITIZE_ALLOW_ALL), "SANITIZE_ALL fails");
+        $this->assertEquals('1', Sanitize::sanitize('1', SANITIZE_ALLOW_ALLBUT), "SANITIZE_ALLBUT fails");
 
         # Check '-3'
         $this->assertEquals('-3', Sanitize::sanitize('-3', SANITIZE_ALLOW_ALNUMX), "SANITIZE_ALNUMX fails");
@@ -46,6 +48,7 @@ class SanitizeTest extends \PHPUnit_Framework_TestCase {
         $this->assertEquals('', Sanitize::sanitize('-3', SANITIZE_ALLOW_EMAIL), "SANITIZE_EMAIL fails");
         $this->assertEquals('-3', Sanitize::sanitize('-3', SANITIZE_ALLOW_PATTERN, '.*'), "SANITIZE_PATTERN fails");
         $this->assertEquals('-3', Sanitize::sanitize('-3', SANITIZE_ALLOW_ALL), "SANITIZE_ALL fails");
+        $this->assertEquals('-3', Sanitize::sanitize('-3', SANITIZE_ALLOW_ALLBUT), "SANITIZE_ALLBUT fails");
 
         # Check 'a'
         $this->assertEquals('a', Sanitize::sanitize('a', SANITIZE_ALLOW_ALNUMX), "SANITIZE_ALNUMX fails");
@@ -54,6 +57,7 @@ class SanitizeTest extends \PHPUnit_Framework_TestCase {
         $this->assertEquals('', Sanitize::sanitize('a', SANITIZE_ALLOW_EMAIL), "SANITIZE_EMAIL fails");
         $this->assertEquals('a', Sanitize::sanitize('a', SANITIZE_ALLOW_PATTERN, '.*'), "SANITIZE_PATTERN fails");
         $this->assertEquals('a', Sanitize::sanitize('a', SANITIZE_ALLOW_ALL), "SANITIZE_ALL fails");
+        $this->assertEquals('a', Sanitize::sanitize('a', SANITIZE_ALLOW_ALLBUT), "SANITIZE_ALLBUT fails");
 
 
         # Check 'a@-_.,;Z09'
@@ -64,6 +68,7 @@ class SanitizeTest extends \PHPUnit_Framework_TestCase {
         $this->assertEquals('', Sanitize::sanitize($val, SANITIZE_ALLOW_EMAIL), "SANITIZE_EMAIL fails");
         $this->assertEquals($val, Sanitize::sanitize($val, SANITIZE_ALLOW_PATTERN, '.*'), "SANITIZE_PATTERN fails");
         $this->assertEquals($val, Sanitize::sanitize($val, SANITIZE_ALLOW_ALL), "SANITIZE_ALL fails");
+        $this->assertEquals($val, Sanitize::sanitize($val, SANITIZE_ALLOW_ALLBUT), "SANITIZE_ALLBUT fails");
 
         # Check 'a+Z09'
         $val = 'a+Z09';
@@ -73,6 +78,7 @@ class SanitizeTest extends \PHPUnit_Framework_TestCase {
         $this->assertEquals('', Sanitize::sanitize($val, SANITIZE_ALLOW_EMAIL), "SANITIZE_EMAIL fails");
         $this->assertEquals($val, Sanitize::sanitize($val, SANITIZE_ALLOW_PATTERN, '.*'), "SANITIZE_PATTERN fails");
         $this->assertEquals($val, Sanitize::sanitize($val, SANITIZE_ALLOW_ALL), "SANITIZE_ALL fails");
+        $this->assertEquals($val, Sanitize::sanitize($val, SANITIZE_ALLOW_ALLBUT), "SANITIZE_ALLBUT fails");
     }
 
     /**
@@ -184,6 +190,29 @@ class SanitizeTest extends \PHPUnit_Framework_TestCase {
         $this->assertEquals($val, Sanitize::sanitize($val, SANITIZE_ALLOW_PATTERN, '(John)*'), "SANITIZE_ALLOW_PATTERN fails");
     }
 
+    //[ ]  { } % & \ #
+    /**
+     */
+    public function testSanitizeExceptionAllBut() {
+        $bad = "[]{}%&\\#";
+        $good = 'abCD01`~!@$^*()_+=-|":;.,<>/?\'';
+
+        // Single
+        $this->assertEquals('', Sanitize::sanitize('[', SANITIZE_ALLOW_ALLBUT), "SANITIZE_ALLOW_ALLBUT fails");
+        $this->assertEquals('a', Sanitize::sanitize('a', SANITIZE_ALLOW_ALLBUT), "SANITIZE_ALLOW_ALLBUT fails");
+
+
+        for ($i = 0; $i < strlen($bad); $i++) {
+            $str = '-' . substr($bad, $i, 1) . '-';
+            $this->assertEquals('', Sanitize::sanitize($str, SANITIZE_ALLOW_ALLBUT), "SANITIZE_ALLOW_ALLBUT fails");
+        }
+
+        for ($i = 0; $i < strlen($good); $i++) {
+            $str = '-' . substr($good, $i, 1) . '-';
+            $this->assertEquals($str, Sanitize::sanitize($str, SANITIZE_ALLOW_ALLBUT), "SANITIZE_ALLOW_ALLBUT fails");
+        }
+    }
+
     /**
      * @expectedException \qfq\CodeException
      */
@@ -225,5 +254,4 @@ class SanitizeTest extends \PHPUnit_Framework_TestCase {
     public function testSanitizeExceptionCheckFailed() {
         Sanitize::sanitize('string', SANITIZE_ALLOW_DIGIT, '', SANATIZE_EXCEPTION);
     }
-
 }
diff --git a/extension/qfq/tests/phpunit/SessionTest.php b/extension/qfq/tests/phpunit/SessionTest.php
index 89daa9500ae778bbf08ca27699444db9e1f92b82..d2c74a3938cf1771defe03f2ecd414b15aaf29a7 100644
--- a/extension/qfq/tests/phpunit/SessionTest.php
+++ b/extension/qfq/tests/phpunit/SessionTest.php
@@ -62,7 +62,7 @@ class SessionTest extends \PHPUnit_Framework_TestCase {
         // write/read data1
         Session::set('var1', 'data1');
 
-        Session::clear();
+        Session::clearAll();
 
         $val = Session::get('var1');
         $this->assertEquals(false, $val);