From a76185db96741fe6bc3e09cd2069725d3b8bad87 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Sat, 17 Feb 2018 18:24:08 +0100 Subject: [PATCH 1/4] +add build.error --- build/error/core/Err.php | 112 +++++++++++++++++++++ build/error/core/Error.php | 197 +++++++++++++++++++++++++++++++++++++ 2 files changed, 309 insertions(+) create mode 100755 build/error/core/Err.php create mode 100755 build/error/core/Error.php diff --git a/build/error/core/Err.php b/build/error/core/Err.php new file mode 100755 index 0000000..449733e --- /dev/null +++ b/build/error/core/Err.php @@ -0,0 +1,112 @@ + diff --git a/build/error/core/Error.php b/build/error/core/Error.php new file mode 100755 index 0000000..9d2d2d0 --- /dev/null +++ b/build/error/core/Error.php @@ -0,0 +1,197 @@ + Const error + * @arg1 [OPT] Argument 1 + * @arg2 [OPT] Argument 2 + * @arg... [OPT] Argument ... + * + * @return instance Error instance + * + */ + public function __construct($const){ + call_user_func_array([$this, 'set'], func_get_args()); + } + + /* ERROR GETTER + * + * @return Err Error + * + */ + public function get(){ return $this->error; } + + /* ERROR SETTER + * + * @error Const error + * @arg1 [OPT] Argument 1 + * @arg2 [OPT] Argument 2 + * @arg... [OPT] Argument ... + * + * @return instance Error instance + * + */ + public function set($const){ + /* [1] On découpe les arguments + =========================================================*/ + /* (1) On récupère l'erreur */ + $this->error = !is_numeric($const) ? Err::UnknownError : $const; + + /* (2) On récupère les arguments */ + $this->arguments = array_slice(func_get_args(), 1); + } + + + /* EXPLICITE UN CODE D'ERREUR + * + * @return explicit Description explicite du code d'erreur + * + */ + public function explicit(){ + switch($this->error){ + case Err::Success: return $this->Success(); break; + case Err::ParsingFailed: return $this->ParsingFailed(); break; + case Err::UnreachableResource: return $this->UnreachableResource(); break; + case Err::UploadError: return $this->UploadError(); break; + case Err::FormatError: return $this->FormatError(); break; + case Err::TokenError: return $this->TokenError(); break; + case Err::PermissionError: return $this->PermissionError(); break; + case Err::DisabledModule: return $this->DisabledModule(); break; + case Err::MissingPath: return $this->MissingPath(); break; + case Err::WrongPathModule: return $this->WrongPathModule(); break; + case Err::UnknownModule: return $this->UnknownModule(); break; + case Err::UnknownMethod: return $this->UnknownMethod(); break; + case Err::UncallableModule: return $this->UncallableModule(); break; + case Err::UncallableMethod: return $this->UncallableMethod(); break; + case Err::UnknownHttpMethod: return $this->UnknownHttpMethod(); break; + case Err::ConfigError: return $this->ConfigError(); break; + case Err::MissingParam: return $this->MissingParam(); break; + case Err::WrongParam: return $this->WrongParam(); break; + case Err::ModuleError: return $this->ModuleError(); break; + case Err::PDOConnection: return $this->PDOConnection(); break; + case Err::WrongPathRepo: return $this->WrongPathRepo(); break; + case Err::UnknownRepo: return $this->UnknownRepo(); break; + case Err::RepoError: return $this->RepoError(); break; + case Err::UnknownTable: return $this->UnknownTable(); break; + case Err::NotAllowedSchema: return $this->NotAllowedSchema(); break; + case Err::NoMatchFound: return $this->NoMatchFound(); break; + case Err::UnknownTemplate: return $this->UnknownTemplate(); break; + case Err::UnknownAddress: return $this->UnknownAddress(); break; + case Err::UnknownError: return $this->UnknownError(); break; + case Err::AlreadyExists: return $this->AlreadyExists(); break; + + default: return $this->UnknownDebugError(); break; + } + } + + + private function Success(){ + return 'all right'; + }private function ParsingFailed(){ + if( count($this->arguments) > 0 ) + return $this->arguments[0].' parsing failed'; + else + return 'parsing failed'; + }private function UnreachableResource(){ + return 'unreachable resource'; + }private function UploadError(){ + return 'upload error'; + }private function FormatError(){ + return 'format error'; + }private function TokenError(){ + return 'bad or expired token'; + }private function PermissionError(){ + if( count($this->arguments) > 0 ) + return "missing permission: '".$this->arguments[0]."'"; + else + return 'permission error'; + }private function DisabledModule(){ + return 'disabled module'; + }private function MissingPath(){ + return 'missing path'; + }private function WrongPathModule(){ + return 'wrong module\'s path'; + }private function UnknownModule(){ + if( count($this->arguments) > 0 ) + return 'unknown module \''.$this->arguments[0].'\''; + else + return 'unknown module'; + }private function UnknownMethod(){ + if( count($this->arguments) > 0 ) + return 'unknown method \''.$this->arguments[0].'\''; + else + return 'unknown method'; + }private function UncallableModule(){ + if( count($this->arguments) > 0 ) + return 'uncallable module \''.$this->arguments[0].'\''; + else + return 'uncallable module'; + }private function UncallableMethod(){ + if( count($this->arguments) > 0 ) + return 'uncallable method \''.$this->arguments[0].'\''; + else + return 'uncallable method'; + }private function UnknownHttpMethod(){ + return 'unknown HTTP method'; + }private function ConfigError(){ + return 'configuration error'; + }private function MissingParam(){ + if( count($this->arguments) > 0 ) + return 'missing param \''.$this->arguments[0].'\''; + else + return 'missing param'; + }private function WrongParam(){ + if( count($this->arguments) > 0 ) + if( count($this->arguments) > 1 ) + return 'wrong param \''.$this->arguments[0].'\' expected to be of type \''.$this->arguments[1].'\''; + else + return 'wrong param \''.$this->arguments[0].'\''; + else + return 'wrong param'; + }private function ModuleError(){ + return 'module error'; + }private function PDOConnection(){ + return 'database error'; + }private function WrongPathRepo(){ + return 'wrong repository\'s path'; + }private function UnknownRepo(){ + return 'unknown repository'; + }private function RepoError(){ + return 'repository error'; + }private function UnknownTable(){ + return 'unknown table'; + }private function NotAllowedSchema(){ + return 'schema browsing not allowed'; + }private function NoMatchFound(){ + return 'no match found'; + }private function UnknownTemplate(){ + return 'unknown template'; + }private function UnknownAddress(){ + return 'unknown'; + }private function UnknownError(){ + return 'unknown error'; + }private function AlreadyExists(){ + return 'item already exists'; + }private function UnknownDebugError(){ + return 'unknown debug error'; + } + + + public function setHttpCode(){ + http_response_code( $this->error == Err::Success ? 200 : 417 ); + } + + } + + +?> From 18959632610b80c9329edc4adbc327c1fe7f4402 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Sat, 17 Feb 2018 18:27:46 +0100 Subject: [PATCH 2/4] +add default api.core.authsystemdefault --- build/api/core/AuthSystemDefault.php | 31 ++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 build/api/core/AuthSystemDefault.php diff --git a/build/api/core/AuthSystemDefault.php b/build/api/core/AuthSystemDefault.php new file mode 100644 index 0000000..e6b5814 --- /dev/null +++ b/build/api/core/AuthSystemDefault.php @@ -0,0 +1,31 @@ + Liste des permissions attendues + * + * @return error Erreur associée à la permission (Success/PermissionError/TokenError/etc) + * + */ + public static function permission($expected){ + return new Error(Err::Success); + } + } + +?> From 6b77c9f3da2c69cd2e11d7897a23ef37fc8f5a90 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Sat, 17 Feb 2018 18:49:56 +0100 Subject: [PATCH 3/4] +add build.http (required by build.api) +fixed router.core.router (allow dot '.' in url) -removed require autoloader in view.homepage (already loaded from autoloader in parent execution tree) --- build/http/core/HttpRequest.php | 198 ++++++++++++++++++++++++++++++++ build/router/core/Router.php | 2 +- public_html/view/homepage.php | 2 +- 3 files changed, 200 insertions(+), 2 deletions(-) create mode 100644 build/http/core/HttpRequest.php diff --git a/build/http/core/HttpRequest.php b/build/http/core/HttpRequest.php new file mode 100644 index 0000000..de3a294 --- /dev/null +++ b/build/http/core/HttpRequest.php @@ -0,0 +1,198 @@ + auto-filled HTTP Request + * + =========================================================*/ + public function __construct(){ + /* [1] Define URI & Status Code & method + =========================================================*/ + $this->uri = $_SERVER['REQUEST_URI']; + $this->method = $_SERVER['REQUEST_METHOD']; + + + /* [2] Define headers + =========================================================*/ + $this->headers = \getallheaders(); + + + /* [3] Define default datasets (GET, POST) + =========================================================*/ + $this->getdata = $_GET; + $this->postdata = $_POST; + + + /* [4] Define BODY & its type + =========================================================*/ + /* (1) Default: set plain/text body */ + $this->body = \file_get_contents('php://input'); + + /* (2) Fetch content type */ + $this->type = self::getContentType($this->headers['Content-Type']); + + + /* [5] Parse BODY data -> POST + =========================================================*/ + $this->parseBody(); + } + + + + /* GET CONSTANT CT_* FROM `Content-Type` HEADER + * + * @pContentType `Content-Type` header value + * + * @return type Constant value + * + */ + private static function getContentType($pContentType=null){ + /* [1] Checks argv + =========================================================*/ + if( is_null($pContentType) ) + $pContentType = $_SERVER['CONTENT_TYPE']; + + + /* [2] Checks types + =========================================================*/ + /* (1) Form Data Types + ---------------------------------------------------------*/ + /* (1) multipart/form-data */ + if( preg_match('/^multipart\/form\-data; boundary=(.+)$/i', $pContentType) ) + return self::CT_MULTIPART_FORM_DATA; + + /* (2) application/x-www-form-urlencoded */ + if( preg_match('/^application\/x\-www\-form\-urlencoded/i', $pContentType) ) + return self::CT_X_WWW_FORM_URLENCODED; + + + /* (2) Data types + ---------------------------------------------------------*/ + /* (1) Basic JSON content type */ + if( preg_match('/^application\/json/i', $pContentType) ) + return self::CT_JSON; + + /* (2) Basic YAML content type */ + if( preg_match('/^application\/yaml/i', $pContentType) ) + return self::CT_YAML; + + /* (3) Basic TEXT content type */ + if( preg_match('/text\/[a-z]+/', $pContentType) ) + return self::CT_TEXT; + + + /* (3) Default Type + ---------------------------------------------------------*/ + return self::CT_BINARY; + + } + + + + /* PARSES BODY DATA + * + */ + private function parseBody(){ + /* [1] If empty body -> do nothing + =========================================================*/ + if( strlen($this->body) === 0 ) + return true; + + + /* [2] Management for each ContentType + =========================================================*/ + switch($this->type){ + + /* (1) multipart/form-data -> parse for not-POST methods + ---------------------------------------------------------*/ + case self::CT_MULTIPART_FORM_DATA: + /* (1) Fetch the boundary */ + if( !preg_match('/boundary=(.+)$/i', $this->headers['Content-Type'], $match) ) + return false; + + $boundary = $match[1]; + + /* (2) Break body into parts */ + $splitter = "/(?:\n|\r\n|--)*$boundary(?:\n|\r\n|--)?/im"; + $parts = preg_split($splitter, $this->body); + + /* (3) Process parts */ + foreach($parts as $part) + if( preg_match('/^Content\-Disposition: form\-data; name=\"([^"]+)\"(?:\n|\r\n){2}(.+)$/mi', $part, $match) ) + $this->postdata[$match[1]] = $match[2]; + + /* (4) Erases body */ + $this->body = ''; + break; + + + /* (2) application/x-www-form-urlencoded -> parse for not-POST methods + ---------------------------------------------------------*/ + case self::CT_X_WWW_FORM_URLENCODED: + /* Auto parse builtin-php function */ + parse_str($this->body, $this->postdata); + + /* Erases body */ + $this->body = ''; + break; + + + /* (3) application/json -> parse if no error + ---------------------------------------------------------*/ + case self::CT_JSON: + /* (1) Decode body content */ + $decoded = json_decode($this->body, true); + + /* (2) If error -> do nothing */ + if( is_null($decoded) ) + return; + + /* (3) Parse body into body */ + $this->body = $decoded; + break; + + + /* (4) application/yaml -> parse if no error + ---------------------------------------------------------*/ + case self::CT_YAML: + + break; + } + } + + + public function BODY(){ return $this->body; } + public function POST(){ return $this->postdata; } + public function GET(){ return $this->getdata; } + public function HEADERS(){ return $this->headers; } + public function METHOD(){ return $this->method; } + public function URI(){ return $this->uri; } + } diff --git a/build/router/core/Router.php b/build/router/core/Router.php index f2200a7..19d7f1f 100644 --- a/build/router/core/Router.php +++ b/build/router/core/Router.php @@ -239,7 +239,7 @@ /* (2) Replace special characters + replace vars ---------------------------------------------------------*/ /* (1) Check default URL format */ - if( !preg_match('/^(\/[\w\{\}-]*)*\/?$/', $pattern) ) + if( !preg_match('/^(\/[\w\{\}\.-]*)*\/?$/', $pattern) ) return false; /* (2) Escape special characters */ diff --git a/public_html/view/homepage.php b/public_html/view/homepage.php index 919c3e4..826e0da 100644 --- a/public_html/view/homepage.php +++ b/public_html/view/homepage.php @@ -1,3 +1,3 @@ - Date: Sat, 17 Feb 2018 18:51:53 +0100 Subject: [PATCH 4/4] +fix apache => nginx (getallheaders function) does not exist anymore --- build/http/core/HttpRequest.php | 38 ++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/build/http/core/HttpRequest.php b/build/http/core/HttpRequest.php index de3a294..f2d919a 100644 --- a/build/http/core/HttpRequest.php +++ b/build/http/core/HttpRequest.php @@ -42,7 +42,7 @@ /* [2] Define headers =========================================================*/ - $this->headers = \getallheaders(); + $this->headers = self::getallheaders_adapter(); /* [3] Define default datasets (GET, POST) @@ -57,7 +57,10 @@ $this->body = \file_get_contents('php://input'); /* (2) Fetch content type */ - $this->type = self::getContentType($this->headers['Content-Type']); + if( isset($this->headers['Content-Type']) ) + $this->type = self::getContentType($this->headers['Content-Type']); + else + $this->type = self::getContentType(); /* [5] Parse BODY data -> POST @@ -78,7 +81,10 @@ /* [1] Checks argv =========================================================*/ if( is_null($pContentType) ) - $pContentType = $_SERVER['CONTENT_TYPE']; + if( isset($_SERVER['CONTENT_TYPE']) ) + $pContentType = $_SERVER['CONTENT_TYPE']; + else + $pContentType = 'text/plain'; /* [2] Checks types @@ -195,4 +201,30 @@ public function HEADERS(){ return $this->headers; } public function METHOD(){ return $this->method; } public function URI(){ return $this->uri; } + + + private static function getallheaders_adapter(){ + /* (1) If exists -> use it + ---------------------------------------------------------*/ + if( function_exists('getallheaders') ) + return getallheaders(); + + /* (2) If does not (php-fpm) + ---------------------------------------------------------*/ + /* (1) init. variables */ + $fetched_headers = []; + + /* (2) Get all headers from $_SERVER */ + foreach($_SERVER as $hname=>$hvalue ){ + + // {1} Store only if begins with 'HTTP_' // + if( substr($hname,0,5) == 'HTTP_' ) + $fetched_headers[ str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($hname,5)))))] = $hvalue; + + } + + /* (3) Return created headers */ + return $fetched_headers; + + } }