Commit 446e7e7f authored by Carsten  Rose's avatar Carsten Rose
Browse files

Refactor to use form.restMethod instead of form.permNew|edit=rest. Next step...

Refactor to use form.restMethod instead of form.permNew|edit=rest. Next step will be to eliminate formMode=FORM_REST
parent 3e2d2805
...@@ -24,11 +24,38 @@ try { ...@@ -24,11 +24,38 @@ try {
try { try {
$form = OnString::splitPathInfoToIdForm($_SERVER['PATH_INFO'], $restId, $restForm); $form = OnString::splitPathInfoToIdForm($_SERVER['PATH_INFO'], $restId, $restForm);
// get latest `ìd`
$id=end($restId); $id=end($restId);
// Fake Bodytext setup // Fake Bodytext setup
$bodytext = TYPO3_RECORD_ID . '=' . $id . PHP_EOL; $bodytext = TYPO3_RECORD_ID . '=' . $id . PHP_EOL;
$bodytext .= TYPO3_FORM . '=' . $form . PHP_EOL; $bodytext .= TYPO3_FORM . '=' . $form . PHP_EOL;
$method=$_SERVER['REQUEST_METHOD'];
switch($method){
case REQUEST_METHOD_GET:
break;
case REQUEST_METHOD_POST:
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);
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);
break;
case REQUEST_METHOD_DELETE:
if($id==0){
throw new UserFormException('Method DELETE needs an id>0', ERROR_REST_INVALID_ID);
}
break;
default:
break;
}
$qfq = new QuickFormQuery(['bodytext' => $bodytext]); $qfq = new QuickFormQuery(['bodytext' => $bodytext]);
$answer = $qfq->rest($restId, $restForm); $answer = $qfq->rest($restId, $restForm);
$status='HTTP/1.0 200 OK'; $status='HTTP/1.0 200 OK';
...@@ -50,4 +77,3 @@ try { ...@@ -50,4 +77,3 @@ try {
header($status); header($status);
header("Content-Type: application/json"); header("Content-Type: application/json");
echo json_encode($answer); echo json_encode($answer);
...@@ -365,6 +365,7 @@ const ERROR_IMPORT_LIST_SHEET_NAMES = 2901; ...@@ -365,6 +365,7 @@ const ERROR_IMPORT_LIST_SHEET_NAMES = 2901;
// REST // REST
const ERROR_FORM_REST = 3000; const ERROR_FORM_REST = 3000;
const ERROR_REST_AUTHORIZATION = 3001; const ERROR_REST_AUTHORIZATION = 3001;
const ERROR_REST_INVALID_ID = 3002;
// //
// Store Names: Identifier // Store Names: Identifier
// //
...@@ -420,12 +421,18 @@ const CLIENT_SERVER_ADDRESS = 'SERVER_ADDR'; ...@@ -420,12 +421,18 @@ const CLIENT_SERVER_ADDRESS = 'SERVER_ADDR';
const CLIENT_SERVER_PORT = 'SERVER_PORT'; const CLIENT_SERVER_PORT = 'SERVER_PORT';
const CLIENT_REMOTE_ADDRESS = 'REMOTE_ADDR'; const CLIENT_REMOTE_ADDRESS = 'REMOTE_ADDR';
const CLIENT_REQUEST_SCHEME = 'REQUEST_SCHEME'; const CLIENT_REQUEST_SCHEME = 'REQUEST_SCHEME';
const CLIENT_REQUEST_METHOD = 'REQUEST_METHOD';
const CLIENT_SCRIPT_FILENAME = 'SCRIPT_FILENAME'; const CLIENT_SCRIPT_FILENAME = 'SCRIPT_FILENAME';
const CLIENT_QUERY_STRING = 'QUERY_STRING'; const CLIENT_QUERY_STRING = 'QUERY_STRING';
const CLIENT_REQUEST_URI = 'REQUEST_URI'; const CLIENT_REQUEST_URI = 'REQUEST_URI';
const CLIENT_SCRIPT_NAME = 'SCRIPT_NAME'; const CLIENT_SCRIPT_NAME = 'SCRIPT_NAME';
const CLIENT_PHP_SELF = 'PHP_SELF'; const CLIENT_PHP_SELF = 'PHP_SELF';
const REQUEST_METHOD_GET = 'GET';
const REQUEST_METHOD_POST = 'POST';
const REQUEST_METHOD_PUT = 'PUT';
const REQUEST_METHOD_DELETE = 'DELETE';
// _COOKIE // _COOKIE
const CLIENT_COOKIE_QFQ = 'cookieQfq'; const CLIENT_COOKIE_QFQ = 'cookieQfq';
...@@ -879,6 +886,7 @@ const F_TITLE = 'title'; ...@@ -879,6 +886,7 @@ const F_TITLE = 'title';
const F_TABLE_NAME = 'tableName'; const F_TABLE_NAME = 'tableName';
const F_PRIMARY_KEY = 'primaryKey'; const F_PRIMARY_KEY = 'primaryKey';
const F_PRIMARY_KEY_DEFAULT = 'id'; const F_PRIMARY_KEY_DEFAULT = 'id';
const F_REST_METHOD = 'restMethod';
const F_REQUIRED_PARAMETER_NEW = 'requiredParameterNew'; const F_REQUIRED_PARAMETER_NEW = 'requiredParameterNew';
const F_REQUIRED_PARAMETER_EDIT = 'requiredParameterEdit'; const F_REQUIRED_PARAMETER_EDIT = 'requiredParameterEdit';
const F_EXTRA_DELETE_FORM = 'extraDeleteForm'; const F_EXTRA_DELETE_FORM = 'extraDeleteForm';
......
...@@ -172,7 +172,7 @@ class QuickFormQuery { ...@@ -172,7 +172,7 @@ class QuickFormQuery {
Session::checkSessionExpired($timeout); Session::checkSessionExpired($timeout);
// If an FE user logs out and a different user logs in (same browser session) - the old values has to be destroyed! // If an FE user logs out and a different user logs in (same browser session) - the old values has to be destroyed!
if (Session::getAndDestroyFlagFeUserHasChanged() ) { if (Session::getAndDestroyFlagFeUserHasChanged()) {
$this->store->unsetStore(STORE_USER); $this->store->unsetStore(STORE_USER);
} }
...@@ -371,7 +371,6 @@ class QuickFormQuery { ...@@ -371,7 +371,6 @@ class QuickFormQuery {
// Check 'session expire' happens quite late, cause it can be configured per form. // Check 'session expire' happens quite late, cause it can be configured per form.
Session::checkSessionExpired($this->formSpec[F_SESSION_TIMEOUT_SECONDS]); Session::checkSessionExpired($this->formSpec[F_SESSION_TIMEOUT_SECONDS]);
if ($formName !== false) { if ($formName !== false) {
// Validate only if there is a 'real' form (not a FORM_DELETE with only a tablename). // Validate only if there is a 'real' form (not a FORM_DELETE with only a tablename).
$sipFound = $this->validateForm($foundInStore, $formMode); $sipFound = $this->validateForm($foundInStore, $formMode);
...@@ -984,13 +983,10 @@ class QuickFormQuery { ...@@ -984,13 +983,10 @@ class QuickFormQuery {
HelperFormElement::explodeParameter($form, F_PARAMETER); HelperFormElement::explodeParameter($form, F_PARAMETER);
unset($form[F_PARAMETER]); unset($form[F_PARAMETER]);
if (isset($form[FE_FILL_STORE_VAR])) {
$fillStoreVar = $form[FE_FILL_STORE_VAR];
unset($form[FE_FILL_STORE_VAR]);
}
// Save specific elements to be expanded later. // Save specific elements to be expanded later.
$parseLater = OnArray::getArrayItems($form, [F_FORWARD_PAGE, F_REST_SQL_LIST, F_REST_SQL_DATA]); $parseLater = OnArray::getArrayItems($form, [F_FORWARD_PAGE, FE_FILL_STORE_VAR, F_REST_SQL_LIST, F_REST_SQL_DATA]);
$form[FE_FILL_STORE_VAR] = '';
$form[F_FORWARD_PAGE] = ''; $form[F_FORWARD_PAGE] = '';
$form[F_REST_SQL_LIST] = ''; $form[F_REST_SQL_LIST] = '';
$form[F_REST_SQL_DATA] = ''; $form[F_REST_SQL_DATA] = '';
...@@ -1054,8 +1050,11 @@ class QuickFormQuery { ...@@ -1054,8 +1050,11 @@ class QuickFormQuery {
!empty($form[FORM_LOG_ACTIVE]) && Logger::logFormLine($form, "F:$mode:evaluated:" . date('Y-m-d H:i:s'), $form, true); !empty($form[FORM_LOG_ACTIVE]) && Logger::logFormLine($form, "F:$mode:evaluated:" . date('Y-m-d H:i:s'), $form, true);
// Fire FE_FILL_STORE_VAR after the primary form record has been loaded // Fire FE_FILL_STORE_VAR after the primary form record has been loaded
if (!empty($fillStoreVar)) { if (!empty($formSpec[FE_FILL_STORE_VAR])) {
$rows = $this->evaluate->parse($fillStoreVar, ROW_EXPECT_0_1);
$rows = $this->evaluate->parse($formSpec[FE_FILL_STORE_VAR], ROW_EXPECT_0_1);
unset($formSpec[FE_FILL_STORE_VAR]);
if (is_array($rows)) { if (is_array($rows)) {
$this->store->appendToStore($rows, STORE_VAR); $this->store->appendToStore($rows, STORE_VAR);
// LOG // LOG
...@@ -1422,10 +1421,10 @@ class QuickFormQuery { ...@@ -1422,10 +1421,10 @@ class QuickFormQuery {
*/ */
private function validateForm($formNameFoundInStore, $formMode) { private function validateForm($formNameFoundInStore, $formMode) {
// Retrieve record_id either from SIP (prefered) or via URL // Retrieve record_id either from SIP (preferred) or via URL
$r = $this->store->getVar(SIP_RECORD_ID, STORE_SIP . STORE_TYPO3 . STORE_CLIENT, '', $recordIdFoundInStore); $r = $this->store->getVar(SIP_RECORD_ID, STORE_SIP . STORE_TYPO3 . STORE_CLIENT, '', $recordIdFoundInStore);
// If not found: Fake a definition in STORE_TYPO3. // no record id: Fake a definition in STORE_TYPO3.
if ($r === false) { if ($r === false) {
$r = 0; $r = 0;
$this->store->setVar(TYPO3_RECORD_ID, $r, STORE_TYPO3); $this->store->setVar(TYPO3_RECORD_ID, $r, STORE_TYPO3);
...@@ -1466,22 +1465,23 @@ class QuickFormQuery { ...@@ -1466,22 +1465,23 @@ class QuickFormQuery {
case FORM_PERMISSION_NEVER: case FORM_PERMISSION_NEVER:
throw new UserFormException("Loading form forbidden.", ERROR_FORM_FORBIDDEN); throw new UserFormException("Loading form forbidden.", ERROR_FORM_FORBIDDEN);
break; break;
case FORM_PERMISSION_REST: // case FORM_PERMISSION_REST:
if ($formMode != FORM_REST) { // if ($formMode != FORM_REST) {
throw new UserFormException("Try to load a REST form", ERROR_FORM_REST); // throw new UserFormException("Try to load a REST form", ERROR_FORM_REST);
} // }
break; // break;
default: default:
throw new CodeException("Unknown permission mode: '" . $permitMode . "'", ERROR_FORM_UNKNOWN_PERMISSION_MODE); throw new CodeException("Unknown permission mode: '" . $permitMode . "'", ERROR_FORM_UNKNOWN_PERMISSION_MODE);
} }
if ($formMode == FORM_REST) { if ($formMode == FORM_REST) {
$this->restCheckAuthToken($this->formSpec[F_REST_TOKEN] ?? ''); $method = strtolower($this->store::getVar(CLIENT_REQUEST_METHOD, STORE_CLIENT));
if (false === Support::findInSet($method, $this->formSpec[F_REST_METHOD])) {
if ($permitMode != FORM_PERMISSION_REST) { throw new UserFormException("Form '". $this->formSpec[F_NAME]. "' is not allowed with method '$method'", ERROR_FORM_REST);
throw new UserFormException("Try to load a non-REST form in REST mode", ERROR_FORM_REST);
} }
$this->restCheckAuthToken($this->formSpec[F_REST_TOKEN] ?? '');
} }
// Form Definition valid? // Form Definition valid?
...@@ -1871,7 +1871,7 @@ EOF; ...@@ -1871,7 +1871,7 @@ EOF;
/** /**
* @param array $restId * @param array $restId
* @param array $restForm * @param string $method
* @return array|string * @return array|string
* @throws CodeException * @throws CodeException
* @throws DbException * @throws DbException
......
...@@ -137,6 +137,10 @@ $UPDATE_ARRAY = array( ...@@ -137,6 +137,10 @@ $UPDATE_ARRAY = array(
"ALTER TABLE `FormElement` ADD `labelAlign` ENUM('default','left','center','right') NOT NULL DEFAULT 'default' AFTER `maxLength`;", "ALTER TABLE `FormElement` ADD `labelAlign` ENUM('default','left','center','right') NOT NULL DEFAULT 'default' AFTER `maxLength`;",
], ],
'19.2.3' => [
"ALTER TABLE `Form` ADD `restMethod` SET('get','post','put','delete') NOT NULL DEFAULT '' AFTER `permitEdit`; ",
],
); );
......
...@@ -319,7 +319,7 @@ class Support { ...@@ -319,7 +319,7 @@ class Support {
/** /**
* Search for the parameter $needle in $haystack. The arguments has to be separated by ','. * Search for the parameter $needle in $haystack. The arguments has to be separated by ','.
* *
* Returns false if not found or index of found place. Be careful: use unary operator to compare for 'false' * Returns false if not found, or index (starting with 0) of found place. Be careful: use unary operator to compare for 'false'
* *
* @param string $needle * @param string $needle
* @param string $haystack * @param string $haystack
......
...@@ -42,14 +42,12 @@ class Client { ...@@ -42,14 +42,12 @@ class Client {
if (isset($_POST)) { if (isset($_POST)) {
$post = $_POST; $post = $_POST;
// Logger::logMessage(var_export($post, true) . PHP_EOL . PHP_EOL,'post.txt');
} }
if (isset($_COOKIE[SESSION_NAME])) { if (isset($_COOKIE[SESSION_NAME])) {
$cookie[CLIENT_COOKIE_QFQ] = $_COOKIE[SESSION_NAME]; $cookie[CLIENT_COOKIE_QFQ] = $_COOKIE[SESSION_NAME];
} }
// It's important to merge the SERVER array last: those entries shall overwrite client values.
if (isset($_SERVER)) { if (isset($_SERVER)) {
$server = Sanitize::htmlentitiesArr($_SERVER); // $_SERVER values might be compromised. $server = Sanitize::htmlentitiesArr($_SERVER); // $_SERVER values might be compromised.
} }
...@@ -59,6 +57,7 @@ class Client { ...@@ -59,6 +57,7 @@ class Client {
$server[CLIENT_REMOTE_ADDRESS] = '0.0.0.0'; $server[CLIENT_REMOTE_ADDRESS] = '0.0.0.0';
} }
// It's important to merge the SERVER array last: those entries shall overwrite client values.
$arr = array_merge($header, $get, $post, $cookie, $server); $arr = array_merge($header, $get, $post, $cookie, $server);
return Sanitize::normalize($arr); return Sanitize::normalize($arr);
......
...@@ -124,6 +124,7 @@ class Store { ...@@ -124,6 +124,7 @@ class Store {
CLIENT_SERVER_PORT => SANITIZE_ALLOW_DIGIT, CLIENT_SERVER_PORT => SANITIZE_ALLOW_DIGIT,
CLIENT_REMOTE_ADDRESS => SANITIZE_ALLOW_ALNUMX, CLIENT_REMOTE_ADDRESS => SANITIZE_ALLOW_ALNUMX,
CLIENT_REQUEST_SCHEME => SANITIZE_ALLOW_ALNUMX, CLIENT_REQUEST_SCHEME => SANITIZE_ALLOW_ALNUMX,
CLIENT_REQUEST_METHOD => SANITIZE_ALLOW_ALNUMX,
CLIENT_SCRIPT_FILENAME => SANITIZE_ALLOW_ALNUMX, CLIENT_SCRIPT_FILENAME => SANITIZE_ALLOW_ALNUMX,
CLIENT_QUERY_STRING => SANITIZE_ALLOW_ALL, CLIENT_QUERY_STRING => SANITIZE_ALLOW_ALL,
CLIENT_REQUEST_URI => SANITIZE_ALLOW_ALL, CLIENT_REQUEST_URI => SANITIZE_ALLOW_ALL,
......
This diff is collapsed.
Supports Markdown
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