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

Fixes #7293: Implement new logging for file upload.

Logger.php: remove UserAgent - that one is logged in FormSubmitLog Table. Add 'cookie' to filter individual actions.
parent ad263dcd
Pipeline #1080 passed with stage
in 1 minute and 40 seconds
...@@ -1222,6 +1222,7 @@ const UPLOAD_MODE_DELETEOLD = 'deleteOld'; ...@@ -1222,6 +1222,7 @@ const UPLOAD_MODE_DELETEOLD = 'deleteOld';
const UPLOAD_MODE_DELETEOLD_NEW = 'deleteOld+new'; const UPLOAD_MODE_DELETEOLD_NEW = 'deleteOld+new';
const UPLOAD_DEFAULT_MAX_SIZE = '10M'; const UPLOAD_DEFAULT_MAX_SIZE = '10M';
const UPLOAD_DEFAULT_MIME_TYPE = 'application/pdf'; const UPLOAD_DEFAULT_MIME_TYPE = 'application/pdf';
const UPLOAD_LOG_PREFIX = 'Upload';
const MIME_TYPE_SPLIT_CAPABLE = 'application/pdf'; const MIME_TYPE_SPLIT_CAPABLE = 'application/pdf';
......
...@@ -30,6 +30,8 @@ class File { ...@@ -30,6 +30,8 @@ class File {
*/ */
private $session = null; private $session = null;
private $qfqLogFilename = '';
/** /**
* @param bool|false $phpUnit * @param bool|false $phpUnit
* @throws CodeException * @throws CodeException
...@@ -40,6 +42,7 @@ class File { ...@@ -40,6 +42,7 @@ class File {
$this->session = Session::getInstance($phpUnit); $this->session = Session::getInstance($phpUnit);
$this->store = Store::getInstance('', $phpUnit); $this->store = Store::getInstance('', $phpUnit);
$this->qfqLogFilename = $this->store->getVar(SYSTEM_QFQ_LOG, STORE_SYSTEM);
$this->uploadErrMsg = [ $this->uploadErrMsg = [
UPLOAD_ERR_INI_SIZE => "The uploaded file exceeds the upload_max_filesize directive in php.ini", UPLOAD_ERR_INI_SIZE => "The uploaded file exceeds the upload_max_filesize directive in php.ini",
...@@ -61,16 +64,17 @@ class File { ...@@ -61,16 +64,17 @@ class File {
$sipUpload = $this->store->getVar(SIP_SIP, STORE_SIP); $sipUpload = $this->store->getVar(SIP_SIP, STORE_SIP);
if ($sipUpload === false) { if ($sipUpload === false) {
// Throws an exception if content is too big - if content is bigger than 'post_max_size', the POST is lost together with the PHP Upload error message. if (empty($_FILES)) {
$this->checkMaxFileSize($_SERVER['CONTENT_LENGTH']);
if(empty($_FILES)){
throw new UserFormException('Missing $_FILES[] - the whole request seems broken', ERROR_UPLOAD_FILES_BROKEN); throw new UserFormException('Missing $_FILES[] - the whole request seems broken', ERROR_UPLOAD_FILES_BROKEN);
} }
throw new UserFormException('SIP invalid: ' . $sipUpload, ERROR_SIP_INVALID); throw new UserFormException('SIP invalid: ' . $sipUpload, ERROR_SIP_INVALID);
} }
// Throws an exception if content is too big - if content is bigger than 'post_max_size', the POST is lost together with the PHP Upload error message.
$size = isset($_SERVER['CONTENT_LENGTH']) ? $_SERVER['CONTENT_LENGTH'] : 0;
$this->checkMaxFileSize($size);
$statusUpload = $this->store->getVar($sipUpload, STORE_EXTRA, SANITIZE_ALLOW_ALL); $statusUpload = $this->store->getVar($sipUpload, STORE_EXTRA, SANITIZE_ALLOW_ALL);
if ($statusUpload === false) { if ($statusUpload === false) {
$statusUpload = array(); $statusUpload = array();
...@@ -99,15 +103,11 @@ class File { ...@@ -99,15 +103,11 @@ class File {
*/ */
private function checkMaxFileSize($size) { private function checkMaxFileSize($size) {
$maxFileSize = $this->store->getVar(FE_FILE_MAX_FILE_SIZE, STORE_SIP); // Checked and set during form build.
$maxFileSize = $this->store->getVar(FE_FILE_MAX_FILE_SIZE, STORE_SIP . STORE_ZERO);
$msg = 'File too big.';
if($maxFileSize!==false){
$msg .= ' Max allowed size: ' . $maxFileSize;
}
if ($maxFileSize===false || $size >= $maxFileSize) { if ($size >= $maxFileSize) {
throw new UserFormException($msg, ERROR_UPLOAD_TOO_BIG); throw new UserFormException('File too big. Max allowed size: ' . $maxFileSize, ERROR_UPLOAD_TOO_BIG);
} }
} }
...@@ -119,7 +119,10 @@ class File { ...@@ -119,7 +119,10 @@ class File {
* @throws UserFormException * @throws UserFormException
*/ */
private function doUpload($sipUpload, array $statusUpload) { private function doUpload($sipUpload, array $statusUpload) {
// New upload
$newArr = reset($_FILES); $newArr = reset($_FILES);
// Merge new upload date to existing status information
$statusUpload = array_merge($statusUpload, $newArr); $statusUpload = array_merge($statusUpload, $newArr);
if ($statusUpload[FILES_ERROR] !== UPLOAD_ERR_OK) { if ($statusUpload[FILES_ERROR] !== UPLOAD_ERR_OK) {
...@@ -128,6 +131,8 @@ class File { ...@@ -128,6 +131,8 @@ class File {
ERROR_UPLOAD); ERROR_UPLOAD);
} }
Logger::logMessageWithPrefix(UPLOAD_LOG_PREFIX . ': File under ' . $statusUpload['tmp_name'], $this->qfqLogFilename);
$this->checkMaxFileSize($statusUpload['size']); $this->checkMaxFileSize($statusUpload['size']);
$accept = $this->store->getVar(FE_FILE_MIME_TYPE_ACCEPT, STORE_SIP); $accept = $this->store->getVar(FE_FILE_MIME_TYPE_ACCEPT, STORE_SIP);
...@@ -137,7 +142,14 @@ class File { ...@@ -137,7 +142,14 @@ class File {
// rename uploaded file: ?.cached // rename uploaded file: ?.cached
$filenameCached = Support::extendFilename($statusUpload[FILES_TMP_NAME], UPLOAD_CACHED); $filenameCached = Support::extendFilename($statusUpload[FILES_TMP_NAME], UPLOAD_CACHED);
move_uploaded_file($newArr[FILES_TMP_NAME], $filenameCached);
error_clear_last();
if (!move_uploaded_file($newArr[FILES_TMP_NAME], $filenameCached)) {
$msg = error_get_last();
throw new UserFormException(
json_encode([ERROR_MESSAGE_TO_USER => 'Upload: Error', ERROR_MESSAGE_SUPPORT => $msg]),
ERROR_UPLOAD_FILE_TYPE);
}
$this->store->setVar($sipUpload, $statusUpload, STORE_EXTRA); $this->store->setVar($sipUpload, $statusUpload, STORE_EXTRA);
} }
...@@ -155,7 +167,7 @@ class File { ...@@ -155,7 +167,7 @@ class File {
if (isset($statusUpload[FILES_TMP_NAME]) && $statusUpload[FILES_TMP_NAME] != '') { if (isset($statusUpload[FILES_TMP_NAME]) && $statusUpload[FILES_TMP_NAME] != '') {
$file = Support::extendFilename($statusUpload[FILES_TMP_NAME], UPLOAD_CACHED); $file = Support::extendFilename($statusUpload[FILES_TMP_NAME], UPLOAD_CACHED);
if (file_exists($file)) { if (file_exists($file)) {
HelperFile::unlink($file); HelperFile::unlink($file, $this->qfqLogFilename);
} }
$statusUpload[FILES_TMP_NAME] = ''; $statusUpload[FILES_TMP_NAME] = '';
} }
......
...@@ -38,6 +38,8 @@ class Save { ...@@ -38,6 +38,8 @@ class Save {
private $evaluate = null; private $evaluate = null;
private $qfqLogFilename = '';
/** /**
* @param array $formSpec * @param array $formSpec
* @param array $feSpecAction * @param array $feSpecAction
...@@ -56,6 +58,9 @@ class Save { ...@@ -56,6 +58,9 @@ class Save {
$this->store = Store::getInstance(); $this->store = Store::getInstance();
$this->db = new Database($formSpec[F_DB_INDEX]); $this->db = new Database($formSpec[F_DB_INDEX]);
$this->evaluate = new Evaluate($this->store, $this->db); $this->evaluate = new Evaluate($this->store, $this->db);
$this->qfqLogFilename = $this->store->getVar(SYSTEM_QFQ_LOG, STORE_SYSTEM);
} }
/** /**
...@@ -589,7 +594,7 @@ class Save { ...@@ -589,7 +594,7 @@ class Save {
$oldFile = $arr[EXISTING_PATH_FILE_NAME]; $oldFile = $arr[EXISTING_PATH_FILE_NAME];
if (file_exists($oldFile)) { if (file_exists($oldFile)) {
//TODO: it might be possible to delete a file, which is referenced by another record - a check would be nice. //TODO: it might be possible to delete a file, which is referenced by another record - a check would be nice.
HelperFile::unlink($oldFile); HelperFile::unlink($oldFile, $this->qfqLogFilename);
} }
$flagDelete = ($oldFile != ''); $flagDelete = ($oldFile != '');
} }
...@@ -601,9 +606,15 @@ class Save { ...@@ -601,9 +606,15 @@ class Save {
$modeUpload = $flagDelete ? UPLOAD_MODE_DELETEOLD : UPLOAD_MODE_UNCHANGED; $modeUpload = $flagDelete ? UPLOAD_MODE_DELETEOLD : UPLOAD_MODE_UNCHANGED;
} }
Logger::logMessageWithPrefix(UPLOAD_LOG_PREFIX . ': modeUpload= ' . $modeUpload, $this->qfqLogFilename);
// skip uploading the file, if this is an import without a specified file destination // skip uploading the file, if this is an import without a specified file destination
if (!isset($formElement[FE_IMPORT_TO_TABLE]) || isset($formElement[FE_FILE_DESTINATION])) { if (!isset($formElement[FE_IMPORT_TO_TABLE]) || isset($formElement[FE_FILE_DESTINATION])) {
$pathFileName = $this->copyUploadFile($formElement, $statusUpload); $pathFileName = $this->copyUploadFile($formElement, $statusUpload);
$msg = UPLOAD_LOG_PREFIX . ': ';
$msg .= ($pathFileName == '') ? 'Remove old upload / no new upload' : 'File "' . $statusUpload[FILES_TMP_NAME] . '" >> "' . $pathFileName . '"';
Logger::logMessageWithPrefix($msg, $this->qfqLogFilename);
} }
HelperFile::chdir($cwd); HelperFile::chdir($cwd);
...@@ -624,7 +635,9 @@ class Save { ...@@ -624,7 +635,9 @@ class Save {
* @throws \PhpOffice\PhpSpreadsheet\Reader\Exception * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception
*/ */
private function doImport($formElement, $fileName) { private function doImport($formElement, $fileName) {
Support::setIfNotSet($formElement, FE_IMPORT_TYPE, FE_IMPORT_TYPE_AUTO); Support::setIfNotSet($formElement, FE_IMPORT_TYPE, FE_IMPORT_TYPE_AUTO);
switch ($formElement[FE_IMPORT_TYPE]) { switch ($formElement[FE_IMPORT_TYPE]) {
case FE_IMPORT_TYPE_AUTO: case FE_IMPORT_TYPE_AUTO:
$spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($fileName); $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($fileName);
......
...@@ -149,7 +149,7 @@ class HelperFile { ...@@ -149,7 +149,7 @@ class HelperFile {
public static function pathInfo($pathFileName) { public static function pathInfo($pathFileName) {
$vars = array(); $vars = array();
$pathParts = path($pathFileName); $pathParts = pathinfo($pathFileName);
$vars[VAR_FILENAME] = $pathFileName; $vars[VAR_FILENAME] = $pathFileName;
if (isset($pathParts['basename'])) { if (isset($pathParts['basename'])) {
...@@ -273,14 +273,19 @@ class HelperFile { ...@@ -273,14 +273,19 @@ class HelperFile {
/** /**
* PHP System function: unlink() with QFQ exception * PHP System function: unlink() with QFQ exception
* *
* @param $newSrc * @param $filename
* @param string $logFilename
* @return string * @return string
* @throws UserFormException * @throws UserFormException
*/ */
public static function unlink($newSrc) { public static function unlink($filename, $logFilename = '') {
if ($logFilename != '') {
Logger::logMessageWithPrefix("Unlink: $filename", $logFilename);
}
if (false === unlink($newSrc)) { if (false === unlink($filename)) {
$msg = self::errorGetLastAsString() . " - unlink($newSrc)"; $msg = self::errorGetLastAsString() . " - unlink($filename)";
throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'unlink failed', ERROR_MESSAGE_SUPPORT => $msg]), ERROR_IO_UNLINK); throw new UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'unlink failed', ERROR_MESSAGE_SUPPORT => $msg]), ERROR_IO_UNLINK);
} }
......
...@@ -61,6 +61,16 @@ class Logger { ...@@ -61,6 +61,16 @@ class Logger {
fclose($handle); fclose($handle);
} }
/**
* @param $msg
* @param $filename
* @param string $mode
* @throws UserFormException
*/
public static function logMessageWithPrefix($msg, $filename, $mode = FILE_MODE_APPEND) {
self::logMessage(self::linePre() . $msg, $filename, $mode);
}
/** /**
* In case $filename is not absolute and if we're in the API directory: Check if we're in api - update relative filename * In case $filename is not absolute and if we're in the API directory: Check if we're in api - update relative filename
* *
...@@ -82,9 +92,15 @@ class Logger { ...@@ -82,9 +92,15 @@ class Logger {
* @return string * @return string
*/ */
public static function linePre() { public static function linePre() {
$str = '=== [' . date('Y-m-d H:i:s');
$cookie = isset($_COOKIE[SESSION_NAME]) ? $_COOKIE[SESSION_NAME] : '<no session cookie>';
$str = '[' . date('Y-m-d H:i:s');
$str .= ' / ' . htmlentities(empty($_SERVER['REMOTE_ADDR']) ? '<no ip>' : $_SERVER['REMOTE_ADDR']); $str .= ' / ' . htmlentities(empty($_SERVER['REMOTE_ADDR']) ? '<no ip>' : $_SERVER['REMOTE_ADDR']);
$str .= ' / ' . htmlentities(empty($_SERVER['HTTP_USER_AGENT']) ? '<no user agent>' : $_SERVER['HTTP_USER_AGENT']); // $str .= ' / ' . htmlentities(empty($_SERVER['HTTP_USER_AGENT']) ? '<no user agent>' : $_SERVER['HTTP_USER_AGENT']);
$str .= ' / ' . htmlentities($cookie);
$str .= '] '; $str .= '] ';
return $str; return $str;
......
...@@ -1187,6 +1187,8 @@ class Support { ...@@ -1187,6 +1187,8 @@ class Support {
} }
/** /**
* Append $extend to $filename
*
* @param string $filename * @param string $filename
* @param string $extend * @param string $extend
* *
......
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