diff --git a/app/main/controller/accesscontroller.php b/app/main/controller/accesscontroller.php index e025eb0e..ad996a86 100644 --- a/app/main/controller/accesscontroller.php +++ b/app/main/controller/accesscontroller.php @@ -19,9 +19,9 @@ class AccessController extends Controller { function beforeroute(\Base $f3) { parent::beforeroute($f3); - // Any CMS route of a child class of this one, requires a - // valid logged in user! - $loginCheck = $this->checkLogIn($f3); + // Any route/endpoint of a child class of this one, + // requires a valid logged in user! + $loginCheck = $this->checkLogTimer($f3); if( !$loginCheck ){ // no user found or LogIn timer expired @@ -29,32 +29,4 @@ class AccessController extends Controller { } } - /** - * checks weather a user is currently logged in - * @param \Base $f3 - * @return bool - */ - private function checkLogIn($f3){ - $loginCheck = false; - - 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; - } - } \ No newline at end of file diff --git a/app/main/controller/api/route.php b/app/main/controller/api/route.php index dfe71d50..018ba2c1 100644 --- a/app/main/controller/api/route.php +++ b/app/main/controller/api/route.php @@ -568,7 +568,6 @@ class Route extends \Controller\AccessController { $item = false; } $data[0]->reset(); - } }, [$map, $validMaps, $activeCharacter]); diff --git a/app/main/controller/api/user.php b/app/main/controller/api/user.php index 0343c207..525a84d5 100644 --- a/app/main/controller/api/user.php +++ b/app/main/controller/api/user.php @@ -84,6 +84,35 @@ class User extends Controller\Controller{ return $login; } + /** + * validate cookie character information + * -> return character data (if valid) + * @param \Base $f3 + */ + public function getCookieCharacter($f3){ + $data = $f3->get('POST'); + + $return = (object) []; + $return->error = []; + + if( !empty($data['cookie']) ){ + if( !empty($cookieData = $this->getCookieByName($data['cookie']) )){ + // cookie data is valid -> validate data against DB (security check!) + if( !empty($characters = $this->getCookieCharacters(array_slice($cookieData, 0, 1, true))) ){ + // character is valid and allowed to login + $return->character = reset($characters)->getData(); + }else{ + $characterError = (object) []; + $characterError->type = 'warning'; + $characterError->message = 'This can happen through "invalid cookie data", "login restrictions", "CREST problems".'; + $return->error[] = $characterError; + } + } + } + + echo json_encode($return); + } + /** * get captcha image and store key to session * @param \Base $f3 @@ -149,64 +178,6 @@ class User extends Controller\Controller{ parent::logOut($f3); } - /** - * save/update "map sharing" configurations for all map types - * the user has access to - * @param \Base $f3 - */ - public function saveSharingConfig(\Base $f3){ - $data = $f3->get('POST'); - - $return = (object) []; - - $activeCharacter = $this->getCharacter(); - - if($activeCharacter){ - $privateSharing = 0; - $corporationSharing = 0; - $allianceSharing = 0; - - // form values - if(isset($data['formData'])){ - $formData = $data['formData']; - - if(isset($formData['privateSharing'])){ - $privateSharing = 1; - } - - if(isset($formData['corporationSharing'])){ - $corporationSharing = 1; - } - - if(isset($formData['allianceSharing'])){ - $allianceSharing = 1; - } - } - - $activeCharacter->shared = $privateSharing; - $activeCharacter = $activeCharacter->save(); - - // update corp/ally --------------------------------------------------------------- - $corporation = $activeCharacter->getCorporation(); - $alliance = $activeCharacter->getAlliance(); - - if(is_object($corporation)){ - $corporation->shared = $corporationSharing; - $corporation->save(); - } - - if(is_object($alliance)){ - $alliance->shared = $allianceSharing; - $alliance->save(); - } - - $user = $activeCharacter->getUser(); - $return->userData = $user->getData(); - } - - echo json_encode($return); - } - /** * update user account data * -> a fresh user automatically generated on first login with a new character diff --git a/app/main/controller/appcontroller.php b/app/main/controller/appcontroller.php index 4874609a..435576f1 100644 --- a/app/main/controller/appcontroller.php +++ b/app/main/controller/appcontroller.php @@ -8,6 +8,7 @@ namespace Controller; use Controller\Ccp as Ccp; +use Model; class AppController extends Controller { @@ -43,6 +44,12 @@ class AppController extends Controller { // JS main file $f3->set('jsView', 'login'); + + // characters from cookies + $f3->set('cookieCharacters', $this->getCookieByName(self::COOKIE_PREFIX_CHARACTER, true)); + $f3->set('getCharacterGrid', function($characters){ + return ( ((12 / count($characters)) <= 4) ? 4 : (12 / count($characters)) ); + }); } } \ No newline at end of file diff --git a/app/main/controller/ccp/sso.php b/app/main/controller/ccp/sso.php index b78b163f..8573c2e1 100644 --- a/app/main/controller/ccp/sso.php +++ b/app/main/controller/ccp/sso.php @@ -52,6 +52,7 @@ class Sso extends Api\User{ const ERROR_CHARACTER_FORBIDDEN = 'Character "%s" is not authorized to log in'; const ERROR_CHARACTER_MISMATCH = 'The character "%s" you tried to log in, does not match'; const ERROR_SERVICE_TIMEOUT = 'CCP SSO service timeout (%ss). Try again later'; + const ERROR_COOKIE_LOGIN = 'Login from Cookie failed. Please retry by CCP SSO'; /** * CREST "Scopes" are used by pathfinder @@ -156,7 +157,7 @@ class Sso extends Api\User{ // get character data from CREST $characterData = $this->getCharacterData($accessData->accessToken); - if(isset($characterData->character)){ + if( isset($characterData->character) ){ // add "ownerHash" and CREST tokens $characterData->character['ownerHash'] = $verificationCharacterData->CharacterOwnerHash; $characterData->character['crestAccessToken'] = $accessData->accessToken; @@ -203,6 +204,9 @@ class Sso extends Api\User{ $loginCheck = $this->loginByCharacter($characterModel); if($loginCheck){ + // set "login" cookie + $this->setLoginCookie($characterModel); + // route to "map" $f3->reroute('@map'); }else{ @@ -235,6 +239,38 @@ class Sso extends Api\User{ } } + /** + * login by cookie + * @param \Base $f3 + */ + public function login(\Base $f3){ + $data = (array)$f3->get('GET'); + $character = null; + + if( !empty($data['cookie']) ){ + if( !empty($cookieData = $this->getCookieByName($data['cookie']) )){ + // cookie data is valid -> validate data against DB (security check!) + if( !empty($characters = $this->getCookieCharacters(array_slice($cookieData, 0, 1, true))) ){ + // character is valid and allowed to login + $character = $characters[$data['cookie']]; + } + } + } + + if( is_object($character)){ + // login by character + $loginCheck = $this->loginByCharacter($character); + if($loginCheck){ + // route to "map" + $f3->reroute('@map'); + } + } + + // on error -> route back to login form + $f3->set(self::SESSION_KEY_SSO_ERROR, self::ERROR_COOKIE_LOGIN); + $f3->reroute('@login'); + } + /** * get a valid "access_token" for oAuth 2.0 verification * -> if $authCode is set -> request NEW "access_token" @@ -357,7 +393,7 @@ class Sso extends Api\User{ * @param $accessToken * @return mixed|null */ - protected function verifyCharacterData($accessToken){ + public function verifyCharacterData($accessToken){ $verifyUserUrl = self::getVerifyUserEndpoint(); $verifyUrlParts = parse_url($verifyUserUrl); $characterData = null; @@ -492,7 +528,7 @@ class Sso extends Api\User{ * @param array $additionalOptions * @return object */ - protected function getCharacterData($accessToken, $additionalOptions = []){ + public function getCharacterData($accessToken, $additionalOptions = []){ $endpoints = $this->getEndpoints($accessToken, $additionalOptions); $characterData = (object) []; diff --git a/app/main/controller/controller.php b/app/main/controller/controller.php index 4f1603c9..e3924f3a 100644 --- a/app/main/controller/controller.php +++ b/app/main/controller/controller.php @@ -13,6 +13,10 @@ use DB; class Controller { + // cookie specific keys (names) + const COOKIE_NAME_STATE = 'cookie'; + const COOKIE_PREFIX_CHARACTER = 'char'; + /** * @var \Base */ @@ -114,6 +118,200 @@ class Controller { } } + /** + * 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 = md5($character->name); + + $authData = [ + 'characterId' => $character, + 'selector' => $selector, + 'token' => $token, + 'expires' => $expireTime->format('Y-m-d H:i:s') + ]; + + $authenticationModel = $character->rel('characterTokens'); + $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 + * @param array $cookieData + * @return array + * @throws \Exception + */ + protected function getCookieCharacters($cookieData = []){ + $characters = []; + + if( + $this->getCookieState() && + !empty($cookieData) + ){ + /** + * @var $characterAuth Model\CharacterAuthenticationModel + */ + $characterAuth = Model\BasicModel::getNew('CharacterAuthenticationModel'); + + $timezone = new \DateTimeZone( $this->getF3()->get('TZ') ); + $currentTime = new \DateTime('now', $timezone); + + 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() && + 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 + */ + $character = $characterAuth->characterId; + $updateStatus = $character->updateFromCrest(); + + // 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( + empty($updateStatus) && + $character->hasUserCharacter() && + $character->isAuthorized() + ){ + $characters[$name] = $character; + } + }else{ + $invalidCookie = true; + } + $characterAuth->reset(); + }else{ + $invalidCookie = true; + } + + // remove invalid cookie + if($invalidCookie){ + $this->getF3()->clear('COOKIE.' . $name); + } + } + } + + return $characters; + } + + /** + * checks whether a user is currently logged in + * @param \Base $f3 + * @return bool + */ + protected function checkLogTimer($f3){ + $loginCheck = false; + + 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 @@ -127,12 +325,15 @@ class Controller { $characterId = (int)$this->getF3()->get(Api\User::SESSION_KEY_CHARACTER_ID); if($characterId){ /** - * @var $characterModel \Model\CharacterModel + * @var $characterModel Model\CharacterModel */ $characterModel = Model\BasicModel::getNew('CharacterModel'); $characterModel->getById($characterId, $ttl); - if( !$characterModel->dry() ){ + if( + !$characterModel->dry() && + $characterModel->hasUserCharacter() + ){ $character = &$characterModel; } } diff --git a/app/main/controller/setup.php b/app/main/controller/setup.php index 22c937f8..a2d794b4 100644 --- a/app/main/controller/setup.php +++ b/app/main/controller/setup.php @@ -40,6 +40,7 @@ class Setup extends Controller { 'Model\UserCharacterModel', 'Model\CharacterModel', + 'Model\CharacterAuthenticationModel', 'Model\CharacterLogModel', 'Model\SystemModel', diff --git a/app/main/model/basicmodel.php b/app/main/model/basicmodel.php index 672ef3b2..5ea7b3cb 100644 --- a/app/main/model/basicmodel.php +++ b/app/main/model/basicmodel.php @@ -375,18 +375,18 @@ abstract class BasicModel extends \DB\Cortex { /** * get dataSet by foreign column (single result) * @param $key - * @param $id + * @param $value * @param array $options * @param int $ttl * @return \DB\Cortex */ - public function getByForeignKey($key, $id, $options = [], $ttl = 60){ + public function getByForeignKey($key, $value, $options = [], $ttl = 60){ $querySet = []; $query = []; if($this->exists($key)){ $query[] = $key . " = :" . $key; - $querySet[':' . $key] = $id; + $querySet[':' . $key] = $value; } // check active column diff --git a/app/main/model/characterauthenticationmodel.php b/app/main/model/characterauthenticationmodel.php new file mode 100644 index 00000000..2388dec3 --- /dev/null +++ b/app/main/model/characterauthenticationmodel.php @@ -0,0 +1,54 @@ + [ + 'type' => Schema::DT_BOOL, + 'nullable' => false, + 'default' => 1, + 'index' => true + ], + 'characterId' => [ + 'type' => Schema::DT_INT, + 'index' => true, + 'belongs-to-one' => 'Model\CharacterModel', + 'constraint' => [ + [ + 'table' => 'character', + 'on-delete' => 'CASCADE' + ] + ] + ], + 'selector' => [ + 'type' => Schema::DT_VARCHAR128, + 'nullable' => false, + 'default' => '', + 'index' => true, + 'unique' => true + ], + 'token' => [ + 'type' => Schema::DT_VARCHAR128, + 'nullable' => false, + 'default' => '', + 'index' => true + ], + 'expires' => [ + 'type' => Schema::DT_TIMESTAMP, + 'default' => Schema::DF_CURRENT_TIMESTAMP, + 'index' => true + ] + ]; +} \ No newline at end of file diff --git a/app/main/model/charactermodel.php b/app/main/model/charactermodel.php index 76d9601a..44834bd8 100644 --- a/app/main/model/charactermodel.php +++ b/app/main/model/charactermodel.php @@ -9,7 +9,7 @@ namespace Model; use Controller; -use Controller\Ccp; +use Controller\Ccp\Sso as Sso; use DB\SQL\Schema; use Data\Mapper as Mapper; @@ -93,6 +93,9 @@ class CharacterModel extends BasicModel { ], 'characterMaps' => [ 'has-many' => ['Model\CharacterMapModel', 'characterId'] + ], + 'characterTokens' => [ + 'has-many' => ['Model\CharacterAuthenticationModel', 'characterId'] ] ]; @@ -234,7 +237,7 @@ class CharacterModel extends BasicModel { * get CREST API "access_token" from OAuth * @return bool|string */ - private function getAccessToken(){ + public function getAccessToken(){ $accessToken = false; // check if there is already an "accessToken" for this user @@ -252,7 +255,7 @@ class CharacterModel extends BasicModel { // add expire time buffer for this "accessToken" // token should be marked as "deprecated" BEFORE it actually expires. $timeBuffer = 2 * 60; - $tokenTime->add(new \DateInterval('PT' . (Ccp\Sso::ACCESS_KEY_EXPIRE_TIME - $timeBuffer) . 'S')); + $tokenTime->add(new \DateInterval('PT' . (Sso::ACCESS_KEY_EXPIRE_TIME - $timeBuffer) . 'S')); $now = new \DateTime('now', $timezone); if($tokenTime->getTimestamp() > $now->getTimestamp()){ @@ -266,7 +269,7 @@ class CharacterModel extends BasicModel { !empty($this->crestRefreshToken) ){ // no accessToken found OR token is deprecated - $ssoController = new Ccp\Sso(); + $ssoController = new Sso(); $accessData = $ssoController->refreshAccessToken($this->crestRefreshToken); if( @@ -363,7 +366,7 @@ class CharacterModel extends BasicModel { }else{ // get Location Data from CREST endpoint // user is NOT with IGB online OR has not jet set "trusted" page - $ssoController = new Ccp\Sso(); + $ssoController = new Sso(); $logData = $ssoController->getCharacterLocationData($this->getAccessToken(), 10, $additionalOptions); if($logData['timeout'] === false){ @@ -396,6 +399,64 @@ class CharacterModel extends BasicModel { return $this; } + /** + * update character data from CCPs CREST API + * @return array (some status messages) + */ + public function updateFromCrest(){ + $status = []; + + if( $accessToken = $this->getAccessToken() ){ + // et basic character data + // -> this is required for "ownerHash" hash check (e.g. character was sold,..) + // -> the "id" check is just for security and should NEVER fail! + $ssoController = new Sso(); + if( + !is_null( $verificationCharacterData = $ssoController->verifyCharacterData($accessToken) ) && + $verificationCharacterData->CharacterID === $this->_id + ){ + // get character data from CREST + $characterData = $ssoController->getCharacterData($accessToken); + if( isset($characterData->character) ){ + $characterData->character['ownerHash'] = $verificationCharacterData->CharacterOwnerHash; + + $corporation = null; + $alliance = null; + if( isset($characterData->corporation) ){ + /** + * @var $corporation CorporationModel + */ + $corporation = $this->rel('corporationId'); + $corporation->getById($characterData->corporation['id'], 0); + $corporation->copyfrom($characterData->corporation, ['name', 'isNPC']); + $corporation->save(); + } + + if( isset($characterData->alliance) ){ + /** + * @var $alliance AllianceModel + */ + $alliance = $this->rel('allianceId'); + $alliance->getById($characterData->alliance['id'], 0); + $alliance->copyfrom($characterData->alliance, ['name']); + $alliance->save(); + } + + $this->copyfrom($characterData->character, ['name', 'ownerHash']); + $this->set('corporationId', is_object($corporation) ? $corporation->get('id') : null); + $this->set('allianceId', is_object($alliance) ? $corporation->get('id') : null); + $this->save(); + } + }else{ + $status[] = sprintf(Sso::ERROR_VERIFY_CHARACTER, $this->name); + } + }else{ + $status[] = sprintf(Sso::ERROR_ACCESS_TOKEN, $this->name); + } + + return $status; + } + /** * get the character log entry for this character * @return bool|CharacterLogModel diff --git a/app/pathfinder.ini b/app/pathfinder.ini index 3406204e..4c5d3846 100644 --- a/app/pathfinder.ini +++ b/app/pathfinder.ini @@ -35,6 +35,9 @@ INVITE = 0 INVITE_LIMIT = 50 [PATHFINDER.LOGIN] +; expire time (in days) for login cookies +COOKIE_EXPIRE = 30 + ; restrict login to specific corporations/alliances by id (e.g. 1000166,1000080) CORPORATION = ALLIANCE = diff --git a/js/app/init.js b/js/app/init.js index 6d14aedf..d29f41bd 100644 --- a/js/app/init.js +++ b/js/app/init.js @@ -12,12 +12,11 @@ define(['jquery'], function($) { // user API getCaptcha: 'api/user/getCaptcha', // ajax URL - get captcha image sendInviteKey: 'api/user/sendInvite', // ajax URL - send registration key + getCookieCharacterData: 'api/user/getCookieCharacter', // ajax URL - get character data from cookie logIn: 'api/user/logIn', // ajax URL - login logOut: 'api/user/logOut', // ajax URL - logout deleteLog: 'api/user/deleteLog', // ajax URL - delete character log saveUserConfig: 'api/user/saveAccount', // ajax URL - saves/update user account - getUserData: 'api/user/getData', // ajax URL - get user data - saveSharingConfig: 'api/user/saveSharingConfig', // ajax URL - save "sharing settings" dialog deleteAccount: 'api/user/deleteAccount', // ajax URL - delete Account data // access API searchAccess: 'api/access/search', // ajax URL - search user/corporation/ally by name diff --git a/js/app/login.js b/js/app/login.js index 430d7ded..6af5cee8 100644 --- a/js/app/login.js +++ b/js/app/login.js @@ -43,11 +43,15 @@ define([ navigationLinkLicenseClass: 'pf-navbar-license', // class for "license" trigger link navigationVersionLinkClass: 'pf-navbar-version-info', // class for "version information" - // login form - loginFormId: 'pf-login-form', // id for login form - loginButtonClass: 'pf-login-button', // class for "login" button(s) - registerButtonClass: 'pf-register-button', // class for "register" button(s) - loginMessageContainerId: 'pf-login-message-container', // id for login form message container + // cookie hint + cookieHintId: 'pf-cookie-hint', // id for "cookie hint" element + + // character select + characterSelectionClass: 'pf-character-selection', // class for character panel wrapper + characterRowAnimateClass: 'pf-character-row-animate', // class for character panel row during animation + characterImageWrapperClass: 'pf-character-image-wrapper', // class for image wrapper (animated) + characterImageInfoClass: 'pf-character-info', // class for character info layer (visible on hover) + dynamicMessageContainerClass: 'pf-dynamic-message-container', // class for "dynamic" (JS) message container // gallery galleryId: 'pf-gallery', // id for gallery container @@ -59,49 +63,75 @@ define([ animateElementClass: 'pf-animate-on-visible' // class for elements that will be animated to show }; + /** + * set a cookie + * @param cname + * @param cvalue + * @param exdays + */ + var setCookie = function(cname, cvalue, exdays) { + var d = new Date(); + d.setTime(d.getTime() + (exdays*24*60*60*1000)); + var expires = 'expires=' + d.toUTCString(); + document.cookie = cname + '=' + cvalue + '; ' + expires; + }; + + /** + * get cookie value by name + * @param cname + * @returns {*} + */ + var getCookie = function(cname) { + var name = cname + '='; + var ca = document.cookie.split(';'); + + for(var i = 0; i 0 ){ form.showFormMessage(responseData.error); - - }else{ $('.modal').modal('hide'); Util.showNotify({title: 'Registration Key send', text: 'Check your Mails', type: 'success'}); @@ -240,7 +268,7 @@ define([ return newSlideContent[0]; }; - // initialize carousel ------------------------------------------ + // initialize carousel ------------------------------------------------ var carousel = new Gallery([ { title: 'IGB', @@ -363,29 +391,31 @@ define([ var initYoutube = function(){ - $(".youtube").each(function() { + $('.youtube').each(function() { // Based on the YouTube ID, we can easily find the thumbnail image $(this).css('background-image', 'url(https://i.ytimg.com/vi/' + this.id + '/sddefault.jpg)'); // Overlay the Play icon to make it look like a video player $(this).append($('
', {'class': 'play'})); - $(document).delegate('#'+this.id, 'click', function() { + $(document).delegate('#' + this.id, 'click', function() { // Create an iFrame with autoplay set to true - var iframe_url = "https://www.youtube.com/embed/" + this.id + "?autoplay=1&autohide=1"; - if ($(this).data('params')) iframe_url+='&'+$(this).data('params'); + var iFrameUrl = 'https://www.youtube.com/embed/' + this.id + '?autoplay=1&autohide=1'; + if ( $(this).data('params') ){ + iFrameUrl += '&'+$(this).data('params'); + } // The height and width of the iFrame should be the same as parent - var iframe = $('