Funções JavaScript getCookie

Eu encontrei duas funções para obter dados de cookies com Javascript, um em w3schools.com e um em quirksmode.org
Eu gostaria de saber qual deles devo usar?

Por exemplo, creio que li em algum lugar que houve um problema com alguns navegadores dividindo o ; ponto e vírgula?

w3schools:

 function getCookie(c_name) { if (document.cookie.length > 0) { c_start = document.cookie.indexOf(c_name + "="); if (c_start != -1) { c_start = c_start + c_name.length + 1; c_end = document.cookie.indexOf(";", c_start); if (c_end == -1) c_end = document.cookie.length; return unescape(document.cookie.substring(c_start, c_end)); } } return ""; } 

quirksmode:

 function readCokie(name) { var nameEQ = name + "="; var ca = document.cookie.split(';'); for(var i = 0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0) == ' ') c = c.substring(1, c.length); if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length); } return null; } 

A function do W3CSchool está errada. Ele falhará se houver vários cookies que tenham o mesmo sufixo, como:

 ffoo=bar; foo=baz 

Quando você procurar por foo ele retornará o valor de ffoo em vez de foo .

Agora aqui está o que eu faria: Primeiro de tudo, você precisa conhecer a syntax de como os cookies são transportados. A especificação original do Netscape (há apenas cópias disponíveis como esta em haxx.se ) usa ponto e vírgula para separar vários cookies, enquanto cada par nome / valor tem a seguinte syntax:

NAME = VALUE
Esta cadeia é uma seqüência de caracteres, excluindo ponto-e-vírgula, vírgula e espaço em branco. Se houver a necessidade de colocar tais dados no nome ou valor, algum método de codificação, como o estilo de URL %XX é recomendado, embora nenhuma codificação seja definida ou necessária.

Então dividir document.cookie string em ponto-e-vírgula ou vírgula é uma opção viável.

Além disso, o RFC 2109 também especifica que os cookies são separados por ponto-e-vírgula ou vírgula:

 cookie = "Cookie:" cookie-version 1*((";" | ",") cookie-value) cookie-value = NAME "=" VALUE [";" path] [";" domain] cookie-version = "$Version" "=" value NAME = attr VALUE = value path = "$Path" "=" value domain = "$Domain" "=" value 

Embora ambos sejam permitidos, as vírgulas são preferidas, pois são o separador padrão de itens de lista no HTTP.

Nota: Para compatibilidade com versões anteriores, o separador no header Cookie é ponto e vírgula ( ; ) em todos os lugares. Um servidor também deve aceitar vírgula ( , ) como separador entre valores de cookie para compatibilidade futura.

Além disso, o par nome / valor tem algumas restrições adicionais, pois o VALUE também pode ser uma string entre aspas conforme especificado no RFC 2616 :

 attr = token value = token | quoted-string 

Portanto, essas duas versões de cookie precisam ser tratadas separadamente:

 if (typeof String.prototype.trimLeft !== "function") { String.prototype.trimLeft = function() { return this.replace(/^\s+/, ""); }; } if (typeof String.prototype.trimRight !== "function") { String.prototype.trimRight = function() { return this.replace(/\s+$/, ""); }; } if (typeof Array.prototype.map !== "function") { Array.prototype.map = function(callback, thisArg) { for (var i=0, n=this.length, a=[]; i 1 ? decodeURIComponent(parts[1].trimRight()) : null; cookies[name] = value; }); } else { c.match(/(?:^|\s+)([!#$%&'*+\-.0-9A-Z^`az|~]+)=([!#$%&'*+\-.0-9A-Z^`az|~]*|"(?:[\x20-\x7E\x80\xFF]|\\[\x00-\x7F])*")(?=\s*[,;]|$)/g).map(function($0, $1) { var name = $0, value = $1.charAt(0) === '"' ? $1.substr(1, -1).replace(/\\(.)/g, "$1") : $1; cookies[name] = value; }); } return cookies; } function getCookie(name) { return getCookies()[name]; } 

Sim, a solução W3Schools está incorreta .

Para aqueles que gostariam, aqui está uma solução mais simples que funciona. Ele apenas preenche um espaço para que a única chamada para indexOf () retorne apenas o cookie correto.

 function getCookie(c_name) { var c_value = " " + document.cookie; var c_start = c_value.indexOf(" " + c_name + "="); if (c_start == -1) { c_value = null; } else { c_start = c_value.indexOf("=", c_start) + 1; var c_end = c_value.indexOf(";", c_start); if (c_end == -1) { c_end = c_value.length; } c_value = unescape(c_value.substring(c_start,c_end)); } return c_value; } 

Isso, da w3schools, é incorreto porque pode levar ao cookie errado:

 c_start = document.cookie.indexOf(c_name + "="); 

Se você procurar por um cookie chamado foo (que supomos ser um cookie existente), então em algum lugar em document.cookie estará a string foo=bar .

No entanto, não há garantia de que não haverá a string xfoo=something . Note que isto ainda contém substring foo= então o código w3schools irá encontrá-lo. E se o cookie xfoo for listado primeiro, você receberá de volta o valor de something (incorretamente!) Em vez da bar esperada.

Dada a escolha entre dois trechos de código, nunca vá com o que está fundamentalmente quebrado.

Todo o código mostrado acima é BROKEN. Os dois problemas comuns são (1) a function getcookie pode retornar o valor errado se um nome de cookie for um sufixo apropriado de outro nome de cookie; e (2) a function setcookie não protege o valor do cookie, o que significa que se o valor do cookie include (por exemplo) um “;” então todos os cookies estão corrompidos e não podem ser analisados.

TL; DR Use esta biblioteca bem escrita em vez disso: https://github.com/js-cookie/js-cookie