Skip to content

Commit

Permalink
Merge branch 'master' into feature/AG-27340-didomi-loader
Browse files Browse the repository at this point in the history
  • Loading branch information
slavaleleka committed Mar 12, 2024
2 parents 14d9d3f + 6709b30 commit 70be56a
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 15 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ The format is based on [Keep a Changelog], and this project adheres to [Semantic
### Changed

- Validation of scriptlet rules with no name and args for multiple scriptlet exception rules [#377]
- Cookie name is not encoded by cookie setting scriptlets [#408]

### Fixed

- UBO→ADG conversion of `$remove$` scriptlet param [#404]
- `set-constant` scriptlet not setting a constant over falsy values [#403]

[Unreleased]: https://github.com/AdguardTeam/Scriptlets/compare/v1.10.1...HEAD
[#408]: https://github.com/AdguardTeam/Scriptlets/issues/408
[#404]: https://github.com/AdguardTeam/Scriptlets/issues/404
[#403]: https://github.com/AdguardTeam/Scriptlets/issues/403
[#395]: https://github.com/AdguardTeam/Scriptlets/issues/395
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@adguard/scriptlets",
"version": "1.10.8",
"version": "1.10.9",
"description": "AdGuard's JavaScript library of Scriptlets and Redirect resources",
"scripts": {
"build": "babel-node -x .js,.ts scripts/build.js",
Expand Down
27 changes: 19 additions & 8 deletions src/helpers/cookie-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,37 @@ export const getCookiePath = (rawPath: string): string => {
/**
* Combines input cookie name, value, and path into string.
*
* @param rawName name argument of *set-cookie-* scriptlets
* @param name name argument of *set-cookie-* scriptlets
* @param rawValue value argument of *set-cookie-* scriptlets
* @param rawPath path argument of *set-cookie-* scriptlets
* @param shouldEncode if cookie's name and value should be encoded
* @param shouldEncodeValue if cookie value should be encoded. Default is `true`
*
* @returns string OR `null` if name or value is invalid
*/
export const concatCookieNameValuePath = (
rawName: string,
name: string,
rawValue: string,
rawPath: string,
shouldEncode = true,
shouldEncodeValue = true,
) => {
const COOKIE_BREAKER = ';';

// semicolon will cause the cookie to break
if (!shouldEncode && (rawName.includes(COOKIE_BREAKER) || `${rawValue}`.includes(COOKIE_BREAKER))) {
if ((!shouldEncodeValue && `${rawValue}`.includes(COOKIE_BREAKER))
|| name.includes(COOKIE_BREAKER)) {
return null;
}
const name = shouldEncode ? encodeURIComponent(rawName) : rawName;
const value = shouldEncode ? encodeURIComponent(rawValue) : rawValue;
return `${name}=${value}; ${getCookiePath(rawPath)};`;

const value = shouldEncodeValue ? encodeURIComponent(rawValue) : rawValue;

let resultCookie = `${name}=${value}`;

const path = getCookiePath(rawPath);
if (path) {
resultCookie += `; ${path}`;
}

return resultCookie;
};

/**
Expand Down
6 changes: 4 additions & 2 deletions src/scriptlets/set-cookie-reload.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ import {
* - `/` — root path
* - `none` — to set no path at all
*
* > Note that the scriptlet encodes cookie names and values,
* > e.g value `"{ test: 'value'}"` becomes `%7B%20test%3A%20'value'%7D`.
* > Note that the scriptlet does not encode a cookie name,
* > e.g. name 'a:b' will be set as 'a:b' and not as 'a%3Ab'.
* >
* > Also if a cookie name includes `;`, the cookie will not be set since this may cause the cookie to break.
*
* ### Examples
*
Expand Down
6 changes: 4 additions & 2 deletions src/scriptlets/set-cookie.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,10 @@ import {
* - `/` — root path
* - `none` — to set no path at all
*
* > Note that the scriptlet encodes cookie names and values,
* > e.g value `"{ test: 'value'}"` becomes `%7B%20test%3A%20'value'%7D`.
* > Note that the scriptlet does not encode a cookie name,
* > e.g. name 'a:b' will be set as 'a:b' and not as 'a%3Ab'.
* >
* > Also if a cookie name includes `;`, the cookie will not be set since this may cause the cookie to break.
*
* ### Examples
*
Expand Down
2 changes: 1 addition & 1 deletion src/scriptlets/trusted-set-cookie-reload.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export function trustedSetCookieReload(source, name, value, offsetExpiresSec = '
}

const expires = Date.now() + parsedOffsetMs;
cookieToSet += ` expires=${new Date(expires).toUTCString()};`;
cookieToSet += `; expires=${new Date(expires).toUTCString()}`;
}

document.cookie = cookieToSet;
Expand Down
2 changes: 1 addition & 1 deletion src/scriptlets/trusted-set-cookie.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export function trustedSetCookie(source, name, value, offsetExpiresSec = '', pat
}

const expires = Date.now() + parsedOffsetMs;
cookieToSet += ` expires=${new Date(expires).toUTCString()};`;
cookieToSet += `; expires=${new Date(expires).toUTCString()}`;
}

document.cookie = cookieToSet;
Expand Down
80 changes: 80 additions & 0 deletions tests/helpers/cookie-utils.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { concatCookieNameValuePath } from '../../src/helpers/cookie-utils';

describe('concatCookieNameValuePath', () => {
describe('encode cookie value', () => {
test.each([
{
actual: ['name', 'value', ''],
expected: 'name=value',
},
{
actual: ['name', 'value', '/'],
expected: 'name=value; path=/',
},
{
actual: ['pop::138', '138', ''],
// do not encode cookie name
// https://github.com/AdguardTeam/Scriptlets/issues/408
expected: 'pop::138=138',
},
{
actual: ['aa::bb::cc', '1', ''],
expected: 'aa::bb::cc=1',
},
// invalid path
{
actual: ['name', 'value', '/docs'],
// no path is set if unsupported path values passed
expected: 'name=value',
},
// invalid name because of ';'
{
actual: ['a;bc', 'def', ''],
expected: null,
},
// value with ';' but it should be encoded so its ok
{
actual: ['abc', 'de;f', ''],
expected: 'abc=de%3Bf',
},
])('$actual -> $expected', ({ actual, expected }) => {
expect(concatCookieNameValuePath(...actual)).toBe(expected);
});
});

describe('no cookie value encoding', () => {
test.each([
{
actual: ['name', 'value', ''],
expected: 'name=value',
},
{
actual: ['__test-cookie_expires', 'expires', '/'],
expected: '__test-cookie_expires=expires; path=/',
},
{
actual: ['aa::bb::cc', '1', ''],
expected: 'aa::bb::cc=1',
},
{
actual: ['__w_cc11', '{%22cookies_statistical%22:false%2C%22cookies_ad%22:true}', ''],
// do not encode cookie value
// https://github.com/AdguardTeam/Scriptlets/issues/311
expected: '__w_cc11={%22cookies_statistical%22:false%2C%22cookies_ad%22:true}',
},
// invalid name because of ';'
{
actual: ['a;bc', 'def', ''],
expected: null,
},
// invalid value because of ';' and it is not being encoded
{
actual: ['abc', 'de;f', ''],
expected: null,
},
])('$actual -> $expected', ({ actual, expected }) => {
// explicit 'false' to disable encoding
expect(concatCookieNameValuePath(...actual, false)).toBe(expected);
});
});
});

0 comments on commit 70be56a

Please sign in to comment.