Subversion-Projekte lars-tiefland.cakephp

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/* SVN FILE: $Id: cookie.php 7945 2008-12-19 02:16:01Z gwoo $ */
3
/**
4
 * Short description for file.
5
 *
6
 * Long description for file
7
 *
8
 * PHP versions 4 and 5
9
 *
10
 * CakePHP(tm) :  Rapid Development Framework (http://www.cakephp.org)
11
 * Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
12
 *
13
 * Licensed under The MIT License
14
 * Redistributions of files must retain the above copyright notice.
15
 *
16
 * @filesource
17
 * @copyright     Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
18
 * @link          http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
19
 * @package       cake
20
 * @subpackage    cake.cake.libs.controller.components
21
 * @since         CakePHP(tm) v 1.2.0.4213
22
 * @version       $Revision: 7945 $
23
 * @modifiedby    $LastChangedBy: gwoo $
24
 * @lastmodified  $Date: 2008-12-18 18:16:01 -0800 (Thu, 18 Dec 2008) $
25
 * @license       http://www.opensource.org/licenses/mit-license.php The MIT License
26
 */
27
/**
28
 * Load Security class
29
 */
30
App::import('Core', 'Security');
31
/**
32
 * Cookie Component.
33
 *
34
 * Cookie handling for the controller.
35
 *
36
 * @package       cake
37
 * @subpackage    cake.cake.libs.controller.components
38
 *
39
 */
