luci-app-appfilter: bump to 5.0

Signed-off-by: Tianling Shen <cnsztl@immortalwrt.org>
This commit is contained in:
Tianling Shen 2021-03-06 13:28:56 +08:00
parent 1ab39aabda
commit 313f365ce1
No known key found for this signature in database
GPG Key ID: 6850B6345C862176
8 changed files with 674 additions and 33 deletions

View File

@ -11,7 +11,7 @@ LUCI_PKGARCH:=all
LUCI_DEPENDS:=+appfilter
PKG_NAME:=luci-app-appfilter
PKG_VERSION:=3.0
PKG_VERSION:=5.0
PKG_RELEASE:=1
# call BuildPackage - OpenWrt buildroot signature

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,6 @@
module("luci.controller.appfilter", package.seeall)
local utl = require "luci.util"
function index()
if not nixio.fs.access("/etc/config/appfilter") then
@ -6,12 +8,30 @@ function index()
end
local page
--hide save button
page = entry({"admin", "network", "appfilter"}, arcombine(cbi("appfilter/appfilter"), cbi("appfilter/dev_status", {hideapplybtn=true, hidesavebtn=true, hideresetbtn=true})), _("appfilter"), 100)
page = entry({"admin", "network", "appfilter"}, cbi("appfilter/appfilter"), _("appfilter"))
page.dependent = true
page.leaf = true
page.subindex = true
--page.dependent = true
page = entry({"admin", "network", "user_status"}, call("user_status"), nil)
page.leaf = true
page = entry({"admin", "network", "dev_app_status"}, call("dev_app_status"), nil)
page.leaf = true
page = entry({"admin", "network", "dev_visit_list"}, call("get_dev_visit_list"), nil)
page.leaf = true
page = entry({"admin", "network", "feature_upgrade"}, call("handle_feature_upgrade"), nil)
page.leaf = true
page = entry({"admin", "network", "dev_visit_time"}, call("get_dev_visit_time"), nil)
page.leaf = true
page = entry({"admin", "network", "app_class_visit_time"}, call("get_app_class_visit_time"), nil)
page.leaf = true
end
function get_hostname_by_mac(dst_mac)
@ -33,6 +53,30 @@ function get_hostname_by_mac(dst_mac)
return ""
end
function handle_feature_upgrade()
local fs = require "nixio.fs"
local http = require "luci.http"
local image_tmp = "/tmp/feature.cfg"
local fp
http.setfilehandler(
function(meta, chunk, eof)
fp = io.open(image_tmp, "w")
if fp and chunk then
fp:write(chunk)
end
if fp and eof then
fp:close()
end
end
)
end
function get_app_name_by_id(appid)
local class_fd = io.popen("find /tmp/appfilter/ -type f -name *.class |xargs cat |grep "..appid.."|awk '{print $2}'")
if class_fd then
@ -48,40 +92,106 @@ function cmp_func(a,b)
end
function user_status()
local json = require "luci.jsonc"
luci.http.prepare_content("application/json")
--local fs=require "nixio.fs"
--local ok, status_data = pcall(json.parse, fs.readfile("/proc/net/af_client"))
--luci.http.write_json(tb);
local fd = io.open("/proc/net/af_client","r")
status_buf=fd:read('*a')
fd:close()
user_array=json.parse(status_buf)
local visit_obj=utl.ubus("appfilter", "visit_list", {});
local user_array=visit_obj.dev_list
local history={}
for i, v in pairs(user_array) do
visit_array=user_array[i].visit_info
for j,s in pairs(visit_array) do
print(user_array[i].mac, user_array[i].ip,visit_array[j].appid, visit_array[j].latest_time)
total_time=visit_array[j].latest_time - visit_array[j].first_time;
history[#history+1]={
mac=user_array[i].mac,
ip=user_array[i].ip,
hostname=get_hostname_by_mac(user_array[i].mac),
appid=visit_array[j].appid,
appname=get_app_name_by_id(visit_array[j].appid),
total_num=visit_array[j].total_num,
drop_num=visit_array[j].drop_num,
--total_num=visit_array[j].total_num,
--drop_num=visit_array[j].drop_num,
total_num=0,
drop_num=0,
latest_action=visit_array[j].latest_action,
latest_time=os.date("%Y/%m/%d %H:%M:%S", visit_array[j].latest_time)
latest_time=os.date("%Y/%m/%d %H:%M:%S", visit_array[j].latest_time),
first_time=os.date("%Y/%m/%d %H:%M:%S", visit_array[j].first_time),
total_time=total_time
}
end
end
table.sort(history, cmp_func)
--luci.http.write(history);
luci.http.write_json(history);
end
function dev_app_status()
local json = require "luci.jsonc"
luci.http.prepare_content("application/json")
local visit_obj=utl.ubus("appfilter", "dev_list", {});
luci.http.write_json(visit_obj);
end
function get_dev_visit_time(mac)
local json = require "luci.jsonc"
luci.http.prepare_content("application/json")
local fd = io.open("/proc/net/af_client","r")
status_buf=fd:read('*a')
fd:close()
user_array=json.parse(status_buf)
local req_obj = {}
req_obj.mac = mac;
local visit_obj=utl.ubus("appfilter", "dev_visit_time", req_obj);
local user_array=visit_obj.app_list
luci.http.write_json(user_array);
end
function get_app_class_visit_time(mac)
local json = require "luci.jsonc"
luci.http.prepare_content("application/json")
local req_obj = {}
req_obj.mac = mac;
local visit_obj=utl.ubus("appfilter", "app_class_visit_time", req_obj);
local class_array=visit_obj.class_list
luci.http.write_json(class_array);
end
function get_dev_visit_list(mac)
local json = require "luci.jsonc"
luci.http.prepare_content("application/json")
local req_obj = {}
req_obj.mac = mac;
local visit_obj=utl.ubus("appfilter", "visit_list", req_obj);
local user_array=visit_obj.dev_list
local history={}
for i, v in pairs(user_array) do
visit_array=user_array[i].visit_info
for j,s in pairs(visit_array) do
print(user_array[i].mac, user_array[i].ip,visit_array[j].appid, visit_array[j].latest_time)
total_time=visit_array[j].latest_time - visit_array[j].first_time;
history[#history+1]={
mac=user_array[i].mac,
ip=user_array[i].ip,
hostname=get_hostname_by_mac(user_array[i].mac),
appid=visit_array[j].appid,
appname=get_app_name_by_id(visit_array[j].appid),
total_num=0,
drop_num=0,
latest_action=visit_array[j].latest_action,
latest_time=os.date("%Y/%m/%d %H:%M:%S", visit_array[j].latest_time),
first_time=os.date("%Y/%m/%d %H:%M:%S", visit_array[j].first_time),
total_time=total_time
}
end
end
table.sort(history, cmp_func)
luci.http.write_json(history);
end

