Commit 7ce09a7c authored by Carsten  Rose's avatar Carsten Rose
Browse files

Implemented caching and deleting of temporary uploaded files.

file.php: API described.
Store.php: Fixed STORE_EXTRA initialization bug
AbstractBuildForm.php: code rearranged.
Constants.php:  UPLOAD added
parent 9f0da3ae
......@@ -6,6 +6,31 @@
* Time: 8:02 PM
*/
namespace qfq;
use qfq;
require_once(__DIR__ . '/../qfq/store/Store.php');
require_once(__DIR__ . '/../qfq/Constants.php');
require_once(__DIR__ . '/../qfq/File.php');
/**
* Return JSON encoded answer
*
* status: success|error
* message: <message>
*
* Description:
*
* Upload successfull & File accepted by server.
* status = 'success'
* message = <message>
*
* Upload failed:
* status = 'error'
* message = <message>
*/
$answer = array();
$answer[API_MESSAGE] = '';
......@@ -13,12 +38,12 @@ $answer[API_STATUS] = API_ANSWER_STATUS_ERROR;
try {
$upload = new \qfq\File();
$fileUpload = new \qfq\File();
$upload->process();
$fileUpload->process();
$answer[API_MESSAGE] = 'upload: success';
$answer[API_REDIRECT] = API_ANSWER_REDIRECT_NO;
// $answer[API_REDIRECT] = API_ANSWER_REDIRECT_NO;
$answer[API_STATUS] = API_ANSWER_STATUS_SUCCESS;
} catch (qfq\UserFormException $e) {
......
......@@ -1528,7 +1528,7 @@ abstract class AbstractBuildForm {
$attribute .= Support::doAttribute('class', $uploadClass, true);
$htmlInputFile = '<input ' . $attribute . '>' . $this->getHelpBlock();
$deleteButton = Support::wrapTag("<button class='delete-file' data-sip='$sip' name='trash-$htmlFormElementId'>", $this->symbol[SYMBOL_DELETE]);
$deleteButton = Support::wrapTag("<button class='delete-file' data-sip='$sip' name='delete-$htmlFormElementId'>", $this->symbol[SYMBOL_DELETE]);
$htmlFilename = Support::wrapTag("<span class='uploaded-file-name'>", $value, false);
$htmlTextDelete = Support::wrapTag("<div class='uploaded-file $textDeleteClass'>", $htmlFilename . ' ' . $deleteButton);
......
......@@ -151,6 +151,10 @@ const ERROR_MISSING_VALUE = 1302;
const ERROR_MULTIPLE_DEFINITION = 1303;
const ERROR_MULTIPLE_URL_PAGE_MAILTO_DEFINITION = 1304;
// Upload
const ERROR_UPLOAD = 1400;
const ERROR_DELETE_TMP_UPLOAD = 1401;
// KeyValueParser
const ERROR_KVP_VALUE_HAS_NO_KEY = 1900;
......@@ -201,8 +205,7 @@ const CLIENT_KEY_SEM_ID_USER = 'keySemIdUser';
const CLIENT_PAGE_ID = 'id';
const CLIENT_PAGE_TYPE = 'type';
const CLIENT_PAGE_LANGUAGE = 'L';
const CLIENT_UPLOAD_FE_NAME = 'uploadFeName';
const CLIENT_UPLOAD_DELETE = 'uploadDeleteOld';
const CLIENT_UPLOAD_FE_NAME = 'name';
// ALL $_SERVER variables: http://php.net/manual/en/reserved.variables.server.php
// The following exist and might be the most used ones.
......@@ -221,9 +224,6 @@ const CLIENT_REQUEST_URI = 'REQUEST_URI';
const CLIENT_SCRIPT_NAME = 'SCRIPT_NAME';
const CLIENT_PHP_SELF = 'PHP_SELF';
// Extra:
const EXTRA_UPLOAD_DELETE = CLIENT_UPLOAD_DELETE;
// T3 Bodytext Keywords
const TYPO3_FORM = CLIENT_FORM;
const TYPO3_RECORD_ID = CLIENT_RECORD_ID;
......@@ -380,3 +380,9 @@ const QUERY_TYPE_UPDATE = 'type: update,replace,delete';
// Date/ DateTime formats
const FORMAT_DATE_INTERNATIONAL = 'yyyy-mm-dd';
const FORMAT_DATE_GERMAN = 'dd.mm.yyyy';
// $_FILES
const FILES_NAME = 'name';
const FILES_TMP_NAME = 'tmp_name';
const FILES_ERROR = 'error';
const FILES_SIZE = 'size';
......@@ -13,6 +13,8 @@ require_once(__DIR__ . '/Constants.php');
class File {
private $uploadErrMsg = array();
/**
* @var null|Store
*/
......@@ -20,28 +22,46 @@ class File {
public function __construct($phpUnit = false) {
$this->store = Store::getInstance('', $phpUnit);
$this->uploadErrMsg = [
UPLOAD_ERR_INI_SIZE => "The uploaded file exceeds the upload_max_filesize directive in php.ini",
UPLOAD_ERR_FORM_SIZE => "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form",
UPLOAD_ERR_PARTIAL => "The uploaded file was only partially uploaded",
UPLOAD_ERR_NO_FILE => "No file was uploaded",
UPLOAD_ERR_NO_TMP_DIR => "Missing a temporary folder",
UPLOAD_ERR_CANT_WRITE => "Failed to write file to disk",
UPLOAD_ERR_EXTENSION => "File upload stopped by extension"
];
}
public function process() {
$sClient = $this->store->getVar(CLIENT_SIP, STORE_CLIENT, SANITIZE_ALLOW_ALNUMX);
$sStore = $this->store->getVar(SIP_SIP, STORE_SIP);
if ($sClient === false || $sStore === false || $sClient !== $sStore) {
$sipClient = $this->store->getVar(CLIENT_SIP, STORE_CLIENT, SANITIZE_ALLOW_ALNUMX);
$sipStore = $this->store->getVar(SIP_SIP, STORE_SIP);
if ($sipClient === false || $sipStore === false || $sipClient !== $sipStore) {
throw new UserFormException('SIP invalid', ERROR_SIP_INVALID);
}
$uploadFeName = $this->store->getVar(CLIENT_UPLOAD_FE_NAME, STORE_CLIENT, SANITIZE_ALLOW_ALNUMX);
$uploadDelete = $this->store->getVar(CLIENT_UPLOAD_DELETE, STORE_CLIENT, SANITIZE_ALLOW_ALNUMX);
$newArr = $_FILES;
$oldArr = $this->store->getVar($uploadFeName . STORE_EXTRA, SANITIZE_ALLOW_ALL);
if (isset($oldArr[EXTRA_UPLOAD_DELETE]) && $oldArr[EXTRA_UPLOAD_DELETE] === 'yes') {
$uploadDelete = 'yes';
$keyStoreExtra = $sipStore . '-' . $uploadFeName;
list($dummy, $newArr) = each($_FILES);
$oldArr = $this->store->getVar($keyStoreExtra, STORE_EXTRA, SANITIZE_ALLOW_ALL);
// Exist old cached upload? remove.
if (isset($oldArr[FILES_TMP_NAME]) && $oldArr[FILES_TMP_NAME] != '' && file_exists($oldArr[FILES_TMP_NAME] . '.cached')) {
if (!unlink($oldArr[FILES_TMP_NAME] . '.cached')) {
throw new UserFormException("Failed to delete previous temporary uploaded file: " . $oldArr[FILES_TMP_NAME] . '.cached', ERROR_DELETE_TMP_UPLOAD);
}
}
if ($newArr[FILES_ERROR] !== UPLOAD_ERR_OK) {
throw new UserFormException($this->uploadErrMsg[$newArr[FILES_ERROR]], ERROR_UPLOAD);
}
if ($uploadDelete === 'yes')
$newArr[EXTRA_UPLOAD_DELETE] = 'yes';
move_uploaded_file($newArr[FILES_TMP_NAME], $newArr[FILES_TMP_NAME] . '.cached');
$this->store->setVar($uploadFeName, $newArr, STORE_EXTRA);
$this->store->setVar($keyStoreExtra, $newArr, STORE_EXTRA);
}
}
\ No newline at end of file
......@@ -141,7 +141,8 @@ class Store {
STORE_CLIENT => true,
STORE_TYPO3 => false,
STORE_ZERO => false,
STORE_SYSTEM => false
STORE_SYSTEM => false,
STORE_EXTRA => true
];
self::fillSystemStore();
......
......@@ -615,6 +615,7 @@ var QfqNS = QfqNS || {};
/**
* Retrieve SIP as stored in hidden input field.
*
* @deprecated SIP should be passed via url or data attribute.
* @returns {string} sip
*/
n.QfqForm.prototype.getSip = function () {
......
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