Path: csiph.com!weretis.net!feeder8.news.weretis.net!news.mb-net.net!open-news-network.org!.POSTED.178.197.213.187!not-for-mail From: Thomas 'PointedEars' Lahn Newsgroups: comp.lang.javascript Subject: Re: Create cookie from ID of tag Date: Fri, 26 Mar 2021 23:22:31 +0100 Organization: PointedEars Software (PES) Lines: 174 Message-ID: <2196370.ElGaqSPkdT@PointedEars.de> References: <06c15260-54cb-43fd-99f0-cba71b0caa36n@googlegroups.com> <01863a61-d1bf-47ec-9955-1a1579e9aca2n@googlegroups.com> <48e39d8c-ec2d-4759-8ddd-8ac063e510c3n@googlegroups.com> <2578953.mvXUDI8C0e@PointedEars.de> <4641170.31r3eYUQgx@PointedEars.de> Reply-To: Thomas 'PointedEars' Lahn Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8Bit Injection-Info: gwaiyur.mb-net.net; posting-host="178.197.213.187"; logging-data="29494"; mail-complaints-to="abuse@open-news-network.org" User-Agent: KNode/4.14.10 Cancel-Lock: sha1:PnczCWD0i4fZbNUSBn2p9dwsknA= Face: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAGFBMVEXTxa4RFk5dUWANED8PFEfy7+MGBiW+n3ZNF/QuAAACaElEQVQ4jVXUwVOcMBQG8Dc7Rc4PUntdWV2uxjDpGaGeozOp1woar4jd5t/v9wLstMwsA/ntlxdCAgUc1hjTc9/JCZfGoo3wG3HdmdAWrIJRHe7GM/TmpY5VFefuVcAkkPbLIaN8rmPmjloyZxgyR3GuJ4K0AGtJ2htz8o7yqikm759fldQXaMpbDzjKAG+8v+AugVTOPO5DOjLvGtUYQwh0CPjnVMyGd+8/GfUB5nLKJDD2aLDh5HYyMDJGDwQIo2ZmZcKbowNmAdB/AzyFhrmF2MHRb0QJJfaAnwGB6orZhoykLzJtGwF/xpYxI1dswomiUj3gTuAIqCn/4C7cULwGNBtwMTk3Y4LfKB5YUaOKBKYtpplm7u0vip8tU1NWWyI/7XdcSuIDoMt6rVHMWT0DbjHPGqDqZVSa6zleLcUTcIKLoMv3ueJluALtAo9B302zPPlrtiVScRdCjXvVh3e3JpYa/jjkuC9N+LrBMlz/eAN4eQijX2EdLo6c5tGGHwLyHFtXk89dDGHwCVhG9T0S/j55AhRZgkMCmUQXJ49TnS1wnQDvw0eAh9ICeMmEFbCnPMFzjAvsWoEWEFdYEx+S0MoUZ1gT1wId8+AF3Bl2OoEu906AUHx5VLw/gXYg/x84loOah/2UYNrgiwSwGO7RfUzVBbx/kgpckumGOi6QirtD6gkLTitbnxNol47S2jVc2vsN5kPqaAHT8uUdAJM4v/DanjYOwmUjWznGfwB7sGtAtor5BgofDuzaRj4kSQAqDakTsKORa3Q3xKi3gE1fhl71KRMqrdZ2AWNNg/YOhQyrVBnb+i+nEg4bsDA+egAAAABJRU5ErkJggg== X-User-ID: U2FsdGVkX1/aDEqLlMy8kZjufs+lZ/T2qSF5M6miEsVXoDcgGpnHVg== X-Face: %i>XG-yXR'\"2P/C_aO%~;2o~?g0pPKmbOw^=NT`tprDEf++D.m7"}HW6.#=U:?2GGctkL,f89@H46O$ASoW&?s}.k+&. Jon Ribbens wrote: >> On 2021-03-26, Thomas 'PointedEars' Lahn wrote: >>> That is *very* inefficient and error-prone. Consider this: >>> >>> function readCookie (name) >>> { >>> return ( >>> ( >>> document.cookie.split(';') >>> .map((cookie) => cookie.split('=')) >>> .filter((cookie) => cookie[0] == name) || [] >>> )[0] || [] >>> )[1]; >>> } >> >> Bear in mind this will fail on cookies whose values contain an '='. > > It will NOT fail, but it will return an incomplete value. > > It is possible indeed for a read cookie value to contain an unescaped “=” > character: > > document.cookie = 'foo=bar=baz'; > > creates a session cookie with the name “foo” and the value “bar=baz”, and > after that “document.cookie” contains the substring “bar=baz” unescaped > (in Chromium). > > Thank you for pointing that out. > > It is recommended to use the encodeURIComponent() function on the value to > compatibly avoid storing this and other problematic/forbidden cookie > values: > > document.cookie = 'foo=' + encodeURIComponent('bar=baz'); > > stores the value “bar%3Dbaz”. > > Correspondingly, decodeURIComponent() should be used then when reading > cookie values: > > This was poorly worded. I mean: It is recommended to use encodeURIComponent() to allow storing cookie values that would otherwise not be able to be stored, for example values containing “;”; this *also* avoids the problem of dealing with “=” because then there are no unescaped “=” in cookie values, and the escaped “=” do not have to be treated differently than the other escaped characters. It actually appears to be *necessary* to not simply split on “;”, but consider whitespace after “;”, so a RegExp SHOULD be used for splitting/matching. As I keep thinking about this, one would hope that after all this time that cookies have been around, and given my impression that cookies are not going away anytime soon, a standard DOM attribute and built-in property will finally be introduced to make dealing with cookies easier and less error- prone. I would suggest document.cookies for that. The Web IDL¹ for it could be (similar to the Storage interface²) [Exposed=Document] interface mixin DocumentStorage { readonly attribute Cookies cookies; } [Exposed=DocumentStorage] interface Cookies { readonly attribute unsigned long length; DOMString? name(unsigned long index); sequence names(); sequence values(); sequence > items(); getter DOMString? getItem(DOMString name); boolean hasItem(DOMString name); setter boolean setItem(DOMString name, DOMString value); setter boolean setItem(DOMString name, CookieAttributes attributes); deleter boolean removeItem(DOMString name); boolean clear(); } dictionary CookieAttributes { required DOMString value; DOMString path = Location::pathname; unsigned long? maxAge = null; /* default: end of session */ /* or unsigned long, but Date would be more convenient */ Date? expires = null; /* default: at the end of the session */ DOMString domain = Location::hostname; boolean secure = false; boolean sameSite = false; } Then we could finally simply write /* Get the number of readable cookies */ console.log(document.cookies.length); /* Get a cookie based on the order in which it was saved */ console.log(document.cookies[document.cookies.name(1)]); /* Retrieve all cookie names an Array */ console.log(document.cookies.names()); /* Retrieve all cookie values an Array */ console.log(document.cookies.values()); /* Retrieve all cookies as an object */ console.log(document.cookies.items()); /* Save/modify session cookie with name “foo” and value “bar=baz” */ document.cookies['foo'] = 'bar=baz'; /* equivalent to */ document.cookies.setItem('bla', 'bar=baz'); /* Save persistent secure cookie with name “bla” and value “bar=baz” */ document.cookies['bla'] = { value: 'bar=baz', expires: Date.tomorrow, /* “a man can dream, though” */ secure: true }; /* equivalent to */ document.cookies.setItem('bla', { value: 'bar=baz', expires: Date.tomorrow, /* “a man can dream, though” */ secure: true }); /* Read the cookie with name “foo” */ console.log(document.cookies['foo']); /* equivalent to */ console.log(document.cookies.getItem('foo')); /* Delete the cookie with name “foo” */ delete document.cookies['foo']; /* equivalent to */ document.cookies.removeItem('foo'); /* Delete all readable cookies for this URI */ document.cookies.clear(); instead of all the shebang with constructing and parsing strings. [In fact, it is already possible to use ECMAScript Ed. 6 features to implement this, although I would not recommend attempting to modify the document object (as it is a host object).] On the other hand, we have the Web Storage API.³ One major advantage of Storage over cookies, in addition to currently easier data handling, is that nothing of it is sent in the HTTP request; one major disadvantage of Storage over cookies is that the former does not provide for a mechanism to let data expire after a specific time: .localStorage stores the data forever (until explicitly deleted), and .sessionStorage only for the current session. As a result of the former, storage data can easily fill up the client’s disk space with garbage that is never discarded, especially as the length of a Storage item can be much longer than a cookie value. _______ ¹ ² ³ -- PointedEars FAQ: | | Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.