Commit 866b8ef1 authored by Dave Barker's avatar Dave Barker 🐈

Merge branch 'master' back into 'next'

parents 5d311c91 ce593abf
Pipeline #75984153 failed with stages
in 6108 minutes
Hi,
You tried to submit a pull request for adblockpluschrome.
While we love GitHub, the project is hosted on GitLab, therefor we do
not monitor pull request submitted on GitHub.
Please visit: https://gitlab.com/eyeo/adblockplus/adblockpluschrome
Thank you.
\ No newline at end of file
......@@ -159,3 +159,8 @@ e8bad2822517e4c4c80af6a1af28a25432430e11 0.9.14-edge
83ffdfe7b359bd05ea10d64835e16273c31f6008 3.5.1-chrome-gecko
a830773f5663e006bbc4b07723793752fcecdd0b 3.5.2-chrome-gecko
488c131917daad22218b252735cff2276873c628 0.9.15-edge
282fe04eebea28badde09a520e09db11428b83e5 3.6-chrome-gecko
cea9fcb9a5460dc14d1b81cf1215e6b5c56035ef 0.9.16-edge
f20719cf745fdaacf3bd1236d5f7df569220b5fa 3.6.1-chrome-gecko
e7636970515d759ffe28251ae8e57bdab282e978 0.9.17-edge
64e9d22abdf68503f0513263046317b5ba244f0c 3.6.2-chrome-gecko
......@@ -2,4 +2,4 @@ _root = hg:https://hg.adblockplus.org/ git:https://github.com/adblockplus/
_self = buildtools/ensure_dependencies.py
buildtools = buildtools hg:0ebf8cd23b36 git:04d50e0
adblockpluscore = adblockpluscore hg:3c40e08b7eaa git:1ea9471
adblockplusui = adblockplusui hg:238bac6af317 git:b9a5480
adblockplusui = adblockplusui hg:bd03c7fd123e git:437d5cf
/*
* This file is part of Adblock Plus <https://adblockplus.org/>,
* Copyright (C) 2006-present eyeo GmbH
*
* Adblock Plus is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* Adblock Plus is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
*/
/** @module filterValidation */
"use strict";
const {Filter, InvalidFilter, ElemHideBase, ElemHideEmulationFilter,
ElemHideException} = require("../adblockpluscore/lib/filterClasses");
/**
* An error returned by
* {@link module:filterValidation.parseFilter parseFilter()} or
* {@link module:filterValidation.parseFilters parseFilters()}
* indicating that a given filter cannot be parsed,
* contains an invalid CSS selector or is a filter list header.
*
* @param {string} type See documentation in the constructor below.
* @param {Object} [details] Contains the "reason" and / or "selector"
* properties.
* @constructor
*/
function FilterParsingError(type, details)
{
/**
* Indicates why the filter is rejected. Possible choices:
* "invalid-filter", "invalid-css-selector", "unexpected-filter-list-header"
*
* @type {string}
*/
this.type = type;
if (details)
{
if ("reason" in details)
this.reason = details.reason;
if ("selector" in details)
this.selector = details.selector;
}
}
FilterParsingError.prototype = {
/**
* The line number the error occurred on if
* {@link module:filterValidation.parseFilters parseFilters()}
* were used. Or null if the error was returned by
* {@link module:filterValidation.parseFilter parseFilter()}.
*
* @type {?number}
*/
lineno: null,
/**
* Returns a detailed translated error message.
*
* @return {string}
*/
toString()
{
let message;
if (this.reason)
message = browser.i18n.getMessage(this.reason);
else
{
message = browser.i18n.getMessage(
this.type.replace(/-/g, "_"),
"selector" in this ? "'" + this.selector + "'" : null
);
}
if (this.lineno)
{
message = browser.i18n.getMessage(
"line", this.lineno.toLocaleString()
) + ": " + message;
}
return message;
}
};
function isValidCSSSelector(selector)
{
let style = document.createElement("style");
document.documentElement.appendChild(style);
let {sheet} = style;
document.documentElement.removeChild(style);
try
{
document.querySelector(selector);
sheet.insertRule(selector + "{}", 0);
}
catch (e)
{
return false;
}
return true;
}
function isValidFilterSelector(filter)
{
// Only ElemHideBase has selectors.
if (!(filter instanceof ElemHideBase))
return true;
// We don't check the syntax of ElemHideEmulationFilter yet.
if (filter instanceof ElemHideEmulationFilter)
return true;
// If it is an ElemHideException, and it has an extended CSS
// selector we don't validate and assume it is valid.
if (filter instanceof ElemHideException &&
filter.selector.includes(":-abp-"))
{
return true;
}
return isValidCSSSelector(filter.selector);
}
/**
* @typedef ParsedFilter
* @property {?Filter} [filter]
* The parsed filter if it is valid. Or null if the given string is empty.
* @property {FilterParsingError} [error]
* See {@link module:filterValidation~FilterParsingError FilterParsingError}
*/
let parseFilter =
/**
* Parses and validates a filter given by the user.
*
* @param {string} text
* @return {ParsedFilter}
*/
exports.parseFilter = text =>
{
let filter = null;
text = Filter.normalize(text);
if (text)
{
if (text[0] == "[")
return {error: new FilterParsingError("unexpected-filter-list-header")};
filter = Filter.fromText(text);
if (filter instanceof InvalidFilter)
{
return {error: new FilterParsingError("invalid-filter",
{reason: filter.reason})};
}
if (!isValidFilterSelector(filter))
{
return {error: new FilterParsingError("invalid-css-selector",
{selector: filter.selector})};
}
}
return {filter};
};
/**
* @typedef ParsedFilters
* @property {Filter[]} filters
* The parsed result without invalid filters.
* @property {FilterParsingError[]} errors
* See {@link module:filterValidation~FilterParsingError FilterParsingError}
*/
/**
* Parses and validates a newline-separated list of filters given by the user.
*
* @param {string} text
* @return {ParsedFilters}
*/
exports.parseFilters = text =>
{
let lines = text.split("\n");
let filters = [];
let errors = [];
for (let i = 0; i < lines.length; i++)
{
let {filter, error} = parseFilter(lines[i]);
if (filter)
filters.push(filter);
if (error)
{
error.lineno = i + 1;
errors.push(error);
}
}
return {filters, errors};
};
......@@ -50,7 +50,7 @@ let dataCorrupted = false;
*/
function detectFirstRun()
{
firstRun = filterStorage.subscriptionCount == 0;
firstRun = filterStorage.getSubscriptionCount() == 0;
if (firstRun && (!filterStorage.firstRun || Prefs.currentVersion))
reinitialized = true;
......
......@@ -89,7 +89,7 @@ port.on("filters.whitelist", message =>
let page = new ext.Page(message.tab);
let host = page.url.hostname.replace(/^www\./, "");
let filter = Filter.fromText("@@||" + host + "^$document");
if (filter.subscriptionCount && filter.disabled)
if (filterStorage.getSubscriptionCount(filter.text) && filter.disabled)
{
filter.disabled = false;
}
......@@ -108,7 +108,7 @@ port.on("filters.unwhitelist", message =>
while (filter)
{
filterStorage.removeFilter(filter);
if (filter.subscriptionCount)
if (filterStorage.getSubscriptionCount(filter.text))
filter.disabled = true;
filter = checkWhitelisted(page);
}
......
[general]
basename = adblockpluschrome
version = 3.5.2
version = 3.6.2
author = eyeo GmbH
backgroundScripts = polyfill.js
ext/common.js
......
......@@ -2,7 +2,7 @@
inherit = metadata.chrome
[general]
version = 0.9.15
version = 0.9.17
basename = adblockplusedge
app_id_release = EyeoGmbH.AdblockPlus
app_id_devbuild = EyeoGmbH.AdblockPlusdevelopmentbuild
......
"use strict";
{
const {parseFilter, parseFilters} = require("../../lib/filterValidation");
const {BlockingFilter,
ElemHideFilter,
CommentFilter} = require("../../adblockpluscore/lib/filterClasses");
QUnit.module("Filter validation");
test("Detecting invalid filters", () =>
{
equal(parseFilter("||example.com^$unknown").error.type, "invalid-filter",
"unknown option");
equal(parseFilter("[foobar]").error.type, "unexpected-filter-list-header",
"filter list header");
equal(parseFilter("##[foo").error.type, "invalid-css-selector",
"invalid selector");
ok(
/\b4\b/.test(parseFilters("!comment\r\n||example.com^\n\n##/").errors[0]),
"error contains corresponding line number"
);
});
test("Allowing valid filters", () =>
{
let text;
let filter;
text = "||example.com^";
({filter} = parseFilter(text));
ok(filter instanceof BlockingFilter, "blocking filter parsed");
equal(filter.text, text, "blocking filter text matches");
text = '##div:first-child a[src="http://example.com"] > .foo + #bar';
({filter} = parseFilter(text));
ok(filter instanceof ElemHideFilter, "elemhide filter parsed");
equal(filter.text, text, "elemhide filter text matches");
text = "! foo bar";
({filter} = parseFilter(text));
ok(filter instanceof CommentFilter, "comment filter parsed");
equal(filter.text, text, "comment filter text matches");
equal(parseFilter("").filter, null, "empty filter parsed as 'null'");
});
test("Normalizing filters", () =>
{
let ws = " \t\r\n";
let filterText = ws + "@@" + ws + "||" + ws + "example.com" + ws + "^" + ws;
equal(parseFilter(filterText).filter.text, "@@||example.com^",
"unnecessary spaces");
equal(parseFilter(ws).filter, null, "only spaces");
});
test("Parsing multiple filters", () =>
{
let result = parseFilters("||example.com^\n \n###foobar\r\n! foo bar\n");
equal(result.errors.length, 0, "no error occurred");
equal(result.filters.length, 3, "all filters parsed");
ok(result.filters[0] instanceof BlockingFilter, "1st filter is blocking");
equal(result.filters[0].text, "||example.com^", "1st filter text matches");
ok(result.filters[1] instanceof ElemHideFilter, "2nd filter is elemhide");
equal(result.filters[1].text, "###foobar", "2nd filter text matches");
ok(result.filters[2] instanceof CommentFilter, "3rd filter is comment");
equal(result.filters[2].text, "! foo bar", "3rd filter text matches");
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment