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

Implemented new escape class 'mysql' (realEscapeString).

Implemented defaultEscapeType. configurable via config.qfq.ini (global) and per Form.
Implemented max GET parameter lenght. Default: 50. BTW: in phpunit test there have been a parameter 'file' which exceeds the limit of 32.

Config.qfq: Skip empty variable names - happens in phpunit tests. Read new `systemEscapeTypeDefault`.
Constants.php: renamed  TOKEN_LDAP_ESCAPE_* to TOKEN_ESCAPE_LDAP_*. Add TOKEN_ESCAPE_MYSQL, TOKEN_ESCAPE_NONE
Database.php: Set charset to real_escape_string() functions properly. Proxy for mysqli::real_escape_string()
Evaluate.php: Respect global escapeTypeDefault. Implement
formEditor.sql: add column `escapeTypeDefault`. Add FormElement 'escapeTypeDefault'.
parent cb2784bd
......@@ -245,6 +245,14 @@ config.qfq.ini
+-----------------------------+-------------------------------------------------+ crendentials is supported. |
| LDAP_1_PASSWORD | LDAP_1_PASSWORD=mySecurePassword | |
+-----------------------------+-------------------------------------------------+----------------------------------------------------------------------------+
| SECURITY_VARS_HONEYPOT | SECURITY_VARS_HONEYPOT = email,username,password| If empty: no check. All named variables will rendered as INPUT elements |
+-----------------------------+-------------------------------------------------+----------------------------------------------------------------------------+
| SECURITY_ATTACK_DELAY | SECURITY_ATTACK_DELAY = 5 | If an attack is detected, sleep 'x' seconds and exit PHP process |
+-----------------------------+-------------------------------------------------+----------------------------------------------------------------------------+
| SECURITY_SHOW_MESSAGE | SECURITY_SHOW_MESSAGE = true | If an attack is detected, show a message |
+-----------------------------+-------------------------------------------------+----------------------------------------------------------------------------+
| SECURITY_GET_MAX_LENGTH | SECURITY_GET_MAX_LENGTH = 32 | Check that there are no GET vars longer than 'x' chars |
+-----------------------------+-------------------------------------------------+----------------------------------------------------------------------------+
Example: *typo3conf/config.qfq.ini*
......@@ -278,6 +286,10 @@ Example: *typo3conf/config.qfq.ini*
;EDIT_FORM_PAGE = form
;LDAP_1_RDN='ou=Admin,dc=example,dc=com'
;LDAP_1_PASSWORD=mySecurePassword
;SECURITY_VARS_HONEYPOT=email,username,password
;SECURITY_ATTACK_DELAY=5
;SECURITY_SHOW_MESSAGE=true
;SECURITY_GET_MAX_LENGTH=32
.. _local-documentation:
......@@ -507,8 +519,13 @@ All values passed to QFQ will be:
Get Parameter
-------------
Get parameter might contain urlencoded content (%xx). 'urldDecode' all GET parameter.
GET parameter might contain urlencoded content (%xx). 'urldDecode' all GET parameter.
The string length of GET parameter is limited on SECURITY_GET_MAX_LENGTH chars (see `config.qfq.ini`_)
**QFQ security restiction**:
* '%nn' in GET variables will always be decoded. It's not possible to transfer '%nn' itself.
* GET variables are limited to SECURITY_GET_MAX_LENGTH chars - any violation will break QFQ.
Post Parameter
--------------
......@@ -520,15 +537,26 @@ required, the encoding can be disabled per FormElement. During Form load, the ht
$_SERVER
--------
All $_SERVER vars are htmlentities (all, not only specialchars) encoded.
All $_SERVER vars are htmlentities (all, not only specialchars!) encoded.
Honeypot
--------
Every QFQ Form contains 'honeypot'-HTML input elements (hidden & readonly). Which to use is configured in `config.qfq.ini`_
(default: 'username', 'password' and 'email'). Independet of the QFQ Form, on every start of QFQ these variables are
tested if they are non-empty and if 'yes', QFQ will sleep <x> seconds and than exit the running PHP process (prevent
brute force attacks) - an detected attack leads to a complete white (=empty) page. By default an error message is displayed.
(default: 'username', 'password' and 'email'). Independet of the QFQ Form, on every start of QFQ, these variables are
tested if they are non-empty.
**QFQ security restiction**:
* The honeypot variables can't be used in GET or POST as regular HTML input elements - any use of it will break QFQ.
Violation
---------
On any violation, QFQ will sleep SYSTEM_SECURITY_ATTACK_DELAY seconds (`config.qfq.ini`_) and than exit the running PHP process.
A detected attack leads to a complete white (=empty) page.
If SECURITY_SHOW_MESSAGE == true (`config.qfq.ini`_), a message is displayed.
SIP
---
......
......@@ -54,6 +54,10 @@ WKHTMLTOPDF = /opt/wkhtmltox/bin/wkhtmltopdf
;LDAP_1_RDN =
;LDAP_1_PASSWORD =
;ESCAPE_TYPE_DEFAULT=s
;SECURITY_VARS_HONEYPOT=email,username,password
;SECURITY_ATTACK_DELAY=5
;SECURITY_SHOW_MESSAGE=true
\ No newline at end of file
;SECURITY_SHOW_MESSAGE=true
;SECURITY_GET_MAX_LENGTH=50
......@@ -291,6 +291,10 @@ abstract class AbstractBuildForm {
// Iterate over all fake vars
$arr = explode(',', $vars);
foreach ($arr as $name) {
$name = trim($name);
if ($name === '') {
continue;
}
$html .= "<input name='$name' type='hidden' value='' readonly>";
}
......
......@@ -233,6 +233,7 @@ const ERROR_DB_UNKNOWN_COLUMN = 2011;
const ERROR_DB_UNKNOWN_COMMAND = 2012;
const ERROR_DB_MISSING_COLUMN_ID = 2013;
const ERROR_DB_COLUMN_NOT_FOUND_IN_TABLE = 2014;
const ERROR_DB_SET_CHARSET = 2015;
// onArray
const ERROR_SUBSTITUTE_FOUND = 2100;
......@@ -350,6 +351,16 @@ const SYSTEM_EDIT_FORM_PAGE = 'EDIT_FORM_PAGE';
const SYSTEM_PATH_EXT = 'EXT_PATH';
const SYSTEM_SITE_PATH = 'SITE_PATH';
const SYSTEM_LDAP_1_RDN = 'LDAP_1_RDN'; // Credentials to access LDAP
const SYSTEM_LDAP_1_PASSWORD = 'LDAP_1_PASSWORD'; // Credentials to access LDAP
const SYSTEM_ESCAPE_TYPE_DEFAULT = 'ESCAPE_TYPE_DEFAULT';
const SYSTEM_SECURITY_VARS_HONEYPOT = 'SECURITY_VARS_HONEYPOT'; // Fake variables
const SYSTEM_SECURITY_ATTACK_DELAY = 'SECURITY_ATTACK_DELAY'; // Detected attack causes x seconds delay
const SYSTEM_SECURITY_SHOW_MESSAGE = 'SECURITY_SHOW_MESSAGE'; // Detected attack shows an error message
const SYSTEM_SECURITY_GET_MAX_LENGTH = 'SECURITY_GET_MAX_LENGTH'; // Trim every character (before conversion) to SECURITY_GET_MAX_LENGTH chars;
// Not stored in config.qfq.ini, but used in STORE_SYSTEM
// Information for: Log / Debug / Exception
const SYSTEM_SQL_RAW = 'sqlRaw'; // Type: SANITIZE_ALL / String. SQL Query (before substitute). Useful for error reporting.
const SYSTEM_SQL_FINAL = 'sqlFinal'; // Type: SANITIZE_ALL / String. SQL Query (after substitute). Useful for error reporting.
......@@ -363,15 +374,6 @@ const SYSTEM_REPORT_COLUMN_INDEX = 'reportColumnIndex'; // Keyname of SQL-column
const SYSTEM_REPORT_COLUMN_NAME = 'reportColumnName'; // Keyname of SQL-column processed at the moment.
const SYSTEM_REPORT_COLUMN_VALUE = 'reportColumnValue'; // Keyname of SQL-column processed at the moment.
const SYSTEM_REPORT_FULL_LEVEL = 'reportFullLevel'; // Keyname of SQL-column processed at the moment.
const SYSTEM_LDAP_1_RDN = 'LDAP_1_RDN'; // Credentials to access LDAP
const SYSTEM_LDAP_1_PASSWORD = 'LDAP_1_PASSWORD'; // Credentials to access LDAP
const SYSTEM_SECURITY_VARS_HONEYPOT = 'SECURITY_VARS_HONEYPOT'; // Fake variables
const SYSTEM_SECURITY_ATTACK_DELAY = 'SECURITY_ATTACK_DELAY'; // Fake variables
const SYSTEM_SECURITY_SHOW_MESSAGE = 'SECURITY_SHOW_MESSAGE'; // Fake variables
// Not stored in config.qfq.ini, but used in STORE_SYSTEM
const SYSTEM_DOWNLOAD_POPUP = 'hasDownloadPopup'; // Marker which is set to 'true' if there is at least one Download Link rendered
const DOWNLOAD_POPUP_REQUEST = 'true';
......@@ -432,8 +434,10 @@ const DOUBLE_TICK = '"';
// TOKEN evaluate
const TOKEN_ESCAPE_SINGLE_TICK = 's';
const TOKEN_ESCAPE_DOUBLE_TICK = 'd';
const TOKEN_LDAP_ESCAPE_FILTER = 'l';
const TOKEN_LDAP_ESCAPE_DN = 'L';
const TOKEN_ESCAPE_LDAP_FILTER = 'l';
const TOKEN_ESCAPE_LDAP_DN = 'L';
const TOKEN_ESCAPE_MYSQL = 'm';
const TOKEN_ESCAPE_NONE = '-';
// Workaround for PHP < 5.6.0
if (!function_exists('ldap_escape')) {
......@@ -584,6 +588,8 @@ const F_FINAL_DELETE_FORM = 'finalDeleteForm';
const F_SUBMIT_BUTTON_TEXT = 'submitButtonText';
const F_BUTTON_ON_CHANGE_CLASS = 'buttonOnChangeClass';
const F_ESCAPE_TYPE_DEFAULT = 'escapeTypeDefault';
const F_CLASS = 'class';
const F_CLASS_PILL = 'classPill';
const F_CLASS_BODY = 'classBody';
......
......@@ -107,6 +107,11 @@ class Database {
throw new UserFormException ("Error open Database 'mysql:host=" . $config[SYSTEM_DB_SERVER] . ";dbname=" . $config[SYSTEM_DB_NAME] . ";dbuser=" . $config[SYSTEM_DB_USER] . "'': " . $mysqli->connect_errno . PHP_EOL . $mysqli->connect_error, ERROR_DB_OPEN);
}
// Necessary that mysqli::real_escape_string() functions properly.
if (!$mysqli->set_charset('utf8')) {
throw new UserFormException ("Error set_charset('utf8') Database: " . $mysqli->connect_errno . PHP_EOL . $mysqli->connect_error, ERROR_DB_SET_CHARSET);
}
return $mysqli;
}
......@@ -738,4 +743,14 @@ class Database {
return $new;
}
/**
* Proxy for mysqli::real_escape_string()
*
* @param string $value
* @return string
*/
public function realEscapeString($value) {
return $this->mysqli->real_escape_string($value);
}
}
\ No newline at end of file
......@@ -20,13 +20,21 @@ require_once(__DIR__ . '/helper/Support.php');
* @package qfq
*/
class Evaluate {
/**
* @var Store
*/
private $store = null;
/**
* @var Database
*/
private $db = null;
private $startDelimiter = '';
private $startDelimiterLength = 0;
private $endDelimiter = '';
private $endDelimiterLength = 0;
private $sqlKeywords = array('SELECT ', 'INSERT ', 'DELETE ', 'UPDATE ', 'SHOW ');
private $escapeTypeDefault = '';
// private $debugStack = array();
......@@ -44,6 +52,7 @@ class Evaluate {
$this->startDelimiterLength = strlen($startDelimiter);
$this->endDelimiter = $endDelimiter;
$this->endDelimiterLength = strlen($endDelimiter);
$this->escapeTypeDefault = $this->store->getVar(F_ESCAPE_TYPE_DEFAULT, STORE_SYSTEM);
}
/**
......@@ -174,6 +183,7 @@ class Evaluate {
* @return array|null|string
* @throws CodeException
* @throws DbException
* @throws UserFormException
*/
public function substitute($token, &$foundInStore = '') {
$sqlMode = ROW_IMPLODE_ALL;
......@@ -198,6 +208,10 @@ class Evaluate {
// explode for: <key>:<store priority>:<sanitize class>:<escape>
$arr = explode(':', $token, 4);
$arr = array_merge($arr, [null, null, null, null]); // fake isset()
$escapeTypes = $arr[3];
if ($escapeTypes == '') {
$escapeTypes = $this->escapeTypeDefault;
}
// search for value in stores
$value = $this->store->getVar($arr[0], $arr[1], $arr[2], $foundInStore);
......@@ -206,7 +220,7 @@ class Evaluate {
if (is_string($value)) {
// Process all escape requests in the given order.
for ($ii = 0; $ii < strlen($arr[3]); $ii++) {
$escape = $arr[3][$ii];
$escape = $escapeTypes[$ii];
switch ($escape) {
case TOKEN_ESCAPE_SINGLE_TICK:
$value = str_replace("'", "\\'", $value);
......@@ -214,13 +228,19 @@ class Evaluate {
case TOKEN_ESCAPE_DOUBLE_TICK:
$value = str_replace('"', '\\"', $value);
break;
case TOKEN_LDAP_ESCAPE_FILTER:
case TOKEN_ESCAPE_LDAP_FILTER:
$value = Support::ldap_escape($value, null, LDAP_ESCAPE_FILTER);
break;
case TOKEN_LDAP_ESCAPE_DN:
case TOKEN_ESCAPE_LDAP_DN:
$value = Support::ldap_escape($value, null, LDAP_ESCAPE_DN);
break;
case TOKEN_ESCAPE_MYSQL:
$value = $this->db->realEscapeString($value);
break;
case TOKEN_ESCAPE_NONE: // do nothing
break;
default:
throw new UserFormException("Unknown Escape qualifier: $escape", UNKNOWN_TYPE);
break;
}
}
......
......@@ -634,11 +634,12 @@ class QuickFormQuery {
F_CLASS_PILL,
F_CLASS_BODY,
F_BUTTON_ON_CHANGE_CLASS,
F_ESCAPE_TYPE_DEFAULT,
];
// By definition: existing vars which are empty, means: EMPTY - do not use any default!
// But: if these variables are table columns, they always exist. For those: empty value means 'not set' - unset those.
foreach ([F_BS_LABEL_COLUMNS, F_BS_INPUT_COLUMNS, F_BS_NOTE_COLUMNS] as $key) {
foreach ([F_BS_LABEL_COLUMNS, F_BS_INPUT_COLUMNS, F_BS_NOTE_COLUMNS, F_ESCAPE_TYPE_DEFAULT] as $key) {
if ($formSpec[$key] == '') {
unset ($formSpec[$key]);
}
......@@ -675,6 +676,10 @@ class QuickFormQuery {
$formSpec[F_SUBMIT_BUTTON_TEXT] = '';
}
if ($formSpec[F_ESCAPE_TYPE_DEFAULT] == '') {
$formSpec[F_ESCAPE_TYPE_DEFAULT] = $this->store->getVar(F_ESCAPE_TYPE_DEFAULT, STORE_SYSTEM);
}
return $formSpec;
}
......
......@@ -52,18 +52,32 @@ class Config {
* @param array $config
*/
private static function checkForAttack(array $config) {
$flag = false;
$attack = false;
// Iterate over all fake vars
$arr = explode(',', $config[SYSTEM_SECURITY_VARS_HONEYPOT]);
foreach ($arr as $key) {
$key = trim($key);
if ($key === '') {
continue;
}
if (!empty($_POST[$key]) || !empty($_GET[$key])) {
$flag = true;
$attack = true;
}
}
// Limit length of all get vars: protect against SQL injection based on long ...%34%34%24%34...
$maxLength = $config[SYSTEM_SECURITY_GET_MAX_LENGTH];
if ($maxLength > 0) {
foreach ($_GET as $value) {
if (strlen($value) > $maxLength) {
$attack = true;
}
}
}
// Nothing found?
if (!$flag) {
if ($attack === false) {
return;
}
......@@ -72,7 +86,7 @@ class Config {
sleep($config[SYSTEM_SECURITY_ATTACK_DELAY]);
}
if ($config[SYSTEM_SECURITY_SHOW_MESSAGE] == 'true') {
if ($config[SYSTEM_SECURITY_SHOW_MESSAGE] == 'true' || $config[SYSTEM_SECURITY_SHOW_MESSAGE] == 1) {
echo "Attack detected - stop process";
}
......@@ -98,6 +112,8 @@ class Config {
Support::setIfNotSet($config, SYSTEM_SECURITY_VARS_HONEYPOT, 'email,username,password');
Support::setIfNotSet($config, SYSTEM_SECURITY_ATTACK_DELAY, '5');
Support::setIfNotSet($config, SYSTEM_SECURITY_SHOW_MESSAGE, 'true');
Support::setIfNotSet($config, SYSTEM_SECURITY_GET_MAX_LENGTH, '50');
Support::setIfNotSet($config, SYSTEM_ESCAPE_TYPE_DEFAULT, TOKEN_ESCAPE_SINGLE_TICK);
return $config;
}
......@@ -125,6 +141,7 @@ class Config {
[SYSTEM_CSS_CLASS_QFQ_FORM_PILL, F_CLASS_PILL],
[SYSTEM_CSS_CLASS_QFQ_FORM_BODY, F_CLASS_BODY],
[SYSTEM_FORM_BUTTON_ON_CHANGE_CLASS, F_BUTTON_ON_CHANGE_CLASS],
[SYSTEM_ESCAPE_TYPE_DEFAULT, F_ESCAPE_TYPE_DEFAULT],
];
foreach ($setting as $row) {
......
......@@ -9,7 +9,8 @@ CREATE TABLE IF NOT EXISTS `Form` (
`permitNew` ENUM('sip', 'logged_in', 'logged_out', 'always', 'never') NOT NULL DEFAULT 'sip',
`permitEdit` ENUM('sip', 'logged_in', 'logged_out', 'always', 'never') NOT NULL DEFAULT 'sip',
`render` ENUM('bootstrap', 'table', 'plain') NOT NULL DEFAULT 'bootstrap',
`escapeTypeDefault` ENUM('', 's', 'd', 'l', 'L', 'm', '-') NOT NULL DEFAULT 's',
`render` ENUM('bootstrap', 'table', 'plain') NOT NULL DEFAULT 'bootstrap',
`requiredParameter` VARCHAR(255) NOT NULL DEFAULT '',
`showButton` SET('new', 'delete', 'close', 'save') NOT NULL DEFAULT 'new,delete,close,save',
`multiMode` ENUM('none', 'horizontal', 'vertical') NOT NULL DEFAULT 'none',
......@@ -27,7 +28,7 @@ CREATE TABLE IF NOT EXISTS `Form` (
`parameter` TEXT NOT NULL,
`deleted` ENUM('yes', 'no') NOT NULL DEFAULT 'no',
`modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
......@@ -164,8 +165,9 @@ VALUES
(1, 'requiredParameter', 'Required Parameter', 'show', 'text', 'all', 'native', 200, 0, 0, '', '', '', '', '', 2, '', '', '', 'specialchar'),
(1, 'permitNew', 'Permit New', 'show', 'radio', 'all', 'native', 210, 0, 10, '', '', '', '', '', 2, '', '', '', 'specialchar'),
(1, 'permitEdit', 'Permit Edit', 'show', 'radio', 'all', 'native', 220, 0, 10, '', '', '', '', '', 2, '', '', '', 'specialchar'),
(1, 'render', 'Render', 'show', 'radio', 'all', 'native', 230, 0, 3, '', '', '', '', '', 2, '', '', '', 'specialchar'),
(1, 'showButton', 'Show button', 'show', 'checkbox', 'all', 'native', 240, 0, 5, '', '', '', '', 'checkBoxMode = multi\norientation=vertical', 2, '', '', '', 'specialchar'),
(1, 'escapeTypeDefault', 'Escape type default', 'show', 'radio', 'all', 'native', 230, 0, 10, '', '', '', '', '', 2, '', '', '', 'specialchar'),
(1, 'render', 'Render', 'show', 'radio', 'all', 'native', 240, 0, 3, '', '', '', '', '', 2, '', '', '', 'specialchar'),
(1, 'showButton', 'Show button', 'show', 'checkbox', 'all', 'native', 250, 0, 5, '', '', '', '', 'checkBoxMode = multi\norientation=vertical', 2, '', '', '', 'specialchar'),
(1, 'forwardMode', 'Forward', 'show', 'radio', 'all', 'native', 300, 0, 0, '', '', '', '', '', 3, '', '', '', 'specialchar'),
(1, 'forwardPage', 'Forward Page', 'show', 'text', 'all', 'native', 310, 0, 0, '', '', '', '', '', 3, '', '', '', 'none'),
......@@ -179,7 +181,8 @@ VALUES
(1, 'multi', 'Multi', 'show', 'fieldset', 'all', 'native', 400, 0, 0, '', '', '', '', '', 4, '', '', '', 'specialchar'),
(1, 'multiMode', 'Multi Mode', 'show', 'radio', 'all', 'native', 410, 0, 0, '', '', '', '', '', 4, '', '', '', 'specialchar'),
(1, 'multiSql', 'Multi SQL', 'show', 'text', 'all', 'native', 420, '40,3', 0, '', '', '', '', '', 4, '', '', '', 'none'),
(1, 'multiSql', 'Multi SQL', 'show', 'text', 'all', 'native', 420, '40,3', 0, '', '', '', '', '', 4, '', '', '',
'none'),
(1, 'multiDetailForm', 'Multi Detail Form', 'show', 'text', 'all', 'native', 430, 0, 0, '', '', '', '', '', 4,
'', '', '', 'specialchar'),
(1, 'multiDetailFormParameter', 'Multi Detail Form Parameter', 'show', 'text', 'all', 'native', 440, 0, 0, '', '',
......
......@@ -239,6 +239,12 @@ EOT;
F_CLASS_BODY => 'qfq-color-grey-2',
F_BUTTON_ON_CHANGE_CLASS => 'btn-info alert-info',
SYSTEM_EDIT_FORM_PAGE => 'form',
SYSTEM_SECURITY_VARS_HONEYPOT => 'email,username,password',
SYSTEM_SECURITY_ATTACK_DELAY => '5',
SYSTEM_SECURITY_SHOW_MESSAGE => 'true',
SYSTEM_SECURITY_GET_MAX_LENGTH => '50',
SYSTEM_ESCAPE_TYPE_DEFAULT => 's',
];
$fileName = $this->createFile($body);
......
......@@ -9,8 +9,9 @@ CREATE TABLE IF NOT EXISTS `Form` (
`permitNew` ENUM('sip', 'logged_in', 'logged_out', 'always', 'never') NOT NULL DEFAULT 'sip',
`permitEdit` ENUM('sip', 'logged_in', 'logged_out', 'always', 'never') NOT NULL DEFAULT 'sip',
`escapeTypeDefault` ENUM('', 's', 'd', 'l', 'L', 'm', '-') NOT NULL DEFAULT 's',
`render` ENUM('plain', 'table', 'bootstrap') NOT NULL DEFAULT 'plain',
`requiredParameter` VARCHAR(255) NOT NULL DEFAULT '',
`requiredParameter` VARCHAR(255) NOT NULL DEFAULT '',
`showButton` SET('new', 'delete') NOT NULL DEFAULT 'new,delete',
`multiMode` ENUM('none', 'horizontal', 'vertical') NOT NULL DEFAULT 'none',
`multiSql` TEXT NOT NULL,
......@@ -54,58 +55,58 @@ CREATE TABLE IF NOT EXISTS `Form` (
DROP TABLE IF EXISTS `FormElement`;
CREATE TABLE IF NOT EXISTS `FormElement` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`formId` INT(11) NOT NULL,
`feIdContainer` INT(11) NOT NULL DEFAULT '0',
`dynamicUpdate` ENUM('yes', 'no') NOT NULL DEFAULT 'no',
`id` INT(11) NOT NULL AUTO_INCREMENT,
`formId` INT(11) NOT NULL,
`feIdContainer` INT(11) NOT NULL DEFAULT '0',
`dynamicUpdate` ENUM('yes', 'no') NOT NULL DEFAULT 'no',
`enabled` ENUM('yes', 'no') NOT NULL DEFAULT 'yes',
`enabled` ENUM('yes', 'no') NOT NULL DEFAULT 'yes',
`name` VARCHAR(255) NOT NULL DEFAULT '',
`label` VARCHAR(255) NOT NULL DEFAULT '',
`name` VARCHAR(255) NOT NULL DEFAULT '',
`label` VARCHAR(255) NOT NULL DEFAULT '',
`mode` ENUM('show', 'readonly', 'required', 'lock', 'disabled') NOT NULL DEFAULT 'show',
`modeSql` TEXT NOT NULL,
`class` ENUM('native', 'action', 'container') NOT NULL DEFAULT 'native',
`mode` ENUM('show', 'readonly', 'required', 'lock', 'disabled') NOT NULL DEFAULT 'show',
`modeSql` TEXT NOT NULL,
`class` ENUM('native', 'action', 'container') NOT NULL DEFAULT 'native',
`type` ENUM('checkbox', 'date', 'datetime', 'dateJQW', 'datetimeJQW', 'extra', 'gridJQW', 'text', 'editor', 'time',
'note', 'password', 'radio', 'select', 'subrecord', 'upload', 'fieldset', 'pill',
'beforeLoad', 'beforeSave', 'beforeInsert', 'beforeUpdate', 'beforeDelete', 'afterLoad',
'afterSave', 'afterInsert', 'afterUpdate', 'afterDelete',
'sendmail') NOT NULL DEFAULT 'text',
`subrecordOption` SET('edit', 'delete', 'new') NOT NULL DEFAULT '',
`encode` ENUM('none', 'specialchar') NOT NULL DEFAULT 'specialchar',
'sendmail') NOT NULL DEFAULT 'text',
`subrecordOption` SET('edit', 'delete', 'new') NOT NULL DEFAULT '',
`encode` ENUM('none', 'specialchar') NOT NULL DEFAULT 'specialchar',
`checkType` ENUM('alnumx', 'digit', 'numerical', 'email', 'min|max', 'min|max date', 'pattern', 'all') NOT NULL DEFAULT 'alnumx',
`checkPattern` VARCHAR(255) NOT NULL DEFAULT '',
`checkPattern` VARCHAR(255) NOT NULL DEFAULT '',
`onChange` VARCHAR(255) NOT NULL DEFAULT '',
`onChange` VARCHAR(255) NOT NULL DEFAULT '',
`ord` INT(11) NOT NULL DEFAULT '0',
`tabindex` INT(11) NOT NULL DEFAULT '0',
`ord` INT(11) NOT NULL DEFAULT '0',
`tabindex` INT(11) NOT NULL DEFAULT '0',
`size` VARCHAR(255) NOT NULL DEFAULT '',
`maxLength` VARCHAR(255) NOT NULL DEFAULT '',
`bsLabelColumns` VARCHAR(255) NOT NULL DEFAULT '',
`bsInputColumns` VARCHAR(255) NOT NULL DEFAULT '',
`bsNoteColumns` VARCHAR(255) NOT NULL DEFAULT '',
`rowLabelInputNote` SET('row', 'label', '/label', 'input', '/input', 'note', '/note', '/row') NOT NULL DEFAULT 'row,label,/label,input,/input,note,/note,/row',
`size` VARCHAR(255) NOT NULL DEFAULT '',
`maxLength` VARCHAR(255) NOT NULL DEFAULT '',
`bsLabelColumns` VARCHAR(255) NOT NULL DEFAULT '',
`bsInputColumns` VARCHAR(255) NOT NULL DEFAULT '',
`bsNoteColumns` VARCHAR(255) NOT NULL DEFAULT '',
`rowLabelInputNote` SET('row', 'label', '/label', 'input', '/input', 'note', '/note', '/row') NOT NULL DEFAULT 'row,label,/label,input,/input,note,/note,/row',
`note` TEXT NOT NULL,
`tooltip` VARCHAR(255) NOT NULL DEFAULT '',
`placeholder` VARCHAR(255) NOT NULL DEFAULT '',
`note` TEXT NOT NULL,
`tooltip` VARCHAR(255) NOT NULL DEFAULT '',
`placeholder` VARCHAR(255) NOT NULL DEFAULT '',
`value` TEXT NOT NULL,
`sql1` TEXT NOT NULL,
`sql2` TEXT NOT NULL,
`parameter` TEXT NOT NULL,
`value` TEXT NOT NULL,
`sql1` TEXT NOT NULL,
`sql2` TEXT NOT NULL,
`parameter` TEXT NOT NULL,
`clientJs` TEXT,
`feGroup` VARCHAR(255) NOT NULL DEFAULT '',
`debug` ENUM('yes', 'no') NOT NULL DEFAULT 'no',
`deleted` ENUM('yes', 'no') NOT NULL DEFAULT 'no',
`modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
`feGroup` VARCHAR(255) NOT NULL DEFAULT '',
`debug` ENUM('yes', 'no') NOT NULL DEFAULT 'no',
`deleted` ENUM('yes', 'no') NOT NULL DEFAULT 'no',
`modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`created` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`id`),
KEY `formId` (`formId`),
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment