parent
69c7aca00f
commit
2b26db7d30
|
@ -0,0 +1,2 @@
|
|||
RewriteEngine on
|
||||
RewriteRule ^(.*)$ public_html/$1 [QSA,L]
|
|
@ -0,0 +1,2 @@
|
|||
Order deny,allow
|
||||
Deny from all
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
/**************************
|
||||
* Builder *
|
||||
* 05-11-16 *
|
||||
***************************
|
||||
* Designed & Developed by *
|
||||
* xdrm-brackets *
|
||||
***************************
|
||||
* https://xdrm.io/ *
|
||||
**************************/
|
||||
|
||||
|
||||
|
||||
class Builder{
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
<?php
|
||||
|
||||
namespace api\core;
|
||||
|
||||
|
||||
class Checker{
|
||||
|
||||
|
||||
/* VERIFICATIONS DES TYPES UTILES GENERIQUES
|
||||
*
|
||||
* @type<String> Type que l'on veut verifier
|
||||
* @value<mixed*> Valeur a verifier
|
||||
*
|
||||
* @return match<Boolean> 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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,530 @@
|
|||
<?php
|
||||
|
||||
namespace api\core;
|
||||
use \database\core\DatabaseDriver;
|
||||
use \manager\ManagerError;
|
||||
use \api\core\Checker;
|
||||
|
||||
|
||||
class ModuleRequest{
|
||||
|
||||
// Constantes
|
||||
public static function config_path(){ return __CONFIG__.'/modules.json'; }
|
||||
public static $default_options = [
|
||||
'download' => 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<String> Chemin de delegation ("module/methode")
|
||||
* @param<Array> Tableau associatif contenant les parametres utiles au traitement
|
||||
* @token<String> Token d'acces a l'api (OPTIONNEL)
|
||||
*
|
||||
* @return status<Boolean> 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<ModuleResponse> Retourne une reponse de type <ModuleResponse> 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, '<?php'.PHP_EOL);
|
||||
|
||||
/* (2) Script qui écrira les headers */
|
||||
foreach($returned['headers'] as $header=>$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<String> Contenu de l'url après api/ (si existe)
|
||||
* @post<Array> Tableau des donnes $_POST => @path + @data (opt)
|
||||
*
|
||||
* @return instance<ModuleRequest> Retourne un objet de type <ModuleRequest>
|
||||
*
|
||||
*/
|
||||
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 <ModuleRequest>
|
||||
=========================================================*/
|
||||
// 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> String correspondant au chemin de delegation ("module/methode")
|
||||
*
|
||||
* @return validity<Boolean> 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<String> Token d'acces a l'API (OPTIONNEL)
|
||||
*
|
||||
* @return permission<bool> 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<Array> 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<bool> 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<Array> Retourne le chemin d'amorcage de la requete
|
||||
*
|
||||
*/
|
||||
private function getFunctionCaller(){
|
||||
return [ '\\api\\module\\'.$this->path['module'], $this->path['method'] ];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,163 @@
|
|||
<?php
|
||||
|
||||
namespace api\core;
|
||||
use \manager\ManagerError;
|
||||
|
||||
|
||||
// FORMAT:
|
||||
//
|
||||
// path: "nomModule/nomMethode"
|
||||
// data1: {donnee1}
|
||||
// data2: {donnee2}
|
||||
// ...
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
class ModuleResponse{
|
||||
|
||||
// Attributs prives utiles (initialisation)
|
||||
private $data;
|
||||
public $error;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* CONSTRUCTEUR D'UNE REPONSE DE MODULE
|
||||
*
|
||||
* @error<ModuleError> 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<String> Le nom de la valeur a ajouter
|
||||
* @value<mixed*> 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<Array> 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<String> Le nom de la valeur a recuperer
|
||||
*
|
||||
* @return value<mixed*> La valeur a cette cle
|
||||
* @return error<null> 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<Array> Les donnees de la reponse
|
||||
*
|
||||
*/
|
||||
public function getAll(){
|
||||
// Sinon, on retourne la valeur associee
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* SERIALISATION A PARTIR DES DONNEES
|
||||
*
|
||||
* @return json<String> 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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,2 @@
|
|||
Order deny,allow
|
||||
Deny from all
|
|
@ -0,0 +1,127 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace manager;
|
||||
|
||||
|
||||
class ManagerError{
|
||||
|
||||
/* SUCCESS */
|
||||
const Success = 0;
|
||||
|
||||
/* Parsage json */
|
||||
const ParsingFailed = 1;
|
||||
|
||||
/* ResourceDispatcher */
|
||||
|
||||
// Drapeaux invalides
|
||||
const InvalidFlags = 2;
|
||||
|
||||
// Fichier inexistant
|
||||
const UnreachableResource = 3;
|
||||
|
||||
|
||||
/* ModuleRequest */
|
||||
|
||||
// Le @path n'est pas renseigne
|
||||
const MissingPath = 4;
|
||||
|
||||
// Verification de la coherence du chemin (existe dans la conf)
|
||||
const WrongPathModule = 5;
|
||||
|
||||
// Module non specifie dans la conf
|
||||
const UnknownModule = 6;
|
||||
|
||||
// Methode non specifie pour ce Module dans la conf
|
||||
const UnknownMethod = 7;
|
||||
|
||||
// Methode inamorcable
|
||||
const UncallableMethod = 8;
|
||||
|
||||
// Erreur de parametre(s)
|
||||
const ParamError = 9;
|
||||
|
||||
// Erreur dans le traitement
|
||||
const ModuleError = 10;
|
||||
|
||||
/* Repo */
|
||||
|
||||
// Verification de la coherence du chemin (existe dans la conf)
|
||||
const WrongPathRepo = 11;
|
||||
|
||||
// Module non specifie dans la conf
|
||||
const UnknownRepo = 12;
|
||||
|
||||
// Erreur dans le traitement
|
||||
const RepoError = 13;
|
||||
|
||||
/* Database */
|
||||
|
||||
// Erreur lors de la creation d'un objet PDO (connection)
|
||||
const PDOConnection = 14;
|
||||
|
||||
/* API token */
|
||||
// Token inexistant ou faux
|
||||
const TokenError = 15;
|
||||
|
||||
const PermissionError = 16;
|
||||
|
||||
/* Erreur d'UPLOAD */
|
||||
const UploadError = 17;
|
||||
|
||||
// Mauvais format de fichier
|
||||
const FormatError = 18;
|
||||
|
||||
/* Erreur au niveau javascript */
|
||||
//const JavascriptError = 19; // -> géré en js
|
||||
|
||||
|
||||
/* EXPLICITE UN CODE D'ERREUR
|
||||
*
|
||||
* @error<Integer> Code d'erreur
|
||||
*
|
||||
* @return explicit<String> 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 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
/**************************************/
|
||||
/* Classe de gestion de route (match) */
|
||||
/**************************************/
|
||||
|
||||
namespace router\core;
|
||||
|
||||
class Route{
|
||||
|
||||
// ATTRIBUTS
|
||||
private $pattern;
|
||||
private $callback;
|
||||
private $matches = [];
|
||||
|
||||
/* Initialise la route
|
||||
*
|
||||
* @pattern<String> Pattern correspondant a la route
|
||||
* @callback<Function> Fonction de callback de la route
|
||||
*
|
||||
* @return this<Route> 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<String> URL pour laquelle on veut verifier
|
||||
*
|
||||
* @return match<Boolean> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
/*************************************************/
|
||||
/* Classe de gestion des routes (URL/ressources) */
|
||||
/*************************************************/
|
||||
|
||||
namespace router\core;
|
||||
|
||||
class Router{
|
||||
// ATTRIBUTS
|
||||
private $url;
|
||||
private $routes;
|
||||
|
||||
/* Initialise le routeur
|
||||
*
|
||||
* @url<String> l'URL de la page courante
|
||||
*
|
||||
* @return this<Router> 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<String> le format de l'URL associe
|
||||
* @callback<Function> function a appeler si l'URL correspond
|
||||
*
|
||||
* @return this<Router> 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<String> le format de l'URL associe
|
||||
* @callback<Function> function a appeler si l'URL correspond
|
||||
*
|
||||
* @return this<Router> 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;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,2 @@
|
|||
Order deny,allow
|
||||
Deny from all
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
|
||||
"local" : {
|
||||
"host" : "http://prod-releaser/",
|
||||
"root" : "/"
|
||||
},
|
||||
|
||||
"remote" : {
|
||||
"host" : "https://prod-releaser.xdrm.io/",
|
||||
"root" : "/"
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
RewriteEngine on
|
||||
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
|
|
@ -0,0 +1,49 @@
|
|||
<?php define('__ROOT__', dirname(dirname(__FILE__)) );
|
||||
|
||||
require_once __ROOT__.'/autoloader.php';
|
||||
|
||||
use \router\core\Router;
|
||||
use \api\core\ModuleRequest;
|
||||
use \api\core\ModuleResponse;
|
||||
use \manager\ManagerError;
|
||||
|
||||
// var_dump($_SESSION);
|
||||
|
||||
|
||||
/*******************************************/
|
||||
/* DEBUGGER */
|
||||
/*******************************************/
|
||||
debug();
|
||||
/*******************************************/
|
||||
|
||||
|
||||
/* [3] On initialise le routeur
|
||||
===================================================*/
|
||||
/* (1) New Router */
|
||||
$R = new Router( $_GET['url'] );
|
||||
|
||||
|
||||
/* [2] host.xxx/api/{module}/{method} -> 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();
|
||||
|
||||
?>
|
Loading…
Reference in New Issue