From 2b26db7d30e9b9c9679d655a4db5eba23ed302a3 Mon Sep 17 00:00:00 2001 From: xdrm-brackets Date: Sun, 6 Nov 2016 17:04:17 +0100 Subject: [PATCH] Building project's base Inherited from NxTIC --- .htaccess | 2 + build/.htaccess | 2 + build/Builder.php | 17 + build/api/core/Checker.php | 146 ++++++++ build/api/core/ModuleRequest.php | 530 ++++++++++++++++++++++++++++++ build/api/core/ModuleResponse.php | 163 +++++++++ build/manager/.htaccess | 2 + build/manager/ManagerError.php | 127 +++++++ build/router/core/Route.php | 63 ++++ build/router/core/Router.php | 91 +++++ config/.htaccess | 2 + config/modules.json | 3 + config/server.json | 13 + public_html/.htaccess | 4 + public_html/index.php | 49 +++ 15 files changed, 1214 insertions(+) create mode 100644 .htaccess create mode 100644 build/.htaccess create mode 100644 build/Builder.php create mode 100644 build/api/core/Checker.php create mode 100644 build/api/core/ModuleRequest.php create mode 100644 build/api/core/ModuleResponse.php create mode 100644 build/manager/.htaccess create mode 100644 build/manager/ManagerError.php create mode 100644 build/router/core/Route.php create mode 100644 build/router/core/Router.php create mode 100644 config/.htaccess create mode 100755 config/modules.json create mode 100644 config/server.json create mode 100644 public_html/.htaccess create mode 100644 public_html/index.php diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..31586d9 --- /dev/null +++ b/.htaccess @@ -0,0 +1,2 @@ +RewriteEngine on +RewriteRule ^(.*)$ public_html/$1 [QSA,L] diff --git a/build/.htaccess b/build/.htaccess new file mode 100644 index 0000000..93169e4 --- /dev/null +++ b/build/.htaccess @@ -0,0 +1,2 @@ +Order deny,allow +Deny from all diff --git a/build/Builder.php b/build/Builder.php new file mode 100644 index 0000000..e084f24 --- /dev/null +++ b/build/Builder.php @@ -0,0 +1,17 @@ + Type que l'on veut verifier + * @value Valeur a verifier + * + * @return match Retourne si oui ou non la valeur @value est du bon type @type + * + */ + public static function run($type, $value){ + $checker = true; + + /* [0] On verifie que $value n'est pas nul + =========================================================*/ + if( is_null($value) ) return false; + + + + /* [1] Si de type VARCHAR(min, max, flags) + =========================================================*/ + if( preg_match('/^varchar\((\d+), ?(\d+)((?:, ?\w+)+)?\)$/', $type, $match) ){ + // On recupere la taille min + $min = (int) $match[1]; + // On recupere la taille max + $max = (int) $match[2]; + + // On recupere le sous-type si défini + $flags = isset($match[3]) ? explode(',', substr($match[3], 1)) : null; + + // On effectue la verification de taille + $lenCheck = $checker && is_string($value) && strlen($value) <= $max && strlen($value) >= $min; + + // On vérifie les FLAGS s'il est donné + if( is_array($flags) ) + foreach( $flags as $flag ) + $lenCheck = $lenCheck && self::run($flag, $value); + + return $lenCheck; + } + + + /* [2] Si de type ARRAY(type_elements) + =========================================================*/ + if( preg_match('/^array<(.+)>$/', $type, $match) ){ + + // Si c'est pas un tableau on retourne une erreur + if( !is_array($value) ) + return false; + + + $elements_type = $match[1]; + + // On verifie le type pour chaque element + foreach($value as $element) + // Si erreur dans au moins 1 element, on retourne que c'est incorrect + if( !self::run($elements_type, ($element) ) ) + return false; + + // Si aucune erreur, on retourne que tout est bon + return true; + } + + + /* [n] Sinon, tous les autres types definis + =========================================================*/ + switch($type){ + // Quoi que ce soit + case 'mixed': + return $checker && !is_null($value); + break; + + // Entier positif (id dans BDD) + case 'id': + return $checker && is_numeric($value) && $value <= 2147483647 && $value >= 0; + break; + + // Code RFID + case 'rfid': + return $checker && is_string($value) && preg_match('/^[\dA-F]{2}(\-[\dA-F]{2}){3,5}$/i', $value); + break; + + // String quelconque (peut etre vide) + case 'text': + return $checker && is_string($value); + + // Adresse mail (255 caracteres max) + case 'mail': + return $checker && is_string($value) && strlen($value) <= 50 && preg_match('/^[\w\.-]+@[\w\.-]+\.[a-z]{2,4}$/i', $value); + break; + + // Hash sha1/md5 + case 'hash': + return $checker && is_string($value) && preg_match('/^[\da-f]+$/i', $value) && (strlen($value) == 40 || strlen($value) == 64); + break; + + case 'alphanumeric': + return $checker && is_string($value) && preg_match('/^[\w\.-]+$/ui', $value); + break; + + case 'letters': + return $checker && is_string($value) && preg_match('/^[a-z -]+$/i', $value); + break; + + case 'status': + return $checker && is_numeric($value) && floor($value) == $value && $value >= 0 && $value <= 100; + break; + + // Tableau non vide + case 'array': + return $checker && is_array($value) && count($value) > 0; + break; + + // Boolean + case 'boolean': + return $checker && is_bool($value); + break; + + // Objet non vide + case 'object': + return $checker && is_object($value) && count((array) $value) > 0; + break; + + // Chaine JSON (on vérifie via le parser) + case 'json': + return $checker && is_string($value) && json_decode($value, true) !== NULL; + break; + + default: + return false; + break; + } + + return $checker; + + } + + + } +?> diff --git a/build/api/core/ModuleRequest.php b/build/api/core/ModuleRequest.php new file mode 100644 index 0000000..2d79f0b --- /dev/null +++ b/build/api/core/ModuleRequest.php @@ -0,0 +1,530 @@ + false + ]; + + // Attributs prives utiles (initialisation) + private $path; + private $params; + private $modules; + private $options; + + // Contiendra la reponse a la requete + public $answer; + + // Contiendra l'etat de la requete + public $error; + + + + + + /* CONSTRUCTEUR D'UNE REQUETE DE MODULE + * + * @path Chemin de delegation ("module/methode") + * @param Tableau associatif contenant les parametres utiles au traitement + * @token Token d'acces a l'api (OPTIONNEL) + * + * @return status Retourne si oui ou non tout s'est bien passe + * + */ + public function __construct($path=null, $params=null, $token=null){ + // Si pas parametre manquant, on quitte + if( $path == null ){ + $this->error = ManagerError::MissingPath; + return false; + } + + /* [0] On met a jour la configuration + =========================================================*/ + // Modules specifies + $this->modules = json_decode( file_get_contents(self::config_path()), true ); + + // Gestion de l'erreur de parsage + if( $this->modules == null ){ + $this->error = ManagerError::ParsingFailed; + return false; + } + + + + /* [1] Verification des types des parametres + =========================================================*/ + // Type de @path + if( !is_string($path) ){ // Si le type est incorrect + $this->error = ManagerError::WrongPathModule; + return false; // On retourne FALSE, si erreur + } + + // Type de @data (optionnel) + $params = (is_array($params)) ? $params : []; + + + /* [2] Verification du chemin (existence module+methode) + =========================================================*/ + if( !$this->checkPath($path) ) // Verification de la coherence du chemin + attribution + return false; + + + + /* [3] Verification des droits + =========================================================*/ + if( !$this->checkPermission($token) ) // Si on a pas les droits + return false; + + + /* [4] Verification des parametres (si @type est defini) + =========================================================*/ + if( !$this->checkParams($params) ){ // Verification de tous les types + $this->error = ManagerError::ParamError; + return false; + } + + /* [5] Récupèration des options + =========================================================*/ + $this->buildOptions(); + + + /* [6] Construction de l'objet + =========================================================*/ + $this->params = $params; + $this->error = ManagerError::Success; + + return true; // On retourne que tout s'est bien passe + + } + + + /* EXECUTE LE TRAITEMENT ASSOCIE ET REMPLIE LA REPONSE + * + * @return answer Retourne une reponse de type si tout s'est bien passe + * + */ + public function dispatch(){ + /* [0] Si c'est un download, on lance la methode `download()` + =========================================================*/ + if( $this->options['download'] === true ) + return $this->download(); + + /* [1] On verifie qu'aucune erreur n'a ete signalee + =========================================================*/ + if( $this->error != ManagerError::Success ) // si il y a une erreur + return new ModuleResponse($this->error); // on la passe a la reponse + + + /* [2] On verifie que la methode est amorcable + =========================================================*/ + if( !is_callable($this->getFunctionCaller()) ){ + $this->error = ManagerError::UncallableMethod; + return new ModuleResponse($this->error); + } + + + /* [3] On amorce la methode + =========================================================*/ + $returned = call_user_func( $this->getFunctionCaller(), $this->params ); + + + /* [4] Gestion de la reponse + =========================================================*/ + $response = new ModuleResponse($this->error); + $response->appendAll($returned); + + return $response; + } + + + /* EXECUTE LE TRAITEMENT ASSOCIE ET RENVOIE UN FICHIER AVEC LE HEADER ET LE BODY SPECIFIE + * + */ + public function download(){ + /* [1] On verifie qu'aucune erreur n'a ete signalee + =========================================================*/ + if( $this->error != ManagerError::Success ) // si il y a une erreur + return new ModuleResponse($this->error); // on la passe a la reponse + + + /* [2] On verifie que la methode est amorcable + =========================================================*/ + if( !is_callable($this->getFunctionCaller()) ){ + $this->error = ManagerError::UncallableMethod; + return new ModuleResponse($this->error); + } + + + /* [3] On amorce la methode + =========================================================*/ + $returned = call_user_func( $this->getFunctionCaller(), $this->params ); + + + /* [4] Vérification des erreurs et paramètres + =========================================================*/ + /* (1) Vérification de l'erreur retournée, si pas Success, on retourne l'erreur */ + if( isset($returned['ModuleError']) && $returned['ModuleError'] != ManagerError::Success ){ + $this->error = $returned['ModuleError']; + return new ModuleResponse($this->error); + } + + /* (2) Vérification du contenu, si pas défini */ + if( !isset($returned['body']) ){ + $this->error = ManagerError::ParamError; + return new ModuleResponse($this->error); + } + + /* (3) Si @headers n'est pas défini on met par défaut */ + if( !isset($returned['headers']) || !is_array($returned['headers']) ) + $returned['headers'] = []; + + + $fromAjax = isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'; + + /* [5] Si la requête vient d'ajax on crée un fichier temporaire et on renvoie son URL + =========================================================*/ + if( $fromAjax ){ + + + $tmpfname = '/tmp/download_'.uniqid().'.php'; + $bodyfname = __BUILD__.'/tmp/content_'.uniqid().'.php'; + + /* (1) On crée le fichier temporaire */ + $tmpfnameroot = __BUILD__.$tmpfname; + $tmpfile = fopen($tmpfnameroot, 'w'); + + fwrite($tmpfile, '$value) + fwrite($tmpfile, "header(\"$header: $value\");".PHP_EOL); + + /* (3) Script qui écrira le contenu */ + // 1) On écrit le contenu dans un fichier temporaire (et oui encore) + $bodyfile = fopen($bodyfname, 'w'); + fwrite($bodyfile, $returned['body']); + fclose($bodyfile); + chmod($bodyfname, 0775); + + fwrite($tmpfile, "readfile('$bodyfname');".PHP_EOL); + + /* (4) Script qui supprimera les fichiers temporaires */ + fwrite($tmpfile, "unlink('$bodyfname');".PHP_EOL); + fwrite($tmpfile, "unlink(__FILE__);".PHP_EOL); + + fwrite($tmpfile, '?>'.PHP_EOL); + + /* (5) On ferme le fichier */ + fclose($tmpfile); + chmod($tmpfnameroot, 0775); + + $response = new ModuleResponse(ManagerError::Success); + $response->append('link', $tmpfname); + + return $response; + + /* [6] Gestion du download direct si pas AJAX + =========================================================*/ + }else{ + /* (1) On définit les headers */ + foreach($returned['headers'] as $header=>$value) + header($header.': '.$value); + + /* (2) On affiche le contenu */ + echo $returned['body']; + + return true; + } + } + + + /* DESERIALISATION A PARTIR DES DONNEES POST + * + * @url Contenu de l'url après api/ (si existe) + * @post Tableau des donnes $_POST => @path + @data (opt) + * + * @return instance Retourne un objet de type + * + */ + public static function fromPost($url, $post){ + + /* [0] Verification de l'authentification + =========================================================*/ + // On definit le token + $token = isset($_SERVER['PHP_AUTH_DIGEST']) ? $_SERVER['PHP_AUTH_DIGEST'] : null; + + + /* [1] On verifie que le @path est renseigne + =========================================================*/ + /* (1) Si le path est dans @url */ + $pathInUrl = is_string($url[0]) && strlen($url[0]) > 0 && preg_match('#^([\w_-]+)/([\w_-]+)/?$#', $url[0], $urlMatches); + + // On l'utilise pour le chemin + if( $pathInUrl ) + $post['path'] = $urlMatches[1].'/'.$urlMatches[2]; + + /* (2) On vérifie dans tous les cas si le path existe */ + if( !isset($post['path']) ) + return new ModuleRequest(); + + + /* [2] On verifie que @data est renseigne + =========================================================*/ + // Si variable n'existe pas, on cree un tableau vide + $params = $post; + + // On retire le @path de @params + unset($params['path']); + + + + /* [3] On met les paramètres JSON en JSON (si ils décodent sans erreur) + =========================================================*/ + foreach($params as $name=>$value){ + $json = json_decode( $value, true ); + // Si aucune erreur, on affecte la valeur + if( !is_null($json) ) + $params[$name] = $json; + } + /* [4] On retourne une instance de + =========================================================*/ + // On cree notre requete avec le token + return new ModuleRequest($post['path'], $params, $token); + } + + + /* VERIFICATION DU FORMAT ET DE LA COHERENCE DU CHEMIN SPECIFIE + * + * @path String correspondant au chemin de delegation ("module/methode") + * + * @return validity Retourne si oui ou non l'objet est correct + * + */ + private function checkPath($path){ + /* [1] Verification format general + =========================================================*/ + if( !preg_match('#^([\w_-]+)/([\w_-]+)$#i', $path, $matches) ){ // Si mauvais format + $this->error = ManagerError::WrongPathModule; + return false; + } + + // On recupere les donnes de la regex + $module = $matches[1]; + $method = $matches[2]; + + + /* [2] Verification de l'existence du module (conf) + =========================================================*/ + if( !array_key_exists($module, $this->modules) ){ // Si le module n'est pas specifie dans la conf + $this->error = ManagerError::UnknownModule; + return false; // On retourne FALSE, si erreur + } + + /* [3] Verification de l'existence de la methode (conf) + =========================================================*/ + if( array_key_exists($method, $this->modules[$module]) === false ){ // Si la methode n'est pas specifie dans la conf + $this->error = ManagerError::UnknownMethod; + return false; // On retourne FALSE, si erreur + } + + + + /* [4] Enregistrement du chemin et renvoi de SUCCESS + =========================================================*/ + $this->path = [ + 'module' => $module, + 'method' => $method + ]; + + return true; + } + + + /* RETOURNE SI ON A LA PERMISSION D'EXECUTER CETTE METHODE + * + * @token Token d'acces a l'API (OPTIONNEL) + * + * @return permission Retourne si on a les droits ou pas pour executer cette methode + * + */ + private function checkPermission($token=null){ + /* [1] On recupere les informations utiles + =========================================================*/ + // On recupere le nom de la methode + $method = $this->modules[$this->path['module']][$this->path['method']]; + + // Si aucune permission n'est definie + if( !isset($method['permissions']) ) return true; + + /* [2] Gestion si un @token est defini + =========================================================*/ + if( Checker::run('hash', $token) ){ + + + /* (1) On verifie que le token est valide */ + $checkToken = new Repo('token/check', [$token] ); + $token_permissions = $checkToken->answer(); + + // Si le token est invalide, on retourne une erreur -> FAUX + if( $token_permissions === false ){ + $this->error = ManagerError::TokenError; + return false; + } + + $local_permissions = $token_permissions; + + + /* [3] Gestion si aucun token, avec utilisateur connecté + =========================================================*/ + }else if( isset($_SESSION['permission']) ) + $local_permissions = $_SESSION['permission']; + + // Si ni token, ni SESSION, erreur + else{ + $this->error = ManagerError::PermissionError; + return false; + } + + /* [4] Verification des droits parmi les permissions donnees + =========================================================*/ + /* (1) On recupere la liste des permissions possibles */ + $permissions = $method['permissions']; + + /* (2) Si aucune permission n'est definie, on laisse l'acces */ + if( !$permissions == 0 ) return true; + + /* (3) On verifie qu'il y a aucune permission manquante */ + foreach($permissions as $permission) + if( !in_array($permission, $local_permissions) ){ + $this->error = ManagerError::PermissionError; + return false; + } + + + /* [5] On retourne FAUX si aucun droit n'a ete trouve + =========================================================*/ + return true; + } + + + /* VERIFICATION DU TYPE DES PARAMETRES ENVOYES + * + * @params Tableau associatif contenant les parametres + * @params peut se voir rajouter les paramètres optionnels s'ils ne sont pas renseignés (initialisés à NULL) + * + * @return correct Retourne si oui ou non les parametres ont le bon type + * + */ + private function checkParams(&$params){ + /* [1] On verifie qu'il ne manque aucun parametre + =========================================================*/ + // Si @params n'est pas un tableau + if( !is_array($params) ) return false; + + $method = $this->modules[$this->path['module']][$this->path['method']]; + + + /* [2] Si le type est defini, pour chaque param, on teste + =========================================================*/ + foreach($method['parameters'] as $name=>$paramsdata){ + /* (1) On récupère si le paramètre est optionnel ou pas */ + $optional = isset($paramsdata['optional']) && $paramsdata['optional'] === true; + + /* (2) Récupère si le paramètre est un fichier et définit comme de type 'FILE' */ + $isFile = isset($paramsdata['type']) && $paramsdata['type'] == 'FILE' && isset($_FILES[$name]); + + /* (3) Si le paramètre est obligatoire et qu'il n'est pas donné -> erreur */ + if( !isset($params[$name]) && !$optional && !$isFile ) + return false; + + /* (4) Si le type n'est pas defini, on a pas besoin de le vérifier */ + if( !isset($paramsdata['type']) ) + continue; + + /* (5) Si le paramètre est optionnel et n'est pas donné */ + if( $isFile || $optional && (!isset($params[$name]) || is_null($params[$name])) ){ + // On le crée le param optionnel avec la valeur NULL + $params[$name] = null; + + // On donne une référence vers le fichier, si c'en est un + if( $isFile ) + $params[$name] = &$_FILES[$name]; + + continue; // On passe au paramètre suivant + + + /* (6) Si le paramètre est renseigné */ + }else + // Si la verification est fausse, on retourne faux + if( !Checker::run($paramsdata['type'], $params[$name]) ) + return false; + + } + + /* [3] Gestion du retour, si tout s'est bien passe + =========================================================*/ + return true; + } + + + /* AJOUT DES OPTIONS A PARTIR DE LA CONFIGURATION + * + */ + private function buildOptions(){ + /* [0] On récupère les options de la méthode en cours + =========================================================*/ + $method = $this->modules[$this->path['module']][$this->path['method']]; + + /* (1) Si 'option' n'est pas défini (ou incorrect), on met les valeurs par défaut */ + if( !isset($method['options']) || !is_array($method['options']) ) + return true; + + /* (2) Par défaut on définit les options par défaut */ + $this->options = self::$default_options; + + + /* (3) On récupère les options données */ + $options = $method['options']; + + + /* [1] Gestion des différentes options + =========================================================*/ + foreach($options as $option=>$value){ + /* (1) On ne prend en compte l'option que si elle est dans les options par défaut */ + if( !isset(self::$default_options[$option]) ) + continue; + + /* (2) Le type de la valeur doit être le même que celui de la valeur par défaut */ + if( gettype($value) != gettype(self::$default_options[$option]) ) + continue; + + /* (3) Si tout est bon, on définit la valeur */ + $this->options[$option] = $value; + } + + return true; + + } + + + /* RENVOI LE CHEMIN D'AMORCAGE DE LA METHODE + * + * @return path Retourne le chemin d'amorcage de la requete + * + */ + private function getFunctionCaller(){ + return [ '\\api\\module\\'.$this->path['module'], $this->path['method'] ]; + } + + + } + +?> diff --git a/build/api/core/ModuleResponse.php b/build/api/core/ModuleResponse.php new file mode 100644 index 0000000..17c570e --- /dev/null +++ b/build/api/core/ModuleResponse.php @@ -0,0 +1,163 @@ + Erreur passee par la requete (si existe) + * + */ + public function __construct($error=ManagerError::Success){ + $this->data = []; + $this->error = $error; + } + + + + + + + + /* AJOUTE UNE DONNEE A LA REPONSE + * + * @key Le nom de la valeur a ajouter + * @value La valeur a ajouter + * + */ + public function append($key, $value){ + // Ajoute une entree pour la cle @key et de valeur @value + $this->data[$key] = $value; + + return $this; + } + + + + + + + + + /* AJOUTE TOUTES LES DONNEES A LA REPONSE + * + * @dataset Le tableau associatif correspondant a la reponse + * + */ + public function appendAll($dataset){ + // Si ce n'est pas un tableau, on ne fais rien + if( !is_array($dataset) ) return $this; + + // Si une valeur contient une erreur + if( array_key_exists('ModuleError', $dataset) ){ + // On definit cette erreur + $this->error = $dataset['ModuleError']; + // On enleve cette entree des donnees + unset($dataset['ModuleError']); + } + + // Ajoute une entree pour la cle @key et de valeur @value + $this->data = $dataset; + + return $this; + } + + + + + + + + /* RECUPERE UNE DONNEE DE LA REPONSE + * + * @key Le nom de la valeur a recuperer + * + * @return value La valeur a cette cle + * @return error Retourne NULL si aucune valeur pour cette cle + * + */ + public function get($key){ + // Si la valeur de cle @key n'existe pas, on retourne NULL + if( !isset($this->data[$key]) ) + return null; + + // Sinon, on retourne la valeur associee + return $this->data[$key]; + } + + + + + + + + + /* RECUPERE TOUTES LES DONNEES DE LA REPONSE + * + * @return data Les donnees de la reponse + * + */ + public function getAll(){ + // Sinon, on retourne la valeur associee + return $this->data; + } + + + + + + + /* SERIALISATION A PARTIR DES DONNEES + * + * @return json Retourne les donnees serialisees + * + */ + public function serialize(){ + + // Code Http + ManagerError::setHttpCode($this->error); + + // Type de contenu + header('Content-Type: application/json; charset=utf-8'); + + // On rajoute l'erreur au message + $returnData = array_merge( + [ + 'ModuleError' => $this->error, + 'ErrorDescription' => ManagerError::explicit($this->error) + ], + $this->data + ); + + return json_encode($returnData); + + } + + + + } + +?> diff --git a/build/manager/.htaccess b/build/manager/.htaccess new file mode 100644 index 0000000..896fbc5 --- /dev/null +++ b/build/manager/.htaccess @@ -0,0 +1,2 @@ +Order deny,allow +Deny from all \ No newline at end of file diff --git a/build/manager/ManagerError.php b/build/manager/ManagerError.php new file mode 100644 index 0000000..d6a5994 --- /dev/null +++ b/build/manager/ManagerError.php @@ -0,0 +1,127 @@ + géré en js + + + /* EXPLICITE UN CODE D'ERREUR + * + * @error Code d'erreur + * + * @return explicit Description explicite du code d'erreur + * + */ + public static function explicit($error){ + switch($error){ + case self::Success: return "Tout s'est bien deroulé."; break; + + case self::ParsingFailed: return "La lecture du fichier JSON ou XML a echouée."; break; + + case self::InvalidFlags: return "Les spécifications (drapeaux) sont incorrects."; break; + case self::UnreachableResource: return "La ressource n'existe pas (404)."; break; + case self::MissingPath: return "Le chemin de délégation n'a pas été renseigné."; break; + case self::WrongPathModule: return "Le chemin de délégation est incorrect ('nomModule/nomMethode')."; break; + case self::WrongPathRepo: return "Le chemin de délégation est incorrect ('nomRepo/nomMethode')."; break; + case self::UnknownModule: return "Le module n'existe pas."; break; + case self::UnknownRepo: return "Le repo n'existe pas."; break; + case self::UnknownMethod: return "Le methode n'existe pas."; break; + case self::UncallableMethod: return "Le methode n'est pas amorçable."; break; + + case self::ParamError: return "Un ou plusieurs paramètres sont manquants ou incorrects."; break; + case self::ModuleError: return "Erreur lors du traitement du module."; break; + case self::RepoError: return "Erreur lors du traitement du repo."; break; + + case self::PDOConnection: return "La connexion avec la base de données a echouée."; break; + + case self::TokenError: return "Le token de connection est absent, érroné ou expiré."; break; + case self::PermissionError: return "Vous n'avez pas la permission d'effectuer cette action."; break; + case self::UploadError: return "Une erreur d'upload est survenue."; break; + case self::FormatError: return "Le fichier n'est pas au bon format."; break; + + default: return "Description d'erreur inconnue..."; break; + } + + // Erreur inconnue + return null; + } + + + public static function setHttpCode($error){ + http_response_code( $error == self::Success ? 200 : 417 ); + } + + } + +?> diff --git a/build/router/core/Route.php b/build/router/core/Route.php new file mode 100644 index 0000000..6753091 --- /dev/null +++ b/build/router/core/Route.php @@ -0,0 +1,63 @@ + Pattern correspondant a la route + * @callback Fonction de callback de la route + * + * @return this Retour de l'instance courante + * + */ + public function __construct($pattern, $callback){ + // On enregistre la fonction de callback + $this->callback = $callback; + + // On formatte le pattern en regexp + $this->pattern = '#^'.$pattern.'$#'; + + return $this; + } + + /* Verifie si l'URL correspond a la route + * + * @url URL pour laquelle on veut verifier + * + * @return match TRUE si match sinon FAUX + * + */ + public function match($url){ + // Si ne match pas -> FALSE + if( !preg_match($this->pattern, $url, $matches) ) + return false; + + // On supprime le premier match global + array_shift($matches); + + $this->matches = $matches; + + return true; + + } + + /* Amorcage de la fonction de callback + * + */ + public function call(){ + return call_user_func($this->callback, $this->matches); + } + +} + +?> diff --git a/build/router/core/Router.php b/build/router/core/Router.php new file mode 100644 index 0000000..ee62743 --- /dev/null +++ b/build/router/core/Router.php @@ -0,0 +1,91 @@ + l'URL de la page courante + * + * @return this Retour de l'instance courante + * + */ + public function __construct($url){ + $this->url = $url; + + // On initialise les routes + $this->routes = [ + 'GET' => [], + 'POST' => [] + ]; + + return $this; + } + + /* Ajoute une route GET + * + * @pattern le format de l'URL associe + * @callback function a appeler si l'URL correspond + * + * @return this Retour de l'instance courante + * + */ + public function get($pattern, $callback){ + array_push( + $this->routes['GET'], + new Route($pattern, $callback) + ); + + return $this; + } + + + /* Ajoute une route POST + * + * @pattern le format de l'URL associe + * @callback function a appeler si l'URL correspond + * + * @return this Retour de l'instance courante + * + */ + public function post($pattern, $callback){ + array_push( + $this->routes['POST'], + new Route($pattern, $callback) + ); + + return $this; + } + + /* Demarre le routeur + * + * @return this Retour de l'instance courante + * + */ + public function run(){ + $httpMethod = $_SERVER['REQUEST_METHOD']; + + // Si aucune route pour la methode courante -> false + if( count($this->routes[$httpMethod]) <= 0 ) + return false; + + // Pour chaque route + foreach($this->routes[$httpMethod] as $route){ + // Si la route match + if( $route->match($this->url) ) + return $route->call(); // On l'amorce + } + + // Retourne false si erreur + return false; + } +} + +?> diff --git a/config/.htaccess b/config/.htaccess new file mode 100644 index 0000000..896fbc5 --- /dev/null +++ b/config/.htaccess @@ -0,0 +1,2 @@ +Order deny,allow +Deny from all \ No newline at end of file diff --git a/config/modules.json b/config/modules.json new file mode 100755 index 0000000..36a3713 --- /dev/null +++ b/config/modules.json @@ -0,0 +1,3 @@ +{ + +} diff --git a/config/server.json b/config/server.json new file mode 100644 index 0000000..d5c847c --- /dev/null +++ b/config/server.json @@ -0,0 +1,13 @@ +{ + + "local" : { + "host" : "http://prod-releaser/", + "root" : "/" + }, + + "remote" : { + "host" : "https://prod-releaser.xdrm.io/", + "root" : "/" + } + +} diff --git a/public_html/.htaccess b/public_html/.htaccess new file mode 100644 index 0000000..ab2545e --- /dev/null +++ b/public_html/.htaccess @@ -0,0 +1,4 @@ +RewriteEngine on + +RewriteCond %{REQUEST_FILENAME} !-f +RewriteRule ^(.*)$ index.php?url=$1 [QSA,L] diff --git a/public_html/index.php b/public_html/index.php new file mode 100644 index 0000000..43d0d34 --- /dev/null +++ b/public_html/index.php @@ -0,0 +1,49 @@ + api + =========================================================*/ + $R->post('api(?:/(.*))?', function($url){ + $request = ModuleRequest::fromPost($url, $_POST); + $answer = $request->dispatch(); + + // Si c'est une réponse + if( $answer instanceof ModuleResponse ) + echo $answer->serialize(); + + }); + + + /* [3] Any other URL -> homepage + =========================================================*/ + $R->get('.+', function(){ header(__REDIRECT__); }); + $R->post('.+', function(){ header(__REDIRECT__); }); + + + /* [8] Launch Router + ===================================================*/ + $R->run(); + +?>