title: Cakephp 3 converting cakephp 2 cookies
body: <p>we need to read Cakephp 2 user cookies in Cakephp 3. But it seems like during update, <code>CakeCookie</code> tag was removed from cookies. So each Cakephp cookie is seperate. Regarding to <a href="https://github.com/cakephp/cakephp/issues/7030" rel="nofollow noreferrer">here</a>, Cakephp 3 can read old cookies if they were written with AES. But in old cakephp, default option was cipher and our cookies were written with cipher. So we can't read old cookies now. </p>
  
  <p>It's an option to read old cookies in Cakephp 2 and update them with AES. But when we update to Cakephp 3, there will be users that has Cakephp 2 cookies. So we need to check this inside Cakephp 3.</p>
  
  <p>We're planning that, in cakephp 3, read old cookies with cipher, and write their values to new cookies. We used code from Security cipher method, and created following code. </p>
  
  <p>Problem is, this code works well for strings, but it fails on some of the nested arrays. Problem can be plus sign, or any other encoding issues. Sometimes it works, sometimes it doesn't.</p>
  
  <p>I shared our code to show our process. You can propose another way to convert old cookies.</p>
  
  <pre><code>if (isset($_COOKIE['CakeCookie'])) {
      if (is_array($_COOKIE['CakeCookie'])) {
          foreach ($_COOKIE['CakeCookie'] as $key =&gt; $value) {
              $valueDecr=$this-&gt;decryptSaltedData($value);
              $this-&gt;Cookie-&gt;configKey($key, ['expires' =&gt; '+60 days']);
              $this-&gt;Cookie-&gt;write($key, $valueDecr);
  
              $this-&gt;Cookie-&gt;delete("CakeCookie[$key]");
              unset($_COOKIE['CakeCookie'][$key]);
              setcookie("CakeCookie[$key]", "aaa", time()-3600, '/');
              setcookie("CakeCookie[$key]", "aaa", time()-3600, '/', '.example.com');
          }
      }
  }
  
  public function decryptSaltedData($data) {
      $data2 = substr($data, 8);
      $text = base64_decode($data2);
      $key = Security::salt();
  
      $cipherSeed='45454545454545454545';
      srand($cipherSeed);
  
      $out = '';
      $keyLength = strlen($key);
      for ($i = 0, $textLength = strlen($text); $i &lt; $textLength; $i++) {
          $j = ord(substr($key, $i % $keyLength, 1));
          while ($j--) {
              rand(0, 255);
          }
          $mask = rand(0, 255);
          $out .= chr(ord(substr($text, $i, 1)) ^ $mask);
      }
      srand();
  
      $first = substr($out, 0, 1);
      if ($first === '{' || $first === '[') {
          $decoded = json_decode($out, true);
          if($decoded !== null) $out = $decoded;
      }
      return $out;
  }
  </code></pre>
  
  <h1>Solution:</h1>
  
  <p>After more tests we found out that the problem exists from a browser extension that changes cookies. So code above works well for converting Cakephp 2 cookies.</p>