View File

@ -1,7 +1,16 @@
local ds = require "luci.dispatcher"
local nxo = require "nixio"
local nfs = require "nixio.fs"
local ipc = require "luci.ip"
local sys = require "luci.sys"
local utl = require "luci.util"
local dsp = require "luci.dispatcher"
local uci = require "luci.model.uci"
local lng = require "luci.i18n"
local jsc = require "luci.jsonc"
local http = luci.http
local SYS = require "luci.sys"
local m, s
m = Map("appfilter",
@ -12,7 +21,23 @@ s = m:section(TypedSection, "global", translate("Basic Settings"))
s:option(Flag, "enable", translate("Enable App Filter"),translate(""))
s.anonymous = true
local rule_count=0
local version=""
if nixio.fs.access("/etc/appfilter/feature.cfg") then
rule_count=tonumber(SYS.exec("cat /etc/appfilter/feature.cfg | wc -l"))
version=SYS.exec("cat /etc/appfilter/feature.cfg |grep \"#version\" | awk '{print $2}'")
end
local display_str="<strong>当前版本: </strong>"..version.."<br><strong>特征码个数:</strong> "..rule_count.."<br><strong> 下载地址:</strong><a href=\"https://destan19.github.io\">https://destan19.github.io</a>"
s = m:section(TypedSection, "feature", translate("特征库更新"), display_str )
fu = s:option(FileUpload, "")
fu.template = "cbi/other_upload"
s.anonymous = true
um = s:option(DummyValue, "rule_data")
um.template = "cbi/other_dvalue"
--um.value =rule_count .. " " .. translate("Records").. " "..version
s = m:section(TypedSection, "appfilter", translate("App Filter Rules"))
s.anonymous = true
s.addremove = false
@ -108,18 +133,17 @@ users.widget="checkbox"
--users.widget="select"
users.size=1
local fd = io.open("/proc/net/arp", "r")
local fd = io.open("/tmp/dev_list", "r")
if not fd then return m end
while true do
local line = fd:read("*l")
if not line then
break
end
if not line:match("Ip*") then
local ip=get_cmd_result(string.format("echo '%s' | awk '{print $1}'", line))
local mac=get_cmd_result(string.format("echo '%s' | awk '{print $4}'", line))
local device=get_cmd_result(string.format("echo '%s' | awk '{print $6}'", line))
if device ~= nil and mac ~= nil and device:match("lan") then
if not line:match("Id*") then
local ip=get_cmd_result(string.format("echo '%s' | awk '{print $3}'", line))
local mac=get_cmd_result(string.format("echo '%s' | awk '{print $2}'", line))
if mac ~= nil then
local hostname=get_hostname_by_mac(mac)
if not hostname or hostname == "*" then
users:value(mac, mac);
@ -139,6 +163,49 @@ for i=1,max,1 do
end
end
m:section(SimpleSection).template = "admin_network/user_status"
local dir, fd
dir = "/tmp/upload/"
nixio.fs.mkdir(dir)
http.setfilehandler(
function(meta, chunk, eof)
if not fd then
if not meta then return end
if meta and chunk then fd = nixio.open(dir .. meta.file, "w") end
if not fd then
--um.value = translate("Create upload file error.")
return
end
end
if chunk and fd then
fd:write(chunk)
end
if eof and fd then
fd:close()
local fd2 = io.open("/tmp/upload/"..meta.file)
local line=fd2:read("*l");
local ret=string.match(line, "#version")
if ret ~= nil then
local cmd="cp /tmp/upload/"..meta.file.." /etc/appfilter/feature.cfg";
os.execute(cmd);
os.execute("rm /tmp/appfilter -fr");
luci.sys.exec("/etc/init.d/appfilter restart &");
um.value = translate("更新成功,请刷新页面!")
else
um.value = translate("更新失败,格式错误!")
end
end
end
)
if luci.http.formvalue("upload") then
local f = luci.http.formvalue("ulfile")
if #f <= 0 then
--um.value = translate("No specify upload file.")
end
elseif luci.http.formvalue("download") then
Download()
end
return m

View File

@ -0,0 +1,24 @@
local ds = require "luci.dispatcher"
local nxo = require "nixio"
local nfs = require "nixio.fs"
local ipc = require "luci.ip"
local sys = require "luci.sys"
local utl = require "luci.util"
local dsp = require "luci.dispatcher"
local uci = require "luci.model.uci"
local lng = require "luci.i18n"
local jsc = require "luci.jsonc"
local m, s
arg[1] = arg[1] or ""
m = Map("appfilter",
translate("上网统计("..arg[1]..")"),
translate(""))
local v
v=m:section(SimpleSection)
v.template="admin_network/dev_status"
v.mac=arg[1]
m.redirect = luci.dispatcher.build_url("admin", "network", "appfilter")
return m

View File

@ -0,0 +1,353 @@
<style type="text/css">
<%
local dsp = require "luci.dispatcher"
-%>
#display{
display: flex;
}
table.imagetable {
font-family: verdana,arial,sans-serif;
font-size:11px;
color:#333333;
border-width: 1px;
border-color: #999999;
border-collapse: collapse;
}
<!--
table.imagetable th {
background:#f5f5f5
border-width: 0px;
padding: 5px;
border-style: solid;
border-color: #999999;
}
table.imagetable td {
background:#ffffffff
border-width: 0px;
padding: 5px;
border-style: solid;
border-color: #999999;
}-->
</style>
<script type="text/javascript" src="<%=resource%>/echarts.min.js"></script>
<script type="text/javascript">//<![CDATA[
window.onload =function(){
}
var app_class_data;
var app_time_data;
var mac='<%=self.mac%>';
function get_display_time(total_time){
var hour=parseInt(total_time / 3600);
var seconds=total_time % 3600;
var min=parseInt(seconds / 60)
var seconds2=seconds % 60;
var total_time_str;
if (hour > 0)
total_time_str=hour + "小时" + min + "分"
else{
if (min == 0 && seconds2 != 0)
min = 1;
total_time_str=min + "分"
}
return total_time_str;
}
function display_app_visit_view(data){
var myChart = echarts.init(document.getElementById('main2'));
var dev_array=new Array();
var m2R2Data=new Array()
var total_time=0
for(var i = 0; i < data.length; i++){
var dev_obj = data[i];
var m2_obj={};
m2_obj.value=dev_obj.visit_time;
m2_obj.legendname=dev_obj.app_id;
var tmp_time = get_display_time(dev_obj.visit_time);
m2_obj.name=dev_obj.app_id + " " + tmp_time;
total_time+=dev_obj.visit_time
m2R2Data.push(m2_obj);
}
var total_time_str = get_display_time(total_time);
option = {
title: [
{
text: 'APP时间统计',
textStyle: {
fontSize: 16,
color: "black"
},
left: "2%"
},
{
text: '',
subtext: total_time_str,
textStyle:{
fontSize:15,
color:"black"
},
subtextStyle: {
fontSize: 15,
color: 'black'
},
textAlign:"center",
x: '34.5%',
y: '44%',
}],
tooltip: {
trigger: 'item',
formatter:function (parms){
var total_time = get_display_time(parms.data.value);
var str= parms.seriesName+"</br>"+
parms.marker+""+parms.data.legendname+"</br>"+
"时间:"+ total_time+"</br>"+
"占比:"+ parms.percent+"%";
return str ;
}
},
legend: {
type:"scroll",
orient: 'vertical',
left:'70%',
align:'left',
top:'middle',
textStyle: {
color:'#8C8C8C'
},
height:250
},
series: [
{
name: "访问时间",
type:'pie',
center: ['35%', '50%'],
radius: ['40%', '65%'],
clockwise: false, //饼图的扇区是否是顺时针排布
avoidLabelOverlap: false,
label: {
normal: {
show: true,
position: 'outter',
formatter:function (parms){
return parms.data.legendname
}
}
},
labelLine: {
normal: {
length:8,
length2:7,
smooth:true,
}
},
data:m2R2Data
}
]
};
myChart.setOption(option);
}
function display_app_class_view(data){
console.log("begin display.");
var myChart = echarts.init(document.getElementById('main'));
var dev_array=new Array();
var m2R2Data=new Array()
var total_time=0
for(var i = 0; i < data.length; i++){
console.log("begin display222.");
var dev_obj = data[i];
if (dev_obj.visit_time == 0)
continue;
var m2_obj={};
m2_obj.value=dev_obj.visit_time;
m2_obj.legendname=dev_obj.name;
var tmp_time = get_display_time(dev_obj.visit_time);
m2_obj.name=dev_obj.name + " " + tmp_time;
total_time+=dev_obj.visit_time
m2R2Data.push(m2_obj);
}
var total_time_str = get_display_time(total_time);
option = {
title: [
{
text: 'APP分类时间统计',
textStyle: {
fontSize: 16,
color: "black"
},
left: "2%"
},
{
text: '',
subtext: total_time_str,
textStyle:{
fontSize:15,
color:"black"
},
subtextStyle: {
fontSize: 15,
color: 'black'
},
textAlign:"center",
x: '34.5%',
y: '44%',
}],
tooltip: {
trigger: 'item',
formatter:function (parms){
var total_time = get_display_time(parms.data.value);
var str= parms.seriesName+"</br>"+
parms.marker+""+parms.data.legendname+"</br>"+
"时间:"+ total_time +"</br>"+
"占比:"+ parms.percent+"%";
return str ;
}
},
legend: {
type:"scroll",
orient: 'vertical',
left:'70%',
align:'left',
top:'middle',
textStyle: {
color:'#8C8C8C'
},
height:250
},
series: [
{
name:'访问时间',
type:'pie',
center: ['35%', '50%'],
radius: ['40%', '65%'],
clockwise: false, //饼图的扇区是否是顺时针排布
avoidLabelOverlap: false,
label: {
normal: {
show: true,
position: 'outter',
formatter:function (parms){
return parms.data.legendname
}
}
},
labelLine: {
normal: {
length:8,
length2:7,
smooth:true,
}
},
data:m2R2Data
}
]
};
myChart.setOption(option);
}
new XHR().get('<%=url('admin/network/app_class_visit_time')%>/' + mac, null,
function(x, st)
{
display_app_class_view(st);
}
);
new XHR().get('<%=url('admin/network/dev_visit_time')%>/' + mac, null,
function(x, st)
{
display_app_visit_view(st);
}
);
new XHR().get('<%=url('admin/network/dev_visit_list')%>/' + mac, null,
function(x, st)
{
var tb = document.getElementById('user_status_table');
var str=JSON.stringify(st);
if (st && tb)
{
/* clear all rows */
while(tb.rows.length > 1)
tb.deleteRow(1);
for(var i = 0; i < st.length; i++ )
{
var action_status=""
if(st[i].latest_action == 1)
action_status="已过滤"
else
action_status="未过滤"
var hostname=""
if(st[i].hostname == "" || st[i].hostname == "*"){
hostname="?";
}
else{
hostname=st[i].hostname;
}
var tr = tb.insertRow(-1);
//tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
tr.insertCell(-1).innerHTML = st[i].appname;
tr.insertCell(-1).innerHTML = hostname;
tr.insertCell(-1).innerHTML = st[i].mac;
tr.insertCell(-1).innerHTML = st[i].first_time;
var hour=parseInt(st[i].total_time / 3600);
var seconds=st[i].total_time % 3600;
var min=parseInt(seconds / 60)
var total_time_str;
if (st[i].latest_action == 1)
total_time_str="-"
else {
if (hour > 0)
total_time_str=hour + "小时" + min + "分"
else{
if (min == 0)
min = 1;
total_time_str=min + "分"
}
}
tr.insertCell(-1).innerHTML = total_time_str;
tr.insertCell(-1).innerHTML = action_status;
}
}
}
);
//]]></script>
<fieldset class="cbi-section">
<div id="display">
<div id="main" style="width: 500px;height:300px;"></div>
<div id="main2" style="width: 400px;height:300px;"></div>
</div>
<table class="imagetable" id="user_status_table">
<tr>
<th ><%:App%></th>
<th ><%:主机名%></th>
<th ><%:mac地址%></th>
<th><%:开始时间%></th>
<th><%:访问时长%></th>
<th><%:过滤状态%></th>
</tr>
<tr>
<td colspan="8"><em><br /><%:Collecting data...%></em></td>
</tr>
</table>
</fieldset>

