diff --git a/dev/Common/Folders.js b/dev/Common/Folders.js index e255ac1f9..3f02cdce0 100644 --- a/dev/Common/Folders.js +++ b/dev/Common/Folders.js @@ -9,8 +9,6 @@ import { SettingsUserStore } from 'Stores/User/Settings'; import { FolderUserStore } from 'Stores/User/Folder'; import { MessagelistUserStore } from 'Stores/User/Messagelist'; import { getNotification } from 'Common/Translator'; -import { Settings } from 'Common/Globals'; -import { serverRequest } from 'Common/Links'; import Remote from 'Remote/User/Fetch'; @@ -286,28 +284,20 @@ moveMessagesToFolder = (sFromFolderFullName, oUids, sToFolderFullName, bCopy) => }, dropFilesInFolder = (sFolderFullName, files) => { - let count = 0, - fn = () => 0 == --count - && FolderUserStore.currentFolderFullName() == sFolderFullName - && MessagelistUserStore.reload(true, true); + let count = files.length; for (const file of files) { if ('message/rfc822' === file.type) { - ++count; let data = new FormData; data.append('folder', sFolderFullName); data.append('appendFile', file); - data.XToken = Settings.app('token'); - fetch(serverRequest('Append'), { - method: 'POST', - mode: 'same-origin', - cache: 'no-cache', - redirect: 'error', - referrerPolicy: 'no-referrer', - credentials: 'same-origin', - body: data - }) - .then(fn) - .catch(fn); + Remote.request('FolderAppend', (iError, data)=>{ + iError && console.error(data.ErrorMessage); + 0 == --count + && FolderUserStore.currentFolderFullName() == sFolderFullName + && MessagelistUserStore.reload(true, true); + }, data); + } else { + --count; } } }; diff --git a/dev/bootstrap.js b/dev/bootstrap.js index 6f0afbeaa..3c83a9f4e 100644 --- a/dev/bootstrap.js +++ b/dev/bootstrap.js @@ -44,21 +44,31 @@ export default App => { }, init); if (postData) { init.method = 'POST'; - init.headers['Content-Type'] = 'application/json'; + let asJSON = 1, + XToken = Settings.app('token'), + object = {}; if (postData instanceof FormData) { - const object = {}; postData.forEach((value, key) => { - if (!Reflect.has(object, key)){ + if (value instanceof File) { + asJSON = 0; + } else if (!Reflect.has(object, key)) { object[key] = value; } else { isArray(object[key]) || (object[key] = [object[key]]); object[key].push(value); } }); - postData = object; + if (asJSON) { + postData = object; + } else { + postData.set('XToken', XToken); + } } - postData.XToken = Settings.app('token'); - init.body = JSON.stringify(postData); + if (asJSON) { + init.headers['Content-Type'] = 'application/json'; + postData = JSON.stringify(postData); + } + init.body = postData; } init.headers['X-SM-Token'] = Settings.app('token'); // init.headers = new Headers(init.headers); diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php index 731dbbf72..74f35b6fa 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -2,8 +2,6 @@ namespace RainLoop; -use RainLoop\Enumerations\UploadError; - class Actions { use Actions\Admin; @@ -942,52 +940,6 @@ class Actions return \MailSo\Base\Utils::SecureFileName(\MailSo\Base\Utils::Utf8Clear($sClearedFileName)); } - protected function getUploadErrorMessageByCode(int $iError, int &$iClientError): string - { - $sError = ''; - $iClientError = UploadError::NORMAL; - switch ($iError) { - case UPLOAD_ERR_OK: - break; - case UPLOAD_ERR_INI_SIZE: - case UPLOAD_ERR_FORM_SIZE: - case UploadError::CONFIG_SIZE: - case UploadError::EMPTY_FILES_DATA: - $sError = 'File is too big'; - $iClientError = UploadError::FILE_IS_TOO_BIG; - break; - case UPLOAD_ERR_PARTIAL: - $sError = 'File partially uploaded'; - $iClientError = UploadError::FILE_PARTIALLY_UPLOADED; - break; - case UPLOAD_ERR_NO_FILE: - $sError = 'No file uploaded'; - $iClientError = UploadError::FILE_NO_UPLOADED; - break; - case UPLOAD_ERR_NO_TMP_DIR: - case UPLOAD_ERR_CANT_WRITE: - case UPLOAD_ERR_EXTENSION: - $sError = 'Missing temp folder'; - $iClientError = UploadError::MISSING_TEMP_FOLDER; - break; - case UploadError::ON_SAVING: - $sError = 'Error on saving file'; - $iClientError = UploadError::FILE_ON_SAVING_ERROR; - break; - case UploadError::FILE_TYPE: - $sError = 'Invalid file type'; - $iClientError = UploadError::FILE_TYPE; - break; - case UploadError::UNKNOWN: - default: - $sError = 'Unknown error'; - $iClientError = UploadError::UNKNOWN; - break; - } - - return $sError; - } - public function Upload(?array $aFile, int $iError): array { $oAccount = $this->getAccountFromToken(); @@ -1018,8 +970,8 @@ class Actions } if (UPLOAD_ERR_OK !== $iError) { - $iClientError = Enumerations\UploadError::NORMAL; - $sError = $this->getUploadErrorMessageByCode($iError, $iClientError); + $iClientError = 0; + $sError = Enumerations\UploadError::getUserMessage($iError, $iClientError); if (!empty($sError)) { $aResponse['ErrorCode'] = $iClientError; diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Contacts.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Contacts.php index 2805556df..81eaaa058 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Contacts.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Contacts.php @@ -157,8 +157,8 @@ trait Contacts } if (UPLOAD_ERR_OK !== $iError) { - $iClientError = \RainLoop\Enumerations\UploadError::NORMAL; - $sError = $this->getUploadErrorMessageByCode($iError, $iClientError); + $iClientError = 0; + $sError = \RainLoop\Enumerations\UploadError::getUserMessage($iError, $iClientError); if (!empty($sError)) { return $this->FalseResponse($iClientError, $sError); } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Folders.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Folders.php index dbe616acf..5d3aae6e4 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Folders.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Folders.php @@ -14,31 +14,35 @@ trait Folders * Appends uploaded rfc822 message to mailbox * @throws \MailSo\RuntimeException */ - public function Append(): bool + public function DoFolderAppend(): array { $oAccount = $this->initMailClientConnection(); $sFolderFullName = $this->GetActionParam('folder', ''); - if ($oAccount - && !empty($sFolderFullName) - && !empty($_FILES['appendFile']) - && \is_uploaded_file($_FILES['appendFile']['tmp_name']) - && \UPLOAD_ERR_OK == $_FILES['appendFile']['error'] - && $this->oConfig->Get('labs', 'allow_message_append', false) - ) { + if (!$this->oConfig->Get('labs', 'allow_message_append', false)) { + return $this->FalseResponse(999, 'Permission denied'); + } + + if (empty($_FILES['appendFile'])) { + return $this->FalseResponse(999, 'No file'); + } + + if (\UPLOAD_ERR_OK != $_FILES['appendFile']['error']) { + return $this->FalseResponse($iErrorCode, \RainLoop\Enumerations\UploadError::getMessage($iErrorCode)); + } + + if ($oAccount && !empty($sFolderFullName) && \is_uploaded_file($_FILES['appendFile']['tmp_name'])) { $sSavedName = 'append-post-' . \md5($sFolderFullName . $_FILES['appendFile']['name'] . $_FILES['appendFile']['tmp_name']); if ($this->FilesProvider()->MoveUploadedFile($oAccount, $sSavedName, $_FILES['appendFile']['tmp_name'])) { $iMessageStreamSize = $this->FilesProvider()->FileSize($oAccount, $sSavedName); $rMessageStream = $this->FilesProvider()->GetFile($oAccount, $sSavedName); - $this->MailClient()->MessageAppendStream($rMessageStream, $iMessageStreamSize, $sFolderFullName); - $this->FilesProvider()->Clear($oAccount, $sSavedName); + return $this->TrueResponse(); } } - - return $this->TrueResponse(); + return $this->FalseResponse(999); } public function DoFolders() : array diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Themes.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Themes.php index 6b26f36c8..3fa64a8f1 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Themes.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Themes.php @@ -209,8 +209,8 @@ trait Themes } if (UPLOAD_ERR_OK !== $iError) { - $iClientError = \RainLoop\Enumerations\UploadError::NORMAL; - $sError = $this->getUploadErrorMessageByCode($iError, $iClientError); + $iClientError = 0; + $sError = \RainLoop\Enumerations\UploadError::getUserMessage($iError, $iClientError); if (!empty($sError)) { return $this->FalseResponse($iClientError, $sError); } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/UploadError.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/UploadError.php index eb7160c36..72a3e6477 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/UploadError.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Enumerations/UploadError.php @@ -4,27 +4,62 @@ namespace RainLoop\Enumerations; abstract class UploadError { - // UPLOAD_ERR_OK; There is no error, the file uploaded with success. - const NORMAL = 0; - // UPLOAD_ERR_INI_SIZE; The uploaded file exceeds the upload_max_filesize directive in php.ini. - const FILE_IS_TOO_BIG = 1; - // UPLOAD_ERR_FORM_SIZE; The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form. -// const FORM_SIZE = 2; - // UPLOAD_ERR_PARTIAL; The uploaded file was only partially uploaded. - const FILE_PARTIALLY_UPLOADED = 3; - // UPLOAD_ERR_NO_FILE; No file was uploaded. - const FILE_NO_UPLOADED = 4; - // UPLOAD_ERR_NO_TMP_DIR; Missing a temporary folder. - const MISSING_TEMP_FOLDER = 6; - // UPLOAD_ERR_CANT_WRITE; Failed to write file to disk. - const FILE_ON_SAVING_ERROR = 7; - // UPLOAD_ERR_EXTENSION; A PHP extension stopped the file upload -// const EXTENSION = 8; - const FILE_TYPE = 98; const UNKNOWN = 99; const CONFIG_SIZE = 1001; const ON_SAVING = 1002; const EMPTY_FILES_DATA = 1003; + + private static $messages = [ + \UPLOAD_ERR_INI_SIZE => 'Filesize exceeds the upload_max_filesize directive in php.ini', + \UPLOAD_ERR_FORM_SIZE => 'Filesize exceeds the MAX_FILE_SIZE directive that was specified in the html form', + \UPLOAD_ERR_PARTIAL => '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', + 98 => 'Invalid file type', + 99 => 'Unknown error', + 1001 => 'Filesize exceeds the config setting', + 1002 => 'Error saving file', + 1003 => 'File is empty' + ]; + + public static function getMessage(int $code): string + { + return isset(static::$messages[$code]) ? static::$messages[$code] : 0; + } + + protected function getUserMessage(int $iError, int &$iClientError): string + { + $iClientError = $iError; + switch ($iError) { + case \UPLOAD_ERR_OK: + case \UPLOAD_ERR_PARTIAL: + case \UPLOAD_ERR_NO_FILE: + case static::FILE_TYPE: + break; + + case \UPLOAD_ERR_INI_SIZE: + case \UPLOAD_ERR_FORM_SIZE: + case static::CONFIG_SIZE: + case static::EMPTY_FILES_DATA: + return 'File is too big'; + + case \UPLOAD_ERR_NO_TMP_DIR: + case \UPLOAD_ERR_CANT_WRITE: + case \UPLOAD_ERR_EXTENSION: + case static::ON_SAVING: + $iClientError = static::FILE_ON_SAVING_ERROR; + break; + + default: + $iClientError = static::UNKNOWN; + break; + } + + return static::getMessage($iClientError); + } + } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php b/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php index b8d59ad16..532732d63 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/ServiceActions.php @@ -77,7 +77,9 @@ class ServiceActions $aResponse = null; $oException = null; - $_POST = \json_decode(\file_get_contents('php://input'), true); + if (empty($_POST) || (!empty($_SERVER['CONTENT_TYPE']) && \str_contains($_SERVER['CONTENT_TYPE'], 'application/json'))) { + $_POST = \json_decode(\file_get_contents('php://input'), true); + } $sAction = $_POST['Action'] ?? ''; if (empty($sAction) && $this->oHttp->IsGet() && !empty($this->aPaths[2])) { @@ -195,40 +197,6 @@ class ServiceActions return $sResult; } - public function ServiceAppend() : string - { - \ob_start(); - $bResponse = false; - $oException = null; - try - { - if (\method_exists($this->oActions, 'Append') && \is_callable(array($this->oActions, 'Append'))) { - isset($_POST) && $this->oActions->SetActionParams($_POST, 'Append'); - $bResponse = $this->oActions->Append(); - } - } - catch (\Throwable $oException) - { - $bResponse = false; - } - - \header('Content-Type: text/plain; charset=utf-8'); - $sResult = true === $bResponse ? '1' : '0'; - - $sObResult = \ob_get_clean(); - if (\strlen($sObResult)) { - $this->Logger()->Write($sObResult, \LOG_ERR, 'OB-DATA'); - } - - if ($oException) { - $this->Logger()->WriteException($oException, \LOG_ERR); - } - - $this->Logger()->Write($sResult, \LOG_INFO, 'APPEND'); - - return $sResult; - } - private function privateUpload(string $sAction, int $iSizeLimit = 0) : string { $oConfig = $this->Config(); @@ -239,10 +207,8 @@ class ServiceActions { $aFile = null; $sInputName = 'uploader'; - $iError = Enumerations\UploadError::UNKNOWN; $iSizeLimit = (0 < $iSizeLimit ? $iSizeLimit : ((int) $oConfig->Get('webmail', 'attachment_size_limit', 0))) * 1024 * 1024; - $iError = UPLOAD_ERR_OK; $_FILES = isset($_FILES) ? $_FILES : null; if (isset($_FILES[$sInputName], $_FILES[$sInputName]['name'], $_FILES[$sInputName]['tmp_name'], $_FILES[$sInputName]['size'])) { $iError = (isset($_FILES[$sInputName]['error'])) ? (int) $_FILES[$sInputName]['error'] : UPLOAD_ERR_OK;