File indexing completed on 2024-10-13 13:29:13
0001 <?php 0002 0003 /** 0004 * ocs-webserver 0005 * 0006 * Copyright 2016 by pling GmbH. 0007 * 0008 * This file is part of ocs-webserver. 0009 * 0010 * This program is free software: you can redistribute it and/or modify 0011 * it under the terms of the GNU Affero General Public License as 0012 * published by the Free Software Foundation, either version 3 of the 0013 * License, or (at your option) any later version. 0014 * 0015 * This program is distributed in the hope that it will be useful, 0016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0018 * GNU Affero General Public License for more details. 0019 * 0020 * You should have received a copy of the GNU Affero General Public License 0021 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0022 **/ 0023 class Application_Model_RememberMe 0024 { 0025 0026 protected $salt = 'slkdmclskdaruiowrjasndf224323423rwersdf§$%ZTFG§EWRSGFSD!§RWESFD'; 0027 0028 /** @var null|Zend_Controller_Request_Http */ 0029 protected $request; 0030 /** @var string */ 0031 protected $dataTableName; 0032 /** @var Application_Model_DbTable_Comments */ 0033 protected $dataTable; 0034 /** @var string */ 0035 protected $cookieName; 0036 /** @var int */ 0037 protected $cookieTimeout; 0038 0039 /** 0040 * PHP 5 allows developers to declare constructor methods for classes. 0041 * Classes which have a constructor method call this method on each newly-created object, 0042 * so it is suitable for any initialization that the object may need before it is used. 0043 * 0044 * Note: Parent constructors are not called implicitly if the child class defines a constructor. 0045 * In order to run a parent constructor, a call to parent::__construct() within the child constructor is required. 0046 * 0047 * param [ mixed $args [, $... ]] 0048 * 0049 * @param string $_dataTableName 0050 * 0051 * @throws Zend_Exception 0052 * @link http://php.net/manual/en/language.oop5.decon.php 0053 */ 0054 public function __construct($_dataTableName = 'Application_Model_DbTable_Session') 0055 { 0056 $this->request = Zend_Controller_Front::getInstance()->getRequest(); 0057 0058 $this->dataTableName = $_dataTableName; 0059 $this->dataTable = new $this->dataTableName; 0060 0061 $config = Zend_Registry::get('config'); 0062 $this->cookieName = $config->settings->session->remember_me->name; 0063 $this->cookieTimeout = $config->settings->session->remember_me->cookie_lifetime; 0064 } 0065 0066 /** 0067 * @param $identifier 0068 * 0069 * @return array|null 0070 * @throws Zend_Db_Statement_Exception 0071 */ 0072 public function updateSession($identifier) 0073 { 0074 $currentSessionCookie = $this->getCookieData(); 0075 0076 if (empty($currentSessionCookie)) { 0077 return $this->createSession($identifier); 0078 } 0079 0080 $newSessionData = $this->createSessionData($identifier); 0081 $this->setCookie($newSessionData); 0082 0083 $countUpdated = $this->updateSessionData($currentSessionCookie, $newSessionData, $identifier); 0084 0085 if (empty($countUpdated)) { 0086 $this->saveSessionData($newSessionData); // old session entry not found; we create a new one 0087 } 0088 0089 return $newSessionData; 0090 } 0091 0092 /** 0093 * @return null|array 0094 */ 0095 public function getCookieData() 0096 { 0097 $cookieRememberMe = $this->request->getCookie($this->cookieName, null); 0098 if (false === isset($cookieRememberMe)) { 0099 return null; 0100 } 0101 $cookieData = unserialize($cookieRememberMe); 0102 if (empty($cookieData)) { 0103 return null; 0104 } 0105 $sessionData = array(); 0106 $sessionData['member_id'] = (int)$cookieData['mi']; 0107 $sessionData['remember_me_id'] = $cookieData['u']; 0108 $sessionData['token'] = isset($cookieData['t']) ? $cookieData['t'] : null; 0109 0110 return $sessionData; 0111 } 0112 0113 /** 0114 * @param int $identifier 0115 * 0116 * @return array return new session data 0117 * @throws Exception 0118 */ 0119 public function createSession($identifier) 0120 { 0121 $newSessionData = $this->createSessionData($identifier); 0122 $this->setCookie($newSessionData); 0123 $this->saveSessionData($newSessionData); 0124 0125 return $newSessionData; 0126 } 0127 0128 /** 0129 * @param int $identifier 0130 * 0131 * @return array 0132 */ 0133 protected function createSessionData($identifier) 0134 { 0135 $sessionData = array(); 0136 $sessionData['member_id'] = (int)$identifier; 0137 $sessionData['remember_me_id'] = Local_Tools_UUID::generateUUID(); 0138 $sessionData['expiry'] = time() + (int)$this->cookieTimeout; 0139 $sessionData['token'] = 0140 base64_encode(hash('sha256', $sessionData['member_id'] . $sessionData['remember_me_id'] . $this->salt)); 0141 0142 return $sessionData; 0143 } 0144 0145 /** 0146 * @param array $newSessionData 0147 * 0148 * @return bool 0149 */ 0150 protected function setCookie($newSessionData) 0151 { 0152 if (empty($newSessionData)) { 0153 return false; 0154 } 0155 0156 $domain = Local_Tools_ParseDomain::get_domain($this->request->getHttpHost()); 0157 0158 $sessionData = array(); 0159 $sessionData['mi'] = $newSessionData['member_id']; 0160 $sessionData['u'] = $newSessionData['remember_me_id']; 0161 $sessionData['t'] = $newSessionData['token']; 0162 0163 // delete old cookie with wrong domain 0164 //setcookie($this->cookieName, null, time() - $this->cookieTimeout, '/', $this->request->getHttpHost(), null, true); 0165 0166 return setcookie($this->cookieName, serialize($sessionData), $newSessionData['expiry'], '/', $domain, null, true); 0167 } 0168 0169 /** 0170 * @param $newSessionData 0171 * 0172 * @return mixed 0173 * @throws Exception 0174 */ 0175 protected function saveSessionData($newSessionData) 0176 { 0177 $newSessionData['expiry'] = date('Y-m-d H:i:s', $newSessionData['expiry']); // change to mysql datetime format 0178 $this->dataTable->save($newSessionData); 0179 0180 return $newSessionData; 0181 } 0182 0183 /** 0184 * @param array $currentSessionData 0185 * @param array $newSessionData 0186 * @param int $identifier 0187 * 0188 * @return int count of updated rows 0189 * @throws Zend_Db_Statement_Exception 0190 */ 0191 private function updateSessionData($currentSessionData, $newSessionData, $identifier) 0192 { 0193 if (false == isset($currentSessionData) OR (count($currentSessionData) == 0)) { 0194 return null; 0195 } 0196 0197 $sql = 0198 "UPDATE `session` SET `remember_me_id` = :remember_new, `expiry` = FROM_UNIXTIME(:expiry_new), `changed` = NOW() WHERE `member_id` = :member_id AND `remember_me_id` = :remember_old"; 0199 0200 $result = $this->dataTable->getAdapter()->query($sql, array( 0201 'remember_new' => $newSessionData['remember_me_id'], 0202 'expiry_new' => $newSessionData['expiry'], 0203 'member_id' => $identifier, 0204 'remember_old' => $currentSessionData['remember_me_id'] 0205 )) 0206 ; 0207 0208 return $result->rowCount(); 0209 } 0210 0211 public function hasValidCookie() 0212 { 0213 $sessionCookieData = $this->getCookieData(); 0214 0215 return $this->validateCookieData($sessionCookieData); 0216 } 0217 0218 protected function validateCookieData($currentCookie) 0219 { 0220 if (empty($currentCookie)) { 0221 return false; 0222 } 0223 if (empty($currentCookie['token'])) { 0224 return false; 0225 } 0226 if (empty($currentCookie['member_id']) OR (false == is_int($currentCookie['member_id']))) { 0227 return false; 0228 } 0229 if (empty($currentCookie['remember_me_id'])) { 0230 return false; 0231 } 0232 $cookieToken = base64_decode($currentCookie['token']); 0233 $validateToken = hash('sha256', $currentCookie['member_id'] . $currentCookie['remember_me_id'] . $this->salt); 0234 if ($cookieToken != $validateToken) { 0235 return false; 0236 } 0237 0238 return true; 0239 } 0240 0241 public function deleteSession() 0242 { 0243 $currentSessionCookie = $this->getCookieData(); 0244 if (empty($currentSessionCookie)) { 0245 return; 0246 } 0247 $this->removeSessionData($currentSessionCookie); 0248 $this->deleteCookie(); 0249 } 0250 0251 /** 0252 * @param array $currentSessionCookie 0253 * 0254 * @return bool 0255 * @throws Zend_Db_Statement_Exception 0256 */ 0257 protected function removeSessionData($currentSessionCookie) 0258 { 0259 $sql = "DELETE FROM `session` WHERE `member_id` = :member_id AND `remember_me_id` = :uuid"; 0260 0261 $result = $this->dataTable->getAdapter()->query($sql, array( 0262 'member_id' => $currentSessionCookie['member_id'], 0263 'uuid' => $currentSessionCookie['remember_me_id'] 0264 )) 0265 ; 0266 if ($result->rowCount() > 0) { 0267 return true; 0268 } else { 0269 return false; 0270 } 0271 } 0272 0273 public function deleteCookie() 0274 { 0275 $domain = Local_Tools_ParseDomain::get_domain($this->request->getHttpHost()); 0276 $cookieExpire = time() - $this->cookieTimeout; 0277 0278 setcookie($this->cookieName, false, $cookieExpire, '/', $this->request->getHttpHost(), null, true); 0279 setcookie($this->cookieName, false, $cookieExpire, '/', $domain, null, true); 0280 } 0281 0282 }