40
class CookieComponent extends Object {
41
/**
42
 * The name of the cookie.
43
 *
44
 * Overridden with the controller beforeFilter();
45
 * $this->Cookie->name = 'CookieName';
46
 *
47
 * @var string
48
 * @access public
49
 */
50
	var $name = 'CakeCookie';
51
/**
52
 * The time a cookie will remain valid.
53
 *
54
 * Can be either integer Unix timestamp or a date string.
55
 *
56
 * Overridden with the controller beforeFilter();
57
 * $this->Cookie->time = '5 Days';
58
 *
59
 * @var mixed
60
 * @access public
61
 */
62
	var $time = null;
63
/**
64
 * Cookie path.
65
 *
66
 * Overridden with the controller beforeFilter();
67
 * $this->Cookie->path = '/';
68
 *
69
 * The path on the server in which the cookie will be available on.
70
 * If  var $cookiePath is set to '/foo/', the cookie will only be available
71
 * within the /foo/ directory and all sub-directories such as /foo/bar/ of domain.
72
 * The default value is the entire domain.
73
 *
74
 * @var string
75
 * @access public
76
 */
77
	var $path = '/';
78
/**
79
 * Domain path.
80
 *
81
 * The domain that the cookie is available.
82
 *
83
 * Overridden with the controller beforeFilter();
84
 * $this->Cookie->domain = '.example.com';
85
 *
86
 * To make the cookie available on all subdomains of example.com.
87
 * Set $this->Cookie->domain = '.example.com'; in your controller beforeFilter
88
 *
89
 * @var string
90
 * @access public
91
 */
92
	var $domain = '';
93
/**
94
 * Secure HTTPS only cookie.
95
 *
96
 * Overridden with the controller beforeFilter();
97
 * $this->Cookie->secure = true;
98
 *
99
 * Indicates that the cookie should only be transmitted over a secure HTTPS connection.
100
 * When set to true, the cookie will only be set if a secure connection exists.
101
 *
102
 * @var boolean
103
 * @access public
104
 */
105
	var $secure = false;
106
/**
107
 * Encryption key.
108
 *
109
 * Overridden with the controller beforeFilter();
110
 * $this->Cookie->key = 'SomeRandomString';
111
 *
112
 * @var string
113
 * @access protected
114
 */
115
	var $key = null;
116
/**
117
 * Values stored in the cookie.
118
 *
119
 * Accessed in the controller using $this->Cookie->read('Name.key');
120
 *
121
 * @see CookieComponent::read();
122
 * @var string
123
 * @access private
124
 */
125
	var $__values = array();
126
/**
127
 * Type of encryption to use.
128
 *
129
 * Currently only one method is available
130
 * Defaults to Security::cipher();
131
 *
132
 * @var string
133
 * @access private
134
 * @todo add additional encryption methods
135
 */
136
	var $__type = 'cipher';
137
/**
138
 * Used to reset cookie time if $expire is passed to CookieComponent::write()
139
 *
140
 * @var string
141
 * @access private
142
 */
143
	var $__reset = null;
144
/**
145
 * Expire time of the cookie
146
 *
147
 * This is controlled by CookieComponent::time;
148
 *
149
 * @var string
150
 * @access private
151
 */
152
	var $__expires = 0;
153
/**
154
 * Main execution method.
155
 *
156
 * @param object $controller A reference to the instantiating controller object
157
 * @access public
158
 */
159
	function initialize(&$controller, $settings) {
160
		$this->key = Configure::read('Security.salt');
161
		$this->_set($settings);
162
	}
163
/**
164
 * Start CookieComponent for use in the controller
165
 *
166
 * @access public
167
 */
168
	function startup() {
169
		$this->__expire($this->time);
170
 
171
		if (isset($_COOKIE[$this->name])) {
172
			$this->__values = $this->__decrypt($_COOKIE[$this->name]);
173
		}
174
	}
175
/**
176
 * Write a value to the $_COOKIE[$key];
177
 *
178
 * Optional [Name.], reguired key, optional $value, optional $encrypt, optional $expires
179
 * $this->Cookie->write('[Name.]key, $value);
180
 *
181
 * By default all values are encrypted.
182
 * You must pass $encrypt false to store values in clear test
183
 *
184
 * You must use this method before any output is sent to the browser.
185
 * Failure to do so will result in header already sent errors.
186
 *
187
 * @param mixed $key Key for the value
188
 * @param mixed $value Value
189
 * @param boolean $encrypt Set to true to encrypt value, false otherwise
190
 * @param string $expires Can be either Unix timestamp, or date string
191
 * @access public
192
 */
193
	function write($key, $value = null, $encrypt = true, $expires = null) {
194
		if (is_null($encrypt)) {
195
			$encrypt = true;
196
		}
197
 
198
		$this->__encrypted = $encrypt;
199
		$this->__expire($expires);
200
 
201
		if (!is_array($key) && $value !== null) {
202
			$name = $this->__cookieVarNames($key);
203
 
204
			if (count($name) > 1) {
205
				$this->__values[$name[0]][$name[1]] = $value;
206
				$this->__write("[".$name[0]."][".$name[1]."]", $value);
207
			} else {
208
				$this->__values[$name[0]] = $value;
209
				$this->__write("[".$name[0]."]", $value);
210
			}
211
		} else {
212
			foreach ($key as $names => $value) {
213
				$name = $this->__cookieVarNames($names);
214
 
215
				if (count($name) > 1) {
216
					$this->__values[$name[0]][$name[1]] = $value;
217
					$this->__write("[".$name[0]."][".$name[1]."]", $value);
218
				} else {
219
					$this->__values[$name[0]] = $value;
220
					$this->__write("[".$name[0]."]", $value);
221
				}
222
			}
223
		}
224
		$this->__encrypted = true;
225
	}
226
/**
227
 * Read the value of the $_COOKIE[$key];
228
 *
229
 * Optional [Name.], reguired key
230
 * $this->Cookie->read(Name.key);
231
 *
232
 * @param mixed $key Key of the value to be obtained. If none specified, obtain map key => values
233
 * @return string or null, value for specified key
234
 * @access public
235
 */
236
	function read($key = null) {
237
		if (empty($this->__values) && isset($_COOKIE[$this->name])) {
238
			$this->__values = $this->__decrypt($_COOKIE[$this->name]);
239
		}
240
 
241
		if (is_null($key)) {
242
			return $this->__values;
243
		}
244
		$name = $this->__cookieVarNames($key);
245
 
246
		if (count($name) > 1) {
247
			if (isset($this->__values[$name[0]])) {
248
				if (isset($this->__values[$name[0]][$name[1]])) {
249
					return $this->__values[$name[0]][$name[1]];
250
				}
251
			}
252
			return null;
253
		} else {
254
			if (isset($this->__values[$name[0]])) {
255
				$value = $this->__values[$name[0]];
256
				return $value;
257
			}
258
			return null;
259
		}
260
	}
261
/**
262
 * Delete a cookie value
263
 *
264
 * Optional [Name.], reguired key
265
 * $this->Cookie->read('Name.key);
266
 *
267
 * You must use this method before any output is sent to the browser.
268
 * Failure to do so will result in header already sent errors.
269
 *
270
 * @param string $key Key of the value to be deleted
271
 * @return void
272
 * @access public
273
 */
274
	function del($key) {
275
		if (empty($this->__values)) {
276
			$this->read();
277
		}
278
		$name = $this->__cookieVarNames($key);
279
		if (count($name) > 1) {
280
			if (isset($this->__values[$name[0]])) {
281
				$this->__delete("[".$name[0]."][".$name[1]."]");
282
				unset($this->__values[$name[0]][$name[1]]);
283
			}
284
		} else {
285
			if (isset($this->__values[$name[0]])) {
286
				if (is_array($this->__values[$name[0]])) {
287
					foreach ($this->__values[$name[0]] as $key => $value) {
288
						$this->__delete("[".$name[0]."][".$key."]");
289
					}
290
				}
291
				$this->__delete("[".$name[0]."]");
292
				unset($this->__values[$name[0]]);
293
			}
294
		}
295
	}
296
/**
297
 * Destroy current cookie
298
 *
299
 * You must use this method before any output is sent to the browser.
300
 * Failure to do so will result in header already sent errors.
301
 *
302
 * @return void
303
 * @access public
304
 */
305
	function destroy() {
306
		if (isset($_COOKIE[$this->name])) {
307
			$this->__values = $this->__decrypt($_COOKIE[$this->name]);
308
		}
309
 
310
		foreach ($this->__values as $name => $value) {
311
			if (is_array($value)) {
312
				foreach ($value as $key => $val) {
313
					unset($this->__values[$name][$key]);
314
					$this->__delete("[$name][$key]");
315
				}
316
			}
317
			unset($this->__values[$name]);
318
			$this->__delete("[$name]");
319
		}
320
	}
321
/**
322
 * Will allow overriding default encryption method.
323
 *
324
 * @param string $type Encryption method
325
 * @access public
326
 * @todo NOT IMPLEMENTED
327
 */
328
	function type($type = 'cipher') {
329
		$this->__type = 'cipher';
330
	}
331
/**
332
 * Set the expire time for a session variable.
333
 *
334
 * Creates a new expire time for a session variable.
335
 * $expire can be either integer Unix timestamp or a date string.
336
 *
337
 * Used by write()
338
 * CookieComponent::write(string, string, boolean, 8400);
339
 * CookieComponent::write(string, string, boolean, '5 Days');
340
 *
341
 * @param mixed $expires Can be either Unix timestamp, or date string
342
 * @return int Unix timestamp
343
 * @access private
344
 */
345
	function __expire($expires = null) {
346
		$now = time();
347
		if (is_null($expires)) {
348
			return $this->__expires;
349
		}
350
		$this->__reset = $this->__expires;
351
		if (is_integer($expires) || is_numeric($expires)) {
352
			return $this->__expires = $now + intval($expires);
353
		}
354
		return $this->__expires = strtotime($expires, $now);
355
	}
356
/**
357
 * Set cookie
358
 *
359
 * @param string $name Name for cookie
360
 * @param string $value Value for cookie
361
 * @access private
362
 */
363
	function __write($name, $value) {
364
		setcookie($this->name . "$name", $this->__encrypt($value), $this->__expires, $this->path, $this->domain, $this->secure);
365
 
366
		if (!is_null($this->__reset)) {
367
			$this->__expires = $this->__reset;
368
			$this->__reset = null;
369
		}
370
	}
371
/**
372
 * Sets a cookie expire time to remove cookie value
373
 *
374
 * @param string $name Name of cookie
375
 * @access private
376
 */
377
	function __delete($name) {
378
		setcookie($this->name . $name, '', time() - 42000, $this->path, $this->domain, $this->secure);
379
	}
380
/**
381
 * Encrypts $value using var $type method in Security class
382
 *
383
 * @param string $value Value to encrypt
384
 * @return string encrypted string
385
 * @access private
386
 */
387
	function __encrypt($value) {
388
		if (is_array($value)) {
389
			$value = $this->__implode($value);
390
		}
391
 
392
		if ($this->__encrypted === true) {
393
			$type = $this->__type;
394
			$value = "Q2FrZQ==." .base64_encode(Security::$type($value, $this->key));
395
		}
396
		return($value);
397
	}
398
/**
399
 * Decrypts $value using var $type method in Security class
400
 *
401
 * @param array $values Values to decrypt
402
 * @return string decrypted string
403
 * @access private
404
 */
405
	function __decrypt($values) {
406
		$decrypted = array();
407
		$type = $this->__type;
408
 
409
		foreach ($values as $name => $value) {
410
			if (is_array($value)) {
411
				foreach ($value as $key => $val) {
412
					$pos = strpos($val, 'Q2FrZQ==.');
413
					$decrypted[$name][$key] = $this->__explode($val);
414
 
415
					if ($pos !== false) {
416
						$val = substr($val, 8);
417
						$decrypted[$name][$key] = $this->__explode(Security::$type(base64_decode($val), $this->key));
418
					}
419
				}
420
			} else {
421
				$pos = strpos($value, 'Q2FrZQ==.');
422
				$decrypted[$name] = $this->__explode($value);
423
 
424
				if ($pos !== false) {
425
					$value = substr($value, 8);
426
					$decrypted[$name] = $this->__explode(Security::$type(base64_decode($value), $this->key));
427
				}
428
			}
429
		}
430
 
431
		return($decrypted);
432
	}
433
 
434
/**
435
 * Creates an array from the $name parameter which allows the dot notation
436
 * similar to one used by Session and Configure classes
437
 *
438
 * @param string $name Name with or without dot notation
439
 * @return array Extracted names
440
 * @access private
441
 */
442
	function __cookieVarNames($name) {
443
		if (is_string($name)) {
444
			if (strpos($name, ".")) {
445
				$name = explode(".", $name);
446
			} else {
447
				$name = array($name);
448
			}
449
		}
450
		return $name;
451
	}
452
/**
453
 * Implode method to keep keys are multidimensional arrays
454
 *
455
 * @param array $array Map of key and values
456
 * @return string String in the form key1|value1,key2|value2
457
 * @access private
458
 */
459
	function __implode($array) {
460
		$string = '';
461
		foreach ($array as $key => $value) {
462
			$string .= ',' . $key . '|' . $value;
463
		}
464
		return substr($string, 1);
465
	}
466
/**
467
 * Explode method to return array from string set in CookieComponent::__implode()
468
 *
469
 * @param string $string String in the form key1|value1,key2|value2
470
 * @return array Map of key and values
471
 * @access private
472
 */
473
	function __explode($string) {
474
		$array = array();
475
		foreach (explode(',', $string) as $pair) {
476
			$key = explode('|', $pair);
477
			if (!isset($key[1])) {
478
				return $key[0];
479
			}
480
			$array[$key[0]] = $key[1];
481
		}
482
		return $array;
483
	}
484
}
485
?>