diff --git a/extension/Documentation/Manual.rst b/extension/Documentation/Manual.rst index 316b49009c32c62d0cc28a9660e9ed596e45c483..50993de543ac77ca8e2c4b3ae771254c25ad2705 100644 --- a/extension/Documentation/Manual.rst +++ b/extension/Documentation/Manual.rst @@ -9,6 +9,9 @@ .. .. -------------------------------------------------- .. Best Practice T3 reST https://docs.typo3.org/typo3cms/drafts/github/xperseguers/RstPrimer/ +.. Italic *italic* +.. Bold **bold** +.. Code ``text`` .. External Links: `Bootstrap <http://getbootstrap.com/>`_ .. Add Images: https://wiki.typo3.org/ReST_Syntax#Images ... .. @@ -7459,7 +7462,7 @@ To define a QFQ form becomes a REST form by enable one or more of: Form: Access > Permit REST: get / insert / update / delete Endpoint -^^^^^^^^ +-------- .. tip:: @@ -7498,7 +7501,7 @@ Only the last <level> of an URI will be processed. The former ones are just to f GET - Read -^^^^^^^^^^ +---------- A REST (GET) form has two modes: :: @@ -7524,39 +7527,69 @@ Form: +-------------------+------------------------------------------------------------------------------+ | Attribute | Description | +===================+==============================================================================+ -| name=<level> | Level name in URI | +| name | *<level>* Mandatory. Level name (Endpoint) in URI. | +-------------------+------------------------------------------------------------------------------+ -| permitNew=rest | The form can be loaded in REST mode with mising parameter 'id' or 'id=0' | +| table | Mandatory. Name of the primary table | +-------------------+------------------------------------------------------------------------------+ -| permitEdit=rest | The form can be loaded in REST mode with parameter 'id' > 0 | +| Permit REST | *get* Mandatory. The form can be loaded in REST mode. | +-------------------+------------------------------------------------------------------------------+ Form.parameter: ++-------------------+----------------------------------------------------------------------------------+ +| Attribute | Description | ++===================+==================================================================================+ +| restSqlData | Mandatory. SQL query selects content shown in data mode. | +| | | ``restSqlData={{!SELECT id, name, gender FROM Person WHERE id='{{r:T0}}'' }}`` | ++-------------------+----------------------------------------------------------------------------------+ +| restSqlList | Mandatory. SQL query selects content shown in data mode. | +| | | ``restSqlData={{!SELECT id, name FROM Person }}`` | ++-------------------+----------------------------------------------------------------------------------+ +| restParam | Optional. CSV list of variable names. E.g.: ``restParam=pId,adrId`` | ++-------------------+----------------------------------------------------------------------------------+ +| restToken | Optional. User defined string or dynamic token (see below). | ++-------------------+----------------------------------------------------------------------------------+ + +.. note: + + There are no `special-column-names`_ available in `restSqlData` or `restSqlList`. Also there are no + SIPs possible, cause REST typically does not offer sessions/cookies (which are necessary for SIPs). + + +POST - Insert +------------- + +Form: + +-------------------+------------------------------------------------------------------------------+ | Attribute | Description | +===================+==============================================================================+ -| restSqlData | SQL query selects content shown in data mode. | -| | `restSqlData={{!SELECT id, name, gender FROM Person WHERE id='{{r:T0}}'' }}` | -+-------------------+------------------------------------------------------------------------------+ -| restSqlList | SQL query selects content shown in data mode. | -| | `restSqlData={{!SELECT id, name FROM Person }}` | +| name | *<level>* Mandatory. Level name (Endpoint) in URI. | +-------------------+------------------------------------------------------------------------------+ -| restParam | Optional. CSV list of variable names. E.g.: `restParam=pId,adrId` | +| table | Mandatory. Name of the primary table | +-------------------+------------------------------------------------------------------------------+ -| restToken | Optional. User defined string. For dynamic token see below. | +| Permit REST | *insert* Mandatory. The form can be loaded in REST mode. | +-------------------+------------------------------------------------------------------------------+ +| id | Missing or '0'. -.. note: +PUT - Update +------------ + +DELETE - Delete +--------------- - There are no `special-column-names`_ available in `restSqlData` or `restSqlList`. Also there are no - SIPs possible, cause REST typically does not offer sessions/cookies (which are necessary for SIPs). Authorization ------------- -By default, the REST API is public accessible. +A QFQ form is only acessible via REST API, if ``Form.permitREST`` enables the HTTP Method (get, post, put, delete) + +``Permit New`` or ``Permit Edit`` don't apply to QFQ forms called via REST. + +.. important:: + + By default, the REST API is public accessible. If this is not wished, HTTP AUTH might be used (configured via webserver) or the QFQ internal 'HTTP header token based authorization'. @@ -7564,10 +7597,9 @@ QFQ internal 'HTTP header token based authorization'. Token based authorization ^^^^^^^^^^^^^^^^^^^^^^^^^ -A form will require a 'token based authorization', as soon as there is a `form.parameter.restToken` defined. -Therefore the HTTP Header 'Authorization' has to be set with `token=<secret token>`. The 'secret token' will -be checked against the server. Using HTTPS, such token can't be sniffed and will typically not be logged in -any server logs. +A form will require a 'token based authorization', as soon as there is a ``form.parameter.restToken`` defined. +Therefore the HTTP Header 'Authorization' has to be set with ``token=<secret token>``. The 'secret token' will +be checked against the server. Example: :: @@ -7578,9 +7610,11 @@ Example: :: The static setup with `form.parameter.restToken=myCrypticString0123456789 is fine, as long as only one token exist. In case of multiple tokens, replace the static string against a SQL query. -General: The HTML Header Authorization token is available in STORE_CLIENT via '`{{Authorization:C:alnumx}}`. +.. tip:: + + The HTML Header Authorization token is available in STORE_CLIENT via '`{{Authorization:C:alnumx}}`. -For example all created tokens are saved in a table 'Auth' with a column 'token'. Define: :: +Best Practice: For example all created tokens are saved in a table 'Auth' with a column 'token'. Define:: form.parameter.restToken={{SELECT a.token FROM Auth AS a WHERE a.token='{{Authorization:C:alnumx}}' }} diff --git a/extension/Source/api/rest.php b/extension/Source/api/rest.php index 4aca469d8283d098fc07d45ce8cba38a835660c8..250e219d6564e7b2df0a581a1f7dc07a2c5d6cdf 100644 --- a/extension/Source/api/rest.php +++ b/extension/Source/api/rest.php @@ -19,6 +19,7 @@ $restId = array(); $restForm = array(); $status = 'HTTP/1.0 409 Bad Request'; +$data = array(); try { try { @@ -39,13 +40,13 @@ try { if ($id != 0) { throw new UserFormException('Method POST needs no id or id=0', ERROR_REST_INVALID_ID); } - $_POST = json_decode(file_get_contents('php://input'), true); + $data = json_decode(file_get_contents('php://input'), true); break; case REQUEST_METHOD_PUT: if ($id == 0) { throw new UserFormException('Method PUT needs an id>0', ERROR_REST_INVALID_ID); } - $_POST = json_decode(file_get_contents('php://input'), true); + $data = json_decode(file_get_contents('php://input'), true); break; case REQUEST_METHOD_DELETE: if ($id == 0) { @@ -56,20 +57,33 @@ try { break; } + if ($data === null) { + throw new NotAcceptableResponseException( + json_encode([ERROR_MESSAGE_TO_USER => 'Invalid JSON', + ERROR_MESSAGE_SUPPORT => json_last_error_msg()]), ERROR_INVALID_VALUE); + } + + if(!empty($data)){ + $_POST = $data; + } + $qfq = new QuickFormQuery(['bodytext' => $bodytext]); $answer = $qfq->rest($restId, $restForm); $status = 'HTTP/1.0 200 OK'; } catch (qfq\CodeException $e) { $answer[API_MESSAGE] = $e->formatMessage(); + $status=$e->getHttpStatus(); } catch (qfq\UserFormException $e) { $answer[API_MESSAGE] = $e->formatMessage(); + $status=$e->getHttpStatus(); } catch (qfq\DbException $e) { $answer[API_MESSAGE] = $e->formatMessage(); - + $status=$e->getHttpStatus(); } + } catch (\Exception $e) { $answer[API_MESSAGE] = "Generic Exception: " . $e->getMessage(); } diff --git a/extension/Source/core/Constants.php b/extension/Source/core/Constants.php index 3f8c294271d0af2851185b06c219e8eab1bea737..75e4f9ef72143e93188a3178d41e27e159c66f00 100644 --- a/extension/Source/core/Constants.php +++ b/extension/Source/core/Constants.php @@ -141,6 +141,7 @@ const KVP_VALUE_GIVEN = 'value_given'; const ERROR_MESSAGE_TO_USER = 'toUser'; // always shown to the user. const ERROR_MESSAGE_SUPPORT = 'support'; // Message to help the developer to understand the problem. const ERROR_MESSAGE_OS = 'os'; // Error message from the OS - like 'file not found' or specific SQL problem +const ERROR_MESSAGE_HTTP_STATUS = 'httpStatus'; // HTTP Status Code to report // QFQ Error Codes const ERROR_UNKNOW_SANITIZE_CLASS = 1001; @@ -1762,3 +1763,5 @@ const ATTRIBUTE_DATA_REFERENCE = 'data-reference'; // REST const HTTP_HEADER_AUTHORIZATION = 'Authorization'; +const HTTP_401 = '401 Unauthorized'; +const HTTP_403 = '403 Forbidden'; \ No newline at end of file diff --git a/extension/Source/core/QuickFormQuery.php b/extension/Source/core/QuickFormQuery.php index c9654862d86f0791907f2c54e226941d596f65e3..98bc51a5efdcab8c4642edc26ccfb528181cd56b 100644 --- a/extension/Source/core/QuickFormQuery.php +++ b/extension/Source/core/QuickFormQuery.php @@ -546,7 +546,7 @@ class QuickFormQuery { if ($formMode == FORM_REST) { $data = ['id' => $rc]; - $flagApiStructureReGroup=false; + $flagApiStructureReGroup = false; break; } @@ -588,7 +588,7 @@ class QuickFormQuery { break; case FORM_REST: - $flagApiStructureReGroup=false; + $flagApiStructureReGroup = false; $data = $this->doRestGet(); break; @@ -596,7 +596,7 @@ class QuickFormQuery { throw new CodeException("This statement should never be reached", ERROR_CODE_SHOULD_NOT_HAPPEN); } - if ($flagApiStructureReGroup && is_array($data) ) { + if ($flagApiStructureReGroup && is_array($data)) { // $data['element-update']=... $data = $this->groupElementUpdateEntries($data); } @@ -632,6 +632,7 @@ class QuickFormQuery { * If not: throw an exception. * * @param string|array $serverToken + * @throws RestException * @throws CodeException * @throws UserFormException */ @@ -642,7 +643,8 @@ class QuickFormQuery { return; } - if ($serverToken === $this->store::getVar(HTTP_HEADER_AUTHORIZATION, STORE_CLIENT . STORE_EMPTY, SANITIZE_ALLOW_ALL)) { + $clientToken = $this->store::getVar(HTTP_HEADER_AUTHORIZATION, STORE_CLIENT, SANITIZE_ALLOW_ALL); + if ($serverToken === $clientToken) { return; } @@ -650,7 +652,17 @@ class QuickFormQuery { $seconds = $this->store::getVar(SYSTEM_SECURITY_FAILED_AUTH_DELAY, STORE_SYSTEM); sleep($seconds); - throw new UserFormException('Missing or wrong authorization token', ERROR_REST_AUTHORIZATION); + if ($clientToken == false) { + throw new RestException(json_encode([ERROR_MESSAGE_TO_USER => 'Missing authorization token', + ERROR_MESSAGE_SUPPORT => "Missing HTTP Header: " . HTTP_HEADER_AUTHORIZATION, + ERROR_MESSAGE_HTTP_STATUS => HTTP_401 + ]), ERROR_REST_AUTHORIZATION); + } + + throw new RestException(json_encode([ERROR_MESSAGE_TO_USER => 'Authorization token not accepted', + ERROR_MESSAGE_SUPPORT => "Missing HTTP Header: " . HTTP_HEADER_AUTHORIZATION, + ERROR_MESSAGE_HTTP_STATUS => HTTP_401 + ]), ERROR_REST_AUTHORIZATION); } /** @@ -1423,9 +1435,9 @@ class QuickFormQuery { * @param string $formMode * * @return bool 'true' if SIP exists, else 'false' - * @throws \qfq\CodeException - * @throws \qfq\UserFormException - * @internal param $foundInStore + * @throws RestException + * @throws CodeException + * @throws UserFormException */ private function validateForm($formNameFoundInStore, $formMode, &$formModeNew) { @@ -1458,7 +1470,7 @@ class QuickFormQuery { $method = $this->store::getVar(CLIENT_REQUEST_METHOD, STORE_CLIENT); if (false === Support::findInSet(strtolower($method), $this->formSpec[F_REST_METHOD])) { - throw new UserFormException("Form '" . $this->formSpec[F_NAME] . "' is not allowed with method '$method'", ERROR_FORM_REST); + throw new RestException("Endpoint '" . $this->formSpec[F_NAME] . "' is not allowed with method '$method'", ERROR_FORM_REST); } $this->restCheckAuthToken($this->formSpec[F_REST_TOKEN] ?? ''); @@ -1467,6 +1479,11 @@ class QuickFormQuery { case REQUEST_METHOD_GET: break; case REQUEST_METHOD_POST: + if ($r != 0) { + throw new RestException('Mode GET with id>0 is forbidden', ERROR_UNKNOWN_MODE); + } + $formModeNew = FORM_SAVE; + break; case REQUEST_METHOD_PUT: $formModeNew = FORM_SAVE; break; @@ -1474,7 +1491,7 @@ class QuickFormQuery { $formModeNew = FORM_DELETE; break; default: - throw new CodeException('Unknown Request Method: ' . $method, ERROR_UNKNOWN_MODE); + throw new RestException('Unknown Request Method: ' . $method, ERROR_UNKNOWN_MODE); } } else { diff --git a/extension/Source/core/exceptions/AbstractException.php b/extension/Source/core/exceptions/AbstractException.php index cb0243ba3a3dc25c65559d249df26ba82a6459f5..dc03ca98e5fe5867924baf284d87cb290e0969a0 100644 --- a/extension/Source/core/exceptions/AbstractException.php +++ b/extension/Source/core/exceptions/AbstractException.php @@ -29,10 +29,11 @@ require_once(__DIR__ . '/../helper/Support.php'); * * Throw with message for User and message for Support. * - * throw new UserFormException( json_encode( - * [ERROR_MESSAGE_TO_USER => 'Failed: chmod', - * ERROR_MESSAGE_SUPPORT => "Failed: chmod $mode '$pathFileName'"]), - * ERROR_IO_CHMOD); + throw new UserFormException( json_encode( + [ERROR_MESSAGE_TO_USER => 'Failed: chmod', + ERROR_MESSAGE_SUPPORT => "Failed: chmod $mode '$pathFileName'", + ERROR_MESSAGE_HTTP_STATUS => 'HTTP/1.0 409 Bad Request' ]), + ERROR_IO_CHMOD); * * @package qfq */ @@ -46,6 +47,8 @@ class AbstractException extends \Exception { protected $file = ''; protected $line = ''; + protected $httpStatusCode = '400 Bad Request'; + /** * $this->getMessage() might give * a) a simple string, or @@ -92,10 +95,17 @@ class AbstractException extends \Exception { $msg = $this->getMessage(); $arrMsg = json_decode($msg, true); if ($arrMsg === null) { + $arrShow[EXCEPTION_MESSAGE] = $msg; $arrMsg[ERROR_MESSAGE_TO_USER] = $msg; + } else { $arrShow[EXCEPTION_MESSAGE] = $arrMsg[ERROR_MESSAGE_TO_USER]; + + if (isset($arrMsg[ERROR_MESSAGE_HTTP_STATUS])) { + $this->httpStatusCode = $arrMsg[ERROR_MESSAGE_HTTP_STATUS]; + } + } $arrDebugHidden[EXCEPTION_FILE] = $this->getFile(); @@ -137,7 +147,7 @@ class AbstractException extends \Exception { if (!empty($os = $arrMerged[ERROR_MESSAGE_OS] ?? '')) { // [ mysqli: 1146 ] Table 'qfq_db.UNKNOWN_TABLE' doesn't exist - $before=$this->getTableToken( html_entity_decode($arrMerged[ERROR_MESSAGE_OS],ENT_QUOTES)); + $before = $this->getTableToken(html_entity_decode($arrMerged[ERROR_MESSAGE_OS], ENT_QUOTES)); $arrMerged[EXCEPTION_SQL_FINAL] = $this->sqlHighlightError($arrMerged[ERROR_MESSAGE_OS], 'mysqli: 1146', $arrMerged[EXCEPTION_SQL_FINAL], $before, "' doesn't exist"); $arrMerged[EXCEPTION_SQL_FINAL] = $this->sqlHighlightError($arrMerged[ERROR_MESSAGE_OS], 'mysqli: 1064', $arrMerged[EXCEPTION_SQL_FINAL], "the right syntax to use near '", "' at line [0-9]*$"); // [ mysqli: 1054 ] Unknown column "noPsp.pspElement' in 'field list" | "... in 'order clause'" @@ -173,6 +183,13 @@ class AbstractException extends \Exception { } + /** + * @return string + */ + public function getHttpStatus() { + return $this->$this->httpStatusCode; + } + /** * Extract 'beforeMatch', incl. dynamic db name as token to do underlining later. * E.g.: "[ mysqli: 1146 ] Table 'qfq_db.UNKNOWN_TABLE' doesn't exist" @@ -184,8 +201,8 @@ class AbstractException extends \Exception { private function getTableToken($os) { $subject = "Table '.*' "; $arr = preg_match("/$subject/", $os, $matches); - $arr= explode('.', $matches[0]??''); - return ($arr[0]??'') . '.'; + $arr = explode('.', $matches[0] ?? ''); + return ($arr[0] ?? '') . '.'; } /** diff --git a/extension/Source/core/exceptions/CodeException.php b/extension/Source/core/exceptions/CodeException.php index 125a96331a85a93c5fbe6b1a099337a67c091fa6..cea02cc255c063c4f5508ae0a0a5b4891710408a 100644 --- a/extension/Source/core/exceptions/CodeException.php +++ b/extension/Source/core/exceptions/CodeException.php @@ -21,10 +21,10 @@ require_once(__DIR__ . '/AbstractException.php'); * * Throw with message for User and message for Support. * - * throw new UserFormException( json_encode( - * [ERROR_MESSAGE_TO_USER => 'Failed: chmod', - * ERROR_MESSAGE_SUPPORT => "Failed: chmod $mode '$pathFileName'"]), - * ERROR_IO_CHMOD); + throw new UserFormException( json_encode( + [ERROR_MESSAGE_TO_USER => 'Failed: chmod', + ERROR_MESSAGE_SUPPORT => "Failed: chmod $mode '$pathFileName'"]), + ERROR_IO_CHMOD); * * @package qfq\exceptions */ diff --git a/extension/Source/core/exceptions/DbException.php b/extension/Source/core/exceptions/DbException.php index b9d07e0985e46a0dc70aa9d65239685c9776a524..bfbbfae13088bbbcae3a6dc85cd933afd289f5de 100644 --- a/extension/Source/core/exceptions/DbException.php +++ b/extension/Source/core/exceptions/DbException.php @@ -38,6 +38,13 @@ class DbException extends AbstractException { * [ERROR_MESSAGE_TO_USER] 'toUser' - shown in the client to the user - no details here!!! * [ERROR_MESSAGE_SUPPORT] 'support' - help for the developer * [ERROR_MESSAGE_OS] 'os' - message from the OS, like 'file not found' + * + throw new UserFormException( json_encode( + [ERROR_MESSAGE_TO_USER => 'Failed: chmod', + ERROR_MESSAGE_SUPPORT => "Failed: chmod $mode '$pathFileName'", + ERROR_MESSAGE_OS => 'os' - message from the OS, like 'file not found' + ERROR_MESSAGE_HTTP_STATUS => 'HTTP/1.0 409 Bad Request' ]), + ERROR_IO_CHMOD); * * @return string HTML formatted error string * @return string diff --git a/extension/Source/core/exceptions/DownloadException.php b/extension/Source/core/exceptions/DownloadException.php index 15c3d767a69203940245d98eeeb60c4ed6a214be..cb9a76def4ce437c5cd2b6d662faba131d53c2c0 100644 --- a/extension/Source/core/exceptions/DownloadException.php +++ b/extension/Source/core/exceptions/DownloadException.php @@ -21,10 +21,11 @@ require_once(__DIR__ . '/AbstractException.php'); * * Throw with message for User and message for Support. * - * throw new UserFormException( json_encode( - * [ERROR_MESSAGE_TO_USER => 'Failed: chmod', - * ERROR_MESSAGE_SUPPORT => "Failed: chmod $mode '$pathFileName'"]), - * ERROR_IO_CHMOD); + throw new UserFormException( json_encode( + [ERROR_MESSAGE_TO_USER => 'Failed: chmod', + ERROR_MESSAGE_SUPPORT => "Failed: chmod $mode '$pathFileName'", + ERROR_MESSAGE_HTTP_STATUS => 'HTTP/1.0 409 Bad Request' ]), + ERROR_IO_CHMOD); * * @package qfq\exceptions */ diff --git a/extension/Source/core/exceptions/NotAcceptableResponseException.php b/extension/Source/core/exceptions/NotAcceptableResponseException.php new file mode 100644 index 0000000000000000000000000000000000000000..26ec070624e44ed42b278c6870e85cde5e266028 --- /dev/null +++ b/extension/Source/core/exceptions/NotAcceptableResponseException.php @@ -0,0 +1,52 @@ +<?php +/** + * Created by PhpStorm. + * User: crose + * Date: 21.02.19 + * Time: 23:47 + */ + +namespace qfq; + +require_once(__DIR__ . '/AbstractException.php'); + +/** + * Class NotAcceptableResponseException + * + * Thrown by API call with bad content type + * + * Throw with ONE message + * + * throw new UserFormException('Failed: chmod ....', ERROR_IO_CHMOD); + * + * Throw with message for User and message for Support. + * + * throw new UserFormException( json_encode( + * [ERROR_MESSAGE_TO_USER => 'Failed: chmod', + * ERROR_MESSAGE_SUPPORT => "Failed: chmod $mode '$pathFileName'"]), + * ERROR_IO_CHMOD); + * + * @package qfq\exceptions + */ + +class NotAcceptableResponseException extends AbstractException { + + /** + * $this->getMessage() might give a) a simple string or b) an JSON String. + * + * JSON String: There are 3+1 different messages: + * [ERROR_MESSAGE_TO_USER] 'toUser' - shown in the client to the user - no details here!!! + * [ERROR_MESSAGE_SUPPORT] 'support' - help for the developer + * [ERROR_MESSAGE_OS] 'os' - message from the OS, like 'file not found' + * + * @return string HTML formatted error string + * @throws CodeException + * @throws UserFormException + */ + public function formatMessage() { + + $this->messageArrayDebug[EXCEPTION_TYPE] = 'Not Acceptable Response'; + + return parent::formatException(); + } +} \ No newline at end of file diff --git a/extension/Source/core/exceptions/RestException.php b/extension/Source/core/exceptions/RestException.php new file mode 100644 index 0000000000000000000000000000000000000000..5135943b26532dd0d2e5acc8e3fba342bf08d452 --- /dev/null +++ b/extension/Source/core/exceptions/RestException.php @@ -0,0 +1,52 @@ +<?php +/** + * Created by PhpStorm. + * User: crose + * Date: 21.02.19 + * Time: 23:47 + */ + +namespace qfq; + +require_once(__DIR__ . '/AbstractException.php'); + +/** + * Class RestException + * + * Thrown by API call with violated access rules + * + * Throw with ONE message + * + * throw new UserFormException('Failed: chmod ....', ERROR_IO_CHMOD); + * + * Throw with message for User and message for Support. + * + * throw new UserFormException( json_encode( + * [ERROR_MESSAGE_TO_USER => 'Failed: chmod', + * ERROR_MESSAGE_SUPPORT => "Failed: chmod $mode '$pathFileName'"]), + * ERROR_IO_CHMOD); + * + * @package qfq\exceptions + */ + +class RestException extends AbstractException { + + /** + * $this->getMessage() might give a) a simple string or b) an JSON String. + * + * JSON String: There are 3+1 different messages: + * [ERROR_MESSAGE_TO_USER] 'toUser' - shown in the client to the user - no details here!!! + * [ERROR_MESSAGE_SUPPORT] 'support' - help for the developer + * [ERROR_MESSAGE_OS] 'os' - message from the OS, like 'file not found' + * + * @return string HTML formatted error string + * @throws CodeException + * @throws UserFormException + */ + public function formatMessage() { + + $this->messageArrayDebug[EXCEPTION_TYPE] = 'Access Forbidden Exception'; + + return parent::formatException(); + } +} \ No newline at end of file diff --git a/extension/Source/core/exceptions/ShellException.php b/extension/Source/core/exceptions/ShellException.php index 4b98a6daaaf02de9f109f34561f9e04282f26b10..77e131852b4f896bce54408a12ab6164af013561 100644 --- a/extension/Source/core/exceptions/ShellException.php +++ b/extension/Source/core/exceptions/ShellException.php @@ -21,10 +21,11 @@ require_once(__DIR__ . '/AbstractException.php'); * * Throw with message for User and message for Support. * - * throw new UserFormException( json_encode( - * [ERROR_MESSAGE_TO_USER => 'Failed: chmod', - * ERROR_MESSAGE_SUPPORT => "Failed: chmod $mode '$pathFileName'"]), - * ERROR_IO_CHMOD); + throw new UserFormException( json_encode( + [ERROR_MESSAGE_TO_USER => 'Failed: chmod', + ERROR_MESSAGE_SUPPORT => "Failed: chmod $mode '$pathFileName'", + ERROR_MESSAGE_HTTP_STATUS => 'HTTP/1.0 409 Bad Request' ]), + ERROR_IO_CHMOD); * * @package qfq\exceptions */ diff --git a/extension/Source/core/exceptions/UserFormException.php b/extension/Source/core/exceptions/UserFormException.php index f2711d62fc4d17f26b04f4b90d7559dca9eaeb79..855baacd3f790b8b5c6eb1048f93d90b8d263ad1 100644 --- a/extension/Source/core/exceptions/UserFormException.php +++ b/extension/Source/core/exceptions/UserFormException.php @@ -22,10 +22,11 @@ require_once(__DIR__ . '/AbstractException.php'); * * Throw with message for User and message for Support. * - * throw new UserFormException( json_encode( - * [ERROR_MESSAGE_TO_USER => 'Failed: chmod', - * ERROR_MESSAGE_SUPPORT => "Failed: chmod $mode '$pathFileName'"]), - * ERROR_IO_CHMOD); + throw new UserFormException( json_encode( + [ERROR_MESSAGE_TO_USER => 'Failed: chmod', + ERROR_MESSAGE_SUPPORT => "Failed: chmod $mode '$pathFileName'", + ERROR_MESSAGE_HTTP_STATUS => 'HTTP/1.0 409 Bad Request' ]), + ERROR_IO_CHMOD); * * Call * diff --git a/extension/Source/core/exceptions/UserReportException.php b/extension/Source/core/exceptions/UserReportException.php index c3f5bdc1b5cc4643f66666cb3f1e6400fed322e5..3f10a32f986c52697a715de774885259191e6652 100644 --- a/extension/Source/core/exceptions/UserReportException.php +++ b/extension/Source/core/exceptions/UserReportException.php @@ -21,10 +21,11 @@ require_once(__DIR__ . '/AbstractException.php'); * * Throw with message for User and message for Support. * - * throw new UserFormException( json_encode( - * [ERROR_MESSAGE_TO_USER => 'Failed: chmod', - * ERROR_MESSAGE_SUPPORT => "Failed: chmod $mode '$pathFileName'"]), - * ERROR_IO_CHMOD); + throw new UserFormException( json_encode( + [ERROR_MESSAGE_TO_USER => 'Failed: chmod', + ERROR_MESSAGE_SUPPORT => "Failed: chmod $mode '$pathFileName'", + ERROR_MESSAGE_HTTP_STATUS => 'HTTP/1.0 409 Bad Request' ]), + ERROR_IO_CHMOD); * * @package qfq\exceptions */ diff --git a/extension/Source/core/helper/Logger.php b/extension/Source/core/helper/Logger.php index 4812e92f05c761f441985c122335fec147a81299..b2d4c7609cc73ff37402d151d06fab39be6335bb 100644 --- a/extension/Source/core/helper/Logger.php +++ b/extension/Source/core/helper/Logger.php @@ -40,6 +40,7 @@ class Logger { * * @param string $mode * @param bool $recursion + * @throws CodeException * @throws UserFormException */ public static function logMessage($msg, $filename, $mode = FILE_MODE_APPEND, $recursion = false) {