CookieComponentTest.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  11. * @link https://cakephp.org CakePHP(tm) Project
  12. * @since 1.2.0
  13. * @license https://opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Test\TestCase\Controller\Component;
  16. use Cake\Controller\ComponentRegistry;
  17. use Cake\Controller\Component\CookieComponent;
  18. use Cake\Http\Response;
  19. use Cake\Http\ServerRequest;
  20. use Cake\I18n\Time;
  21. use Cake\TestSuite\TestCase;
  22. use Cake\Utility\Security;
  23. /**
  24. * CookieComponentTest class
  25. */
  26. class CookieComponentTest extends TestCase
  27. {
  28. /**
  29. * @var \Cake\Controller\Component\CookieComponent
  30. */
  31. protected $Cookie;
  32. /**
  33. * start
  34. *
  35. * @return void
  36. */
  37. public function setUp()
  38. {
  39. parent::setUp();
  40. $controller = $this->getMockBuilder('Cake\Controller\Controller')
  41. ->setMethods(['redirect'])
  42. ->setConstructorArgs([new ServerRequest(), new Response()])
  43. ->getMock();
  44. $controller->loadComponent('Cookie');
  45. $this->Controller = $controller;
  46. $this->Cookie = $controller->Cookie;
  47. $this->request = $controller->request;
  48. $this->Cookie->setConfig([
  49. 'expires' => '+10 seconds',
  50. 'path' => '/',
  51. 'domain' => '',
  52. 'secure' => false,
  53. 'key' => 'somerandomhaskeysomerandomhaskey',
  54. 'encryption' => false,
  55. ]);
  56. }
  57. /**
  58. * Test setting config per key.
  59. *
  60. * @return void
  61. */
  62. public function testConfigKey()
  63. {
  64. $this->Cookie->configKey('User', 'expires', '+3 days');
  65. $result = $this->Cookie->configKey('User');
  66. $expected = [
  67. 'expires' => '+3 days',
  68. 'path' => '/',
  69. 'domain' => '',
  70. 'key' => 'somerandomhaskeysomerandomhaskey',
  71. 'secure' => false,
  72. 'httpOnly' => false,
  73. 'encryption' => false,
  74. ];
  75. $this->assertEquals($expected, $result);
  76. }
  77. /**
  78. * Test setting config per key.
  79. *
  80. * @return void
  81. */
  82. public function testConfigKeyArray()
  83. {
  84. $this->Cookie->configKey('User', [
  85. 'expires' => '+3 days',
  86. 'path' => '/shop'
  87. ]);
  88. $result = $this->Cookie->configKey('User');
  89. $expected = [
  90. 'expires' => '+3 days',
  91. 'path' => '/shop',
  92. 'domain' => '',
  93. 'key' => 'somerandomhaskeysomerandomhaskey',
  94. 'secure' => false,
  95. 'httpOnly' => false,
  96. 'encryption' => false,
  97. ];
  98. $this->assertEquals($expected, $result);
  99. }
  100. /**
  101. * Test backwards compatibility with settings that use type juggling.
  102. *
  103. * @return void
  104. */
  105. public function testSettingsCompatibility()
  106. {
  107. $this->Cookie->setConfig([
  108. 'expires' => '+10 seconds',
  109. 'path' => '/',
  110. 'domain' => '',
  111. 'secure' => 0,
  112. 'key' => 'somerandomhaskeysomerandomhaskey',
  113. 'encryption' => 0,
  114. ]);
  115. $this->Cookie->write('key', 'value');
  116. $this->assertSame('value', $this->Cookie->read('key'));
  117. }
  118. /**
  119. * sets up some default cookie data.
  120. *
  121. * @return void
  122. */
  123. protected function _setCookieData()
  124. {
  125. $this->Cookie->write(['Encrypted_array' => ['name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!']]);
  126. $this->Cookie->write(['Encrypted_multi_cookies.name' => 'CakePHP']);
  127. $this->Cookie->write(['Encrypted_multi_cookies.version' => '1.2.0.x']);
  128. $this->Cookie->write(['Encrypted_multi_cookies.tag' => 'CakePHP Rocks!']);
  129. $this->Cookie->write(['Plain_array' => ['name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!']], null, false);
  130. $this->Cookie->write(['Plain_multi_cookies.name' => 'CakePHP'], null, false);
  131. $this->Cookie->write(['Plain_multi_cookies.version' => '1.2.0.x'], null, false);
  132. $this->Cookie->write(['Plain_multi_cookies.tag' => 'CakePHP Rocks!'], null, false);
  133. }
  134. /**
  135. * test that initialize sets settings from components array
  136. *
  137. * @return void
  138. */
  139. public function testSettings()
  140. {
  141. $settings = [
  142. 'time' => '5 days',
  143. 'path' => '/'
  144. ];
  145. $Cookie = new CookieComponent(new ComponentRegistry(), $settings);
  146. $this->assertEquals($Cookie->getConfig('time'), $settings['time']);
  147. $this->assertEquals($Cookie->getConfig('path'), $settings['path']);
  148. }
  149. /**
  150. * Test read when an invalid cipher is configured.
  151. *
  152. * @return void
  153. */
  154. public function testReadInvalidCipher()
  155. {
  156. $this->expectException(\RuntimeException::class);
  157. $this->expectExceptionMessage('Invalid encryption cipher. Must be one of aes, rijndael.');
  158. $this->Controller->request = $this->request->withCookieParams([
  159. 'Test' => $this->_encrypt('value'),
  160. ]);
  161. $this->Cookie->setConfig('encryption', 'derp');
  162. $this->Cookie->read('Test');
  163. }
  164. /**
  165. * testReadEncryptedCookieData
  166. *
  167. * @return void
  168. */
  169. public function testReadEncryptedCookieData()
  170. {
  171. $this->_setCookieData();
  172. $data = $this->Cookie->read('Encrypted_array');
  173. $expected = ['name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'];
  174. $this->assertEquals($expected, $data);
  175. $data = $this->Cookie->read('Encrypted_multi_cookies');
  176. $expected = ['name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'];
  177. $this->assertEquals($expected, $data);
  178. }
  179. /**
  180. * testReadPlainCookieData
  181. *
  182. * @return void
  183. */
  184. public function testReadPlainCookieData()
  185. {
  186. $this->_setCookieData();
  187. $data = $this->Cookie->read('Plain_array');
  188. $expected = ['name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'];
  189. $this->assertEquals($expected, $data);
  190. $data = $this->Cookie->read('Plain_multi_cookies');
  191. $expected = ['name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'];
  192. $this->assertEquals($expected, $data);
  193. }
  194. /**
  195. * test read() after switching the cookie name.
  196. *
  197. * @return void
  198. */
  199. public function testReadMultipleNames()
  200. {
  201. $this->Controller->request = $this->request->withCookieParams([
  202. 'CakeCookie' => [
  203. 'key' => 'value'
  204. ],
  205. 'OtherCookie' => [
  206. 'key' => 'other value'
  207. ]
  208. ]);
  209. $this->assertEquals('value', $this->Cookie->read('CakeCookie.key'));
  210. $this->assertEquals(['key' => 'value'], $this->Cookie->read('CakeCookie'));
  211. $this->assertEquals('other value', $this->Cookie->read('OtherCookie.key'));
  212. }
  213. /**
  214. * test a simple write()
  215. *
  216. * @return void
  217. */
  218. public function testWriteSimple()
  219. {
  220. $this->Cookie->write('Testing', 'value');
  221. $result = $this->Cookie->read('Testing');
  222. $this->assertEquals('value', $result);
  223. }
  224. /**
  225. * Test write when an invalid cipher is configured.
  226. *
  227. * @return void
  228. */
  229. public function testWriteInvalidCipher()
  230. {
  231. $this->expectException(\RuntimeException::class);
  232. $this->expectExceptionMessage('Invalid encryption cipher. Must be one of aes, rijndael.');
  233. $this->Cookie->setConfig('encryption', 'derp');
  234. $this->Cookie->write('Test', 'nope');
  235. }
  236. /**
  237. * Test writes don't omit request data from being read.
  238. *
  239. * @return void
  240. */
  241. public function testWriteThanRead()
  242. {
  243. $this->Controller->request = $this->request->withCookieParams([
  244. 'User' => ['name' => 'mark']
  245. ]);
  246. $this->Cookie->write('Testing', 'value');
  247. $this->assertEquals('mark', $this->Cookie->read('User.name'));
  248. }
  249. /**
  250. * test write() encrypted data with falsey value
  251. *
  252. * @return void
  253. */
  254. public function testWriteWithFalseyValue()
  255. {
  256. $this->Cookie->setConfig([
  257. 'encryption' => 'aes',
  258. 'key' => 'qSI232qs*&sXOw!adre@34SAv!@*(XSL#$%)asGb$@11~_+!@#HKis~#^',
  259. ]);
  260. $this->Cookie->write('Testing');
  261. $result = $this->Cookie->read('Testing');
  262. $this->assertNull($result);
  263. $this->Cookie->write('Testing', '');
  264. $result = $this->Cookie->read('Testing');
  265. $this->assertEquals('', $result);
  266. $this->Cookie->write('Testing', false);
  267. $result = $this->Cookie->read('Testing');
  268. $this->assertFalse($result);
  269. $this->Cookie->write('Testing', 1);
  270. $result = $this->Cookie->read('Testing');
  271. $this->assertEquals(1, $result);
  272. $this->Cookie->write('Testing', '0');
  273. $result = $this->Cookie->read('Testing');
  274. $this->assertSame('0', $result);
  275. $this->Cookie->write('Testing', 0);
  276. $result = $this->Cookie->read('Testing');
  277. $this->assertSame(0, $result);
  278. }
  279. /**
  280. * test write with distant future cookies
  281. *
  282. * @return void
  283. */
  284. public function testWriteFarFuture()
  285. {
  286. $this->Cookie->configKey('Testing', 'expires', '+90 years');
  287. $this->Cookie->write('Testing', 'value');
  288. $future = new Time('now');
  289. $future = $future->modify('+90 years');
  290. $expected = [
  291. 'name' => 'Testing',
  292. 'value' => 'value',
  293. 'path' => '/',
  294. 'domain' => '',
  295. 'secure' => false,
  296. 'httpOnly' => false];
  297. $result = $this->Controller->response->getCookie('Testing');
  298. $this->assertEquals($future->format('U'), $result['expire'], '', 3);
  299. unset($result['expire']);
  300. $this->assertEquals($expected, $result);
  301. }
  302. /**
  303. * test write with httpOnly cookies
  304. *
  305. * @return void
  306. */
  307. public function testWriteHttpOnly()
  308. {
  309. $this->Cookie->setConfig([
  310. 'httpOnly' => true,
  311. 'secure' => false
  312. ]);
  313. $this->Cookie->write('Testing', 'value', false);
  314. $expected = [
  315. 'name' => 'Testing',
  316. 'value' => 'value',
  317. 'expire' => (new Time('+10 seconds'))->format('U'),
  318. 'path' => '/',
  319. 'domain' => '',
  320. 'secure' => false,
  321. 'httpOnly' => true];
  322. $result = $this->Controller->response->getCookie('Testing');
  323. $this->assertEquals($expected, $result);
  324. }
  325. /**
  326. * Test writing multiple nested keys when some are encrypted.
  327. *
  328. * @return void
  329. */
  330. public function testWriteMulitMixedEncryption()
  331. {
  332. $this->Cookie->configKey('Open', 'encryption', false);
  333. $this->Cookie->configKey('Closed', 'encryption', 'aes');
  334. $this->Cookie->write([
  335. 'Closed.key' => 'secret',
  336. 'Open.key' => 'not secret',
  337. ]);
  338. $expected = [
  339. 'name' => 'Open',
  340. 'value' => '{"key":"not secret"}',
  341. 'path' => '/',
  342. 'domain' => '',
  343. 'secure' => false,
  344. 'httpOnly' => false
  345. ];
  346. $result = $this->Controller->response->getCookie('Open');
  347. unset($result['expire']);
  348. $this->assertEquals($expected, $result);
  349. $result = $this->Controller->response->getCookie('Closed');
  350. $this->assertContains('Q2FrZQ==.', $result['value']);
  351. }
  352. /**
  353. * Test writing with a custom encryption key using ConfigKey
  354. *
  355. * @return void
  356. */
  357. public function testWriteConfigKeyWithCustomEncryptionKey()
  358. {
  359. $name = 'sampleCookieTest';
  360. $value = 'some data';
  361. $encryption = 'aes';
  362. $prefix = 'Q2FrZQ==.';
  363. $key = 'justanotherencryptionkeyjustanotherencryptionkey';
  364. $this->Cookie->configKey($name, compact('key', 'encryption'));
  365. $this->Cookie->write($name, $value);
  366. $cookie = $this->Controller->response->getCookie($name);
  367. $this->assertEquals($value, Security::decrypt(base64_decode(substr($cookie['value'], strlen($prefix))), $key));
  368. }
  369. /**
  370. * Test reading with a custom encryption key using ConfigKey
  371. *
  372. * @return void
  373. */
  374. public function testReadConfigKeyWithCustomEncryptionKey()
  375. {
  376. $name = 'sampleCookieTest';
  377. $value = 'some data';
  378. $encryption = 'aes';
  379. $key = 'justanotherencryptionkeyjustanotherencryptionkey';
  380. $this->Cookie->configKey($name, compact('key', 'encryption'));
  381. $this->Cookie->write($name, $value);
  382. $this->assertEquals('some data', $this->Cookie->read($name));
  383. }
  384. /**
  385. * test delete with httpOnly
  386. *
  387. * @return void
  388. */
  389. public function testDeleteHttpOnly()
  390. {
  391. $this->Cookie->setConfig([
  392. 'httpOnly' => true,
  393. 'secure' => false
  394. ]);
  395. $this->Cookie->delete('Testing');
  396. $expected = [
  397. 'name' => 'Testing',
  398. 'value' => '',
  399. 'expire' => (new Time('now'))->format('U') - 42000,
  400. 'path' => '/',
  401. 'domain' => '',
  402. 'secure' => false,
  403. 'httpOnly' => true];
  404. $result = $this->Controller->response->getCookie('Testing');
  405. $this->assertEquals($expected, $result);
  406. }
  407. /**
  408. * test writing values that are not scalars
  409. *
  410. * @return void
  411. */
  412. public function testWriteArrayValues()
  413. {
  414. $this->Cookie->write('Testing', [1, 2, 3]);
  415. $expected = [
  416. 'name' => 'Testing',
  417. 'value' => '[1,2,3]',
  418. 'path' => '/',
  419. 'domain' => '',
  420. 'secure' => false,
  421. 'httpOnly' => false
  422. ];
  423. $result = $this->Controller->response->getCookie('Testing');
  424. $time = new Time('now');
  425. $this->assertWithinRange($time->format('U') + 10, $result['expire'], 1);
  426. unset($result['expire']);
  427. $this->assertEquals($expected, $result);
  428. }
  429. /**
  430. * Test that writing mixed arrays results in the correct data.
  431. *
  432. * @return void
  433. */
  434. public function testWriteMixedArray()
  435. {
  436. $this->Cookie->write('User', ['name' => 'mark'], false);
  437. $this->Cookie->write('User.email', 'mark@example.com', false);
  438. $expected = [
  439. 'name' => 'User',
  440. 'value' => '{"name":"mark","email":"mark@example.com"}',
  441. 'path' => '/',
  442. 'domain' => '',
  443. 'secure' => false,
  444. 'httpOnly' => false
  445. ];
  446. $result = $this->Controller->response->getCookie('User');
  447. unset($result['expire']);
  448. $this->assertEquals($expected, $result);
  449. $this->Cookie->write('User.email', 'mark@example.com', false);
  450. $this->Cookie->write('User', ['name' => 'mark'], false);
  451. $expected = [
  452. 'name' => 'User',
  453. 'value' => '{"name":"mark"}',
  454. 'path' => '/',
  455. 'domain' => '',
  456. 'secure' => false,
  457. 'httpOnly' => false
  458. ];
  459. $result = $this->Controller->response->getCookie('User');
  460. unset($result['expire']);
  461. $this->assertEquals($expected, $result);
  462. }
  463. /**
  464. * testDeleteCookieValue
  465. *
  466. * @return void
  467. */
  468. public function testDeleteCookieValue()
  469. {
  470. $this->_setCookieData();
  471. $this->Cookie->delete('Encrypted_multi_cookies.name');
  472. $data = $this->Cookie->read('Encrypted_multi_cookies');
  473. $expected = ['version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'];
  474. $this->assertEquals($expected, $data);
  475. $this->Cookie->delete('Encrypted_array');
  476. $data = $this->Cookie->read('Encrypted_array');
  477. $this->assertNull($data);
  478. $this->Cookie->delete('Plain_multi_cookies.name');
  479. $data = $this->Cookie->read('Plain_multi_cookies');
  480. $expected = ['version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'];
  481. $this->assertEquals($expected, $data);
  482. $this->Cookie->delete('Plain_array');
  483. $data = $this->Cookie->read('Plain_array');
  484. $this->assertNull($data);
  485. }
  486. /**
  487. * testReadingCookieArray
  488. *
  489. * @return void
  490. */
  491. public function testReadingCookieArray()
  492. {
  493. $this->_setCookieData();
  494. $data = $this->Cookie->read('Encrypted_array.name');
  495. $expected = 'CakePHP';
  496. $this->assertEquals($expected, $data);
  497. $data = $this->Cookie->read('Encrypted_array.version');
  498. $expected = '1.2.0.x';
  499. $this->assertEquals($expected, $data);
  500. $data = $this->Cookie->read('Encrypted_array.tag');
  501. $expected = 'CakePHP Rocks!';
  502. $this->assertEquals($expected, $data);
  503. $data = $this->Cookie->read('Encrypted_multi_cookies.name');
  504. $expected = 'CakePHP';
  505. $this->assertEquals($expected, $data);
  506. $data = $this->Cookie->read('Encrypted_multi_cookies.version');
  507. $expected = '1.2.0.x';
  508. $this->assertEquals($expected, $data);
  509. $data = $this->Cookie->read('Encrypted_multi_cookies.tag');
  510. $expected = 'CakePHP Rocks!';
  511. $this->assertEquals($expected, $data);
  512. $data = $this->Cookie->read('Plain_array.name');
  513. $expected = 'CakePHP';
  514. $this->assertEquals($expected, $data);
  515. $data = $this->Cookie->read('Plain_array.version');
  516. $expected = '1.2.0.x';
  517. $this->assertEquals($expected, $data);
  518. $data = $this->Cookie->read('Plain_array.tag');
  519. $expected = 'CakePHP Rocks!';
  520. $this->assertEquals($expected, $data);
  521. $data = $this->Cookie->read('Plain_multi_cookies.name');
  522. $expected = 'CakePHP';
  523. $this->assertEquals($expected, $data);
  524. $data = $this->Cookie->read('Plain_multi_cookies.version');
  525. $expected = '1.2.0.x';
  526. $this->assertEquals($expected, $data);
  527. $data = $this->Cookie->read('Plain_multi_cookies.tag');
  528. $expected = 'CakePHP Rocks!';
  529. $this->assertEquals($expected, $data);
  530. }
  531. /**
  532. * testReadingCookieDataOnStartup
  533. *
  534. * @return void
  535. */
  536. public function testReadingDataFromRequest()
  537. {
  538. $this->Cookie->configKey('Encrypted_array', 'encryption', 'aes');
  539. $this->Cookie->configKey('Encrypted_multi_cookies', 'encryption', 'aes');
  540. $data = $this->Cookie->read('Encrypted_array');
  541. $this->assertNull($data);
  542. $data = $this->Cookie->read('Encrypted_multi_cookies');
  543. $this->assertNull($data);
  544. $data = $this->Cookie->read('Plain_array');
  545. $this->assertNull($data);
  546. $data = $this->Cookie->read('Plain_multi_cookies');
  547. $this->assertNull($data);
  548. $this->Controller->request = $this->request->withCookieParams([
  549. 'Encrypted_array' => $this->_encrypt(['name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!']),
  550. 'Encrypted_multi_cookies' => [
  551. 'name' => $this->_encrypt('CakePHP'),
  552. 'version' => $this->_encrypt('1.2.0.x'),
  553. 'tag' => $this->_encrypt('CakePHP Rocks!')
  554. ],
  555. 'Plain_array' => '{"name":"CakePHP","version":"1.2.0.x","tag":"CakePHP Rocks!"}',
  556. 'Plain_multi_cookies' => [
  557. 'name' => 'CakePHP',
  558. 'version' => '1.2.0.x',
  559. 'tag' => 'CakePHP Rocks!'
  560. ]
  561. ]);
  562. $data = $this->Cookie->read('Encrypted_array');
  563. $expected = ['name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'];
  564. $this->assertEquals($expected, $data);
  565. $data = $this->Cookie->read('Encrypted_multi_cookies');
  566. $expected = ['name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'];
  567. $this->assertEquals($expected, $data);
  568. $data = $this->Cookie->read('Plain_array');
  569. $expected = ['name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'];
  570. $this->assertEquals($expected, $data);
  571. $data = $this->Cookie->read('Plain_multi_cookies');
  572. $expected = ['name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'];
  573. $this->assertEquals($expected, $data);
  574. }
  575. /**
  576. * Test Reading legacy cookie values.
  577. *
  578. * @return void
  579. */
  580. public function testReadLegacyCookieValue()
  581. {
  582. $this->Controller->request = $this->request->withCookieParams([
  583. 'Legacy' => ['value' => $this->_oldImplode([1, 2, 3])]
  584. ]);
  585. $result = $this->Cookie->read('Legacy.value');
  586. $expected = [1, 2, 3];
  587. $this->assertEquals($expected, $result);
  588. }
  589. /**
  590. * Test reading empty values.
  591. *
  592. * @return void
  593. */
  594. public function testReadEmpty()
  595. {
  596. $this->Controller->request = $this->request->withCookieParams([
  597. 'JSON' => '{"name":"value"}',
  598. 'Empty' => '',
  599. 'String' => '{"somewhat:"broken"}',
  600. 'Array' => '{}'
  601. ]);
  602. $this->assertEquals(['name' => 'value'], $this->Cookie->read('JSON'));
  603. $this->assertEquals('value', $this->Cookie->read('JSON.name'));
  604. $this->assertEquals('', $this->Cookie->read('Empty'));
  605. $this->assertEquals('{"somewhat:"broken"}', $this->Cookie->read('String'));
  606. $this->assertEquals([], $this->Cookie->read('Array'));
  607. }
  608. /**
  609. * testCheck method
  610. *
  611. * @return void
  612. */
  613. public function testCheck()
  614. {
  615. $this->Cookie->write('CookieComponentTestCase', 'value');
  616. $this->assertTrue($this->Cookie->check('CookieComponentTestCase'));
  617. $this->assertFalse($this->Cookie->check('NotExistingCookieComponentTestCase'));
  618. }
  619. /**
  620. * testCheckingSavedEmpty method
  621. *
  622. * @return void
  623. */
  624. public function testCheckingSavedEmpty()
  625. {
  626. $this->Cookie->write('CookieComponentTestCase', 0);
  627. $this->assertTrue($this->Cookie->check('CookieComponentTestCase'));
  628. $this->Cookie->write('CookieComponentTestCase', '0');
  629. $this->assertTrue($this->Cookie->check('CookieComponentTestCase'));
  630. }
  631. /**
  632. * testCheckKeyWithSpaces method
  633. *
  634. * @return void
  635. */
  636. public function testCheckKeyWithSpaces()
  637. {
  638. $this->Cookie->write('CookieComponent Test', 'test');
  639. $this->assertTrue($this->Cookie->check('CookieComponent Test'));
  640. $this->Cookie->delete('CookieComponent Test');
  641. $this->Cookie->write('CookieComponent Test.Test Case', 'test');
  642. $this->assertTrue($this->Cookie->check('CookieComponent Test.Test Case'));
  643. }
  644. /**
  645. * testCheckEmpty
  646. *
  647. * @return void
  648. */
  649. public function testCheckEmpty()
  650. {
  651. $this->assertFalse($this->Cookie->check());
  652. }
  653. /**
  654. * test that deleting a top level keys kills the child elements too.
  655. *
  656. * @return void
  657. */
  658. public function testDeleteRemovesChildren()
  659. {
  660. $this->Controller->request = $this->request->withCookieParams([
  661. 'User' => ['email' => 'example@example.com', 'name' => 'mark'],
  662. 'other' => 'value'
  663. ]);
  664. $this->assertEquals('mark', $this->Cookie->read('User.name'));
  665. $this->Cookie->delete('User');
  666. $this->assertNull($this->Cookie->read('User.email'));
  667. $this->assertNull($this->Cookie->read('User.name'));
  668. $result = $this->Controller->response->getCookie('User');
  669. $this->assertEquals('', $result['value']);
  670. $this->assertLessThan(time(), $result['expire']);
  671. }
  672. /**
  673. * Test deleting recursively with keys that don't exist.
  674. *
  675. * @return void
  676. */
  677. public function testDeleteChildrenNotExist()
  678. {
  679. $this->assertNull($this->Cookie->delete('NotFound'));
  680. $this->assertNull($this->Cookie->delete('Not.Found'));
  681. }
  682. /**
  683. * Helper method for generating old style encoded cookie values.
  684. *
  685. * @param array $array
  686. * @return string
  687. */
  688. protected function _oldImplode(array $array)
  689. {
  690. $string = '';
  691. foreach ($array as $key => $value) {
  692. $string .= ',' . $key . '|' . $value;
  693. }
  694. return substr($string, 1);
  695. }
  696. /**
  697. * Implode method to keep keys are multidimensional arrays
  698. *
  699. * @param array $array Map of key and values
  700. * @return string String in the form key1|value1,key2|value2
  701. */
  702. protected function _implode(array $array)
  703. {
  704. return json_encode($array);
  705. }
  706. /**
  707. * encrypt method
  708. *
  709. * @param array|string $value
  710. * @return string
  711. */
  712. protected function _encrypt($value)
  713. {
  714. if (is_array($value)) {
  715. $value = $this->_implode($value);
  716. }
  717. return 'Q2FrZQ==.' . base64_encode(Security::encrypt($value, $this->Cookie->getConfig('key')));
  718. }
  719. }