View File

@ -1,4 +1,8 @@
<style type="text/css">
<%
local dsp = require "luci.dispatcher"
-%>
table.imagetable {
font-family: verdana,arial,sans-serif;
font-size:11px;
@ -25,6 +29,7 @@ table.imagetable td {
</style>
<script type="text/javascript">//<![CDATA[
/*
XHR.poll(10, '<%=url('admin/network/user_status')%>', null,
function(x, st)
{
@ -32,7 +37,6 @@ table.imagetable td {
var str=JSON.stringify(st);
if (st && tb)
{
/* clear all rows */
while(tb.rows.length > 1)
tb.deleteRow(1);
for(var i = 0; i < st.length; i++ )
@ -51,33 +55,93 @@ table.imagetable td {
}
var tr = tb.insertRow(-1);
//tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
tr.insertCell(-1).innerHTML = hostname;
tr.insertCell(-1).innerHTML = st[i].mac;
tr.insertCell(-1).innerHTML = st[i].ip;
tr.insertCell(-1).innerHTML = st[i].appname;
tr.insertCell(-1).innerHTML = st[i].drop_num;
tr.insertCell(-1).innerHTML = st[i].total_num;
tr.insertCell(-1).innerHTML = st[i].latest_time;
tr.insertCell(-1).innerHTML = hostname;
tr.insertCell(-1).innerHTML = "<a href='<%=url('admin/network/appfilter/')%>"+st[i].mac+"'>"+st[i].mac+"</a>";
tr.insertCell(-1).innerHTML = st[i].first_time;
var hour=parseInt(st[i].total_time / 3600);
var seconds=st[i].total_time % 3600;
var min=parseInt(seconds / 60)
var total_time_str;
if (st[i].latest_action == 1)
total_time_str="-"
else {
if (hour > 0)
total_time_str=hour + "小时" + min + "分"
else{
if (min == 0)
min = 1;
total_time_str=min + "分"
}
}
tr.insertCell(-1).innerHTML = total_time_str;
tr.insertCell(-1).innerHTML = action_status;
}
}
}
);
*/
XHR.poll(5, '<%=url('admin/network/dev_app_status')%>', null,
function(x, st)
{
var tb = document.getElementById('user_status_table');
var dev_list_str=JSON.stringify(st);
if (st && tb)
{
while(tb.rows.length > 1)
tb.deleteRow(1);
var devlist = st.devlist
for(var i = 0; i < devlist.length; i++ )
{
var hostname=""
if(devlist[i].hostname == "" || devlist[i].hostname == "*"){
hostname="?";
}
else{
hostname=devlist[i].hostname;
}
var tr = tb.insertRow(-1);
//tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
tr.insertCell(-1).innerHTML = hostname;
tr.insertCell(-1).innerHTML = "<a href='<%=url('admin/network/appfilter/')%>"+devlist[i].mac+"'>"+devlist[i].mac+"</a>";
tr.insertCell(-1).innerHTML = devlist[i].ip;
var app_list_str="";
for (var j = 0; j < devlist[i].applist.length; j++){
console.log(devlist[i].applist[j].name);
app_list_str+=devlist[i].applist[j].name;
if (j != devlist[i].applist.length - 1)
app_list_str+=","
}
tr.insertCell(-1).innerHTML = app_list_str;
}
}
}
);
//]]></script>
<fieldset class="cbi-section">
<legend><%:访问记录%></legend>
<legend><%:终端列表%></legend>
<table class="imagetable" id="user_status_table">
<!--
<tr>
<th ><%:App%></th>
<th ><%:主机名%></th>
<th ><%:mac地址%></th>
<th><%:开始时间%></th>
<th><%:访问时长%></th>
<th><%:过滤状态%></th>
</tr>
-->
<tr>
<th ><%:主机名%></th>
<th ><%:mac地址%></th>
<th ><%:ip地址%></th>
<th ><%:App名称%></th>
<th><%:丢包次数%></th>
<th ><%:访问次数%></th>
<th><%:最后访问时间%></th>
<th><%:过滤状态%></th>
<th><%:常用APP(TOP5)%></th>
</tr>
<tr>
<td colspan="8"><em><br /><%:Collecting data...%></em></td>

View File

@ -2,6 +2,7 @@
uci -q batch <<-EOF >/dev/null
set appfilter.user=user
appfilter.feature=feature
commit appfilter
EOF
exit 0