1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
21:
22: class Session extends Wire implements IteratorAggregate {
23:
24: 25: 26: 27: 28: 29:
30: protected $config;
31:
32: 33: 34: 35:
36: protected $CSRF = null;
37:
38: 39: 40: 41: 42: 43:
44: public function __construct() {
45:
46: $this->config = $this->fuel('config');
47: @session_start();
48: unregisterGLOBALS();
49: $className = $this->className();
50: $user = null;
51:
52: if(empty($_SESSION[$className])) $_SESSION[$className] = array();
53:
54: if($userID = $this->get('_user_id')) {
55: if($this->isValidSession()) {
56: $user = $this->fuel('users')->get($userID);
57: } else {
58: $this->logout();
59: }
60: }
61:
62: if(!$user || !$user->id) $user = $this->fuel('users')->getGuestUser();
63: $this->fuel('users')->setCurrentUser($user);
64:
65: foreach(array('message', 'error') as $type) {
66: if($items = $this->get($type)) foreach($items as $item) {
67: list($text, $flags) = $item;
68: parent::$type($text, $flags);
69: }
70: $this->remove($type);
71: }
72:
73: $this->setTrackChanges(true);
74: }
75:
76:
77: 78: 79: 80: 81: 82: 83: 84:
85: protected function ___isValidSession() {
86:
87: $valid = true;
88: $sessionName = session_name();
89:
90: if($this->config->sessionChallenge) {
91: if(empty($_COOKIE[$sessionName . "_challenge"]) || ($this->get('_user_challenge') != $_COOKIE[$sessionName . "_challenge"])) {
92: $valid = false;
93: }
94: }
95:
96: if($this->config->sessionFingerprint) {
97: if(($_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT']) != $this->get("_user_fingerprint")) {
98: $valid = false;
99: }
100: }
101:
102: return $valid;
103: }
104:
105:
106: 107: 108: 109: 110: 111: 112:
113: public function get($key) {
114: if($key == 'CSRF') {
115: if(is_null($this->CSRF)) $this->CSRF = new SessionCSRF();
116: return $this->CSRF;
117: }
118: $className = $this->className();
119: return isset($_SESSION[$className][$key]) ? $_SESSION[$className][$key] : null;
120: }
121:
122: 123: 124: 125: 126: 127:
128: public function getAll() {
129: return $_SESSION[$this->className()];
130: }
131:
132: 133: 134: 135: 136: 137: 138: 139:
140: public function set($key, $value) {
141: $className = $this->className();
142: $oldValue = $this->get($key);
143: if($value !== $oldValue) $this->trackChange($key);
144: $_SESSION[$className][$key] = $value;
145: return $this;
146: }
147:
148: 149: 150: 151: 152: 153: 154:
155: public function remove($key) {
156: unset($_SESSION[$this->className()][$key]);
157: return $this;
158: }
159:
160: 161: 162: 163:
164: public function __get($key) {
165: return $this->get($key);
166: }
167:
168: 169: 170: 171:
172: public function __set($key, $value) {
173: return $this->set($key, $value);
174: }
175:
176: 177: 178: 179:
180: public function getIterator() {
181: return new ArrayObject($_SESSION[$this->className()]);
182: }
183:
184: 185: 186: 187: 188: 189: 190: 191: 192: 193:
194: public function ___login($name, $pass) {
195:
196: $name = $this->fuel('sanitizer')->username($name);
197: $user = $this->fuel('users')->get("name=$name");
198:
199: if($user->id && $this->authenticate($user, $pass)) {
200:
201: $this->trackChange('login');
202: session_regenerate_id();
203: $this->set('_user_id', $user->id);
204:
205: if($this->config->sessionChallenge) {
206: $challenge = md5(mt_rand() . $user->id . microtime());
207: $expireSeconds = $this->config->sessionExpireSeconds ? time() + $this->config->sessionExpireSeconds : 0;
208: setcookie(session_name() . "_challenge", $challenge, $expireSeconds, '/', null, false, true);
209: $this->set('_user_challenge', $challenge);
210: }
211:
212: if($this->config->sessionFingerprint) {
213: $this->set('_user_fingerprint', $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT']);
214: }
215:
216: $this->setFuel('user', $user);
217: $this->get('CSRF')->resetToken();
218:
219: return $user;
220: }
221:
222: return null;
223: }
224:
225: 226: 227: 228: 229: 230: 231: 232:
233: public function ___authenticate(User $user, $pass) {
234: return $user->pass->matches($pass);
235: }
236:
237: 238: 239: 240: 241: 242:
243: public function ___logout() {
244: $sessionName = session_name();
245: $_SESSION = array();
246: if(isset($_COOKIE[$sessionName])) setcookie($sessionName, '', time()-42000, '/');
247: if(isset($_COOKIE[$sessionName . "_challenge"])) setcookie($sessionName . "_challenge", '', time()-42000, '/');
248: session_destroy();
249: session_name($sessionName);
250: session_start();
251: session_regenerate_id();
252: $_SESSION[$this->className()] = array();
253: $guest = $this->fuel('users')->getGuestUser();
254: $this->fuel('users')->setCurrentUser($guest);
255: $this->trackChange('logout');
256: return $this;
257: }
258:
259: 260: 261: 262:
263: public function ___redirect($url, $http301 = true) {
264:
265:
266: $notices = $this->fuel('notices');
267: if(count($notices)) foreach($notices as $notice) {
268: $this->queueNotice($notice->text, $notice instanceof NoticeError ? 'error' : 'message', $notice->flags);
269: }
270:
271:
272: if($http301) header("HTTP/1.1 301 Moved Permanently");
273: header("Location: $url");
274: header("Connection: close");
275: exit(0);
276: }
277:
278: 279: 280: 281:
282: protected function queueNotice($text, $type, $flags) {
283: $items = $this->get($type);
284: if(is_null($items)) $items = array();
285: $item = array($text, $flags);
286: $items[] = $item;
287: $this->set($type, $items);
288: }
289:
290:
291: 292: 293: 294:
295: public function message($text, $flags = 0) {
296: $this->queueNotice($text, 'message', $flags);
297: return $this;
298: }
299:
300: 301: 302: 303:
304: public function error($text, $flags = 0) {
305: $this->queueNotice($text, 'error', $flags);
306: return $this;
307: }
308:
309:
310: }
311: