File modules/cms/action/RequestParams.class.php

Last commit: Mon Apr 22 22:29:49 2024 +0200	Jan Dankert	Editing coordinates now possible.
1 <?php 2 3 namespace cms\action; 4 5 use util\exception\ValidationException; 6 use util\json\JSON; 7 use util\mail\Mail; 8 use util\Text; 9 use util\YAML; 10 11 12 class RequestParams 13 { 14 const PARAM_TOKEN = 'token' ; 15 const PARAM_ACTION = 'action' ; 16 const PARAM_SUBACTION = 'subaction' ; 17 const PARAM_ID = 'id' ; 18 const PARAM_LANGUAGE_ID = 'languageid' ; 19 const PARAM_MODEL_ID = 'modelid' ; 20 const PARAM_PROJECT_ID = 'projectid' ; 21 const PARAM_DATABASE_ID = 'dbid' ; 22 const PARAM_OUTPUT = 'output' ; 23 24 public $action; 25 public $method; 26 public $id; 27 28 public $isAction; 29 30 /** 31 * Request headers. 32 * @var array 33 */ 34 35 public $headers; 36 public $authUser; 37 public $authPassword; 38 public $authToken; 39 40 private $parameter; 41 42 /** 43 * @var bool 44 */ 45 public $isUIAction; 46 47 48 /** 49 * @var bool 50 */ 51 public $withAuthorization; 52 53 /** 54 * RequestParams constructor. 55 */ 56 public function __construct() 57 { 58 // Is this a POST request? 59 $this->isAction = @$_SERVER['REQUEST_METHOD'] == 'POST'; 60 $this->headers = array_change_key_case(getallheaders(), CASE_LOWER); 61 62 $this->tryBasicAuthorization(); 63 64 $this->setParameterStore(); 65 66 $this->id = $this->getId(); 67 $this->action = $this->getAlphanum(self::PARAM_ACTION ); 68 $this->method = $this->getAlphanum(self::PARAM_SUBACTION); 69 } 70 71 72 /** 73 * Setting the source for request parameters. 74 */ 75 protected function setParameterStore() { 76 77 78 $contenttype = trim(explode( ';',@$this->headers['content-type'])[0]); 79 80 if ( !$this->isAction ) 81 $this->parameter = &$_GET; 82 // GET method in the HTTP/1.1 spec, section 9.3: 83 // The GET method means retrieve whatever information ([...]) is identified by the Request-URI. 84 // so the request body MUST be ignored here. 85 else 86 // POST requests are NOT idempotent 87 switch( $contenttype ) { 88 // These content-types are known by PHP, so we do NOT have to parse them: 89 case 'application/x-www-form-urlencoded': // the most used form url encoding 90 case 'multipart/form-data': // Multipart-Formdata for File uploads 91 case '': 92 $this->parameter = &$_POST; // Using builtin POST data parsing 93 break; 94 95 // The request body contains a JSON document 96 case 'text/json': 97 case 'application/json': 98 // parsing the JSON data 99 $this->parameter = JSON::decode(file_get_contents("php://input")); 100 break; 101 102 case 'text/xml': 103 case 'application/xml': 104 $this->parameter = (array)simplexml_load_string(file_get_contents("php://input")); 105 break; 106 107 case 'application/yaml': 108 $this->parameter = YAML::parse(file_get_contents("php://input")); 109 break; 110 111 default: 112 // Unknown content type 113 throw new \LogicException('HTTP-POST with unknown content type: ' . $contenttype); 114 } 115 116 } 117 118 119 120 /** 121 * Ermittelt den Inhalt der gew�nschten Request-Variablen. 122 * Falls nicht vorhanden, wird "" zur�ckgegeben. 123 * 124 * @param String $varName Schl�ssel 125 * @return String Inhalt 126 */ 127 protected function getValue($varName) 128 { 129 if ( ! $this->hasKey($varName) ) 130 return null; 131 132 return $this->parameter[$varName]; 133 } 134 135 protected function requireVar( $varName ) 136 { 137 if ( ! $this->hasKey($varName) ) 138 throw new ValidationException( $varName ); 139 140 return; 141 } 142 143 144 public function getAlphanum($varName ) { 145 return Text::clean( $this->getValue($varName), 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.,_-!?%&/()' ); 146 } 147 148 149 public function getFilename($varName ) { 150 151 // RFC 1738, Section 2.2: 152 // Thus, only alphanumerics, the special characters "$-_.+!*'(),", and 153 // reserved characters used for their reserved purposes may be used 154 // unencoded within a URL. 155 return Text::clean( $this->getValue($varName), 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789$-_.+!*(),\'' ); 156 } 157 158 159 /** 160 * Gets a mail adress out of the request. 161 * 162 * Throws a ValidationException if the mail adress is not valid. 163 * 164 * @param $varName 165 * @return String 166 */ 167 public function getValidMail($varName ) { 168 169 $adress = Text::clean( $this->getValue($varName), 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-+@' ); 170 171 if ( ! Mail::checkAddress( $adress ) ) 172 throw new ValidationException( $varName ); 173 174 return $adress; 175 } 176 177 178 public function getRaw($varName ) { 179 return $this->getValue( $varName ); 180 } 181 182 183 /** 184 * Get required parameter value. 185 * 186 * @param $varName 187 * @return String|null 188 * @throws ValidationException 189 */ 190 public function getRequiredRaw($varName ) { 191 192 $this->requireVar( $varName ); 193 194 return $this->getValue( $varName ); 195 } 196 197 198 /** 199 * @param $varName 200 * @return string|null 201 */ 202 public function getText( $varName ) { 203 204 if ( ! $this->hasKey($varName )) 205 return null; 206 207 // Allow all UTF-8 characters. 208 return mb_convert_encoding($this->getValue($varName), 'UTF-8', 'UTF-8'); 209 } 210 211 212 /** 213 * @param $varName string name of request parameter 214 * @param $callback callable only called if the request parameter is given by the client 215 */ 216 public function handleText( $varName,$callback ) { 217 218 if ( $this->hasKey($varName ) ) 219 call_user_func( $callback, $this->getText($varName) ); 220 } 221 222 /** 223 * @param $varName 224 * @param $callback 225 */ 226 public function handleNumber( $varName,$callback ) { 227 228 if ( $this->hasKey($varName ) ) 229 call_user_func( $callback, $this->getNumber($varName) ); 230 } 231 232 /** 233 * @param $varName 234 * @param $callback 235 */ 236 public function handleBool($varName, $callback ) { 237 238 call_user_func( $callback, $this->isTrue($varName) ); 239 } 240 241 242 /** 243 * Gets the value of the request parameter. 244 * 245 * @param $nameOfRequestParameter 246 * @return String 247 * @throws ValidationException 248 */ 249 public function getRequiredText( $nameOfRequestParameter ) { 250 251 $this->requireVar( $nameOfRequestParameter ); 252 253 return $this->getText( $nameOfRequestParameter ); 254 } 255 256 257 258 /** 259 * Gets the value of the request parameter. 260 * 261 * @param $nameOfRequestParameter 262 * @return String 263 * @throws ValidationException 264 */ 265 public function getNotEmptyText( $nameOfRequestParameter ) { 266 267 if ( $value = $this->getRequiredText( $nameOfRequestParameter ) ) 268 return $value; 269 else 270 return new ValidationException( $nameOfRequestParameter ); 271 } 272 273 274 275 /** 276 * Checks if the request contains the parameter. 277 * 278 * @param String $varName Schl�ssel 279 * @return boolean true, falls vorhanden. 280 */ 281 protected function hasKey($varName) 282 { 283 return isset( $this->parameter[$varName] ); 284 } 285 286 287 /** 288 * Gets the ID for the current action. 289 * 290 * @return Integer 291 */ 292 public function getId() 293 { 294 return $this->getAlphanum( self::PARAM_ID ); 295 } 296 297 298 /** 299 * Ermittelt die aktuelle Id aus dem Request.<br> 300 * Um welche ID es sich handelt, ist abh�ngig von der Action. 301 * 302 * @param string $varName name of parameter 303 * @return Integer 304 */ 305 public function getNumber( $varName ) 306 { 307 if ( ! $this->hasKey($varName )) 308 return null; 309 310 return intval($this->getValue( $varName )); 311 } 312 313 314 315 316 /** 317 * Ermittelt einen Float-Wert aus dem Request.<br> 318 * 319 * @param string $varName name of parameter 320 * @return Float 321 */ 322 public function getFloat( $varName ) 323 { 324 if ( ! $this->hasKey($varName )) 325 return null; 326 327 return floatval($this->getValue( $varName )); 328 } 329 /** 330 * Checks if the parameter value is true. 331 * 332 * @param string $varName name of parameter 333 * @return Integer 334 */ 335 public function isTrue( $varName ) 336 { 337 return in_array( $this->getValue($varName),['1','true','on']); 338 } 339 340 341 342 343 /** 344 * Ermittelt die aktuelle Id aus dem Request.<br> 345 * Um welche ID es sich handelt, ist abh�ngig von der Action. 346 * 347 * @param string $varName name of parameter 348 * @return Integer 349 */ 350 public function getRequiredNumber($varName ) 351 { 352 $this->requireVar( $varName ); 353 354 return $this->getNumber( $varName ); 355 } 356 357 358 public function getLanguageId() 359 { 360 return $this->getNumber(self::PARAM_LANGUAGE_ID); 361 } 362 363 364 public function getModelId() 365 { 366 return $this->getNumber(self::PARAM_MODEL_ID ); 367 } 368 369 370 public function getProjectId() 371 { 372 return $this->getNumber(self::PARAM_PROJECT_ID ); 373 } 374 375 376 public function getDatabaseId() 377 { 378 return $this->getAlphanum(self::PARAM_DATABASE_ID ); 379 } 380 381 382 public function getToken() 383 { 384 return $this->getAlphanum(self::PARAM_TOKEN ); 385 } 386 387 388 public function __toString() { 389 return 'Request '.$this->action.'/'.$this->method.'/'.$this->id; 390 } 391 392 393 /** 394 * Redirect to a new action and method. 395 * 396 * @param $action 397 * @param $method 398 */ 399 public function redirectActionAndMethod( $action, $method ) { 400 401 $this->action = $action; 402 $this->method = $method; 403 } 404 405 406 /** 407 * Basic Authorization. 408 * 409 * Try login with basic authorization. This is useful for API clients, they to not need to track a session with cookies. 410 */ 411 private function tryBasicAuthorization() 412 { 413 if ( $auth = @$this->headers['authorization'] ) { 414 415 $this->withAuthorization = true; 416 list( $type,$value ) = array_pad( explode(' ',$auth),2,''); 417 switch( $type ) { 418 case 'Basic': 419 list($this->authUser,$this->authPassword) = array_pad(explode(':',base64_decode( $value )),2,'' ); 420 break; 421 case 'Bearer': 422 $this->authToken = $value; 423 break; 424 default: 425 // Only supporting Basic Auth and Bearer Auth 426 error_log('Only supporting Basic and Bearer authorization. Authorization header will be ignored.'); 427 } 428 429 } 430 } 431 }
Download modules/cms/action/RequestParams.class.php
History Mon, 22 Apr 2024 22:29:49 +0200 Jan Dankert Editing coordinates now possible. Thu, 28 Apr 2022 00:28:24 +0200 Jan Dankert New: Login with Json webtoken (JWT) Mon, 25 Apr 2022 03:26:21 +0200 Jan Dankert New: New Project may be created with sample data. Fri, 15 Apr 2022 14:51:22 +0200 dankert Refactoring: User,Config and Database info is now stored in the Request, because so there is no session required for clients which are using Basic Authorization. Wed, 9 Mar 2022 13:28:52 +0100 dankert Refactoring: Checkbox values are always sent to the server. In the actions we must test the value with 'isTrue()' Wed, 9 Mar 2022 00:52:23 +0100 dankert New: Only save a property if it is send by the client. This is useful using a API, so not sent properties will not be deleted. Sun, 13 Feb 2022 19:39:49 +0100 dankert Refactoring: Special output type "preview" for previewing pages and files. Mon, 7 Feb 2022 21:44:42 +0100 dankert New: Authenticate API users with the HTTP authorization header. Mon, 7 Feb 2022 19:48:06 +0100 dankert New: Support for YAML in request body. Wed, 17 Nov 2021 23:29:17 +0100 Jan Dankert Refactoring: New method for redirecting action and method. Wed, 27 Oct 2021 02:27:59 +0200 Jan Dankert Refactoring: Splitted the mail client into a.) sendmail and b.) smtp. Thu, 11 Mar 2021 00:01:47 +0100 Jan Dankert Refactoring: Cleaned the Request params. Wed, 10 Mar 2021 23:51:22 +0100 Jan Dankert Refactoring: Cleaned the Request params. Sat, 27 Feb 2021 01:07:14 +0100 Jan Dankert Fix: Request-Id may contain '_'. Fri, 26 Feb 2021 01:06:01 +0100 Jan Dankert Refactoring accessing the request parameter values. Fri, 26 Feb 2021 00:04:49 +0100 Jan Dankert New: Request may contain JSON,XML in POST data. This is good for API clients. Thu, 25 Feb 2021 01:22:10 +0100 Jan Dankert New: Edit all page elements in 1 view. Sat, 20 Feb 2021 00:49:37 +0100 Jan Dankert Cleanup of templates. Sat, 31 Oct 2020 01:19:06 +0100 Jan Dankert Better logging in the dispatcher. Tue, 29 Sep 2020 22:17:11 +0200 Jan Dankert Refactoring: Do not use global constants. Sat, 26 Sep 2020 21:42:51 +0200 Jan Dankert Refactoring: The UI Actions are now in their own namespace. No need for a confusing require file. Sat, 26 Sep 2020 12:20:43 +0200 Jan Dankert Refactoring: No global variables like $SESS any more. All constants are capsulated by classes. Thu, 10 Sep 2020 18:30:16 +0200 Jan Dankert Some code cleanup, killing the old "checkMenu()"-methods. Thu, 10 Sep 2020 18:02:54 +0200 Jan Dankert The dispatcher is now able to call the action methods with parameters. Sun, 23 Feb 2020 04:01:30 +0100 Jan Dankert Refactoring with Namespaces for the cms modules, part 1: moving.