-# Copyright (C) 2016 Openwrt.org
-#
-# This is free software, licensed under the Apache License, Version 2.0 .
-#
+# Copyright 2016 Hannu Nyman
+# Copyright 2017 Dirk Brenken (dev@brenken.org)
+# This is free software, licensed under the Apache License, Version 2.0
include $(TOPDIR)/rules.mk
LUCI_PKGARCH:=all
include ../../luci.mk
-
-# call BuildPackage - OpenWrt buildroot signature
--- Copyright 2016 Openwrt.org
--- Licensed to the public under the Apache License 2.0.
+-- Copyright 2016 Hannu Nyman
+-- Copyright 2017 Dirk Brenken (dev@brenken.org)
+-- This is free software, licensed under the Apache License, Version 2.0
module("luci.controller.adblock", package.seeall)
+local fs = require("nixio.fs")
+local util = require("luci.util")
+local template = require("luci.template")
+local i18n = require("luci.i18n")
+
function index()
if not nixio.fs.access("/etc/config/adblock") then
return
end
+ entry({"admin", "services", "adblock"}, firstchild(), _("Adblock"), 30).dependent = false
+ entry({"admin", "services", "adblock", "tab_from_cbi"}, cbi("adblock/overview_tab"), _("Overview"), 10).leaf = true
+ entry({"admin", "services", "adblock", "logfile"}, call("logread"), _("View Logfile"), 20).leaf = true
+ entry({"admin", "services", "adblock", "advanced"}, firstchild(), _("Advanced"), 100)
+ entry({"admin", "services", "adblock", "advanced", "blacklist"}, cbi("adblock/blacklist_tab"), _("Edit Blacklist"), 110).leaf = true
+ entry({"admin", "services", "adblock", "advanced", "whitelist"}, cbi("adblock/whitelist_tab"), _("Edit Whitelist"), 120).leaf = true
+ entry({"admin", "services", "adblock", "advanced", "configuration"}, cbi("adblock/configuration_tab"), _("Edit Configuration"), 130).leaf = true
+ entry({"admin", "services", "adblock", "advanced", "query"}, call("query"), _("Query domains"), 140).leaf = true
+ entry({"admin", "services", "adblock", "advanced", "result"}, call("queryData"), nil, 150).leaf = true
+end
+
+function logread()
+ local logfile = util.trim(util.exec("logread -e 'adblock'"))
+ template.render("adblock/logread", {title = i18n.translate("Adblock Logfile"), content = logfile})
+end
- entry({"admin", "services", "adblock"}, cbi("adblock"), _("Adblock"), 40)
+function query()
+ template.render("adblock/query", {title = i18n.translate("Adblock Domain Query")})
+end
+
+function queryData(domain)
+ if domain and domain:match("^[a-zA-Z0-9%-%._]+$") then
+ luci.http.prepare_content("text/plain")
+ local cmd = "/etc/init.d/adblock query %q 2>&1"
+ local util = io.popen(cmd % domain)
+ if util then
+ while true do
+ local line = util:read("*l")
+ if not line then
+ break
+ end
+ luci.http.write(line)
+ luci.http.write("\n")
+ end
+ util:close()
+ end
+ end
end
+++ /dev/null
--- Copyright 2016 Hannu Nyman
--- Licensed to the public under the Apache License 2.0.
-
-m = Map("adblock", translate("Adblock"),
- translate("Configuration of the adblock package to block ad/abuse domains by using DNS."))
-
--- General options
-
-s = m:section(NamedSection, "global", "adblock", translate("Global options"))
-
-o1 = s:option(Flag, "adb_enabled", translate("Enable adblock"))
-o1.rmempty = false
-o1.default = 0
-
-o3 = s:option(Value, "adb_whitelist", translate("Whitelist file"),
- translate("File with whitelisted hosts/domains that are allowed despite being on a blocklist."))
-o3.rmempty = false
-o3.datatype = "file"
-
--- Blocklist options
-
-bl = m:section(TypedSection, "source", translate("Blocklist sources"),
- translate("Available blocklist sources (")
- .. [[<a href="https://github.com/openwrt/packages/blob/master/net/adblock/files/README.md" target="_blank">]]
- .. translate("see list details")
- .. [[</a>]]
- .. translate("). Note that list URLs and Shallalist category selections are not configurable via Luci."))
-bl.template = "cbi/tblsection"
-
-name = bl:option(Flag, "enabled", translate("Enabled"))
-name.rmempty = false
-
-des = bl:option(DummyValue, "adb_src_desc", translate("Description"))
-
--- Additional options
-
-s2 = m:section(NamedSection, "global", "adblock", translate("Backup options"))
-
-o4 = s2:option(Flag, "adb_backup", translate("Enable blocklist backup"))
-o4.rmempty = false
-o4.default = 0
-
-o5 = s2:option(Value, "adb_backupdir", translate("Backup directory"))
-o5.rmempty = false
-o5.datatype = "directory"
-
--- Extra options
-
-e = m:section(NamedSection, "global", "adblock", translate("Extra options"),
- translate("Options for further tweaking in case the defaults are not suitable for you."))
-
-a = e:option(Flag, "adb_debug", translate("Enable verbose debug logging"))
-a.default = a.disabled
-a.rmempty = false
-
-a = e:option(Value, "adb_iface", translate("Restrict reload trigger to certain interface(s)"),
- translate("Space separated list of wan interfaces that trigger reload action. " ..
- "To disable reload trigger set it to 'false'. Default: empty"))
-a.datatype = "network"
-a.rmempty = true
-
-return m
-
--- /dev/null
+-- Copyright 2016 Hannu Nyman
+-- Copyright 2017 Dirk Brenken (dev@brenken.org)
+-- This is free software, licensed under the Apache License, Version 2.0
+
+local fs = require("nixio.fs")
+local util = require("luci.util")
+local uci = require("uci")
+local adbinput = uci.get("adblock", "blacklist", "adb_src")
+
+if not nixio.fs.access(adbinput) then
+ m = SimpleForm("error", nil, translate("Input file not found, please check your configuration."))
+ return m
+end
+
+m = SimpleForm("input", nil)
+ m:append(Template("adblock/config_css"))
+
+s = m:section(SimpleSection, nil,
+ translate("This form allows you to modify the content of the adblock blacklist (" .. adbinput .. ").<br />")
+ .. translate("Please add only one domain per line. Comments introduced with '#' are allowed - ip addresses, wildcards & regex are not."))
+
+f = s:option(TextValue, "data")
+ f.rmempty = true
+ f.datatype = "string"
+ f.rows = 20
+
+ function f.cfgvalue()
+ return nixio.fs.readfile(adbinput) or ""
+ end
+
+ function f.write(self, section, data)
+ return nixio.fs.writefile(adbinput, "\n" .. util.trim(data:gsub("\r\n", "\n")) .. "\n")
+ end
+
+ function s.handle(self, state, data)
+ return true
+ end
+
+return m
--- /dev/null
+-- Copyright 2016 Hannu Nyman
+-- Copyright 2017 Dirk Brenken (dev@brenken.org)
+-- This is free software, licensed under the Apache License, Version 2.0
+
+local fs = require("nixio.fs")
+local util = require("luci.util")
+local adbinput = "/etc/config/adblock"
+
+if not nixio.fs.access(adbinput) then
+ m = SimpleForm("error", nil, translate("Input file not found, please check your configuration."))
+ return m
+end
+
+m = SimpleForm("input", nil)
+ m:append(Template("adblock/config_css"))
+
+s = m:section(SimpleSection, nil,
+translate("This form allows you to modify the content of the main adblock configuration file (/etc/config/adblock)."))
+
+f = s:option(TextValue, "data")
+ f.rmempty = true
+ f.rows = 20
+
+ function f.cfgvalue()
+ return nixio.fs.readfile(adbinput) or ""
+ end
+
+ function f.write(self, section, data)
+ return nixio.fs.writefile(adbinput, "\n" .. util.trim(data:gsub("\r\n", "\n")) .. "\n")
+ end
+
+ function s.handle(self, state, data)
+ return true
+ end
+
+return m
--- /dev/null
+-- Copyright 2016 Hannu Nyman
+-- Copyright 2017 Dirk Brenken (dev@brenken.org)
+-- This is free software, licensed under the Apache License, Version 2.0
+
+local sys = require("luci.sys")
+local util = require("luci.util")
+local data = util.ubus("service", "get_data", "name", "adblock") or { }
+local dnsFile1 = sys.exec("find '/tmp/dnsmasq.d' -maxdepth 1 -type f -name 'adb_list*' -print")
+local dnsFile2 = sys.exec("find '/var/lib/unbound' -maxdepth 1 -type f -name 'adb_list*' -print")
+
+m = Map("adblock", translate("Adblock"),
+ translate("Configuration of the adblock package to block ad/abuse domains by using DNS. ")
+ .. translate("For further information ")
+ .. [[<a href="https://github.com/openwrt/packages/blob/master/net/adblock/files/README.md" target="_blank">]]
+ .. translate("see online documentation")
+ .. [[</a>]]
+ .. translate("."))
+
+-- Main adblock options
+
+s = m:section(NamedSection, "global", "adblock")
+
+o1 = s:option(Flag, "adb_enabled", translate("Enable adblock"))
+o1.rmempty = false
+o1.default = 0
+
+if data.adblock ~= nil and (dnsFile1 ~= "" or dnsFile2 ~= "") then
+btn = s:option( Button, "_btn", translate("Suspend adblock"))
+ btn.inputstyle = "reset"
+ function btn.write()
+ luci.sys.call("/etc/init.d/adblock suspend")
+ end
+else
+ btn = s:option( Button, "_btn", translate("Resume adblock"))
+ btn.inputstyle = "apply"
+ function btn.write()
+ luci.sys.call("/etc/init.d/adblock resume")
+ end
+end
+
+o2 = s:option(Flag, "adb_debug", translate("Enable verbose debug logging"))
+o2.default = o2.disabled
+o2.rmempty = false
+
+o3 = s:option(Value, "adb_iface", translate("Restrict interface reload trigger to certain interface(s)"),
+ translate("Space separated list of interfaces that trigger a reload action. "..
+ "To disable reload trigger at all set it to 'false'."))
+o3.rmempty =false
+
+-- Runtime information
+
+ ds = s:option(DummyValue, "_dummy", translate("Runtime information"))
+ ds.template = "cbi/nullsection"
+
+ dv1 = s:option(DummyValue, "adblock_version", translate("Adblock version"))
+ if data.adblock ~= nil then
+ dv1.value = data.adblock.adblock.adblock_version or "?"
+ else
+ dv1.value = "?"
+ end
+ dv1.template = "adblock/runtime"
+
+ dv2 = s:option(DummyValue, "status", translate("Status"))
+ if dnsFile1 ~= "" or dnsFile2 ~= "" then
+ dv2.value = "active"
+ else
+ dv2.value = "suspended"
+ end
+ dv2.template = "adblock/runtime"
+
+ dv3 = s:option(DummyValue, "dns_backend", translate("DNS backend"))
+ if data.adblock ~= nil then
+ dv3.value = data.adblock.adblock.dns_backend or "?"
+ else
+ dv3.value = "?"
+ end
+ dv3.template = "adblock/runtime"
+
+ dv4 = s:option(DummyValue, "blocked_domains", translate("Blocked domains (overall)"))
+ if data.adblock ~= nil then
+ dv4.value = data.adblock.adblock.blocked_domains or "?"
+ else
+ dv4.value = "?"
+ end
+ dv4.template = "adblock/runtime"
+
+ dv5 = s:option(DummyValue, "last_rundate", translate("Last rundate"))
+ if data.adblock ~= nil then
+ dv5.value = data.adblock.adblock.last_rundate or "?"
+ else
+ dv5.value = "?"
+ end
+ dv5.template = "adblock/runtime"
+
+-- Blocklist options
+
+bl = m:section(TypedSection, "source", translate("Blocklist sources"),
+ translate("Available blocklist sources. ")
+ .. translate("Note that list URLs and Shallalist category selections are configurable in the 'Advanced' section."))
+bl.template = "cbi/tblsection"
+
+name = bl:option(Flag, "enabled", translate("Enabled"))
+name.rmempty = false
+
+des = bl:option(DummyValue, "adb_src_desc", translate("Description"))
+
+-- Backup options
+
+s = m:section(NamedSection, "global", "adblock", translate("Backup options"))
+
+o4 = s:option(Flag, "adb_backup", translate("Enable blocklist backup"))
+o4.rmempty = false
+o4.default = 0
+
+o5 = s:option(Value, "adb_backupdir", translate("Backup directory"))
+o5.rmempty = false
+o5.datatype = "directory"
+
+return m
--- /dev/null
+-- Copyright 2016 Hannu Nyman
+-- Copyright 2017 Dirk Brenken (dev@brenken.org)
+-- This is free software, licensed under the Apache License, Version 2.0
+
+local fs = require("nixio.fs")
+local util = require("luci.util")
+local uci = require("uci")
+local adbinput = uci.get("adblock", "global", "adb_whitelist") or " "
+
+if not nixio.fs.access(adbinput) then
+ m = SimpleForm("error", nil, translate("Input file not found, please check your configuration."))
+ return m
+end
+
+m = SimpleForm("input", nil)
+ m:append(Template("adblock/config_css"))
+
+s = m:section(SimpleSection, nil,
+ translate("This form allows you to modify the content of the adblock whitelist (" .. adbinput .. ").<br />")
+ .. translate("Please add only one domain per line. Comments introduced with '#' are allowed - ip addresses, wildcards & regex are not."))
+
+f = s:option(TextValue, "data")
+ f.rmempty = true
+ f.datatype = "string"
+ f.rows = 20
+
+ function f.cfgvalue()
+ return nixio.fs.readfile(adbinput) or ""
+ end
+
+ function f.write(self, section, data)
+ return nixio.fs.writefile(adbinput, "\n" .. util.trim(data:gsub("\r\n", "\n")) .. "\n")
+ end
+
+ function s.handle(self, state, data)
+ return true
+ end
+
+return m
--- /dev/null
+<style type="text/css">
+ textarea
+ {
+ border: 1px solid #cccccc;
+ padding: 5px;
+ font-size: 12px;
+ font-family: monospace;
+ resize: none;
+ }
+</style>
--- /dev/null
+<%#
+Copyright 2016 Hannu Nyman
+Copyright 2017 Dirk Brenken (dev@brenken.org)
+This is free software, licensed under the Apache License, Version 2.0
+-%>
+
+<%+header%>
+
+<div class="cbi-map">
+ <fieldset class="cbi-section">
+ <div class="cbi-section-descr">This form shows the syslog output, pre-filtered for adblock related messages only.</div>
+ <textarea id="logread_id" style="width: 100%; height: 450px; border: 1px solid #cccccc; padding: 5px; font-size: 12px; font-family: monospace; resize: none;" readonly="readonly" wrap="off" rows="<%=content:cmatch("\n")+2%>"><%=content:pcdata()%></textarea>
+ </fieldset>
+</div>
+<%+footer%>
--- /dev/null
+<%#
+Copyright 2016 Hannu Nyman
+Copyright 2017 Dirk Brenken (dev@brenken.org)
+This is free software, licensed under the Apache License, Version 2.0
+-%>
+
+<%+header%>
+
+<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
+<script type="text/javascript">
+//<![CDATA[
+ var stxhr = new XHR();
+
+ function update_status(data)
+ {
+ var domain = data.value;
+ var input = document.getElementById('query_input');
+ var output = document.getElementById('query_output');
+
+ if (input && output)
+ {
+ output.innerHTML =
+ '<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> ' +
+ '<%:Waiting for command to complete...%>'
+ ;
+ input.parentNode.style.display = 'block';
+ input.style.display = 'inline';
+ stxhr.post('<%=url('admin/services/adblock/advanced/result/')%>' + domain, { token: '<%=token%>' },
+ function(x)
+ {
+ if (x.responseText)
+ {
+ input.style.display = 'none';
+ output.innerHTML = String.format('<pre>%h</pre>', x.responseText);
+ }
+ else
+ {
+ input.style.display = 'none';
+ output.innerHTML = '<span class="error"><%:Invalid domain specified!%></span>';
+ }
+ }
+ );
+ }
+ }
+//]]>
+</script>
+
+<form method="post" action="<%=REQUEST_URI%>">
+ <div class="cbi-map">
+ <fieldset class="cbi-section">
+ <div class="cbi-section-descr">This form allows you to query active block lists for certain domains, e.g. for whitelisting.</div>
+ <div style="width:33%; float:left;">
+ <input style="margin: 5px 0" type="text" value="www.lede-project.org" name="input" />
+ <input type="button" value="<%:Query%>" class="cbi-button cbi-button-apply" onclick="update_status(this.form.input)" />
+ </div>
+ <br style="clear:both" />
+ <br />
+ </fieldset>
+ </div>
+ <fieldset class="cbi-section" style="display:none">
+ <legend id="query_input"><%:Collecting data...%></legend>
+ <span id="query_output"></span>
+ </fieldset>
+</form>
+
+<%+footer%>
--- /dev/null
+<%#
+Copyright 2016 Hannu Nyman
+Copyright 2017 Dirk Brenken (dev@brenken.org)
+This is free software, licensed under the Apache License, Version 2.0
+-%>
+
+<%+cbi/valueheader%>
+
+<input name="runtime" id="runtime" type="text" class="cbi-input-text" style="border: none; box-shadow: none; background-color: #ffffff; color: #0069d6;" value="<%=self:cfgvalue(section)%>" disabled />
+
+<%+cbi/valuefooter%>