Commit 15bdc7bc authored by Carsten  Rose's avatar Carsten Rose
Browse files

Fixes #8041: maxFileSize based on system maximum, qfq config, form config, formElement config

parent d37c712f
Pipeline #1743 failed with stage
in 2 minutes and 18 seconds
......@@ -351,11 +351,14 @@ Extension Manager: QFQ Configuration
+===================================+=======================================================+============================================================================+
| Config |
+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
| documentation | http://docs.typo3.org... | Link to the online documentation of QFQ. Every QFQ installation also |
| | | contains a local copy: typo3conf/ext/qfq/Documentation/html/Manual.html |
+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
| flagProduction | yes | yes|no: used to differentiate production and development site. |
+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
| maxFileSize | 10M | If empty, take minimum of 'post_max_size' and 'upload_max_filesize'. |
+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
| baseUrl | http://example.com | URL where wkhtmltopdf will fetch the HTML (no parameter, those comes later)|
+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
| dateFormat | yyyy-mm-dd | Possible options: yyyy-mm-dd, dd.mm.yyyy. |
+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
| thumbnailDirSecure | fileadmin/protected/qfqThumbnail | Important: secure directory 'protected' (recursive) against direct access. |
+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
| thumbnailDirPublic | typo3temp/qfqThumbnail | Both thumbnail directories will be created if not existing. |
......@@ -366,11 +369,10 @@ Extension Manager: QFQ Configuration
+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
| cmdWkhtmltopdf | /usr/bin/wkhtmltopdf | PathFilename of wkhtmltopdf. Optional variables like LD_LIBRARY_PATH=... |
+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
| baseUrl | http://example.com | URL where wkhtmltopdf will fetch the HTML (no parameter, those comes later)|
+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
| sendEMailOptions | -o tls=yes | General options. Check: http://caspian.dotconf.net/menu/Software/SendEmail |
+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
| dateFormat | yyyy-mm-dd | Possible options: yyyy-mm-dd, dd.mm.yyyy. |
| documentation | http://docs.typo3.org... | Link to the online documentation of QFQ. Every QFQ installation also |
| | | contains a local copy: typo3conf/ext/qfq/Documentation/html/Manual.html |
+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
| Dynamic |
+-----------------------------------+-------------------------------------------------------+----------------------------------------------------------------------------+
......@@ -2460,6 +2462,9 @@ Parameter
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| sessionTimeoutSeconds | int | Overwrite default from configuration_ . See sessionTimeoutSeconds_. |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
| maxFileSize | int | Overwrite default from configuration_ . |
+-----------------------------+--------+----------------------------------------------------------------------------------------------------------+
* Example:
......@@ -3647,7 +3652,8 @@ See also `downloadButton`_ to offer a download of an uploaded file.
* If for a specific filetype is no mime type available, the definition of file extension(s) is possible. This is **less
secure**, cause there is no *content* check on the server after the upload.
* *maxFileSize* = `<size>` - max filesize in bytes (no unit), kilobytes (k/K) or megabytes (m/M) for an uploaded file. Default: 10M.
* *maxFileSize* = `<size>` - max filesize in bytes (no unit), kilobytes (k/K) or megabytes (m/M) for an uploaded file.
If empty or not given, take value from Form, System or System default.
* *fileDestination* = `<pathFileName>` - Destination where to copy the file. A good practice is to specify a relative `fileDestination` -
such an installation (filesystem and database) are moveable.
......
......@@ -258,7 +258,9 @@ abstract class AbstractBuildForm {
$htmlElements = $this->elements($row['_id'], $filter, 0, $jsonTmp, $modeCollectFe);
$json[] = $jsonTmp;
}
} else {
$recordId = $this->store->getVar(SIP_RECORD_ID, STORE_SIP);
if (!($recordId == '' || is_numeric($recordId))) {
throw new UserFormException(
......@@ -3040,10 +3042,7 @@ abstract class AbstractBuildForm {
$arr[CLIENT_PAGE_ID] = 'fake';
$arr[EXISTING_PATH_FILE_NAME] = $value;
$arr[FE_FILE_MIME_TYPE_ACCEPT] = $formElement[FE_FILE_MIME_TYPE_ACCEPT];
$arr[FE_FILE_MAX_FILE_SIZE] = empty($formElement[FE_FILE_MAX_FILE_SIZE]) ? UPLOAD_DEFAULT_MAX_SIZE : $formElement[FE_FILE_MAX_FILE_SIZE];
$arr[FE_FILE_MAX_FILE_SIZE] = Support::returnBytes($arr[FE_FILE_MAX_FILE_SIZE]);
// Check Safari Bug #5578: in case Safari (Mac OS X or iOS) loads an 'upload element' with more than one filetype, fall back to 'no preselection'.
// Check Safari Bug #5578: in case Safari (Mac OS X or iOS) loads an 'upload element' with more than one file type, fall back to 'no preselection'.
if (strpos($formElement[FE_FILE_MIME_TYPE_ACCEPT], ',') !== false) {
$ua = $this->store->getVar('HTTP_USER_AGENT', STORE_CLIENT, SANITIZE_ALLOW_ALNUMX);
// Look for " Version/11.0 Mobile/15A5370a Safari/" or " Version/9.0.2 Safari/"
......@@ -3054,13 +3053,16 @@ abstract class AbstractBuildForm {
}
}
if ((Support::returnBytes(ini_get('post_max_size')) < $arr[FE_FILE_MAX_FILE_SIZE]) ||
(Support::returnBytes(ini_get('upload_max_filesize')) < $arr[FE_FILE_MAX_FILE_SIZE])
$arr[FE_FILE_MAX_FILE_SIZE] = empty($formElement[FE_FILE_MAX_FILE_SIZE]) ? $this->formSpec[FE_FILE_MAX_FILE_SIZE] : $formElement[FE_FILE_MAX_FILE_SIZE];
$maxFileSize = Support::returnBytes($arr[FE_FILE_MAX_FILE_SIZE]);
if ((Support::returnBytes(ini_get('post_max_size')) < $maxFileSize) ||
(Support::returnBytes(ini_get('upload_max_filesize')) < $maxFileSize)
) {
throw new UserFormException("Configured 'maxFileSize'=" . $arr[FE_FILE_MAX_FILE_SIZE] .
" bigger than at least of one of the php.ini setttings 'post_max_size'=" . ini_get('post_max_size') .
" or 'upload_max_filesize'=" . ini_get('upload_max_filesize'), ERROR_MAX_FILE_SIZE_TOO_BIG);
}
$arr[FE_FILE_MAX_FILE_SIZE] = $maxFileSize;
$sipUpload = $this->sip->queryStringToSip(OnArray::toString($arr), RETURN_SIP);
......
......@@ -595,7 +595,8 @@ const SYSTEM_RECORD_LOCK_TIMEOUT_SECONDS = 'recordLockTimeoutSeconds';
const SYSTEM_RECORD_LOCK_TIMEOUT_SECONDS_DEFAULT = 900; // 15 mins
const SYSTEM_SESSION_TIMEOUT_SECONDS = 'sessionTimeoutSeconds';
const SYSTEM_SESSION_TIMEOUT_SECONDS_DEFAULT = 86400; // 30 mins
const SYSTEM_FILE_MAX_FILE_SIZE = 'maxFileSize';
const SYSTEM_COOKIE_LIFETIME = 259200; // 3 days. Should be more than SYSTEM_SESSION_TIMEOUT_SECONDS_DEFAULT, in case the user setup's a higher value.
......@@ -1056,11 +1057,12 @@ const FE_TIME_IS_OPTIONAL = 'timeIsOptional'; // value: 0|1
const FE_SHOW_ZERO = 'showZero'; // 0|1 - Used for 'date/datime/time': in case of fe.value='0' shows corresponding '00-00-0000'|'00:00:00'
const FE_HIDE_ZERO = 'hideZero'; // 0|1 - In case of fe.value=0|'0', an empty string is shown.
const FE_FILE_DESTINATION = 'fileDestination'; // Target pathFileName for an uploaded file.
const FE_FILE_DESTINATION_SPLIT = 'fileDestinationSplit'; // Target pathFileName for an uploaded file.
const FE_FILE_REPLACE_MODE = 'fileReplace'; // Target pathFileName for an uploaded file.
const FE_FILE_REPLACE_MODE_ALWAYS = 'always'; // Target pathFilename for an uploaded file.
const FE_FILE_MIME_TYPE_ACCEPT = 'accept'; // Target pathFileName for an uploaded file.
const FE_FILE_MAX_FILE_SIZE = 'maxFileSize'; // Target pathFileName for an uploaded file.
const FE_FILE_DESTINATION_SPLIT = 'fileDestinationSplit'; // Target pathFileName for split files
const FE_FILE_REPLACE_MODE = 'fileReplace'; // Flag if a) QFQ throw an error if there is already a file with the same pathFileName or b) if QFQ should overwrite it.
const FE_FILE_REPLACE_MODE_ALWAYS = 'always'; // Value for flag FE_FILE_REPLACE_MODE
const FE_FILE_MIME_TYPE_ACCEPT = 'accept'; // Comma separated list of mime types
const FE_FILE_MAX_FILE_SIZE = SYSTEM_FILE_MAX_FILE_SIZE; // Max upload file size
const FE_FILE_CAPTURE = 'capture'; // On a smartphone opens the camera
const FE_FILE_SPLIT = 'fileSplit';
const FE_FILE_SPLIT_SVG = 'svg';
......
......@@ -1351,13 +1351,17 @@ class QuickFormQuery {
FE_INPUT_EXTRA_BUTTON_INFO_CLASS,
F_SHOW_ID_IN_FORM_TITLE,
FE_FILE_MAX_FILE_SIZE,
F_FE_DATA_PATTERN_ERROR_SYSTEM, // Not a classical element to overwrite by form definition, but should be copied to detect changes per custom setting.
];
// 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, F_ESCAPE_TYPE_DEFAULT] as $key) {
if ($formSpec[$key] == '') {
// But: a) if these variables are table columns, they always exist. For those: empty value means 'not set'
// b) some values have a special meaning. E.g. empty FE_FILE_MAX_FILE_SIZE means take system config
// - unset those.
foreach ([F_BS_LABEL_COLUMNS, F_BS_INPUT_COLUMNS, F_BS_NOTE_COLUMNS, F_ESCAPE_TYPE_DEFAULT, FE_FILE_MAX_FILE_SIZE] as $key) {
if (($formSpec[$key] ?? '') == '') {
unset ($formSpec[$key]);
}
}
......
......@@ -836,7 +836,7 @@ class Support {
self::setIfNotSet($formElement, FE_INPUT_EXTRA_BUTTON_INFO_CLASS, $store->getVar(FE_INPUT_EXTRA_BUTTON_INFO_CLASS, STORE_SYSTEM));
// For specific FE hardcode 'checkType'
// For specific FE hard coded 'checkType'
switch ($formElement[FE_TYPE]) {
case FE_TYPE_IMAGE_CUT:
$formElement[FE_CHECK_TYPE] = SANITIZE_ALLOW_ALLBUT;
......
......@@ -21,6 +21,7 @@ class Config {
/**
* Migrate config.qfq.ini to config.qfq.php
*
* @param $configIni
* @param $configPhp
*/
......@@ -77,8 +78,9 @@ class Config {
/**
* Read config.qfq.ini. In case
*
* @param string $configIni
* @param string $fileConfigPhp
* @return array
* @throws CodeException
* @throws UserFormException
* @throws UserReportException
*/
......@@ -139,6 +141,7 @@ class Config {
}
$configT3qfq = self::getCustomVariable($configT3qfq);
// Settings in config.qfq.php overwrite T3 settings
$config = array_merge($configT3qfq, $config);
......@@ -168,6 +171,7 @@ class Config {
/**
* Checks for deprecated options.
*
* @param array $config
* @throws UserFormException
*/
......@@ -188,6 +192,8 @@ class Config {
/**
* Check for attack
*
* @param array $config
* @throws CodeException
* @throws UserFormException
......@@ -287,7 +293,6 @@ class Config {
* @return array
*/
private static function setDefaults(array $config) {
// Defaults: do not worry: parse_ini_file() will replace 'none' and 'off' by ''.
$default = [
......@@ -367,6 +372,9 @@ class Config {
SYSTEM_THROW_GENERAL_ERROR => 'auto',
SYSTEM_SECURITY_FAILED_AUTH_DELAY => '3',
SYSTEM_FILE_MAX_FILE_SIZE => min(Support::returnBytes(ini_get('post_max_size')), Support::returnBytes(ini_get('upload_max_filesize'))),
];
// To let run legacy code
......@@ -430,6 +438,8 @@ class Config {
}
/**
* Check Session Timeout
*
* @param $timeout
* @throws UserFormException
*/
......@@ -443,7 +453,6 @@ class Config {
if ($timeout > SYSTEM_COOKIE_LIFETIME) {
throw new qfq\UserFormException ("The specified timeout of $timeout seconds is higher than the hardcoded cookie lifetime (" . SYSTEM_COOKIE_LIFETIME . ")");
}
}
......
......@@ -307,7 +307,6 @@ class Store {
}
}
// In case the database credentials are given in the old style: copy them to the new style
if (!isset($config[SYSTEM_DB_1_USER]) && isset($config[SYSTEM_DB_USER])) {
$config[SYSTEM_DB_1_USER] = $config[SYSTEM_DB_USER];
......
# cat=config/config; type=string; label=URL QFQ Documentation:Default is 'https://docs.typo3.org/typo3cms/drafts/github/T3DocumentationStarter/Public-Info-053/Manual.html'. Might be changed to a local repo. Every QFQ installation contains a local copy: <site path>/typo3conf/ext/qfq/Documentation/html/Manual.html (corresponds always to the QFQ version).
documentation = https://docs.typo3.org/typo3cms/drafts/github/T3DocumentationStarter/Public-Info-053/Manual.html
# cat=config/config; type=string; label=Marks a production installation:Possible values: 'yes', 'no'. Retrieve via '{{flagProduction:Y}}''. Default is 'yes'. Used to differentiate between development & production systems.
flagProduction = yes
# cat=config/config; type=string; label=Max file size for file uploads:If empty, take minimum of 'post_max_size' and 'upload_max_filesize' (PHP.INI).
maxFileSize =
# cat=config/config; type=string; label=Base URL of the current Typo3 installation:Default is empty. Example: https://your.base.url/including/sub/dir. Will be used to convert local pages to PDF. In special cases https://localhost/including/sub/dir might be necessary. Use {{baseUrl:Y}} whenever the own URL should be displayed.
baseUrl =
# cat=config/date; type=string; label=Date format:Default is 'dd.mm.yyyy'. Possible options: 'yyyy-mm-dd', 'dd.mm.yyyy'
dateFormat = dd.mm.yyyy
# cat=config/config; type=string; label=Thumbnail directory 'secure':Default is 'fileadmin/protected/qfqThumbnail'. Important: secure the directory (recursive) against direct access. Will be used by a special columnname '_thumbnail'.
thumbnailDirSecure = fileadmin/protected/qfqThumbnail
......@@ -19,14 +25,12 @@ cmdConvert = convert
# cat=config/config; type=string; label=Command 'wkhtmltopdf':Default is '/opt/wkhtmltox/bin/wkhtmltopdf'. Command to convert a HTML page to a PDF.
cmdWkhtmltopdf = /opt/wkhtmltox/bin/wkhtmltopdf
# cat=config/config; type=string; label=Base URL of the current Typo3 installation:Default is empty. Example: https://your.base.url/including/sub/dir. Will be used to convert local pages to PDF. In special cases https://localhost/including/sub/dir might be necessary. Use {{baseUrl:Y}} whenever the own URL should be displayed.
baseUrl =
# cat=config/email; type=string; label=Options for SendEMail:Default is empty. General options. Check: http://caspian.dotconf.net/menu/Software/SendEmail. E.g.: 'sendEMail=-o tls=yes'
sendEMailOptions =
# cat=config/date; type=string; label=Date format:Default is 'dd.mm.yyyy'. Possible options: 'yyyy-mm-dd', 'dd.mm.yyyy'
dateFormat = dd.mm.yyyy
# cat=config/config; type=string; label=URL QFQ Documentation:Default is 'https://docs.typo3.org/typo3cms/drafts/github/T3DocumentationStarter/Public-Info-053/Manual.html'. Might be changed to a local repo. Every QFQ installation contains a local copy: <site path>/typo3conf/ext/qfq/Documentation/html/Manual.html (corresponds always to the QFQ version).
documentation = https://docs.typo3.org/typo3cms/drafts/github/T3DocumentationStarter/Public-Info-053/Manual.html
# cat=dynamic/config; type=string; label=Fill store 'SYSTEM' by SQL 1:Default is empty. SQL query fired during QFQ load. The result have to be exactly one row. That row will be merged to store 'SYSTEM'. Retrieve values via '{{column:Y}}'. Example 'SELECT id AS _periodId FROM Period WHERE start<=NOW() ORDER BY start DESC LIMIT 1'
......
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