v1.0.0 (#183)
* #84 test data dump from CREST login * updated "credits" dialog (Google+ link) fixed login form layout * updated Cortex Data-Mapper * - #84 CREST Login (WIP) - New CREST controller - Database restructuring - improved type-casting for some controller functions - New login process - Fixed some bugs during the setup process (/setup root) - Added CREST request caching by response headers * pathfinder-84 [Feature Request] CREST Pilot Tracking, many smaller Bugfixes * pathfinder-84 [Feature Request] added develop JS files * closed #121 fixed wormhole signature type caching * closed #120 removed map-loading animation for larger maps (same behaviour as IGB) * closed #119 fixed wormhole signature id count * closed #114 Added check for already existing system when adding a new one. (fixed PDO 'duplicate entry' error) * closed #112 fixed DataTables error for missing "status" data (signature table) * closed #111 fixed convertDataToUTC(); client side date transformation * closed #109 fixed system TrueSec rounding * closed #103 fixed system updated timestamp in getData() * fixed CSS class for secStatus in Routes module * closed #121 fixed wormhole signature type caching * changed dateTime format from German to US format fixed some minor bugs in signatureTable module * closed #81 fixed "signature type" overwriting by "signature reader" update * closed #106 added new signature_types form C5/6 wormholes (gas/ore) * closed #129 fixed parameter hinting * closed #131 new "route search" algorithm, added current map systems to live search, added refresh/update functionality for each found route, added bulk route refresh function, added "meta map" route search (search on multiple maps), added route "filters" (restrict search on "stargates", "wormholes", "jumpbridges"), added route "filter" for wormholes (reduced/critical wormholes) closed #89 fixed "loop connections" on same system #84 added error messages for "invalid" CREST "Client ID" added "bootboxjs" (customized styled checkboxes/radio buttons) CSS only "Font Awesome" version upgrade 4.4.0 -> 4.61 "Bootbox.js" version upgrade 4.3.0 -> 4.4.0 fixed "system dialog" (added responsive layout) * closed #134 fixed db column type DT_INT (8 bytes) to DT_BIGINT * closed #138 added new cookie based login * closed #137 fixed javascript errors on trying to establish an "invalid" connection * - #84, #138 improved "character selection" on login page (expired cookies are deleted, character panel layout improvements) - added new "Server info panel" to the login page - added new cronjob to delete expired cookie authentication data * #138 enables character switching between characters which have same user * - PHP Framework upgrade 3.5.0 -> 3.5.1 (fixes some issues with CREST cURL caching, and SESSION management) - #138 added "cookie logout" to "logout" menu entry * - updated "feature page" with new feature descriptions and label - added some new images to the "feature gallery" - removed "beta" status from "magnetizing" feature on map menu - hide "server status" panel on "mobile" breakpoint * - #138 clear character authentication data on sold characters * closed #142 added custom "onsuspect()" session handler * #142 do not log suspect if no file is defined in pathfinder.ini * #142 added NullSec Data/Relic sites to C1/2/3 wormholes as signature option * #144 fixed "Character not found" warning * #144 fixed "Character not found" warning * closed #144 fixed broken routes panel in IGB * updated README.md for upcoming release * #147 response header validation * #149 changed comment for 'BASE' framework var * fixed map import * - added minimal SDE dump (EVE Online: Citadel) - #147 improved CREST API error logging (WIP) - improved SSO controller (removed access_token from public endpoints) * closed #154 added alliance maps to CREST API * - updated Gulp build dependencies - increased CREST timeout from 3s -> 4s - added "Accept" Headers for some CREST endpoints * cloased #147 * - closed #153 added character verification check for getAll(); Signatures Ajax endpoint * - updated README.md (added Slack developer chat information) * Bugfix frig holes (#159) * added missing frigate wormholes and fixed Q003 destination in shattered wormholes * changed C7 to 0.0 for Q003 * - fixed broken "graph" data for system * added a "failover" system for bad crest requests (HTTP status 5xx,.. ) * Red Gaint => Red Giant (#161) * closed #163 added CREST endpoint support for "waypoints" * fixed typo * closed #160 fixed tooltip container * - added new features to login page * closes #154 added alliance map support * fixed XML path for cronjobs * fixed a bug with inactive "private" maps * closes #175 added alternative environment configuration * - v1.0.0 build
This commit is contained in:
@@ -7,50 +7,69 @@
|
||||
*/
|
||||
|
||||
namespace Controller;
|
||||
use Controller\Api as Api;
|
||||
use Controller\Ccp\Sso as Sso;
|
||||
use lib\Config;
|
||||
use Model;
|
||||
use DB;
|
||||
|
||||
class Controller {
|
||||
|
||||
// cookie specific keys (names)
|
||||
const COOKIE_NAME_STATE = 'cookie';
|
||||
const COOKIE_PREFIX_CHARACTER = 'char';
|
||||
|
||||
const ERROR_SESSION_SUSPECT = 'Suspect id: [%30s], ip: [%40s], new ip: [%40s], User-Agent: %s ';
|
||||
/**
|
||||
* @var \Base
|
||||
*/
|
||||
protected $f3;
|
||||
private $template;
|
||||
|
||||
/**
|
||||
* @param mixed $template
|
||||
* @var string template for render
|
||||
*/
|
||||
public function setTemplate($template){
|
||||
protected $template;
|
||||
|
||||
/**
|
||||
* @param string $template
|
||||
*/
|
||||
protected function setTemplate($template){
|
||||
$this->template = $template;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @return string
|
||||
*/
|
||||
public function getTemplate(){
|
||||
protected function getTemplate(){
|
||||
return $this->template;
|
||||
}
|
||||
|
||||
/**
|
||||
* set global f3 instance
|
||||
* @param null $f3
|
||||
* @return null|static
|
||||
* set $f3 base object
|
||||
* @param \Base $f3
|
||||
*/
|
||||
protected function getF3($f3 = null){
|
||||
if(is_object($f3)){
|
||||
$this->f3 = $f3;
|
||||
}else{
|
||||
$this->f3 = \Base::instance();
|
||||
}
|
||||
protected function setF3(\Base $f3){
|
||||
$this->f3 = $f3;
|
||||
}
|
||||
|
||||
/**
|
||||
* get $f3 base object
|
||||
* @return \Base
|
||||
*/
|
||||
protected function getF3(){
|
||||
if( !($this->f3 instanceof \Base) ){
|
||||
$this->setF3( \Base::instance() );
|
||||
}
|
||||
return $this->f3;
|
||||
}
|
||||
|
||||
/**
|
||||
* event handler for all "views"
|
||||
* some global template variables are set in here
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
function beforeroute($f3) {
|
||||
$this->getF3($f3);
|
||||
function beforeroute(\Base $f3) {
|
||||
$this->setF3($f3);
|
||||
|
||||
// initiate DB connection
|
||||
DB\Database::instance('PF');
|
||||
@@ -73,8 +92,9 @@ class Controller {
|
||||
/**
|
||||
* event handler after routing
|
||||
* -> render view
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function afterroute($f3){
|
||||
public function afterroute(\Base $f3){
|
||||
if($this->getTemplate()){
|
||||
// Ajax calls don´t need a page render..
|
||||
// this happens on client side
|
||||
@@ -85,7 +105,7 @@ class Controller {
|
||||
/**
|
||||
* set change the DB connection
|
||||
* @param string $database
|
||||
* @return mixed|void
|
||||
* @return DB\SQL
|
||||
*/
|
||||
protected function getDB($database = 'PF'){
|
||||
return DB\Database::instance()->getDB($database);
|
||||
@@ -95,51 +115,294 @@ class Controller {
|
||||
* init new Session handler
|
||||
*/
|
||||
protected function initSession(){
|
||||
// init DB Session (not file based)
|
||||
if( $this->getDB('PF') instanceof \DB\SQL){
|
||||
new \DB\SQL\Session($this->getDB('PF'));
|
||||
|
||||
// init DB based Session (not file based)
|
||||
if( $this->getDB('PF') instanceof DB\SQL){
|
||||
// init session with custom "onsuspect()" handler
|
||||
new DB\SQL\Session($this->getDB('PF'), 'sessions', true, function($session, $sid){
|
||||
$f3 = $this->getF3();
|
||||
if( ($ip = $session->ip() )!= $f3->get('IP') ){
|
||||
// IP address changed -> not critical
|
||||
$sessionSuspectLogFile = 'PATHFINDER.LOGFILES.SESSION_SUSPECT';
|
||||
if( !$f3->devoid($sessionSuspectLogFile) ){
|
||||
$this->getLogger(
|
||||
$f3->get($sessionSuspectLogFile)
|
||||
)->write( sprintf(
|
||||
self::ERROR_SESSION_SUSPECT,
|
||||
$sid,
|
||||
$session->ip(),
|
||||
$f3->get('IP'),
|
||||
$f3->get('AGENT')
|
||||
));
|
||||
}
|
||||
// no more error handling here
|
||||
return true;
|
||||
}elseif($session->agent() != $f3->get('AGENT') ){
|
||||
// The default behaviour destroys the suspicious session.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get current user model
|
||||
* @param int $ttl
|
||||
* @return bool|null
|
||||
* get cookies "state" information
|
||||
* -> whether user accepts cookies
|
||||
* @return bool
|
||||
*/
|
||||
protected function getCookieState(){
|
||||
return (bool)count( $this->getCookieByName(self::COOKIE_NAME_STATE) );
|
||||
}
|
||||
|
||||
/**
|
||||
* search for existing cookies
|
||||
* -> either a specific cookie by its name
|
||||
* -> or get multiple cookies by their name (search by prefix)
|
||||
* @param $cookieName
|
||||
* @param bool $prefix
|
||||
* @return array
|
||||
*/
|
||||
protected function getCookieByName($cookieName, $prefix = false){
|
||||
$data = [];
|
||||
|
||||
if(!empty($cookieName)){
|
||||
$cookieData = (array)$this->getF3()->get('COOKIE');
|
||||
if($prefix === true){
|
||||
// look for multiple cookies with same prefix
|
||||
foreach($cookieData as $name => $value){
|
||||
if(strpos($name, $cookieName) === 0){
|
||||
$data[$name] = $value;
|
||||
}
|
||||
}
|
||||
}elseif( isset($cookieData[$cookieName]) ){
|
||||
// look for a single cookie
|
||||
$data[$cookieName] = $cookieData[$cookieName];
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* set/update logged in cookie by character model
|
||||
* -> store validation data in DB
|
||||
* @param Model\CharacterModel $character
|
||||
*/
|
||||
protected function setLoginCookie(Model\CharacterModel $character){
|
||||
|
||||
if( $this->getCookieState() ){
|
||||
$expireSeconds = (int) $this->getF3()->get('PATHFINDER.LOGIN.COOKIE_EXPIRE');
|
||||
$expireSeconds *= 24 * 60 * 60;
|
||||
|
||||
$timezone = new \DateTimeZone( $this->getF3()->get('TZ') );
|
||||
$expireTime = new \DateTime('now', $timezone);
|
||||
|
||||
// add cookie expire time
|
||||
$expireTime->add(new \DateInterval('PT' . $expireSeconds . 'S'));
|
||||
|
||||
// unique "selector" -> to facilitate database look-ups (small size)
|
||||
// -> This is preferable to simply using the database id field,
|
||||
// which leaks the number of active users on the application
|
||||
$selector = bin2hex(mcrypt_create_iv(12, MCRYPT_DEV_URANDOM));
|
||||
|
||||
// generate unique "validator" (strong encryption)
|
||||
// -> plaintext set to user (cookie), hashed version of this in DB
|
||||
$size = mcrypt_get_iv_size(MCRYPT_CAST_256, MCRYPT_MODE_CFB);
|
||||
$validator = bin2hex(mcrypt_create_iv($size, MCRYPT_DEV_URANDOM));
|
||||
|
||||
// generate unique cookie token
|
||||
$token = hash('sha256', $validator);
|
||||
|
||||
// get unique cookie name for this character
|
||||
$name = $character->getCookieName();
|
||||
|
||||
$authData = [
|
||||
'characterId' => $character,
|
||||
'selector' => $selector,
|
||||
'token' => $token,
|
||||
'expires' => $expireTime->format('Y-m-d H:i:s')
|
||||
];
|
||||
|
||||
$authenticationModel = $character->rel('characterAuthentications');
|
||||
$authenticationModel->copyfrom($authData);
|
||||
$authenticationModel->save();
|
||||
|
||||
$cookieValue = implode(':', [$selector, $validator]);
|
||||
|
||||
// get cookie name -> save new one OR update existing cookie
|
||||
$cookieName = 'COOKIE.' . self::COOKIE_PREFIX_CHARACTER . '_' . $name;
|
||||
$this->getF3()->set($cookieName, $cookieValue, $expireSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get characters from given cookie data
|
||||
* -> validate cookie data
|
||||
* -> validate characters
|
||||
* -> cf. Sso->requestAuthorization() ( equivalent DB based login)
|
||||
* @param array $cookieData
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function _getUser($ttl = 5){
|
||||
$user = false;
|
||||
protected function getCookieCharacters($cookieData = []){
|
||||
$characters = [];
|
||||
|
||||
if( $this->f3->exists('SESSION.user.id') ){
|
||||
$userId = (int)$this->f3->get('SESSION.user.id');
|
||||
if(
|
||||
$this->getCookieState() &&
|
||||
!empty($cookieData)
|
||||
){
|
||||
/**
|
||||
* @var $characterAuth Model\CharacterAuthenticationModel
|
||||
*/
|
||||
$characterAuth = Model\BasicModel::getNew('CharacterAuthenticationModel');
|
||||
|
||||
if($userId > 0){
|
||||
$userModel = Model\BasicModel::getNew('UserModel', $ttl);
|
||||
$userModel->getById($userId, $ttl);
|
||||
$timezone = new \DateTimeZone( $this->getF3()->get('TZ') );
|
||||
$currentTime = new \DateTime('now', $timezone);
|
||||
|
||||
if( !$userModel->dry() ){
|
||||
$user = $userModel;
|
||||
foreach($cookieData as $name => $value){
|
||||
// remove invalid cookies
|
||||
$invalidCookie = false;
|
||||
|
||||
$data = explode(':', $value);
|
||||
if(count($data) === 2){
|
||||
// cookie data is well formatted
|
||||
$characterAuth->getByForeignKey('selector', $data[0], ['limit' => 1]);
|
||||
|
||||
// validate expire data
|
||||
// validate token
|
||||
if( !$characterAuth->dry() ){
|
||||
if(
|
||||
strtotime($characterAuth->expires) >= $currentTime->getTimestamp() &&
|
||||
hash_equals($characterAuth->token, hash('sha256', $data[1]))
|
||||
){
|
||||
// cookie information is valid
|
||||
// -> try to update character information from CREST
|
||||
// e.g. Corp has changed, this also ensures valid "access_token"
|
||||
/**
|
||||
* @var $character Model\CharacterModel
|
||||
*/
|
||||
$updateStatus = $characterAuth->characterId->updateFromCrest();
|
||||
|
||||
if( empty($updateStatus) ){
|
||||
// make sure character data is up2date!
|
||||
// -> this is not the case if e.g. userCharacters was removed "ownerHash" changed...
|
||||
$character = $characterAuth->rel('characterId');
|
||||
$character->getById($characterAuth->characterId->_id);
|
||||
|
||||
// check if character still has user (is not the case of "ownerHash" changed
|
||||
// check if character is still authorized to log in (e.g. corp/ally or config has changed
|
||||
// -> do NOT remove cookie on failure. This can be a temporary problem (e.g. CREST is down,..)
|
||||
if(
|
||||
$character->hasUserCharacter() &&
|
||||
$character->isAuthorized()
|
||||
){
|
||||
$characters[$name] = $character;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// clear existing authentication data from DB
|
||||
$characterAuth->erase();
|
||||
$invalidCookie = true;
|
||||
}
|
||||
}else{
|
||||
$invalidCookie = true;
|
||||
}
|
||||
$characterAuth->reset();
|
||||
}else{
|
||||
$invalidCookie = true;
|
||||
}
|
||||
|
||||
// remove invalid cookie
|
||||
if($invalidCookie){
|
||||
$this->getF3()->clear('COOKIE.' . $name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $user;
|
||||
return $characters;
|
||||
}
|
||||
|
||||
/**
|
||||
* log the current user out
|
||||
* @param $f3
|
||||
* checks whether a user is currently logged in
|
||||
* @param \Base $f3
|
||||
* @return bool
|
||||
*/
|
||||
public function logOut($f3){
|
||||
protected function checkLogTimer($f3){
|
||||
$loginCheck = false;
|
||||
|
||||
// destroy session
|
||||
if($f3->get(Api\User::SESSION_KEY_CHARACTER_TIME) > 0){
|
||||
// check logIn time
|
||||
$logInTime = new \DateTime();
|
||||
$logInTime->setTimestamp( $f3->get(Api\User::SESSION_KEY_CHARACTER_TIME) );
|
||||
$now = new \DateTime();
|
||||
|
||||
$timeDiff = $now->diff($logInTime);
|
||||
|
||||
$minutes = $timeDiff->days * 60 * 24 * 60;
|
||||
$minutes += $timeDiff->h * 60;
|
||||
$minutes += $timeDiff->i;
|
||||
|
||||
if($minutes <= $f3->get('PATHFINDER.TIMER.LOGGED')){
|
||||
$loginCheck = true;
|
||||
}
|
||||
}
|
||||
|
||||
return $loginCheck;
|
||||
}
|
||||
|
||||
/**
|
||||
* get current character model
|
||||
* @param int $ttl
|
||||
* @return Model\CharacterModel|null
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getCharacter($ttl = 0){
|
||||
$character = null;
|
||||
|
||||
if( $this->getF3()->exists(Api\User::SESSION_KEY_CHARACTER_ID) ){
|
||||
$characterId = (int)$this->getF3()->get(Api\User::SESSION_KEY_CHARACTER_ID);
|
||||
if($characterId){
|
||||
/**
|
||||
* @var $characterModel Model\CharacterModel
|
||||
*/
|
||||
$characterModel = Model\BasicModel::getNew('CharacterModel');
|
||||
$characterModel->getById($characterId, $ttl);
|
||||
|
||||
if(
|
||||
!$characterModel->dry() &&
|
||||
$characterModel->hasUserCharacter()
|
||||
){
|
||||
$character = &$characterModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $character;
|
||||
}
|
||||
|
||||
/**
|
||||
* log out current character
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function logout(\Base $f3){
|
||||
$params = (array)$f3->get('POST');
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// delete server side cookie validation data
|
||||
// for the current character as well
|
||||
if(
|
||||
$params['clearCookies'] === '1' &&
|
||||
( $activeCharacter = $this->getCharacter())
|
||||
){
|
||||
$activeCharacter->logout();
|
||||
}
|
||||
|
||||
// destroy session login data -------------------------------
|
||||
$f3->clear('SESSION');
|
||||
|
||||
if( !$f3->get('AJAX') ){
|
||||
// redirect to landing page
|
||||
$f3->reroute('@login');
|
||||
}else{
|
||||
$params = $f3->get('POST');
|
||||
if( $f3->get('AJAX') ){
|
||||
$return = (object) [];
|
||||
if(
|
||||
isset($params['reroute']) &&
|
||||
@@ -148,272 +411,59 @@ class Controller {
|
||||
$return->reroute = rtrim(self::getEnvironmentData('URL'), '/') . $f3->alias('login');
|
||||
}else{
|
||||
// no reroute -> errors can be shown
|
||||
$return->error[] = $this->getUserLoggedOffError();
|
||||
$return->error[] = $this->getLogoutError();
|
||||
}
|
||||
|
||||
echo json_encode($return);
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* verifies weather a given username and password is valid
|
||||
* @param $userName
|
||||
* @param $password
|
||||
* @return Model\UserModel|null
|
||||
*/
|
||||
protected function _verifyUser($userName, $password) {
|
||||
|
||||
$validUser = null;
|
||||
|
||||
$user = Model\BasicModel::getNew('UserModel', 0);
|
||||
|
||||
$user->getByName($userName);
|
||||
|
||||
// check userName is valid
|
||||
if( !$user->dry() ){
|
||||
// check if password is valid
|
||||
$isValid = $user->verify($password);
|
||||
|
||||
if($isValid === true){
|
||||
$validUser = $user;
|
||||
}
|
||||
}
|
||||
|
||||
return $validUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* check weather the page is IGB trusted or not
|
||||
* @return mixed
|
||||
*/
|
||||
static function isIGBTrusted(){
|
||||
|
||||
$igbHeaderData = self::getIGBHeaderData();
|
||||
|
||||
return $igbHeaderData->trusted;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all eve IGB specific header data
|
||||
* @return object
|
||||
*/
|
||||
static function getIGBHeaderData(){
|
||||
$data = (object) [];
|
||||
$data->trusted = false;
|
||||
$data->values = [];
|
||||
$headerData = self::getRequestHeaders();
|
||||
|
||||
foreach($headerData as $key => $value){
|
||||
$key = strtolower($key);
|
||||
$key = str_replace('eve_', 'eve-', $key);
|
||||
|
||||
|
||||
if (strpos($key, 'eve-') === 0) {
|
||||
$key = str_replace('eve-', '', $key);
|
||||
|
||||
if (
|
||||
$key === 'trusted' &&
|
||||
$value === 'Yes'
|
||||
) {
|
||||
$data->trusted = true;
|
||||
}
|
||||
|
||||
$data->values[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to return all headers because
|
||||
* getallheaders() is not available under nginx
|
||||
*
|
||||
* @return array (string $key -> string $value)
|
||||
*/
|
||||
static function getRequestHeaders(){
|
||||
$headers = [];
|
||||
|
||||
$serverData = self::getServerData();
|
||||
|
||||
if(
|
||||
function_exists('apache_request_headers') &&
|
||||
$serverData->type === 'apache'
|
||||
){
|
||||
// Apache Webserver
|
||||
$headers = apache_request_headers();
|
||||
}else{
|
||||
// Other webserver, e.g. Nginx
|
||||
// Unfortunately this "fallback" does not work for me (Apache)
|
||||
// Therefore we can´t use this for all servers
|
||||
// https://github.com/exodus4d/pathfinder/issues/58
|
||||
foreach($_SERVER as $name => $value){
|
||||
if(substr($name, 0, 5) == 'HTTP_'){
|
||||
$headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
|
||||
}
|
||||
}
|
||||
// redirect to landing page
|
||||
$f3->reroute('@login');
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* get some server information
|
||||
* @param int $ttl cache time (default: 1h)
|
||||
* @return object
|
||||
* get EVE server status from CREST
|
||||
* @param \Base $f3
|
||||
*/
|
||||
static function getServerData($ttl = 3600){
|
||||
$f3 = \Base::instance();
|
||||
$cacheKey = 'PF_SERVER_INFO';
|
||||
public function getEveServerStatus(\Base $f3){
|
||||
$return = (object) [];
|
||||
$return->error = [];
|
||||
|
||||
// server status can be cached for some seconds
|
||||
$cacheKey = 'eve_server_status';
|
||||
if( !$f3->exists($cacheKey) ){
|
||||
$serverData = (object) [];
|
||||
$serverData->type = 'unknown';
|
||||
$serverData->version = 'unknown';
|
||||
$serverData->requiredVersion = 'unknown';
|
||||
$serverData->phpInterfaceType = php_sapi_name();
|
||||
$sso = new Sso();
|
||||
$return->status = $sso->getCrestServerStatus();
|
||||
|
||||
if(strpos(strtolower($_SERVER['SERVER_SOFTWARE']), 'nginx' ) !== false){
|
||||
// Nginx server
|
||||
$serverSoftwareArgs = explode('/', strtolower( $_SERVER['SERVER_SOFTWARE']) );
|
||||
$serverData->type = reset($serverSoftwareArgs);
|
||||
$serverData->version = end($serverSoftwareArgs);
|
||||
$serverData->requiredVersion = $f3->get('REQUIREMENTS.SERVER.NGINX.VERSION');
|
||||
}elseif(strpos(strtolower($_SERVER['SERVER_SOFTWARE']), 'apache' ) !== false){
|
||||
// Apache server
|
||||
$serverData->type = 'apache';
|
||||
$serverData->requiredVersion = $f3->get('REQUIREMENTS.SERVER.APACHE.VERSION');
|
||||
|
||||
// try to get the apache version...
|
||||
if(function_exists('apache_get_version')){
|
||||
// function does not exists if PHP is running as CGI/FPM module!
|
||||
$matches = preg_split('/[\s,\/ ]+/', strtolower( apache_get_version() ) );
|
||||
if(count($matches) > 1){
|
||||
$serverData->version = $matches[1];
|
||||
}
|
||||
}
|
||||
if( !$return->status->crestOffline ){
|
||||
$f3->set($cacheKey, $return, 60);
|
||||
}
|
||||
|
||||
// cache data for one day
|
||||
$f3->set($cacheKey, $serverData, $ttl);
|
||||
}else{
|
||||
// get from cache
|
||||
$return = $f3->get($cacheKey);
|
||||
}
|
||||
|
||||
return $f3->get($cacheKey);
|
||||
echo json_encode($return);
|
||||
}
|
||||
|
||||
/**
|
||||
* check if the current request was send from inGame
|
||||
* @return bool
|
||||
*/
|
||||
static function isIGB(){
|
||||
$isIGB = false;
|
||||
|
||||
$igbHeaderData = self::getIGBHeaderData();
|
||||
|
||||
if(count($igbHeaderData->values) > 0){
|
||||
$isIGB = true;
|
||||
}
|
||||
|
||||
return $isIGB;
|
||||
}
|
||||
|
||||
/**
|
||||
* get error object is a user is not found/logged of
|
||||
* @return object
|
||||
* @return \stdClass
|
||||
*/
|
||||
protected function getUserLoggedOffError(){
|
||||
protected function getLogoutError(){
|
||||
$userError = (object) [];
|
||||
$userError->type = 'error';
|
||||
$userError->message = 'User not found';
|
||||
|
||||
return $userError;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the current registration status
|
||||
* 0=registration stop |1=new registration allowed
|
||||
* @return int
|
||||
*/
|
||||
static function getRegistrationStatus(){
|
||||
return (int)\Base::instance()->get('PATHFINDER.REGISTRATION.STATUS');
|
||||
}
|
||||
|
||||
/**
|
||||
* get a log controller e.g. "debug"
|
||||
* @param $loggerType
|
||||
* @return mixed
|
||||
*/
|
||||
static function getLogger($loggerType){
|
||||
return LogController::getLogger($loggerType);
|
||||
}
|
||||
|
||||
/**
|
||||
* removes illegal characters from a Hive-key that are not allowed
|
||||
* @param $key
|
||||
* @return mixed
|
||||
*/
|
||||
static function formatHiveKey($key){
|
||||
$illegalCharacters = ['-', ' '];
|
||||
return strtolower( str_replace($illegalCharacters, '', $key) );
|
||||
}
|
||||
|
||||
/**
|
||||
* get environment specific configuration data
|
||||
* @param $key
|
||||
* @return mixed|null
|
||||
*/
|
||||
static function getEnvironmentData($key){
|
||||
$f3 = \Base::instance();
|
||||
$environment = self::getEnvironment();
|
||||
$environmentKey = 'ENVIRONMENT[' . $environment . '][' . $key . ']';
|
||||
$data = null;
|
||||
|
||||
if( $f3->exists($environmentKey) ){
|
||||
$data = $f3->get($environmentKey);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* get current server environment status
|
||||
* -> "DEVELOP" or "PRODUCTION"
|
||||
* @return mixed
|
||||
*/
|
||||
static function getEnvironment(){
|
||||
$f3 = \Base::instance();
|
||||
return $f3->get('ENVIRONMENT.SERVER');
|
||||
}
|
||||
|
||||
/**
|
||||
* check if current server is "PRODUCTION"
|
||||
* @return bool
|
||||
*/
|
||||
static function isProduction(){
|
||||
return self::getEnvironment() == 'PRODUCTION';
|
||||
}
|
||||
|
||||
/**
|
||||
* get required MySQL variable value
|
||||
* @param $key
|
||||
* @return mixed|null
|
||||
*/
|
||||
static function getRequiredMySqlVariables($key){
|
||||
$f3 = \Base::instance();
|
||||
$requiredMySqlVarKey = 'REQUIREMENTS[MYSQL][VARS][' . $key . ']';
|
||||
$data = null;
|
||||
|
||||
if( $f3->exists($requiredMySqlVarKey) ){
|
||||
$data = $f3->get($requiredMySqlVarKey);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* get a program URL by alias
|
||||
* -> if no $alias given -> get "default" route (index.php)
|
||||
* @param null $alias
|
||||
* @return bool
|
||||
* @return bool|string
|
||||
*/
|
||||
protected function getRouteUrl($alias = null){
|
||||
$url = false;
|
||||
@@ -452,9 +502,9 @@ class Controller {
|
||||
* onError() callback function
|
||||
* -> on AJAX request -> return JSON with error information
|
||||
* -> on HTTP request -> render error page
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function showError($f3){
|
||||
public function showError(\Base $f3){
|
||||
// set HTTP status
|
||||
$errorCode = $f3->get('ERROR.code');
|
||||
if(!empty($errorCode)){
|
||||
@@ -510,9 +560,224 @@ class Controller {
|
||||
/**
|
||||
* Callback for framework "unload"
|
||||
* check -> config.ini
|
||||
* @param \Base $f3
|
||||
* @return bool
|
||||
*/
|
||||
public function unload($f3){
|
||||
public function unload(\Base $f3){
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* get controller by class name
|
||||
* -> controller class is searched within all controller directories
|
||||
* @param $className
|
||||
* @return null|\Controller\
|
||||
* @throws \Exception
|
||||
*/
|
||||
static function getController($className){
|
||||
$controller = null;
|
||||
// add subNamespaces for controller classes
|
||||
$subNamespaces = ['Api', 'Ccp'];
|
||||
|
||||
for($i = 0; $i <= count($subNamespaces); $i++){
|
||||
$path = [__NAMESPACE__];
|
||||
$path[] = ( isset($subNamespaces[$i - 1]) ) ? $subNamespaces[$i - 1] : '';
|
||||
$path[] = $className;
|
||||
$classPath = implode('\\', array_filter($path));
|
||||
|
||||
if(class_exists($classPath)){
|
||||
$controller = new $classPath();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( is_null($controller) ){
|
||||
throw new \Exception( sprintf('Controller class "%s" not found!', $className) );
|
||||
}
|
||||
|
||||
return $controller;
|
||||
}
|
||||
|
||||
/**
|
||||
* check weather the page is IGB trusted or not
|
||||
* @return boolean
|
||||
*/
|
||||
static function isIGBTrusted(){
|
||||
$igbHeaderData = self::getIGBHeaderData();
|
||||
return $igbHeaderData->trusted;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all eve IGB specific header data
|
||||
* @return \stdClass
|
||||
*/
|
||||
static function getIGBHeaderData(){
|
||||
$data = (object) [];
|
||||
$data->trusted = false;
|
||||
$data->values = [];
|
||||
$headerData = self::getRequestHeaders();
|
||||
|
||||
foreach($headerData as $key => $value){
|
||||
$key = strtolower($key);
|
||||
$key = str_replace('eve_', 'eve-', $key);
|
||||
|
||||
|
||||
if (strpos($key, 'eve-') === 0) {
|
||||
$key = str_replace('eve-', '', $key);
|
||||
|
||||
if (
|
||||
$key === 'trusted' &&
|
||||
$value === 'Yes'
|
||||
) {
|
||||
$data->trusted = true;
|
||||
}
|
||||
|
||||
$data->values[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to return all headers because
|
||||
* getallheaders() is not available under nginx
|
||||
* @return array (string $key -> string $value)
|
||||
*/
|
||||
static function getRequestHeaders(){
|
||||
$headers = [];
|
||||
|
||||
$serverData = self::getServerData();
|
||||
|
||||
if(
|
||||
function_exists('apache_request_headers') &&
|
||||
$serverData->type === 'apache'
|
||||
){
|
||||
// Apache Webserver
|
||||
$headers = apache_request_headers();
|
||||
}else{
|
||||
// Other webserver, e.g. Nginx
|
||||
// Unfortunately this "fallback" does not work for me (Apache)
|
||||
// Therefore we can´t use this for all servers
|
||||
// https://github.com/exodus4d/pathfinder/issues/58
|
||||
foreach($_SERVER as $name => $value){
|
||||
if(substr($name, 0, 5) == 'HTTP_'){
|
||||
$headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* get some server information
|
||||
* @param int $ttl cache time (default: 1h)
|
||||
* @return \stdClass
|
||||
*/
|
||||
static function getServerData($ttl = 3600){
|
||||
$f3 = \Base::instance();
|
||||
$cacheKey = 'PF_SERVER_INFO';
|
||||
|
||||
if( !$f3->exists($cacheKey) ){
|
||||
$serverData = (object) [];
|
||||
$serverData->type = 'unknown';
|
||||
$serverData->version = 'unknown';
|
||||
$serverData->requiredVersion = 'unknown';
|
||||
$serverData->phpInterfaceType = php_sapi_name();
|
||||
|
||||
if(strpos(strtolower($_SERVER['SERVER_SOFTWARE']), 'nginx' ) !== false){
|
||||
// Nginx server
|
||||
$serverSoftwareArgs = explode('/', strtolower( $_SERVER['SERVER_SOFTWARE']) );
|
||||
$serverData->type = reset($serverSoftwareArgs);
|
||||
$serverData->version = end($serverSoftwareArgs);
|
||||
$serverData->requiredVersion = $f3->get('REQUIREMENTS.SERVER.NGINX.VERSION');
|
||||
}elseif(strpos(strtolower($_SERVER['SERVER_SOFTWARE']), 'apache' ) !== false){
|
||||
// Apache server
|
||||
$serverData->type = 'apache';
|
||||
$serverData->requiredVersion = $f3->get('REQUIREMENTS.SERVER.APACHE.VERSION');
|
||||
|
||||
// try to get the apache version...
|
||||
if(function_exists('apache_get_version')){
|
||||
// function does not exists if PHP is running as CGI/FPM module!
|
||||
$matches = preg_split('/[\s,\/ ]+/', strtolower( apache_get_version() ) );
|
||||
if(count($matches) > 1){
|
||||
$serverData->version = $matches[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cache data for one day
|
||||
$f3->set($cacheKey, $serverData, $ttl);
|
||||
}
|
||||
|
||||
return $f3->get($cacheKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* check if the current request was send from inGame
|
||||
* @return bool
|
||||
*/
|
||||
static function isIGB(){
|
||||
$isIGB = false;
|
||||
$igbHeaderData = self::getIGBHeaderData();
|
||||
if(count($igbHeaderData->values) > 0){
|
||||
$isIGB = true;
|
||||
}
|
||||
return $isIGB;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the current registration status
|
||||
* 0=registration stop |1=new registration allowed
|
||||
* @return int
|
||||
*/
|
||||
static function getRegistrationStatus(){
|
||||
return (int)\Base::instance()->get('PATHFINDER.REGISTRATION.STATUS');
|
||||
}
|
||||
|
||||
/**
|
||||
* get a log controller e.g. "debug"
|
||||
* @param string $loggerType
|
||||
* @return \Log
|
||||
*/
|
||||
static function getLogger($loggerType){
|
||||
return LogController::getLogger($loggerType);
|
||||
}
|
||||
|
||||
/**
|
||||
* removes illegal characters from a Hive-key that are not allowed
|
||||
* @param $key
|
||||
* @return string
|
||||
*/
|
||||
static function formatHiveKey($key){
|
||||
$illegalCharacters = ['-', ' '];
|
||||
return strtolower( str_replace($illegalCharacters, '', $key) );
|
||||
}
|
||||
|
||||
/**
|
||||
* get environment specific configuration data
|
||||
* @param string $key
|
||||
* @return string|null
|
||||
*/
|
||||
static function getEnvironmentData($key){
|
||||
return Config::getEnvironmentData($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* get required MySQL variable value
|
||||
* @param $key
|
||||
* @return string|null
|
||||
*/
|
||||
static function getRequiredMySqlVariables($key){
|
||||
$f3 = \Base::instance();
|
||||
$requiredMySqlVarKey = 'REQUIREMENTS[MYSQL][VARS][' . $key . ']';
|
||||
$data = null;
|
||||
|
||||
if( $f3->exists($requiredMySqlVarKey) ){
|
||||
$data = $f3->get($requiredMySqlVarKey);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user