diff options
Diffstat (limited to '.config/luakit/adblock.lua')
| -rw-r--r-- | .config/luakit/adblock.lua | 563 |
1 files changed, 0 insertions, 563 deletions
diff --git a/.config/luakit/adblock.lua b/.config/luakit/adblock.lua deleted file mode 100644 index 6f5ca17..0000000 --- a/.config/luakit/adblock.lua +++ /dev/null @@ -1,563 +0,0 @@ ------------------------------------------------------------------------- --- Simple URI-based content filter v0.3.1a -- --- (C) 2010 Chris van Dijk (quigybo) <quigybo@hotmail.com> -- --- (C) 2010 Mason Larobina (mason-l) <mason.larobina@gmail.com> -- --- © 2012 Plaque FCC <Reslayer@ya.ru> -- --- © 2010 adblock chromepage from bookmarks.lua by Henning Hasemann & -- --- Mason Larobina taken by Plaque FCC. -- --- -- --- Download an Adblock Plus compatible filter lists to luakit data -- --- dir into "/adblock/" directory for multiple lists support or into -- --- data dir root to use single file. EasyList is the most popular -- --- Adblock Plus filter list: http://easylist.adblockplus.org/ -- --- Filterlists need to be updated regularly (~weekly), use cron! -- ------------------------------------------------------------------------- - -local info = info -local pairs = pairs -local ipairs = ipairs -local assert = assert -local unpack = unpack -local type = type -local io = io -local os = os -local string = string -local table = table -local tostring = tostring -local tonumber = tonumber -local webview = webview -local lousy = require("lousy") -local util = lousy.util -local chrome = require("chrome") -local capi = { luakit = luakit } -local add_binds, add_cmds = add_binds, add_cmds -local lfs = require("lfs") -local window = window - - -module("adblock") - ---- Module global variables -local enabled = true --- Adblock Plus compatible filter lists -local adblock_dir = capi.luakit.data_dir .. "/adblock/" - -local filterfiles = {} -local simple_mode = false -local subscriptions_file = adblock_dir .. "/subscriptions" -subscriptions = {} - - - --- String patterns to filter URI's with -rules = {} - --- Functions to filter URI's by --- Return true or false to allow or block respectively, nil to continue matching -local filterfuncs = {} - --- Fitting for adblock.chrome.refresh_views() -refresh_views = function() - -- Dummy. -end - --- Enable or disable filtering -enable = function () - enabled = true - refresh_views() -end -disable = function () - enabled = false - refresh_views() -end - --- Report AdBlock state: «Enabled» or «Disabled» -state = function() - if enabled then - return "Enabled" - else - return "Disabled" - end -end - -mode = function() - if simple_mode then - return "simple" - else - return "normal" - end -end - --- Detect files to read rules from -function detect_files() - local curdir = lfs.currentdir() - -- Try to find subscriptions directory: - if not lfs.chdir(adblock_dir) then - lfs.mkdir(adblock_dir) - else - simple_mode = false - -- Look for filters lists: - lfs.chdir(curdir) - for filename in lfs.dir(adblock_dir) do - if string.find(filename, ".txt$") then - info("adblock: Found adblock list: " .. filename) - table.insert(filterfiles, filename) - end - end - end - - if table.maxn(filterfiles) < 1 then - simple_mode = true - filterfiles = { "/easylist.txt" } - end - - if not simple_mode then - info( "adblock: Found " .. table.maxn(filterfiles) .. " rules lists.\n" ) - end - - return -end - -local function get_abp_opts(s) - local opts = {} - local pos = string.find(s, "%$") - if pos then - local op = string.sub(s, pos+1) - s = string.sub(s, 1, pos-1) - for key in string.gmatch(op, "[^,]+") do - local val - local pos = string.find(key, "=") - if pos then - val = string.sub(key, pos+1) - key = string.sub(key, 1, pos-1) - end - - local negative = false - if string.sub(key, 1, 1) == "~" then - negative = true - key = string.sub(key, 2) - end - - if key == "domain" and val then - local domains = {} - for v in string.gmatch(val, "[^|]+") do - table.insert(domains, v) - end - if #domains > 0 then opts["domain"] = domains end - elseif key == "third-party" then - opts["third-party"] = not negative - else - opts["unknown"] = true - end - end - end - return s, opts -end - --- Convert Adblock Plus filter description to lua string pattern --- See http://adblockplus.org/en/filters for more information -abp_to_pattern = function (s) - -- Strip filter options - local opts - s, opts = get_abp_opts(s) - if opts and opts.unknown == true then return nil end -- Skip rules with unknown options - - if string.len(s) > 0 then - -- Protect magic characters (^$()%.[]*+-?) not used by ABP (^$()[]*) - s = string.gsub(s, "([%%%.%+%-%?])", "%%%1") - - -- Wildcards are globbing - s = string.gsub(s, "%*", "%.%*") - - -- Caret is separator (anything but a letter, a digit, or one of the following:Â - . %) - s = string.gsub(s, "%^", "[^%%w%%-%%.%%%%]") - - -- Double pipe is domain anchor (beginning only) - -- Unfortunately "||example.com" will also match "wexample.com" (lua doesn't do grouping) - s = string.gsub(s, "^||", "^https?://[^/]*%%.?") - - -- Pipe is anchor - s = string.gsub(s, "^|", "%^") - s = string.gsub(s, "|$", "%$") - - -- Convert to lowercase ($match-case option is not honoured) - s = string.lower(s) - end - - return s, opts -end - -add_unique_cached = function (pattern, opts, tab, cache_tab) - if cache_tab[pattern] then - return false - else - --cache_tab[pattern], tab[pattern] = true, pattern - cache_tab[pattern], tab[pattern] = true, opts - return true - end -end - --- Parses an Adblock Plus compatible filter list -parse_abpfilterlist = function (filename, cache) - if os.exists(filename) then - info("adblock: loading filterlist %s", filename) - else - info("adblock: error loading filter list (%s: No such file or directory)", filename) - end - --*** - --local f = io.open(filename .. "~", "w") - --*** - local pat, opts - local white, black, wlen, blen, icnt = {}, {}, 0, 0, 0 - for line in io.lines(filename) do - -- Ignore comments, header and blank lines - if line:match("^[![]") or line:match("^$") then - -- dammitwhydoesntluahaveacontinuestatement - - -- Ignore element hiding - elseif line:match("#") then - --icnt = icnt + 1 - - -- Check for exceptions (whitelist) - elseif line:match("^@@") then - pat, opts = abp_to_pattern(string.sub(line, 3)) - if pat and pat ~= "^http://" then - if add_unique_cached(pat, opts, white, cache.white) then - wlen = wlen + 1 - --*** - --f:write("W " .. pat .. "\n") - --*** - else - icnt = icnt + 1 - end - -- table.insert(white, pat) - else - icnt = icnt + 1 - end - - -- Add everything else to blacklist - else - pat, opts = abp_to_pattern(line) - if pat and pat ~= "^http:" and pat ~= ".*" then - if add_unique_cached(pat, opts, black, cache.black) then - blen = blen + 1 - --*** - --f:write("B " .. pat .. "\n") - --*** - else - icnt = icnt + 1 - end - -- table.insert(black, pat) - else - icnt = icnt + 1 - end - end - end - --*** - --f:close() - --*** - - return white, black, wlen, blen, icnt -end - --- Load filter list files -load = function (reload, single_list) - if reload then subscriptions, filterfiles = {}, {} end - detect_files() - if not simple_mode and not single_list then - read_subscriptions() - local files_list = {} - for _, filename in ipairs(filterfiles) do - local list = subscriptions[filename] - if list and util.table.hasitem(list.opts, "Enabled") then - table.insert(files_list, filename) - else - add_list("", filename, "Disabled", true, false) - end - end - filterfiles = files_list - -- Yes we may have changed subscriptions and even fixed something with them. - write_subscriptions() - end - - -- [re-]loading: - if reload then rules = {} end - local filters_dir = adblock_dir - if simple_mode then - filters_dir = capi.luakit.data_dir - end - local filterfiles_loading = {} - if single_list and not reload then - filterfiles_loading = { single_list } - else - filterfiles_loading = filterfiles - end - local rules_cache = { - black = {}, - white = {} - } -- This cache should let us avoid unnecessary filters duplication. - - for _, filename in ipairs(filterfiles_loading) do - local white, black, wlen, blen, icnt = parse_abpfilterlist(filters_dir .. filename, rules_cache) - local list = {} - if not simple_mode then - list = subscriptions[filename] - else - local list_found = rules[filename] - if list_found then - list = list_found - end - end - if not util.table.hasitem(rules, list) then - rules[filename] = list - end - list.title, list.white, list.black, list.ignored = filename, wlen or 0, blen or 0, icnt or 0 - list.whitelist, list.blacklist = white or {}, black or {} - end - - rules_cache.white, rules_cache.black = nil, nil - rules_cache = nil - refresh_views() -end - -local function domain_match(domain, opts) - local res = false - local cnt = 0 - local dlist = opts["domain"] - if dlist then - for _, s in pairs(dlist) do - if string.len(s) > 0 then - if string.sub(s, 1, 1) == "~" then - if domain == string.sub(s, 2) then return false end - else - cnt = cnt + 1 - if not res and domain == s then res = true end - end - end - end - end - return cnt == 0 or res -end - -local function third_party_match(page_domain, domain2, opts) - local thp = opts["third-party"] - if thp ~= nul then - if thp == true then return domain1 ~= domain2 end - return domain1 == domain2 - end - return true -end - -local function domain_from_uri(uri) - local domain = (uri and string.match(string.lower(uri), "^%a+://([^/]*)/?")) - -- Strip leading www. www2. etc - domain = string.match(domain or "", "^www%d?%.(.+)") or domain - return domain or "" -end - --- Tests URI against user-defined filter functions, then whitelist, then blacklist -match = function (uri, signame, page_uri) - -- Matching is not case sensitive - uri = string.lower(uri) - - signame = signame or "" - - local page_domain, uri_domain - if signame ~= "navigation-request" then - page_domain = domain_from_uri(page_uri) - uri_domain = domain_from_uri(uri) - else - page_domain = domain_from_uri(uri) - uri_domain = page_uri - end - - -- Test uri against filterfuncs - for _, func in ipairs(filterfuncs) do - local ret = func(uri) - if ret ~= nil then - info("adblock: filter function %s returned %s to uri %s", tostring(func), tostring(ret), uri) - return ret - end - end - - -- Test against each list's whitelist rules first - for _, list in pairs(rules) do - -- Check for a match to whitelist - for pattern, opts in pairs(list.whitelist or {}) do - if third_party_match(page_domain, uri_domain, opts) then - if domain_match(page_domain, opts) and string.match(uri, pattern) then - info("adblock: allowing %q as pattern %q matched to uri %s", signame, pattern, uri) - return true - end - end - end - end - - -- Test against each list's blacklist rules - for _, list in pairs(rules) do - -- Check for a match to blacklist - for pattern, opts in pairs(list.blacklist or {}) do - if third_party_match(page_domain, uri_domain, opts) then - if domain_match(page_domain, opts) and string.match(uri, pattern) then - info("adblock: blocking %q as pattern %q matched to uri %s", signame, pattern, uri) - return false - end - end - end - end -end - --- Direct requests to match function -filter = function (v, uri, signame) - if enabled then return match(uri, signame or "", v.uri) end -end - -function table.itemid(t, item) - local pos = 0 - for id, v in pairs(t) do - pos = pos + 1 - if v == item then - return pos - end - end -end - --- Connect signals to all webview widgets on creation -webview.init_funcs.adblock_signals = function (view, w) - --view:add_signal("navigation-request", function (v, uri) return filter(v, uri, "navigation-request") end) - view:add_signal("resource-request-starting", function (v, uri) return filter(v, uri, "resource-request-starting") end) -end - --- Remove options and add new ones to list --- @param list_index Index of the list to modify --- @param opt_ex Options to exclude --- @param opt_inc Options to include -function list_opts_modify(list_index, opt_ex, opt_inc) - assert( simple_mode == false, "adblock list management: not supported in simple mode" ) - assert(type(list_index) == "number", "list options modify: invalid list index") - assert(list_index > 0, "list options modify: index has to be > 0") - if not opt_ex then opt_ex = {} end - if not opt_inc then opt_inc = {} end - - if type(opt_ex) == "string" then opt_ex = util.string.split(opt_ex) end - if type(opt_inc) == "string" then opt_inc = util.string.split(opt_inc) end - - local list = util.table.values(subscriptions)[list_index] - local opts = opt_inc - for _, opt in ipairs(list.opts) do - if not util.table.hasitem(opt_ex, opt) then - table.insert(opts, opt) - end - end - - -- Manage list's rules - local listIDfound = table.itemid(rules, list) - if util.table.hasitem(opt_inc, "Enabled") then - if not listIDfound then - load(false, list.title) - end - elseif util.table.hasitem(opt_inc, "Disabled") then - rules[list.title] = nil - end - - list.opts = opts - write_subscriptions() - refresh_views() -end - ---- Add a list to the in-memory lists table -function add_list(uri, title, opts, replace, save_lists) - assert( (title ~= nil) and (title ~= ""), "adblock list add: no title given") - if not opts then opts = {} end - - -- Create tags table from string - if type(opts) == "string" then opts = util.string.split(opts) end - if table.maxn(opts) == 0 then table.insert(opts, "Disabled") end - if not replace and ( subscriptions[title] or subscriptions[uri] ) then - local list = subscriptions[title] or subscriptions[uri] - -- Merge tags - for _, opts in ipairs(opts) do - if not util.table.hasitem(list, opts) then table.insert(list, opts) end - end - else - -- Insert new adblock list - local list = { uri = uri, title = title, opts = opts } - if not (uri == "" or uri == nil) then - subscriptions[uri] = list - end - if not (title == "" or title == nil) then - subscriptions[title] = list - end - end - - -- Save by default - if save_lists ~= false then write_subscriptions() end -end - ---- Save the in-memory subscriptions to flatfile. --- @param file The destination file or the default location if nil. -function write_subscriptions(file) - if not file then file = subscriptions_file end - - local lines = {} - local added = {} - for _, list in pairs(subscriptions) do - if not util.table.hasitem(added, list) then - local subs = { uri = list.uri, title = list.title, opts = table.concat(list.opts or {}, " "), } - local line = string.gsub("{title}\t{uri}\t{opts}", "{(%w+)}", subs) - table.insert(added, list) - table.insert(lines, line) - end - end - - -- Write table to disk - local fh = io.open(file, "w") - fh:write(table.concat(lines, "\n")) - io.close(fh) -end - ---- Load subscriptions from a flatfile to memory. --- @param file The subscriptions file or the default subscriptions location if nil. --- @param clear_first Should the subscriptions in memory be dumped before loading. -function read_subscriptions(file, clear_first) - if clear_first then clear() end - - -- Find a subscriptions file - if not file then file = subscriptions_file end - if not os.exists(file) then return end - - -- Read lines into subscriptions data table - for line in io.lines(file or subscriptions_file) do - local title, uri, opts = unpack(util.string.split(line, "\t")) - if title ~= "" then add_list(uri, title, opts, false, false) end - end -end - - --- Add commands. -local cmd = lousy.bind.cmd -add_cmds({ - cmd({"adblock-reload", "abr"}, function (w) - info("adblock: Reloading filters.") - load(true) - info("adblock: Reloading filters complete.") - end), - - cmd({"adblock-list-enable", "able"}, function (w, a) - list_opts_modify(tonumber(a), "Disabled", "Enabled") - end), - - cmd({"adblock-list-disable", "abld"}, function (w, a) - list_opts_modify(tonumber(a), "Enabled", "Disabled") - end), - cmd({"adblock-enable", "abe"}, function (w) - enable() - end), - - cmd({"adblock-disable", "abd"}, function (w) - disable() - end), -}) - --- Initialise module -load() |
