Подтвердить что ты не робот

Функции javascript getCookie

Я нашел две функции для получения данных cookie с Javascript, один на w3schools.com и один на quirksmode.org
Я хотел бы знать, какой из них я должен использовать?

Например, я считаю, что где-то я читал, что была проблема с некоторыми браузерами, разделяющими точку с запятой ;?

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;
}
4b9b3361

Ответ 1

Функция из W3CSchool неверна. Он терпит неудачу, если есть несколько файлов cookie, которые имеют такой же суффикс, как:

ffoo=bar; foo=baz

При поиске foo он вернет значение ffoo вместо foo.

Теперь вот что я хотел бы сделать. Прежде всего, вам нужно узнать синтаксис того, как переносятся файлы cookie. Первоначальная спецификация Netscapes (есть только копии, доступные как этот в haxx.se) использует точки с запятой для разделения нескольких файлов cookie, в то время как каждая пара имен/значений имеет следующий синтаксис:

NAME = VALUE
Эта строка представляет собой последовательность символов, исключая запятую, запятую и пробел. Если необходимо поместить такие данные в имя или значение, рекомендуется использовать какой-либо метод кодирования, такой как кодировка URL style %XX, хотя никакая кодировка не определена или не требуется.

Таким образом, разбиение строки document.cookie на полуколоны или запятые является жизнеспособным вариантом.

Кроме того, RFC 2109 также указывает, что файлы cookie разделяются полуколониями или запятыми:

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

Хотя оба разрешены, запятые являются предпочтительными, поскольку они являются разделителями по умолчанию элементов списка в HTTP.

Примечание. Для обратной совместимости разделитель в заголовке файла cookie    является точкой с запятой (;). Сервер также должен принимать запятую (,)    как разделитель между значениями cookie для будущей совместимости.

Кроме того, пара имя/значение имеет некоторые дополнительные ограничения, поскольку VALUE также может быть кавычкой, указанной в RFC 2616:

attr        =     token
value       =     token | quoted-string

Итак, эти две версии файлов cookie нужно обрабатывать отдельно:

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<n; i++) {
            if (i in this) a[i] = callback.call(thisArg, this[i]);
        }
        return a;
    };
}
function getCookies() {
    var c = document.cookie, v = 0, cookies = {};
    if (document.cookie.match(/^\s*\$Version=(?:"1"|1);\s*(.*)/)) {
        c = RegExp.$1;
        v = 1;
    }
    if (v === 0) {
        c.split(/[,;]/).map(function(cookie) {
            var parts = cookie.split(/=/, 2),
                name = decodeURIComponent(parts[0].trimLeft()),
                value = parts.length > 1 ? decodeURIComponent(parts[1].trimRight()) : null;
            cookies[name] = value;
        });
    } else {
        c.match(/(?:^|\s+)([!#$%&'*+\-.0-9A-Z^`a-z|~]+)=([!#$%&'*+\-.0-9A-Z^`a-z|~]*|"(?:[\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];
}

Ответ 2

Да, решение W3Schools неверно.

Для тех, кто захочет, это более простое решение, которое работает. Он просто добавляет пробел, поэтому единственный вызов indexOf() возвращает только правильный файл cookie.

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;
}

Ответ 3

Это, из w3schools, неверно, поскольку это может привести к неправильному файлу cookie:

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

Если вы ищете файл cookie с именем foo (который мы предположим, это уже существующий файл cookie), то где-то в document.cookie будет строка foo=bar.

Однако нет никакой гарантии, что также не будет xfoo=something. Обратите внимание, что это все еще содержит подстроку foo=, поэтому код w3schools найдет ее. И если сначала будет указан файл cookie xfoo, вы вернете значение something (неверно!) Вместо ожидаемого bar.

Учитывая выбор между двумя частями кода, никогда не идете с тем, что фундаментально нарушено.

Ответ 4

Весь код, показанный выше, BROKEN. Две общие проблемы: (1) функция getcookie может возвращать неправильное значение, если одно имя файла cookie является надлежащим суффиксом другого имени cookie; и (2) функция setcookie не защищает значение cookie, а это означает, что если значение cookie включает (например) ";" то все файлы cookie повреждены и не могут быть проанализированы.

TL; DR Вместо этого используйте эту хорошо написанную библиотеку: https://github.com/js-cookie/js-cookie