* e.g. from protocol implementations.
*
* @param string[] $request The $_REQUEST content
+ * @return void
*/
protected function rawContent(array $request = [])
{
* XML feed or a JSON output.
*
* @param string[] $request The $_REQUEST content
+ * @return string
*/
protected function content(array $request = []): string
{
* Doesn't display any content
*
* @param string[] $request The $_REQUEST content
+ * @return void
*/
protected function delete(array $request = [])
{
* Doesn't display any content
*
* @param string[] $request The $_REQUEST content
+ * @return void
*/
protected function patch(array $request = [])
{
* Doesn't display any content
*
* @param string[] $request The $_REQUEST content
- *
+ * @return void
*/
protected function post(array $request = [])
{
* Doesn't display any content
*
* @param string[] $request The $_REQUEST content
+ * @return void
*/
protected function put(array $request = [])
{
}
- /**
- * Module OPTIONS method to process submitted data
- *
- * Extend this method if the module is supposed to process OPTIONS requests.
- * Doesn't display any content
- *
- * @param string[] $request The $_REQUEST content
- */
- protected function options(array $request = [])
- {
- }
-
/**
* {@inheritDoc}
*/
$this->profiler->set(microtime(true) - $timestamp, 'init');
- switch ($this->args->getMethod() ?? Router::GET) {
+ switch ($this->args->getMethod()) {
case Router::DELETE:
$this->delete($request);
break;
case Router::PUT:
$this->put($request);
break;
- case Router::OPTIONS:
- $this->options($request);
- break;
}
$timestamp = microtime(true);
$request = [];
foreach ($defaults as $parameter => $defaultvalue) {
- if (is_string($defaultvalue)) {
- $request[$parameter] = $input[$parameter] ?? $defaultvalue;
- } elseif (is_int($defaultvalue)) {
- $request[$parameter] = (int)($input[$parameter] ?? $defaultvalue);
- } elseif (is_float($defaultvalue)) {
- $request[$parameter] = (float)($input[$parameter] ?? $defaultvalue);
- } elseif (is_array($defaultvalue)) {
- $request[$parameter] = $input[$parameter] ?? [];
- } elseif (is_bool($defaultvalue)) {
- $request[$parameter] = in_array(strtolower($input[$parameter] ?? ''), ['true', '1']);
- } else {
- $this->logger->notice('Unhandled default value type', ['parameter' => $parameter, 'type' => gettype($defaultvalue)]);
- }
+ $request[$parameter] = $this->getRequestValue($input, $parameter, $defaultvalue);
}
foreach ($input ?? [] as $parameter => $value) {
return $request;
}
- /*
+ /**
+ * Fetch a request value and apply default values and check against minimal and maximal values
+ *
+ * @param array $input Input fields
+ * @param string $parameter Parameter
+ * @param mixed $default Default
+ * @param mixed $minimal_value Minimal value
+ * @param mixed $maximum_value Maximum value
+ * @return mixed null on error anything else on success (?)
+ */
+ public function getRequestValue(array $input, string $parameter, $default = null, $minimal_value = null, $maximum_value = null)
+ {
+ if (is_string($default)) {
+ $value = (string)($input[$parameter] ?? $default);
+ } elseif (is_int($default)) {
+ $value = filter_var($input[$parameter] ?? $default, FILTER_VALIDATE_INT);
+ if (!is_null($minimal_value)) {
+ $value = max(filter_var($minimal_value, FILTER_VALIDATE_INT), $value);
+ }
+ if (!is_null($maximum_value)) {
+ $value = min(filter_var($maximum_value, FILTER_VALIDATE_INT), $value);
+ }
+ } elseif (is_float($default)) {
+ $value = filter_var($input[$parameter] ?? $default, FILTER_VALIDATE_FLOAT);
+ if (!is_null($minimal_value)) {
+ $value = max(filter_var($minimal_value, FILTER_VALIDATE_FLOAT), $value);
+ }
+ if (!is_null($maximum_value)) {
+ $value = min(filter_var($maximum_value, FILTER_VALIDATE_FLOAT), $value);
+ }
+ } elseif (is_array($default)) {
+ $value = filter_var($input[$parameter] ?? $default, FILTER_DEFAULT, ['flags' => FILTER_FORCE_ARRAY]);
+ } elseif (is_bool($default)) {
+ $value = filter_var($input[$parameter] ?? $default, FILTER_VALIDATE_BOOLEAN);
+ } elseif (is_null($default)) {
+ $value = $input[$parameter] ?? null;
+ } else {
+ $this->logger->notice('Unhandled default value type', ['parameter' => $parameter, 'type' => gettype($default)]);
+ $value = null;
+ }
+
+ return $value;
+ }
+
+ /**
* Functions used to protect against Cross-Site Request Forgery
* The security token has to base on at least one value that an attacker can't know - here it's the session ID and the private key.
* In this implementation, a security token is reusable (if the user submits a form, goes back and resubmits the form, maybe with small changes;
* If the new page contains by any chance external elements, then the used security token is exposed by the referrer.
* Actually, important actions should not be triggered by Links / GET-Requests at all, but sometimes they still are,
* so this mechanism brings in some damage control (the attacker would be able to forge a request to a form of this type, but not to forms of other types).
+ *
+ * @param string $typename Type name
+ * @return string Security hash with timestamp
*/
- public static function getFormSecurityToken($typename = '')
+ public static function getFormSecurityToken(string $typename = ''): string
{
$user = User::getById(DI::app()->getLoggedInUserId(), ['guid', 'prvkey']);
$timestamp = time();
return $timestamp . '.' . $sec_hash;
}
- public static function checkFormSecurityToken($typename = '', $formname = 'form_security_token')
+ /**
+ * Checks if form's security (CSRF) token is valid.
+ *
+ * @param string $typename ???
+ * @param string $formname Name of form/field (???)
+ * @return bool Whether it is valid
+ */
+ public static function checkFormSecurityToken(string $typename = '', string $formname = 'form_security_token'): bool
{
$hash = null;
return ($sec_hash == $x[1]);
}
- public static function getFormSecurityStandardErrorMessage()
+ public static function getFormSecurityStandardErrorMessage(): string
{
- return DI::l10n()->t("The form security token was not correct. This probably happened because the form has been opened for too long \x28>3 hours\x29 before submitting it.") . EOL;
+ return DI::l10n()->t("The form security token was not correct. This probably happened because the form has been opened for too long \x28>3 hours\x29 before submitting it.");
}
- public static function checkFormSecurityTokenRedirectOnError($err_redirect, $typename = '', $formname = 'form_security_token')
+ public static function checkFormSecurityTokenRedirectOnError(string $err_redirect, string $typename = '', string $formname = 'form_security_token')
{
if (!self::checkFormSecurityToken($typename, $formname)) {
Logger::notice('checkFormSecurityToken failed: user ' . DI::app()->getLoggedInUserNickname() . ' - form element ' . $typename);
Logger::debug('checkFormSecurityToken failed', ['request' => $_REQUEST]);
- notice(self::getFormSecurityStandardErrorMessage());
+ DI::sysmsg()->addNotice(self::getFormSecurityStandardErrorMessage());
DI::baseUrl()->redirect($err_redirect);
}
}
- public static function checkFormSecurityTokenForbiddenOnError($typename = '', $formname = 'form_security_token')
+ public static function checkFormSecurityTokenForbiddenOnError(string $typename = '', string $formname = 'form_security_token')
{
if (!self::checkFormSecurityToken($typename, $formname)) {
Logger::notice('checkFormSecurityToken failed: user ' . DI::app()->getLoggedInUserNickname() . ' - form element ' . $typename);
}
}
- protected static function getContactFilterTabs(string $baseUrl, string $current, bool $displayCommonTab)
+ protected static function getContactFilterTabs(string $baseUrl, string $current, bool $displayCommonTab): array
{
$tabs = [
[