diff --git a/inc/auth.php b/inc/auth.php new file mode 100644 index 0000000..00f926e --- /dev/null +++ b/inc/auth.php @@ -0,0 +1,157 @@ +oMySql = $oMySql; + $this->setUserId(0); + $this->sApiKey = $sApiKey; + $this->autoLogIn(); + } + + private function setUserId($iUserId) + { + $this->iUserId = $iUserId; + } + + public function getUserId() + { + return $this->iUserId; + } + + public function isLoggedIn() + { + return ($this->getUserId() > 0); + } + + public function logMeIn($sToken) + { + $sDesc = ''; + if($sToken!='') + { + $sLoginToken = addslashes(strstr($sToken, self::TOKEN_SEP, true)); + $sPassToken = substr(strstr($sToken, self::TOKEN_SEP), strlen(self::TOKEN_SEP)); + if($sLoginToken!='' && $sPassToken!='') + { + $asEmpl = $this->oMySql->selectRow("EMPLOYEE", array('MD5(EMAIL)'=>$sLoginToken)); + if(!empty($asEmpl)) + { + if(self::CheckPassword($sPassToken, $asEmpl['PASS'])) + { + $this->setUserId($asEmpl['ID']); + $this->resetAuthCookie($this->getUserId()); + } + else $sDesc = 'mot de passe incorrect'; + } + else $sDesc = 'email inconnu'; + } + else $sDesc = 'token corrompu'; + } + else $sDesc = 'Aucune information reçue par le serveur'; + + return CvTheque::getJsonResult($this->isLoggedIn(), $sDesc); + } + + public function autoLogIn() + { + if(isset($_COOKIE[self::USER_COOKIE_PASS])) + { + $sCookie = $_COOKIE[self::USER_COOKIE_PASS]; + $iUserId = addslashes(strstr($sCookie, self::TOKEN_SEP, true)); + $sCookie = substr(strstr($sCookie, self::TOKEN_SEP), strlen(self::TOKEN_SEP)); + + $asEmpl = $this->oMySql->selectRow("EMPLOYEE", array('ID'=>$iUserId)); + if(!empty($asEmpl)) + { + if($sCookie==$asEmpl['COOKIE']) + { + $this->setUserId($asEmpl['ID']); + + //Reset pass once a day + if(mb_substr($asEmpl['LED'], 0, 10) != date('Y-m-d')) $this->resetAuthCookie($this->getUserId()); + } + else $this->addError('token corrompu pour le user '.$asEmpl['ID']); + } + else $this->addError('Utilisateur '.$iUserId.' inconnu'); + } + } + + //TODO integrate with logMeIn() + public function checkApiKey($sApiKey) + { + return ($this->sApiKey!='' && $sApiKey==$this->sApiKey); + } + + public function resetPass($iUserId=0) + { + if($iUserId>0) $asUsers = array($iUserId); + else $asUsers = $this->oMySql->selectRows(array('select'=>array('ID'), 'from'=>'EMPLOYEE')); + + foreach($asUsers as $iUserId) + { + $sToken = $this->HashPassword(self::getLoginToken(self::DEFAULT_PASS)); + $this->oMySql->updateRow('EMPLOYEE', array('ID'=>$iUserId), array('pass'=>$sToken)); + } + } + + private static function getLoginToken($sPass) + { + //Add Server Name + $sServerName = array_key_exists('SERVER_NAME', $_SERVER)?$_SERVER['SERVER_NAME']:$_SERVER['PWD']; + $sAppPath = 'http://'.str_replace('http://', '', $sServerName.dirname($_SERVER['SCRIPT_NAME'])); + $_GET['serv_name'] = $sAppPath.(mb_substr($sAppPath, -1)!='/'?'/':''); + + return md5($sPass.$_GET['serv_name']); + } + + private function resetAuthCookie($iUserId) + { + $sNewPass = self::getAuthCookie($iUserId); + $iTimeLimit = time()+60*60*24*30; + //mysqli_query($con, "UPDATE EMPLOYEE SET COOKIE = '".addslashes($sNewPass)."' WHERE ID = ".$iUserId); + $this->oMySql->updateRow("EMPLOYEE", array("ID"=>$iUserId), array("COOKIE"=>$sNewPass)); + setcookie(self::USER_COOKIE_PASS, $iUserId.self::TOKEN_SEP.$sNewPass, $iTimeLimit); + } + + private static function getAuthCookie() + { + return self::HashPassword + ( + $_SERVER['HTTP_USER_AGENT']. + $_SERVER['REMOTE_ADDR']. + $_SERVER['REQUEST_TIME']. + mb_strstr(microtime(), ' ', true). + $_SERVER['SERVER_SIGNATURE']. + $_SERVER['SERVER_ADMIN'] + ); + } + + private static function HashPassword($sPass) + { + return password_hash($sPass, self::ALGO, array('cost'=>self::COST)); + } + + private static function CheckPassword($sPass, $sHash) + { + return password_verify($sPass, $sHash); + } +} + +?> \ No newline at end of file diff --git a/inc/main.php b/inc/main.php index 076b9ef..216decf 100755 --- a/inc/main.php +++ b/inc/main.php @@ -3,7 +3,7 @@ /** * Main Class * @author franzz - * @version 1.0 + * @version 2.0 */ class Main extends PhpObject { @@ -19,6 +19,7 @@ class Main extends PhpObject //Variables private $sLang; private $asMasks; + private $asContext; //... /** @@ -26,10 +27,11 @@ class Main extends PhpObject * @param ClassManagement $oClassManagement * @param string $sLang */ - public function __construct($oClassManagement, $sLang='') + public function __construct($oClassManagement, $sProcessPage, $sLang='') { parent::__construct(__CLASS__, Settings::DEBUG); $this->oClassManagement = $oClassManagement; + $this->setContext($sProcessPage); //Browser <> PHP <> MySql synchronization date_default_timezone_set(Settings::TIMEZONE); @@ -45,6 +47,7 @@ class Main extends PhpObject $this->oClassManagement->incClass('mask'); $this->oClassManagement->incClass('translator'); $this->oClassManagement->incClass('mysqlmanager'); + $this->oClassManagement->incClass('auth'); //... //Init objects @@ -53,12 +56,76 @@ class Main extends PhpObject $this->oTranslator = new Translator($this->getLanguage()); $this->oMySql = new MySqlManager(Settings::DB_SERVER, Settings::DB_LOGIN, Settings::DB_PASS, Settings::DB_NAME, self::getSqlOptions() , Settings::DB_ENC); if($this->oMySql->sDbState == MySqlManager::DB_NO_DATA) $this->install(); + $this->oAuth = new Auth($this->oMySql, Settings::API_KEY); //... } - /** - * DB structure. See MySqlManager::__construct - */ + private function setContext($sProcessPage) + { + $this->asContext['process_page'] = basename($sProcessPage); + + $sServerName = array_key_exists('SERVER_NAME', $_SERVER)?$_SERVER['SERVER_NAME']:$_SERVER['PWD']; + $sAppPath = 'http://'.str_replace('http://', '', $sServerName.dirname($_SERVER['SCRIPT_NAME'])); + $this->asContext['serv_name'] = $sAppPath.(mb_substr($sAppPath, -1)!='/'?'/':''); + } + + public function addUncaughtError($sError) + { + $this->addError('Uncaught errors:'."\n".$sError); + } + + /* Authorizations handling */ + + public function isLoggedIn() + { + return $this->oAuth->isLoggedIn(); + } + + public function logMeIn($sToken) + { + return $this->oAuth->logMeIn($sToken); + } + + public function checkApiKey($sApiKey) + { + return $this->oAuth->checkApiKey($sApiKey); + } + + /* Building main pages */ + + public function getMainPage() + { + $asPages = array('edit', 'cv'); + foreach($asPages as $sPage) $asGlobalVars['pages'][$sPage] = $this->getPageContent($sPage); + $asGlobalVars['id_to_trig'] = $this->oMySql->selectRows(array('select'=>array('ID', 'TRIG'), 'from'=>'EMPLOYEE'), true, 'ID'); + $asGlobalVars['trig_to_id'] = array_flip($asGlobalVars['id_to_trig']); + $asGlobalVars['id'] = $this->oAuth->getUserId(); + $asGlobalVars['names'] = $this->getNames(); + + return $this->getPage('index', $asGlobalVars); + } + + public function getLogonPage() + { + return $this->getPage('logon'); + } + + private function getPage($sPage, $asGlobalVars=array()) + { + $asGlobalVars['consts'] = array('success'=>self::SUCCESS, 'error'=>self::ERROR, 'process_page'=>$this->asContext['process_page']); + + $sPage = $this->getPageContent($sPage); + $sGlobalVars = "\n".'asGlobalVars = '.json_encode($asGlobalVars).';'; + return $sPage."\n".''; + } + + private function getPageContent($sPage) + { + return /*utf8_encode(*/file_get_contents('masks/'.$sPage.'.html')/*)*/; + } + + /* DB structure. See MySqlManager::__construct */ + private static function getSqlOptions() { return array @@ -114,17 +181,11 @@ class Main extends PhpObject $asMaskPaths = glob(Mask::getMaskFile('*')); $this->asMasks = array_map('basename', $asMaskPaths, array_fill(1, count($asMaskPaths), Mask::MASK_EXT)); } - - private static function jsonExport($asData) + + public static function getJsonResult($bSuccess, $sDesc, $asVars=array()) { header('Content-type: application/json'); - //return htmlspecialchars(json_encode($asData), ENT_NOQUOTES); - return self::jsonConvert($asData); - } - - private static function jsonConvert($asData) - { - return json_encode($asData); + return json_encode(array('result'=>$bSuccess?self::SUCCESS:self::ERROR, 'desc'=>self::mb_ucwords($sDesc))+$asVars); } } diff --git a/inc/toolbox.php b/inc/toolbox.php index 85bceed..0a9a675 100755 --- a/inc/toolbox.php +++ b/inc/toolbox.php @@ -38,11 +38,6 @@ class ToolBox //Add CLI arguments if(defined('STDIN')) mb_parse_str(implode('&', array_slice($argv, 1)), $_GET); $_REQUEST = array_merge($_GET, $_REQUEST); - - //Add Server Name - $sServerName = array_key_exists('SERVER_NAME', $_SERVER)?$_SERVER['SERVER_NAME']:$_SERVER['PWD']; - $sAppPath = 'http://'.str_replace('http://', '', $sServerName.dirname($_SERVER['SCRIPT_NAME'])); - $_GET['serv_name'] = $sAppPath.(mb_substr($sAppPath, -1)!='/'?'/':''); } public static function array_map_encapsulate($oData, $sChar) diff --git a/index.php b/index.php index 22d873f..a68140e 100755 --- a/index.php +++ b/index.php @@ -1,5 +1,24 @@ getPage($sPage); - break; -} +$oMain = new Main($oClassManagement, __FILE__, $sLang); +$bLoggedIn = $oCvTheque->isLoggedIn(); + +$sResult = ''; +if($sAction=='logmein') $sResult = $oMain->logMeIn($sToken); +elseif($sAction!='' && $bLoggedIn) +{ + switch ($sAction) + { + case '': + $sResult = $oCvTheque->function(); + break; + default: + $sResult = Main::getJsonResult(false, CvTheque::NOT_FOUND); + } +} +elseif($sAction!='' && !$bLoggedIn) +{ + if($oCvTheque->checkApiKey($iApiKey)) + { + switch ($sAction) + { + case '': + $sResult = $oCvTheque->apifunction(); + break; + default: + $sResult = CvTheque::getJsonResult(false, Main::NOT_FOUND); + } + } + else $sResult = CvTheque::getJsonResult(false, Main::UNAUTHORIZED); +} +elseif($bLoggedIn) $sResult = $oMain->getMainPage(); +else $sResult = $oMain->getLogonPage(); -//Log and clean buffer $sDebug = ob_get_clean(); -if(Settings::DEBUG && $sDebug!='') dlog($sDebug, true); +if(Settings::DEBUG && $sDebug!='') $oMain->addUncaughtError($sDebug); echo $sResult;