From 2a74defe74f815baca31be6a2fa5fcbfc09519b2 Mon Sep 17 00:00:00 2001 From: SirPdboy <63764630+sirpdboy@users.noreply.github.com> Date: Sat, 27 Aug 2022 21:58:23 +0800 Subject: [PATCH] d --- OpenAppFilter/luci-app-oaf/Makefile | 15 - .../luci-static/resources/echarts.min.js | 22 - .../luasrc/controller/appfilter.lua | 208 --- .../model/cbi/appfilter/base_setting.lua | 90 -- .../luasrc/model/cbi/appfilter/dev_status.lua | 21 - .../luasrc/model/cbi/appfilter/feature.lua | 91 -- .../model/cbi/appfilter/time_setting.lua | 49 - .../luasrc/model/cbi/appfilter/user_list.lua | 19 - .../model/cbi/appfilter/user_setting.lua | 91 -- .../luasrc/view/admin_network/dev_status.htm | 382 ----- .../luasrc/view/admin_network/user_status.htm | 82 -- .../luasrc/view/cbi/oaf_dvalue.htm | 8 - .../luasrc/view/cbi/oaf_upload.htm | 5 - OpenAppFilter/luci-app-oaf/po/zh-cn/oaf.po | 167 --- .../root/etc/uci-defaults/91_luci-oaf | 11 - .../root/etc/uci-defaults/92_oaf_time | 8 - OpenAppFilter/oaf/Makefile | 39 - OpenAppFilter/oaf/src/Makefile | 2 - OpenAppFilter/oaf/src/af_client.c | 438 ------ OpenAppFilter/oaf/src/af_client.h | 73 - OpenAppFilter/oaf/src/af_client_fs.c | 194 --- OpenAppFilter/oaf/src/af_client_fs.h | 7 - OpenAppFilter/oaf/src/af_log.c | 87 -- OpenAppFilter/oaf/src/af_log.h | 33 - OpenAppFilter/oaf/src/af_utils.c | 330 ----- OpenAppFilter/oaf/src/af_utils.h | 16 - OpenAppFilter/oaf/src/app_filter.c | 1255 ----------------- OpenAppFilter/oaf/src/app_filter.h | 172 --- OpenAppFilter/oaf/src/app_filter_config.c | 455 ------ OpenAppFilter/oaf/src/cJSON.c | 519 ------- OpenAppFilter/oaf/src/cJSON.h | 94 -- OpenAppFilter/oaf/src/regexp.c | 302 ---- OpenAppFilter/open-app-filter/Makefile | 60 - .../open-app-filter/files/app_class.txt | 8 - .../open-app-filter/files/app_class_en.txt | 8 - .../open-app-filter/files/appfilter.config | 16 - .../open-app-filter/files/appfilter.init | 48 - .../open-app-filter/files/appfilter.lua | 262 ---- .../open-app-filter/files/appfilter.sh | 88 -- .../open-app-filter/files/feature.cfg | 216 --- .../open-app-filter/files/feature_en.cfg | 51 - .../open-app-filter/files/gen_class.sh | 30 - OpenAppFilter/open-app-filter/files/oaf_rule | 95 -- OpenAppFilter/open-app-filter/src/Makefile | 6 - .../open-app-filter/src/appfilter_config.c | 329 ----- .../open-app-filter/src/appfilter_config.h | 60 - .../open-app-filter/src/appfilter_netlink.c | 241 ---- .../open-app-filter/src/appfilter_netlink.h | 48 - .../open-app-filter/src/appfilter_ubus.c | 526 ------- .../open-app-filter/src/appfilter_ubus.h | 25 - .../open-app-filter/src/appfilter_user.c | 516 ------- .../open-app-filter/src/appfilter_user.h | 118 -- OpenAppFilter/open-app-filter/src/main.c | 138 -- 53 files changed, 8174 deletions(-) delete mode 100644 OpenAppFilter/luci-app-oaf/Makefile delete mode 100644 OpenAppFilter/luci-app-oaf/htdocs/luci-static/resources/echarts.min.js delete mode 100644 OpenAppFilter/luci-app-oaf/luasrc/controller/appfilter.lua delete mode 100644 OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/base_setting.lua delete mode 100644 OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/dev_status.lua delete mode 100644 OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/feature.lua delete mode 100644 OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/time_setting.lua delete mode 100644 OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/user_list.lua delete mode 100644 OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/user_setting.lua delete mode 100644 OpenAppFilter/luci-app-oaf/luasrc/view/admin_network/dev_status.htm delete mode 100644 OpenAppFilter/luci-app-oaf/luasrc/view/admin_network/user_status.htm delete mode 100644 OpenAppFilter/luci-app-oaf/luasrc/view/cbi/oaf_dvalue.htm delete mode 100644 OpenAppFilter/luci-app-oaf/luasrc/view/cbi/oaf_upload.htm delete mode 100644 OpenAppFilter/luci-app-oaf/po/zh-cn/oaf.po delete mode 100644 OpenAppFilter/luci-app-oaf/root/etc/uci-defaults/91_luci-oaf delete mode 100644 OpenAppFilter/luci-app-oaf/root/etc/uci-defaults/92_oaf_time delete mode 100644 OpenAppFilter/oaf/Makefile delete mode 100644 OpenAppFilter/oaf/src/Makefile delete mode 100644 OpenAppFilter/oaf/src/af_client.c delete mode 100644 OpenAppFilter/oaf/src/af_client.h delete mode 100644 OpenAppFilter/oaf/src/af_client_fs.c delete mode 100644 OpenAppFilter/oaf/src/af_client_fs.h delete mode 100644 OpenAppFilter/oaf/src/af_log.c delete mode 100644 OpenAppFilter/oaf/src/af_log.h delete mode 100644 OpenAppFilter/oaf/src/af_utils.c delete mode 100644 OpenAppFilter/oaf/src/af_utils.h delete mode 100644 OpenAppFilter/oaf/src/app_filter.c delete mode 100644 OpenAppFilter/oaf/src/app_filter.h delete mode 100644 OpenAppFilter/oaf/src/app_filter_config.c delete mode 100644 OpenAppFilter/oaf/src/cJSON.c delete mode 100644 OpenAppFilter/oaf/src/cJSON.h delete mode 100644 OpenAppFilter/oaf/src/regexp.c delete mode 100644 OpenAppFilter/open-app-filter/Makefile delete mode 100644 OpenAppFilter/open-app-filter/files/app_class.txt delete mode 100644 OpenAppFilter/open-app-filter/files/app_class_en.txt delete mode 100644 OpenAppFilter/open-app-filter/files/appfilter.config delete mode 100644 OpenAppFilter/open-app-filter/files/appfilter.init delete mode 100644 OpenAppFilter/open-app-filter/files/appfilter.lua delete mode 100644 OpenAppFilter/open-app-filter/files/appfilter.sh delete mode 100644 OpenAppFilter/open-app-filter/files/feature.cfg delete mode 100644 OpenAppFilter/open-app-filter/files/feature_en.cfg delete mode 100644 OpenAppFilter/open-app-filter/files/gen_class.sh delete mode 100644 OpenAppFilter/open-app-filter/files/oaf_rule delete mode 100644 OpenAppFilter/open-app-filter/src/Makefile delete mode 100644 OpenAppFilter/open-app-filter/src/appfilter_config.c delete mode 100644 OpenAppFilter/open-app-filter/src/appfilter_config.h delete mode 100644 OpenAppFilter/open-app-filter/src/appfilter_netlink.c delete mode 100644 OpenAppFilter/open-app-filter/src/appfilter_netlink.h delete mode 100644 OpenAppFilter/open-app-filter/src/appfilter_ubus.c delete mode 100644 OpenAppFilter/open-app-filter/src/appfilter_ubus.h delete mode 100644 OpenAppFilter/open-app-filter/src/appfilter_user.c delete mode 100644 OpenAppFilter/open-app-filter/src/appfilter_user.h delete mode 100644 OpenAppFilter/open-app-filter/src/main.c diff --git a/OpenAppFilter/luci-app-oaf/Makefile b/OpenAppFilter/luci-app-oaf/Makefile deleted file mode 100644 index 764ec74..0000000 --- a/OpenAppFilter/luci-app-oaf/Makefile +++ /dev/null @@ -1,15 +0,0 @@ - -# -# This is free software, licensed under the Apache License, Version 2.0 . -# - -include $(TOPDIR)/rules.mk - -LUCI_TITLE:=Open App Filter Module -LUCI_PKGARCH:=all -LUCI_DEPENDS:=+kmod-oaf +appfilter -PKG_NAME:=luci-app-oaf -PKG_VERSION:=5.0 -PKG_RELEASE:=1 -include $(TOPDIR)/feeds/luci/luci.mk -# call BuildPackage - OpenWrt buildroot signature diff --git a/OpenAppFilter/luci-app-oaf/htdocs/luci-static/resources/echarts.min.js b/OpenAppFilter/luci-app-oaf/htdocs/luci-static/resources/echarts.min.js deleted file mode 100644 index 4b25b97..0000000 --- a/OpenAppFilter/luci-app-oaf/htdocs/luci-static/resources/echarts.min.js +++ /dev/null @@ -1,22 +0,0 @@ - -/* -* Licensed to the Apache Software Foundation (ASF) under one -* or more contributor license agreements. See the NOTICE file -* distributed with this work for additional information -* regarding copyright ownership. The ASF licenses this file -* to you under the Apache License, Version 2.0 (the -* "License"); you may not use this file except in compliance -* with the License. You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, -* software distributed under the License is distributed on an -* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -* KIND, either express or implied. See the License for the -* specific language governing permissions and limitations -* under the License. -*/ - - -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e(t.echarts={})}(this,function(t){"use strict";var e=2311,n=function(){return e++},v="object"==typeof wx&&"function"==typeof wx.getSystemInfoSync?{browser:{},os:{},node:!1,wxa:!0,canvasSupported:!0,svgSupported:!1,touchEventsSupported:!0,domSupported:!1}:"undefined"==typeof document&&"undefined"!=typeof self?{browser:{},os:{},node:!1,worker:!0,canvasSupported:!0,domSupported:!1}:"undefined"==typeof navigator?{browser:{},os:{},node:!0,worker:!1,canvasSupported:!0,svgSupported:!0,domSupported:!1}:function(t){var e={},i=t.match(/Firefox\/([\d.]+)/),n=t.match(/MSIE\s([\d.]+)/)||t.match(/Trident\/.+?rv:(([\d.]+))/),o=t.match(/Edge\/([\d.]+)/),a=/micromessenger/i.test(t);i&&(e.firefox=!0,e.version=i[1]);n&&(e.ie=!0,e.version=n[1]);o&&(e.edge=!0,e.version=o[1]);a&&(e.weChat=!0);return{browser:e,os:{},node:!1,canvasSupported:!!document.createElement("canvas").getContext,svgSupported:"undefined"!=typeof SVGRect,touchEventsSupported:"ontouchstart"in window&&!e.ie&&!e.edge,pointerEventsSupported:"onpointerdown"in window&&(e.edge||e.ie&&11<=e.version),domSupported:"undefined"!=typeof document}}(navigator.userAgent);var s={"[object Function]":1,"[object RegExp]":1,"[object Date]":1,"[object Error]":1,"[object CanvasGradient]":1,"[object CanvasPattern]":1,"[object Image]":1,"[object Canvas]":1},l={"[object Int8Array]":1,"[object Uint8Array]":1,"[object Uint8ClampedArray]":1,"[object Int16Array]":1,"[object Uint16Array]":1,"[object Int32Array]":1,"[object Uint32Array]":1,"[object Float32Array]":1,"[object Float64Array]":1},u=Object.prototype.toString,i=Array.prototype,r=i.forEach,h=i.filter,o=i.slice,c=i.map,d=i.reduce,a={};function f(t,e){"createCanvas"===t&&(g=null),a[t]=e}function k(t){if(null==t||"object"!=typeof t)return t;var e=t,i=u.call(t);if("[object Array]"===i){if(!$(t)){e=[];for(var n=0,o=t.length;n>1)%2;s.cssText=["position: absolute","visibility: hidden","padding: 0","margin: 0","border-width: 0","user-select: none","width:0","height:0",n[l]+":0",o[u]+":0",n[1-l]+":auto",o[1-u]+":auto",""].join("!important;"),t.appendChild(r),i.push(r)}return i}(e,a),a,o);if(r)return r(t,i,n),!0}return!1}function zt(t){return"CANVAS"===t.nodeName.toUpperCase()}var Bt="undefined"!=typeof window&&!!window.addEventListener,Vt=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Gt=[];function Ft(t,e,i,n){return i=i||{},n||!v.canvasSupported?Wt(t,e,i):v.browser.firefox&&null!=e.layerX&&e.layerX!==e.offsetX?(i.zrX=e.layerX,i.zrY=e.layerY):null!=e.offsetX?(i.zrX=e.offsetX,i.zrY=e.offsetY):Wt(t,e,i),i}function Wt(t,e,i){if(v.domSupported&&t.getBoundingClientRect){var n=e.clientX,o=e.clientY;if(zt(t)){var a=t.getBoundingClientRect();return i.zrX=n-a.left,void(i.zrY=o-a.top)}if(Et(Gt,t,n,o))return i.zrX=Gt[0],void(i.zrY=Gt[1])}i.zrX=i.zrY=0}function Ht(t){return t||window.event}function Zt(t,e,i){if(null!=(e=Ht(e)).zrX)return e;var n=e.type;if(n&&0<=n.indexOf("touch")){var o="touchend"!==n?e.targetTouches[0]:e.changedTouches[0];o&&Ft(t,o,e,i)}else Ft(t,e,e,i),e.zrDelta=e.wheelDelta?e.wheelDelta/120:-(e.detail||0)/3;var a=e.button;return null==e.which&&void 0!==a&&Vt.test(e.type)&&(e.which=1&a?1:2&a?3:4&a?2:0),e}function Ut(t,e,i,n){Bt?t.addEventListener(e,i,n):t.attachEvent("on"+e,i)}var Xt=Bt?function(t){t.preventDefault(),t.stopPropagation(),t.cancelBubble=!0}:function(t){t.returnValue=!1,t.cancelBubble=!0};function Yt(t){return 2===t.which||3===t.which}function jt(){this._track=[]}function qt(t){var e=t[1][0]-t[0][0],i=t[1][1]-t[0][1];return Math.sqrt(e*e+i*i)}jt.prototype={constructor:jt,recognize:function(t,e,i){return this._doTrack(t,e,i),this._recognize(t)},clear:function(){return this._track.length=0,this},_doTrack:function(t,e,i){var n=t.touches;if(n){for(var o={points:[],touches:[],target:e,event:t},a=0,r=n.length;an.getWidth()||i<0||i>n.getHeight()}te.prototype={constructor:te,setHandlerProxy:function(e){this.proxy&&this.proxy.dispose(),e&&(R(ee,function(t){e.on&&e.on(t,this[t],this)},this),e.handler=this),this.proxy=e},mousemove:function(t){var e=t.zrX,i=t.zrY,n=ne(this,e,i),o=this._hovered,a=o.target;a&&!a.__zr&&(a=(o=this.findHover(o.x,o.y)).target);var r=this._hovered=n?{x:e,y:i}:this.findHover(e,i),s=r.target,l=this.proxy;l.setCursor&&l.setCursor(s?s.cursor:"default"),a&&s!==a&&this.dispatchToElement(o,"mouseout",t),this.dispatchToElement(r,"mousemove",t),s&&s!==a&&this.dispatchToElement(r,"mouseover",t)},mouseout:function(t){var e=t.zrEventControl,i=t.zrIsToLocalDOM;"only_globalout"!==e&&this.dispatchToElement(this._hovered,"mouseout",t),"no_globalout"!==e&&(i||this.trigger("globalout",{type:"globalout",event:t}))},resize:function(t){this._hovered={}},dispatch:function(t,e){var i=this[t];i&&i.call(this,e)},dispose:function(){this.proxy.dispose(),this.storage=this.proxy=this.painter=null},setCursorStyle:function(t){var e=this.proxy;e.setCursor&&e.setCursor(t)},dispatchToElement:function(t,e,i){var n=(t=t||{}).target;if(!n||!n.silent){for(var o="on"+e,a=function(t,e,i){return{type:t,event:i,target:e.target,topTarget:e.topTarget,cancelBubble:!1,offsetX:i.zrX,offsetY:i.zrY,gestureEvent:i.gestureEvent,pinchX:i.pinchX,pinchY:i.pinchY,pinchScale:i.pinchScale,wheelDelta:i.zrDelta,zrByTouch:i.zrByTouch,which:i.which,stop:Jt}}(e,t,i);n&&(n[o]&&(a.cancelBubble=n[o].call(n,a)),n.trigger(e,a),n=n.parent,!a.cancelBubble););a.cancelBubble||(this.trigger(e,a),this.painter&&this.painter.eachOtherLayer(function(t){"function"==typeof t[o]&&t[o].call(t,a),t.trigger&&t.trigger(e,a)}))}},findHover:function(t,e,i){for(var n=this.storage.getDisplayList(),o={x:t,y:e},a=n.length-1;0<=a;a--){var r;if(n[a]!==i&&!n[a].ignore&&(r=ie(n[a],t,e))&&(o.topTarget||(o.topTarget=n[a]),r!==$t)){o.target=n[a];break}}return o},processGesture:function(t,e){this._gestureMgr||(this._gestureMgr=new jt);var i=this._gestureMgr;"start"===e&&i.clear();var n=i.recognize(t,this.findHover(t.zrX,t.zrY,null).target,this.proxy.dom);if("end"===e&&i.clear(),n){var o=n.type;t.gestureEvent=o,this.dispatchToElement({target:n.target},o,n.event)}}},R(["click","mousedown","mouseup","mousewheel","dblclick","contextmenu"],function(r){te.prototype[r]=function(t){var e,i,n=t.zrX,o=t.zrY,a=ne(this,n,o);if("mouseup"===r&&a||(i=(e=this.findHover(n,o)).target),"mousedown"===r)this._downEl=i,this._downPoint=[t.zrX,t.zrY],this._upEl=i;else if("mouseup"===r)this._upEl=i;else if("click"===r){if(this._downEl!==this._upEl||!this._downPoint||4=this._maxSize&&0>4|(3840&n)>>8,240&n|(240&n)>>4,15&n|(15&n)<<4,1),Ge(t,e),e):void Ee(e,0,0,0,1):7===o.length?0<=(n=parseInt(o.substr(1),16))&&n<=16777215?(Ee(e,(16711680&n)>>16,(65280&n)>>8,255&n,1),Ge(t,e),e):void Ee(e,0,0,0,1):void 0;var a=o.indexOf("("),r=o.indexOf(")");if(-1!==a&&r+1===o.length){var s=o.substr(0,a),l=o.substr(a+1,r-(a+1)).split(","),u=1;switch(s){case"rgba":if(4!==l.length)return void Ee(e,0,0,0,1);u=Ne(l.pop());case"rgb":return 3!==l.length?void Ee(e,0,0,0,1):(Ee(e,Pe(l[0]),Pe(l[1]),Pe(l[2]),u),Ge(t,e),e);case"hsla":return 4!==l.length?void Ee(e,0,0,0,1):(l[3]=Ne(l[3]),We(l,e),Ge(t,e),e);case"hsl":return 3!==l.length?void Ee(e,0,0,0,1):(We(l,e),Ge(t,e),e);default:return}}Ee(e,0,0,0,1)}}function We(t,e){var i=(parseFloat(t[0])%360+360)%360/360,n=Ne(t[1]),o=Ne(t[2]),a=o<=.5?o*(n+1):o+n-o*n,r=2*o-a;return Ee(e=e||[],Le(255*Oe(r,a,i+1/3)),Le(255*Oe(r,a,i)),Le(255*Oe(r,a,i-1/3)),1),4===t.length&&(e[3]=t[3]),e}function He(t,e){var i=Fe(t);if(i){for(var n=0;n<3;n++)i[n]=e<0?i[n]*(1-e)|0:(255-i[n])*e+i[n]|0,255e);i++);i=Math.min(i-1,u-2)}C=e;var n=g[(D=i)+1]-g[i];if(0!=n)if(S=(e-g[i])/n,l)if(I=m[i],M=m[0===i?i:i-1],T=m[u-2=i.x&&t<=i.x+i.width&&e>=i.y&&e<=i.y+i.height},clone:function(){return new Di(this.x,this.y,this.width,this.height)},copy:function(t){this.x=t.x,this.y=t.y,this.width=t.width,this.height=t.height},plain:function(){return{x:this.x,y:this.y,width:this.width,height:this.height}}},Di.create=function(t){return new Di(t.x,t.y,t.width,t.height)};var Ci=function(t){for(var e in t=t||{},_i.call(this,t),t)t.hasOwnProperty(e)&&(this[e]=t[e]);this._children=[],this.__storage=null,this.__dirty=!0};Ci.prototype={constructor:Ci,isGroup:!0,type:"group",silent:!1,children:function(){return this._children.slice()},childAt:function(t){return this._children[t]},childOfName:function(t){for(var e=this._children,i=0;i>>1])<0?l=a:s=1+a;var u=n-s;switch(u){case 3:t[s+3]=t[s+2];case 2:t[s+2]=t[s+1];case 1:t[s+1]=t[s];break;default:for(;0>>1);0>>1);a(t,e[i+h])<0?l=h:r=h+1}return l}function Ei(p,g){var r,s,m=ki,l=0,v=[];function e(t){var e=r[t],i=s[t],n=r[t+1],o=s[t+1];s[t]=i+o,t===l-3&&(r[t+1]=r[t+2],s[t+1]=s[t+2]),l--;var a=Ri(p[n],p,e,i,0,g);e+=a,0!==(i-=a)&&0!==(o=Oi(p[e+i-1],p,n,o,o-1,g))&&(i<=o?function(t,e,i,n){var o=0;for(o=0;os[t+1])break;e(t)}},this.forceMergeRuns=function(){for(;1>=1;return t+e}(o);do{if((a=Pi(t,i,n,e))=e.maxIterations){t+=e.ellipsis;break}var s=0===r?bn(t,o,e.ascCharWidth,e.cnCharWidth):0f)return{lines:[],width:0,height:0};C.textWidth=pn(C.text,w);var S=x.textWidth,M=null==S||"auto"===S;if("string"==typeof S&&"%"===S.charAt(S.length-1))C.percentWidth=S,u.push(C),S=0;else{if(M){S=C.textWidth;var I=x.textBackgroundColor,T=I&&I.image;T&&sn(T=on(T))&&(S=Math.max(S,T.width*b/T.height))}var A=_?_[1]+_[3]:0;S+=A;var D=null!=d?d-v:null;null!=D&&Dn[0]){for(r=0;rt);r++);a=i[n[r]]}if(n.splice(r+1,0,t),!(i[t]=e).virtual)if(a){var l=a.dom;l.nextSibling?s.insertBefore(e.dom,l.nextSibling):s.appendChild(e.dom)}else s.firstChild?s.insertBefore(e.dom,s.firstChild):s.appendChild(e.dom)}else vi("Layer of zlevel "+t+" is not valid")},eachLayer:function(t,e){var i,n,o=this._zlevelList;for(n=0;n=a.length&&a.push({option:t})}}),a}function Zo(t){var r=Q();Ro(t,function(t,e){var i=t.exist;i&&r.set(i.id,t)}),Ro(t,function(t,e){var i=t.option;Y(!i||null==i.id||!r.get(i.id)||r.get(i.id)===t,"id duplicates: "+(i&&i.id)),i&&null!=i.id&&r.set(i.id,t),t.keyInfo||(t.keyInfo={})}),Ro(t,function(t,e){var i=t.exist,n=t.option,o=t.keyInfo;if(Eo(n)){if(o.name=null!=n.name?n.name+"":i?i.name:Bo+e,i)o.id=i.id;else if(null!=n.id)o.id=n.id+"";else for(var a=0;o.id="\0"+o.name+"\0"+a++,r.get(o.id););r.set(o.id,t)}})}function Uo(t){var e=t.name;return!(!e||!e.indexOf(Bo))}function Xo(t){return Eo(t)&&t.id&&0===(t.id+"").indexOf("\0_ec_\0")}function Yo(e,t){return null!=t.dataIndexInside?t.dataIndexInside:null!=t.dataIndex?L(t.dataIndex)?O(t.dataIndex,function(t){return e.indexOfRawIndex(t)}):e.indexOfRawIndex(t.dataIndex):null!=t.name?L(t.name)?O(t.name,function(t){return e.indexOfName(t)}):e.indexOfName(t.name):void 0}function jo(){var e="__\0ec_inner_"+qo+++"_"+Math.random().toFixed(5);return function(t){return t[e]||(t[e]={})}}var qo=0;function Ko(s,l,u){if(E(l)){var t={};t[l+"Index"]=0,l=t}var e=u&&u.defaultMainType;!e||$o(l,e+"Index")||$o(l,e+"Id")||$o(l,e+"Name")||(l[e+"Index"]=0);var h={};return Ro(l,function(t,e){t=l[e];if("dataIndex"!==e&&"dataIndexInside"!==e){var i=e.match(/^(\w+)(Index|Id|Name)$/)||[],n=i[1],o=(i[2]||"").toLowerCase();if(!(!n||!o||null==t||"index"===o&&"none"===t||u&&u.includeMainTypes&&_(u.includeMainTypes,n)<0)){var a={mainType:n};"index"===o&&"all"===t||(a[o]=t);var r=s.queryComponents(a);h[n+"Models"]=r,h[n+"Model"]=r[0]}}else h[e]=t}),h}function $o(t,e){return t&&t.hasOwnProperty(e)}function Jo(t,e,i){t.setAttribute?t.setAttribute(e,i):t[e]=i}function Qo(t){return"auto"===t?v.domSupported?"html":"richText":t||"html"}function ta(t,i){var n=Q(),o=[];return R(t,function(t){var e=i(t);(n.get(e)||(o.push(e),n.set(e,[]))).push(t)}),{keys:o,buckets:n}}var ea=".",ia="___EC__COMPONENT__CONTAINER___";function na(t){var e={main:"",sub:""};return t&&(t=t.split(ea),e.main=t[0]||"",e.sub=t[1]||""),e}function oa(t){(t.$constructor=t).extend=function(t){function e(){t.$constructor?t.$constructor.apply(this,arguments):i.apply(this,arguments)}var i=this;return P(e.prototype,t),e.extend=this.extend,e.superCall=sa,e.superApply=la,w(e,this),e.superClass=i,e}}var aa=0;function ra(t){var e=["__\0is_clz",aa++,Math.random().toFixed(3)].join("_");t.prototype[e]=!0,t.isInstance=function(t){return!(!t||!t[e])}}function sa(t,e){var i=U(arguments,2);return this.superClass.prototype[e].apply(t,i)}function la(t,e,i){return this.superClass.prototype[e].apply(t,i)}function ua(i,t){t=t||{};var o={};if(i.registerClass=function(t,e){if(e)if(function(t){Y(/^[a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)?$/.test(t),'componentType "'+t+'" illegal')}(e),(e=na(e)).sub){if(e.sub!==ia){(function(t){var e=o[t.main];e&&e[ia]||((e=o[t.main]={})[ia]=!0);return e})(e)[e.sub]=t}}else o[e.main]=t;return t},i.getClass=function(t,e,i){var n=o[t];if(n&&n[ia]&&(n=e?n[e]:null),i&&!n)throw new Error(e?"Component "+t+"."+(e||"")+" not exists. Load it first.":t+".type should be specified.");return n},i.getClassesByMainType=function(t){t=na(t);var i=[],e=o[t.main];return e&&e[ia]?R(e,function(t,e){e!==ia&&i.push(t)}):i.push(e),i},i.hasClass=function(t){return t=na(t),!!o[t.main]},i.getAllClassMainTypes=function(){var i=[];return R(o,function(t,e){i.push(e)}),i},i.hasSubTypes=function(t){t=na(t);var e=o[t.main];return e&&e[ia]},i.parseClassType=na,t.registerWhenExtend){var n=i.extend;n&&(i.extend=function(t){var e=n.call(this,t);return i.registerClass(e,t.type)})}return i}function ha(s){for(var t=0;tthis._ux||or(e-this._yi)>this._uy||this._len<5;return this.addData(ja.L,t,e),this._ctx&&i&&(this._needsDash()?this._dashedLineTo(t,e):this._ctx.lineTo(t,e)),i&&(this._xi=t,this._yi=e),this},bezierCurveTo:function(t,e,i,n,o,a){return this.addData(ja.C,t,e,i,n,o,a),this._ctx&&(this._needsDash()?this._dashedBezierTo(t,e,i,n,o,a):this._ctx.bezierCurveTo(t,e,i,n,o,a)),this._xi=o,this._yi=a,this},quadraticCurveTo:function(t,e,i,n){return this.addData(ja.Q,t,e,i,n),this._ctx&&(this._needsDash()?this._dashedQuadraticTo(t,e,i,n):this._ctx.quadraticCurveTo(t,e,i,n)),this._xi=i,this._yi=n,this},arc:function(t,e,i,n,o,a){return this.addData(ja.A,t,e,i,i,n,o-n,0,a?0:1),this._ctx&&this._ctx.arc(t,e,i,n,o,a),this._xi=er(o)*i+t,this._yi=ir(o)*i+e,this},arcTo:function(t,e,i,n,o){return this._ctx&&this._ctx.arcTo(t,e,i,n,o),this},rect:function(t,e,i,n){return this._ctx&&this._ctx.rect(t,e,i,n),this.addData(ja.R,t,e,i,n),this},closePath:function(){this.addData(ja.Z);var t=this._ctx,e=this._x0,i=this._y0;return t&&(this._needsDash()&&this._dashedLineTo(e,i),t.closePath()),this._xi=e,this._yi=i,this},fill:function(t){t&&t.fill(),this.toStatic()},stroke:function(t){t&&t.stroke(),this.toStatic()},setLineDash:function(t){if(t instanceof Array){this._lineDash=t;for(var e=this._dashIdx=0,i=0;ie.length&&(this._expandData(),e=this.data);for(var i=0;il||or(r-o)>u||c===h-1)&&(t.lineTo(a,r),n=a,o=r);break;case ja.C:t.bezierCurveTo(s[c++],s[c++],s[c++],s[c++],s[c++],s[c++]),n=s[c-2],o=s[c-1];break;case ja.Q:t.quadraticCurveTo(s[c++],s[c++],s[c++],s[c++]),n=s[c-2],o=s[c-1];break;case ja.A:var f=s[c++],p=s[c++],g=s[c++],m=s[c++],v=s[c++],y=s[c++],x=s[c++],_=s[c++],w=m=yr[n=0]+t&&r<=yr[1]+t?h:0}if(a){l=n;n=cr(o),o=cr(l)}else n=cr(n),o=cr(o);oMath.PI/2&&p<1.5*Math.PI&&(h=-h),c+=h)}}return c}function Sr(t,e,i,n,o){for(var a=0,r=0,s=0,l=0,u=0,h=0;hMath.abs(a[1])?0=e[1])return i[1]}else{if(t>=e[0])return i[0];if(t<=e[1])return i[1]}else{if(t===e[0])return i[0];if(t===e[1])return i[1]}return(t-e[0])/o*a+i[0]}function El(t,e){switch(t){case"center":case"middle":t="50%";break;case"left":case"top":t="0%";break;case"right":case"bottom":t="100%"}return"string"==typeof t?function(t){return t.replace(/^\s+|\s+$/g,"")}(t).match(/%$/)?parseFloat(t)/100*e:parseFloat(t):null==t?NaN:+t}function zl(t,e,i){return null==e&&(e=10),e=Math.min(Math.max(0,e),20),t=(+t).toFixed(e),i?t:+t}function Bl(t){return t.sort(function(t,e){return t-e}),t}function Vl(t){if(t=+t,isNaN(t))return 0;for(var e=1,i=0;Math.round(t*e)/e!==t;)e*=10,i++;return i}function Gl(t){var e=t.toString(),i=e.indexOf("e");if(0h&&(h=u[d],c=d);++s[c],u[c]=0,++l}return s[e]/o}var Hl=9007199254740991;function Zl(t){var e=2*Math.PI;return(t%e+e)%e}function Ul(t){return-Ol"'])/g,ou={"&":"&","<":"<",">":">",'"':""","'":"'"};function au(t){return null==t?"":(t+"").replace(nu,function(t,e){return ou[e]})}function ru(t,e){return"{"+t+(null==e?"":e)+"}"}var su=["a","b","c","d","e","f","g"];function lu(t,e,i){L(e)||(e=[e]);var n=e.length;if(!n)return"";for(var o=e[0].$vars||[],a=0;a':'':{renderMode:o,content:"{marker"+a+"|} ",style:{color:i}}:""}function cu(t,e){return"0000".substr(0,e-(t+="").length)+t}function du(t,e,i){"week"!==t&&"month"!==t&&"quarter"!==t&&"half-year"!==t&&"year"!==t||(t="MM-dd\nyyyy");var n=Yl(e),o=i?"UTC":"",a=n["get"+o+"FullYear"](),r=n["get"+o+"Month"]()+1,s=n["get"+o+"Date"](),l=n["get"+o+"Hours"](),u=n["get"+o+"Minutes"](),h=n["get"+o+"Seconds"](),c=n["get"+o+"Milliseconds"]();return t=t.replace("MM",cu(r,2)).replace("M",r).replace("yyyy",a).replace("yy",a%100).replace("dd",cu(s,2)).replace("d",s).replace("hh",cu(l,2)).replace("h",l).replace("mm",cu(u,2)).replace("m",u).replace("ss",cu(h,2)).replace("s",h).replace("SSS",cu(c,3))}function fu(t){return t?t.charAt(0).toUpperCase()+t.substr(1):t}var pu=xn;function gu(t,e){if("_blank"===e||"blank"===e){var i=window.open();i.opener=null,i.location=t}else window.open(t,e)}var mu=(Object.freeze||Object)({addCommas:tu,toCamelCase:eu,normalizeCssArray:iu,encodeHTML:au,formatTpl:lu,formatTplSimple:uu,getTooltipMarker:hu,formatTime:du,capitalFirst:fu,truncateText:pu,getTextBoundingRect:function(t){return gn(t.text,t.font,t.textAlign,t.textVerticalAlign,t.textPadding,t.textLineHeight,t.rich,t.truncate)},getTextRect:function(t,e,i,n,o,a,r,s){return gn(t,e,i,n,o,s,a,r)},windowOpen:gu}),vu=R,yu=["left","right","top","bottom","width","height"],xu=[["width","left","right"],["height","top","bottom"]];function _u(h,c,d,f,p){var g=0,m=0;null==f&&(f=1/0),null==p&&(p=1/0);var v=0;c.eachChild(function(t,e){var i,n,o=t.position,a=t.getBoundingRect(),r=c.childAt(e+1),s=r&&r.getBoundingRect();if("horizontal"===h){var l=a.width+(s?-s.x+a.x:0);v=f<(i=g+l)||t.newline?(g=0,i=l,m+=v+d,a.height):Math.max(v,a.height)}else{var u=a.height+(s?-s.y+a.y:0);v=p<(n=m+u)||t.newline?(g+=v+d,m=0,n=u,a.width):Math.max(v,a.width)}t.newline||(o[0]=g,o[1]=m,"horizontal"===h?g=i+d:m=n+d)})}var wu=_u;T(_u,"vertical"),T(_u,"horizontal");function bu(t,e,i){i=iu(i||0);var n=e.width,o=e.height,a=El(t.left,n),r=El(t.top,o),s=El(t.right,n),l=El(t.bottom,o),u=El(t.width,n),h=El(t.height,o),c=i[2]+i[0],d=i[1]+i[3],f=t.aspect;switch(isNaN(u)&&(u=n-s-d-a),isNaN(h)&&(h=o-l-c-r),null!=f&&(isNaN(u)&&isNaN(h)&&(n/oe)return t[n];return t[i-1]}(s,i):r;if((l=l||r)&&l.length){var u=l[o];return t&&(a[t]=u),n.colorIdx=(o+1)%l.length,u}}},zu="original",Bu="arrayRows",Vu="objectRows",Gu="keyedColumns",Fu="unknown",Wu="typedArray",Hu="column",Zu="row";function Uu(t){this.fromDataset=t.fromDataset,this.data=t.data||(t.sourceFormat===Gu?{}:[]),this.sourceFormat=t.sourceFormat||Fu,this.seriesLayoutBy=t.seriesLayoutBy||Hu,this.dimensionsDefine=t.dimensionsDefine,this.encodeDefine=t.encodeDefine&&Q(t.encodeDefine),this.startIndex=t.startIndex||0,this.dimensionsDetectCount=t.dimensionsDetectCount}Uu.seriesDataToSource=function(t){return new Uu({data:t,sourceFormat:V(t)?Wu:zu,fromDataset:!1})},ra(Uu);var Xu={Must:1,Might:2,Not:3},Yu=jo();function ju(t){var e=t.option,i=e.data,n=V(i)?Wu:zu,o=!1,a=e.seriesLayoutBy,r=e.sourceHeader,s=e.dimensions,l=Qu(t);if(l){var u=l.option;i=u.source,n=Yu(l).sourceFormat,o=!0,a=a||u.seriesLayoutBy,null==r&&(r=u.sourceHeader),s=s||u.dimensions}var h=function(t,e,i,n,o){if(!t)return{dimensionsDefine:qu(o)};var a,r;if(e===Bu)"auto"===n||null==n?Ku(function(t){null!=t&&"-"!==t&&(E(t)?null==r&&(r=1):r=0)},i,t,10):r=n?1:0,o||1!==r||(o=[],Ku(function(t,e){o[e]=null!=t?t:""},i,t)),a=o?o.length:i===Zu?t.length:t[0]?t[0].length:null;else if(e===Vu)o=o||function(t){var e,i=0;for(;i":"\n",f="richText"===c,p={},g=0;function i(t){return{renderMode:c,content:au(tu(t)),style:p}}var m=this.getData(),a=m.mapDimension("defaultedTooltip",!0),n=a.length,r=this.getRawValue(o),s=L(r),v=m.getItemVisual(o,"color");z(v)&&v.colorStops&&(v=(v.colorStops[0]||{}).color),v=v||"transparent";var l=(1":"",n=i+u.join(i||", ");return{renderMode:c,content:n,style:p}}(r):i(n?Hh(m,o,a[0]):s?r[0]:r)).content,u=d.seriesIndex+"at"+g,y=hu({color:v,type:"item",renderMode:c,markerId:u});p[u]=v,++g;var x=m.getName(o),_=this.name;Uo(this)||(_=""),_=_?au(_)+(h?": ":e):"";var w="string"==typeof y?y:y.content;return{html:h?w+_+l:_+w+(x?au(x)+": "+l:l),markers:p}},isAnimationEnabled:function(){if(v.node)return!1;var t=this.getShallow("animation");return t&&this.getData().count()>this.getShallow("animationThreshold")&&(t=!1),t},restoreData:function(){this.dataTask.dirty()},getColorFromPalette:function(t,e,i){var n=this.ecModel,o=Eu.getColorFromPalette.call(this,t,e,i);return o=o||n.getColorFromPalette(t,e,i)},coordDimToDataDim:function(t){return this.getRawData().mapDimension(t,!0)},getProgressive:function(){return this.get("progressive")},getProgressiveThreshold:function(){return this.get("progressiveThreshold")},getAxisTooltipData:null,getTooltipPosition:null,pipeTask:null,preventIncremental:null,pipelineContext:null});function lc(t){var e=t.name;Uo(t)||(t.name=function(t){var i=t.getRawData(),e=i.mapDimension("seriesName",!0),n=[];return R(e,function(t){var e=i.getDimensionInfo(t);e.displayName&&n.push(e.displayName)}),n.join(" ")}(t)||e)}function uc(t){return t.model.getRawData().count()}function hc(t){var e=t.model;return e.setData(e.getRawData().cloneShallow()),cc}function cc(t,e){e.outputData&&t.end>e.outputData.count()&&e.model.getRawData().cloneShallow(e.outputData)}function dc(e,i){R(e.CHANGABLE_METHODS,function(t){e.wrapMethod(t,T(fc,i))})}function fc(t){var e=pc(t);e&&e.setOutputEnd(this.count())}function pc(t){var e=(t.ecModel||{}).scheduler,i=e&&e.getPipeline(t.uid);if(i){var n=i.currentTask;if(n){var o=n.agentStubMap;o&&(n=o.get(t.uid))}return n}}b(sc,Xh),b(sc,Eu);var gc=function(){this.group=new Ci,this.uid=Nl("viewComponent")};gc.prototype={constructor:gc,init:function(t,e){},render:function(t,e,i,n){},dispose:function(){},filterForExposedEvent:null};var mc=gc.prototype;mc.updateView=mc.updateLayout=mc.updateVisual=function(t,e,i,n){},oa(gc),ua(gc,{registerWhenExtend:!0});function vc(){var s=jo();return function(t){var e=s(t),i=t.pipelineContext,n=e.large,o=e.progressiveRender,a=e.large=i&&i.large,r=e.progressiveRender=i&&i.progressiveRender;return!!(n^a||o^r)&&"reset"}}var yc=jo(),xc=vc();function _c(){this.group=new Ci,this.uid=Nl("viewChart"),this.renderTask=Yh({plan:Mc,reset:Ic}),this.renderTask.context={view:this}}var wc=_c.prototype={type:"chart",init:function(t,e){},render:function(t,e,i,n){},highlight:function(t,e,i,n){Sc(t.getData(),n,"emphasis")},downplay:function(t,e,i,n){Sc(t.getData(),n,"normal")},remove:function(t,e){this.group.removeAll()},dispose:function(){},incrementalPrepareRender:null,incrementalRender:null,updateTransform:null,filterForExposedEvent:null};function bc(t,e,i){if(t&&(t.trigger(e,i),t.isGroup&&!Qs(t)))for(var n=0,o=t.childCount();nc?i+=p(g("data.partialData"),{displayCnt:c}):i+=g("data.allData");for(var r=[],s=0;si.blockIndex?i.step:null,a=n&&n.modDataCount;return{step:o,modBy:null!=a?Math.ceil(a/o):null,modDataCount:a}}},Bc.getPipeline=function(t){return this._pipelineMap.get(t)},Bc.updateStreamModes=function(t,e){var i=this._pipelineMap.get(t.uid),n=t.getData().count(),o=i.progressiveEnabled&&e.incrementalPrepareRender&&n>=i.threshold,a=t.get("large")&&n>=t.get("largeThreshold"),r="mod"===t.get("progressiveChunkMode")?n:null;t.pipelineContext=i.context={progressiveRender:o,modDataCount:r,large:a}},Bc.restorePipelines=function(t){var n=this,o=n._pipelineMap=Q();t.eachSeries(function(t){var e=t.getProgressive(),i=t.uid;o.set(i,{id:i,head:null,tail:null,threshold:t.getProgressiveThreshold(),progressiveEnabled:e&&!(t.preventIncremental&&t.preventIncremental()),blockIndex:-1,step:Math.round(e||700),count:0}),Kc(n,t,t.dataTask)})},Bc.prepareStageTasks=function(){var i=this._stageTaskMap,n=this.ecInstance.getModel(),o=this.api;R(this._allHandlers,function(t){var e=i.get(t.uid)||i.set(t.uid,[]);t.reset&&function(n,o,t,a,r){var s=t.seriesTaskMap||(t.seriesTaskMap=Q()),e=o.seriesType,i=o.getTargetSeries;o.createOnAllSeries?a.eachRawSeries(l):e?a.eachRawSeriesByType(e,l):i&&i(a,r).each(l);function l(t){var e=t.uid,i=s.get(e)||s.set(e,Yh({plan:Uc,reset:Xc,count:qc}));i.context={model:t,ecModel:a,api:r,useClearVisual:o.isVisual&&!o.isLayout,plan:o.plan,reset:o.reset,scheduler:n},Kc(n,t,i)}var u=n._pipelineMap;s.each(function(t,e){u.get(e)||(t.dispose(),s.removeKey(e))})}(this,t,e,n,o),t.overallReset&&function(n,t,e,i,o){var a=e.overallTask=e.overallTask||Yh({reset:Fc});a.context={ecModel:i,api:o,overallReset:t.overallReset,scheduler:n};var r=a.agentStubMap=a.agentStubMap||Q(),s=t.seriesType,l=t.getTargetSeries,u=!0,h=t.modifyOutputEnd;s?i.eachRawSeriesByType(s,c):l?l(i,o).each(c):(u=!1,R(i.getSeries(),c));function c(t){var e=t.uid,i=r.get(e);i||(i=r.set(e,Yh({reset:Wc,onDirty:Zc})),a.dirty()),i.context={model:t,overallProgress:u,modifyOutputEnd:h},i.agent=a,i.__block=u,Kc(n,t,i)}var d=n._pipelineMap;r.each(function(t,e){d.get(e)||(t.dispose(),a.dirty(),r.removeKey(e))})}(this,t,e,n,o)},this)},Bc.prepareView=function(t,e,i,n){var o=t.renderTask,a=o.context;a.model=e,a.ecModel=i,a.api=n,o.__block=!t.incrementalPrepareRender,Kc(this,e,o)},Bc.performDataProcessorTasks=function(t,e){Vc(this,this._dataProcessorHandlers,t,e,{block:!0})},Bc.performVisualTasks=function(t,e,i){Vc(this,this._visualHandlers,t,e,i)},Bc.performSeriesTasks=function(t){var e;t.eachSeries(function(t){e|=t.dataTask.perform()}),this.unfinished|=e},Bc.plan=function(){this._pipelineMap.each(function(t){var e=t.tail;do{if(e.__block){t.blockIndex=e.__idxInPipeline;break}e=e.getUpstream()}while(e)})};var Gc=Bc.updatePayload=function(t,e){"remain"!==e&&(t.context.payload=e)};function Fc(t){t.overallReset(t.ecModel,t.api,t.payload)}function Wc(t,e){return t.overallProgress&&Hc}function Hc(){this.agent.dirty(),this.getDownstream().dirty()}function Zc(){this.agent&&this.agent.dirty()}function Uc(t){return t.plan&&t.plan(t.model,t.ecModel,t.api,t.payload)}function Xc(t){t.useClearVisual&&t.data.clearAllVisual();var e=t.resetDefines=Vo(t.reset(t.model,t.ecModel,t.api,t.payload));return 1'+t.dom+""}),p.painter.getSvgRoot().innerHTML=g,o.connectedBackgroundColor&&p.painter.setBackgroundColor(o.connectedBackgroundColor),p.refreshImmediately(),p.painter.toDataURL()}return o.connectedBackgroundColor&&p.add(new rs({shape:{x:0,y:0,width:t,height:e},style:{fill:o.connectedBackgroundColor}})),Td(f,function(t){var e=new Qn({style:{x:t.left*i-u,y:t.top*i-h,image:t.dom}});p.add(e)}),p.refreshImmediately(),n.toDataURL("image/"+(o&&o.type||"png"))}return this.getDataURL(o)}},zd.convertToPixel=T(Bd,"convertToPixel"),zd.convertFromPixel=T(Bd,"convertFromPixel"),zd.containPixel=function(t,o){var a;if(!this._disposed)return R(t=Ko(this._model,t),function(t,n){0<=n.indexOf("Models")&&R(t,function(t){var e=t.coordinateSystem;if(e&&e.containPoint)a|=!!e.containPoint(o);else if("seriesModels"===n){var i=this._chartsMap[t.__viewId];i&&i.containPoint&&(a|=i.containPoint(o,t))}},this)},this),!!a},zd.getVisual=function(t,e){var i=(t=Ko(this._model,t,{defaultMainType:"series"})).seriesModel.getData(),n=t.hasOwnProperty("dataIndexInside")?t.dataIndexInside:t.hasOwnProperty("dataIndex")?i.indexOfRawIndex(t.dataIndex):null;return null!=n?i.getItemVisual(n,e):i.getVisual(e)},zd.getViewOfComponentModel=function(t){return this._componentsMap[t.__viewId]},zd.getViewOfSeriesModel=function(t){return this._chartsMap[t.__viewId]};var Vd={prepareAndUpdate:function(t){Gd(this),Vd.update.call(this,t)},update:function(t){var e=this._model,i=this._api,n=this._zr,o=this._coordSysMgr,a=this._scheduler;if(e){a.restoreData(e,t),a.performSeriesTasks(e),o.create(e,i),a.performDataProcessorTasks(e,t),Wd(this,e),o.update(e,i),Yd(e),a.performVisualTasks(e,t),jd(this,e,i,t);var r=e.get("backgroundColor")||"transparent";if(v.canvasSupported)n.setBackgroundColor(r);else{var s=Fe(r);r=$e(s,"rgb"),0===s[3]&&(r="transparent")}Kd(e,i)}},updateTransform:function(o){var a=this._model,r=this,s=this._api;if(a){var l=[];a.eachComponent(function(t,e){var i=r.getViewOfComponentModel(e);if(i&&i.__alive)if(i.updateTransform){var n=i.updateTransform(e,a,s,o);n&&n.update&&l.push(i)}else l.push(i)});var n=Q();a.eachSeries(function(t){var e=r._chartsMap[t.__viewId];if(e.updateTransform){var i=e.updateTransform(t,a,s,o);i&&i.update&&n.set(t.uid,1)}else n.set(t.uid,1)}),Yd(a),this._scheduler.performVisualTasks(a,o,{setDirty:!0,dirtyMap:n}),qd(r,a,s,o,n),Kd(a,this._api)}},updateView:function(t){var e=this._model;e&&(_c.markUpdateMethod(t,"updateView"),Yd(e),this._scheduler.performVisualTasks(e,t,{setDirty:!0}),jd(this,this._model,this._api,t),Kd(e,this._api))},updateVisual:function(t){Vd.update.call(this,t)},updateLayout:function(t){Vd.update.call(this,t)}};function Gd(t){var e=t._model,i=t._scheduler;i.restorePipelines(e),i.prepareStageTasks(),Xd(t,"component",e,i),Xd(t,"chart",e,i),i.plan()}function Fd(e,i,n,o,t){var a=e._model;if(o){var r={};r[o+"Id"]=n[o+"Id"],r[o+"Index"]=n[o+"Index"],r[o+"Name"]=n[o+"Name"];var s={mainType:o,query:r};t&&(s.subType=t);var l=n.excludeSeriesId;null!=l&&(l=Q(Vo(l))),a&&a.eachComponent(s,function(t){l&&null!=l.get(t.id)||u(e["series"===o?"_chartsMap":"_componentsMap"][t.__viewId])},e)}else Td(e._componentsViews.concat(e._chartsViews),u);function u(t){t&&t.__alive&&t[i]&&t[i](t.__model,a,e._api,n)}}function Wd(t,e){var i=t._chartsMap,n=t._scheduler;e.eachSeries(function(t){n.updateStreamModes(t,i[t.__viewId])})}function Hd(e,t){var i=e.type,n=e.escapeConnect,o=tf[i],a=o.actionInfo,r=(a.update||"update").split(":"),s=r.pop();r=null!=r[0]&&Cd(r[0]),this[kd]=!0;var l=[e],u=!1;e.batch&&(u=!0,l=O(e.batch,function(t){return(t=D(P({},t),e)).batch=null,t}));var h,c=[],d="highlight"===i||"downplay"===i;Td(l,function(t){(h=(h=o.action(t,this._model,this._api))||P({},t)).type=a.event||h.type,c.push(h),d?Fd(this,s,t,"series"):r&&Fd(this,s,t,r.main,r.sub)},this),"none"===s||d||r||(this[Pd]?(Gd(this),Vd.update.call(this,e),this[Pd]=!1):Vd[s].call(this,e)),h=u?{type:a.event||i,escapeConnect:n,batch:c}:c[0],this[kd]=!1,t||this._messageCenter.trigger(h.type,h)}function Zd(t){for(var e=this._pendingActions;e.length;){var i=e.shift();Hd.call(this,i,t)}}function Ud(t){t||this.trigger("updated")}function Xd(t,e,o,a){for(var r="component"===e,s=r?t._componentsViews:t._chartsViews,l=r?t._componentsMap:t._chartsMap,u=t._zr,h=t._api,i=0;it.get("hoverLayerThreshold")&&!v.node&&t.eachSeries(function(t){if(!t.preventUsingHoverLayer){var e=i._chartsMap[t.__viewId];e.__alive&&e.group.traverse(function(t){t.useHoverLayer=!0})}})}(n,t),Rc(n._zr.dom,t)}function Kd(e,i){Td(af,function(t){t(e,i)})}zd.resize=function(t){if(!this._disposed){this._zr.resize(t);var e=this._model;if(this._loadingFX&&this._loadingFX.resize(),e){var i=e.resetOption("media"),n=t&&t.silent;this[kd]=!0,i&&Gd(this),Vd.update.call(this),this[kd]=!1,Zd.call(this,n),Ud.call(this,n)}}},zd.showLoading=function(t,e){if(!this._disposed&&(Dd(t)&&(e=t,t=""),t=t||"default",this.hideLoading(),lf[t])){var i=lf[t](this._api,e),n=this._zr;this._loadingFX=i,n.add(i)}},zd.hideLoading=function(){this._disposed||(this._loadingFX&&this._zr.remove(this._loadingFX),this._loadingFX=null)},zd.makeActionFromEvent=function(t){var e=P({},t);return e.type=ef[t.type],e},zd.dispatchAction=function(t,e){this._disposed||(Dd(e)||(e={silent:!!e}),tf[t.type]&&this._model&&(this[kd]?this._pendingActions.push(t):(Hd.call(this,t,e.silent),e.flush?this._zr.flush(!0):!1!==e.flush&&v.browser.weChat&&this._throttledZrFlush(),Zd.call(this,e.silent),Ud.call(this,e.silent))))},zd.appendData=function(t){if(!this._disposed){var e=t.seriesIndex;this.getModel().getSeriesByIndex(e).appendData(t),this._scheduler.unfinished=!0}},zd.on=Od("on",!1),zd.off=Od("off",!1),zd.one=Od("one",!1);var $d=["click","dblclick","mouseover","mouseout","mousemove","mousedown","mouseup","globalout","contextmenu"];function Jd(t,e){var i=t.get("z"),n=t.get("zlevel");e.group.traverse(function(t){"group"!==t.type&&(null!=i&&(t.z=i),null!=n&&(t.zlevel=n))})}function Qd(){this.eventInfo}zd._initEvents=function(){Td($d,function(u){function t(t){var e,i=this.getModel(),n=t.target;if("globalout"===u)e={};else if(n&&null!=n.dataIndex){var o=n.dataModel||i.getSeriesByIndex(n.seriesIndex);e=o&&o.getDataParams(n.dataIndex,n.dataType,n)||{}}else n&&n.eventData&&(e=P({},n.eventData));if(e){var a=e.componentType,r=e.componentIndex;"markLine"!==a&&"markPoint"!==a&&"markArea"!==a||(a="series",r=e.seriesIndex);var s=a&&null!=r&&i.getComponent(a,r),l=s&&this["series"===s.mainType?"_chartsMap":"_componentsMap"][s.__viewId];e.event=t,e.type=u,this._ecEventProcessor.eventInfo={targetEl:n,packedEvent:e,model:s,view:l},this.trigger(u,e)}}t.zrEventfulCallAtLast=!0,this._zr.on(u,t,this)},this),Td(ef,function(t,e){this._messageCenter.on(e,function(t){this.trigger(e,t)},this)},this)},zd.isDisposed=function(){return this._disposed},zd.clear=function(){this._disposed||this.setOption({series:[]},!0)},zd.dispose=function(){if(!this._disposed){this._disposed=!0,Jo(this.getDom(),ff,"");var e=this._api,i=this._model;Td(this._componentsViews,function(t){t.dispose(i,e)}),Td(this._chartsViews,function(t){t.dispose(i,e)}),this._zr.dispose(),delete uf[this.id]}},b(Ed,Ct),Qd.prototype={constructor:Qd,normalizeQuery:function(t){var s={},l={},u={};if(E(t)){var e=Cd(t);s.mainType=e.main||null,s.subType=e.sub||null}else{var h=["Index","Name","Id"],c={name:1,dataIndex:1,dataType:1};R(t,function(t,e){for(var i=!1,n=0;nx[1]&&(x[1]=y)}e&&(this._nameList[d]=e[f])}this._rawCount=this._count=l,this._extent={},Kf(this)},jf._initDataFromProvider=function(t,e){if(!(e<=t)){for(var i,n=this._chunkSize,o=this._rawData,a=this._storage,r=this.dimensions,s=r.length,l=this._dimensionInfos,u=this._nameList,h=this._idList,c=this._rawExtent,d=this._nameRepeatCount={},f=this._chunkCount,p=0;pM[1]&&(M[1]=S)}if(!o.pure){var I=u[v];if(m&&null==I)if(null!=m.name)u[v]=I=m.name;else if(null!=i){var T=r[i],A=a[T][y];if(A){I=A[x];var D=l[T].ordinalMeta;D&&D.categories.length&&(I=D.categories[I])}}var C=null==m?null:m.id;null==C&&null!=I&&(d[I]=d[I]||0,0=this._rawCount||t<0)return-1;if(!this._indices)return t;var e=this._indices,i=e[t];if(null!=i&&it))return a;o=a-1}}return-1},jf.indicesOfNearest=function(t,e,i){var n=[];if(!this._storage[t])return n;null==i&&(i=1/0);for(var o=1/0,a=-1,r=0,s=0,l=this.count();st[I][1])&&(M=!1)}M&&(a[r++]=this.getRawIndex(m))}return rw[1]&&(w[1]=_)}}}return o},jf.downSample=function(t,e,i,n){for(var o=ip(this,[t]),a=o._storage,r=[],s=Math.floor(1/e),l=a[t],u=this.count(),h=this._chunkSize,c=o._rawExtent[t],d=new(Hf(this))(u),f=0,p=0;pc[1]&&(c[1]=x),d[f++]=_}return o._count=f,o._indices=d,o.getRawIndex=Qf,o},jf.getItemModel=function(t){var e=this.hostModel;return new Cl(this.getRawDataItem(t),e,e&&e.ecModel)},jf.diff=function(e){var i=this;return new kf(e?e.getIndices():[],this.getIndices(),function(t){return tp(e,t)},function(t){return tp(i,t)})},jf.getVisual=function(t){var e=this._visual;return e&&e[t]},jf.setVisual=function(t,e){if(zf(t))for(var i in t)t.hasOwnProperty(i)&&this.setVisual(i,t[i]);else this._visual=this._visual||{},this._visual[t]=e},jf.setLayout=function(t,e){if(zf(t))for(var i in t)t.hasOwnProperty(i)&&this.setLayout(i,t[i]);else this._layout[t]=e},jf.getLayout=function(t){return this._layout[t]},jf.getItemLayout=function(t){return this._itemLayouts[t]},jf.setItemLayout=function(t,e,i){this._itemLayouts[t]=i?P(this._itemLayouts[t]||{},e):e},jf.clearItemLayouts=function(){this._itemLayouts.length=0},jf.getItemVisual=function(t,e,i){var n=this._itemVisuals[t],o=n&&n[e];return null!=o||i?o:this.getVisual(e)},jf.setItemVisual=function(t,e,i){var n=this._itemVisuals[t]||{},o=this.hasItemVisual;if(this._itemVisuals[t]=n,zf(e))for(var a in e)e.hasOwnProperty(a)&&(n[a]=e[a],o[a]=!0);else n[e]=i,o[e]=!0},jf.clearAllVisual=function(){this._visual={},this._itemVisuals=[],this.hasItemVisual={}};function ap(t){t.seriesIndex=this.seriesIndex,t.dataIndex=this.dataIndex,t.dataType=this.dataType}function rp(t,e,i){Uu.isInstance(e)||(e=Uu.seriesDataToSource(e)),i=i||{},t=(t||[]).slice();for(var n=(i.dimsDef||[]).slice(),o=Q(),a=Q(),l=[],r=function(t,e,i,n){var o=Math.max(t.dimensionsDetectCount||1,e.length,i.length,n||0);return R(e,function(t){var e=t.dimsDef;e&&(o=Math.max(o,e.length))}),o}(e,t,n,i.dimCount),s=0;s=e[0]&&t<=e[1]},mp.prototype.normalize=function(t){var e=this._extent;return e[1]===e[0]?.5:(t-e[0])/(e[1]-e[0])},mp.prototype.scale=function(t){var e=this._extent;return t*(e[1]-e[0])+e[0]},mp.prototype.unionExtent=function(t){var e=this._extent;t[0]e[1]&&(e[1]=t[1])},mp.prototype.unionExtentFromData=function(t,e){this.unionExtent(t.getApproximateExtent(e))},mp.prototype.getExtent=function(){return this._extent.slice()},mp.prototype.setExtent=function(t,e){var i=this._extent;isNaN(t)||(i[0]=t),isNaN(e)||(i[1]=e)},mp.prototype.isBlank=function(){return this._isBlank},mp.prototype.setBlank=function(t){this._isBlank=t},mp.prototype.getLabel=null,oa(mp),ua(mp,{registerWhenExtend:!0}),vp.createByAxisModel=function(t){var e=t.option,i=e.data,n=i&&O(i,_p);return new vp({categories:n,needCollect:!n,deduplication:!1!==e.dedplication})};var yp=vp.prototype;function xp(t){return t._map||(t._map=Q(t.categories))}function _p(t){return z(t)&&null!=t.value?t.value:t+""}yp.getOrdinal=function(t){return xp(this).get(t)},yp.parseAndCollect=function(t){var e,i=this._needCollect;if("string"!=typeof t&&!i)return t;if(i&&!this._deduplication)return e=this.categories.length,this.categories[e]=t,e;var n=xp(this);return null==(e=n.get(t))&&(i?(e=this.categories.length,this.categories[e]=t,n.set(t,e)):e=NaN),e};var wp=mp.prototype,bp=mp.extend({type:"ordinal",init:function(t,e){t&&!L(t)||(t=new vp({categories:t})),this._ordinalMeta=t,this._extent=e||[0,t.categories.length-1]},parse:function(t){return"string"==typeof t?this._ordinalMeta.getOrdinal(t):Math.round(t)},contain:function(t){return t=this.parse(t),wp.contain.call(this,t)&&null!=this._ordinalMeta.categories[t]},normalize:function(t){return wp.normalize.call(this,this.parse(t))},scale:function(t){return Math.round(wp.scale.call(this,t))},getTicks:function(){for(var t=[],e=this._extent,i=e[0];i<=e[1];)t.push(i),i++;return t},getLabel:function(t){if(!this.isBlank())return this._ordinalMeta.categories[t]},count:function(){return this._extent[1]-this._extent[0]+1},unionExtentFromData:function(t,e){this.unionExtent(t.getApproximateExtent(e))},getOrdinalMeta:function(){return this._ordinalMeta},niceTicks:et,niceExtent:et});bp.create=function(){return new bp};var Sp=zl;function Mp(t){return Gl(t)+2}function Ip(t,e,i){t[e]=Math.max(Math.min(t[e],i[1]),i[0])}function Tp(t,e){isFinite(t[0])||(t[0]=e[0]),isFinite(t[1])||(t[1]=e[1]),Ip(t,0,e),Ip(t,1,e),t[0]>t[1]&&(t[0]=t[1])}var Ap=zl,Dp=mp.extend({type:"interval",_interval:0,_intervalPrecision:2,setExtent:function(t,e){var i=this._extent;isNaN(t)||(i[0]=parseFloat(t)),isNaN(e)||(i[1]=parseFloat(e))},unionExtent:function(t){var e=this._extent;t[0]e[1]&&(e[1]=t[1]),Dp.prototype.setExtent.call(this,e[0],e[1])},getInterval:function(){return this._interval},setInterval:function(t){this._interval=t,this._niceExtent=this._extent.slice(),this._intervalPrecision=Mp(t)},getTicks:function(t){var e=this._interval,i=this._extent,n=this._niceExtent,o=this._intervalPrecision,a=[];if(!e)return a;i[0]s&&(t?a.push(Ap(s+e,o)):a.push(i[1])),a},getMinorTicks:function(t){for(var e=this.getTicks(!0),i=[],n=this.getExtent(),o=1;on[0]&&h>>1;t[o][1]>1^-(1&s),l=l>>1^-(1&l),o=s+=o,a=l+=a,n.push([s/i,l/i])}return n}Ag.prototype={constructor:Ag,properties:null,getBoundingRect:function(){var t=this._rect;if(t)return t;for(var e=Number.MAX_VALUE,i=[e,e],n=[-e,-e],o=[],a=[],r=this.geometries,s=0;ss[1];d(e[0].coord,s[0])&&(n?e[0].coord=s[0]:e.shift());n&&d(s[0],e[0].coord)&&e.unshift({coord:s[0]});d(s[1],a.coord)&&(n?a.coord=s[1]:e.pop());n&&d(a.coord,s[1])&&e.push({coord:s[1]});function d(t,e){return t=zl(t),e=zl(e),c?en[0]&&(n[0]=a[0]),a[1]>n[1]&&(n[1]=a[1])}return{min:e?i:n,max:e?n:i}}var xm=Ar.extend({type:"ec-polyline",shape:{points:[],smooth:0,smoothConstraint:!0,smoothMonotone:null,connectNulls:!1},style:{fill:null,stroke:"#000"},brush:Xr(Ar.prototype.brush),buildPath:function(t,e){var i=e.points,n=0,o=i.length,a=ym(i,e.smoothConstraint);if(e.connectNulls){for(;0n)return!1;return!0}(a,e))){var r=e.mapDimension(a.dim),s={};return R(a.getViewLabels(),function(t){s[t.tickValue]=1}),function(t){return!s.hasOwnProperty(e.get(r,t))}}}}function Cm(t,e,i){if("cartesian2d"!==t.type)return bm(t,e,i);var n=t.getBaseAxis().isHorizontal(),o=wm(t,e,i);if(!i.get("clip",!0)){var a=o.shape,r=Math.max(a.width,a.height);n?(a.y-=r,a.height+=2*r):(a.x-=r,a.width+=2*r)}return o}_c.extend({type:"line",init:function(){var t=new Ci,e=new im;this.group.add(e.group),this._symbolDraw=e,this._lineGroup=t},render:function(t,e,i){var n=t.coordinateSystem,o=this.group,a=t.getData(),r=t.getModel("lineStyle"),s=t.getModel("areaStyle"),l=a.mapArray(a.getItemLayout),u="polar"===n.type,h=this._coordSys,c=this._symbolDraw,d=this._polyline,f=this._polygon,p=this._lineGroup,g=t.get("animation"),m=!s.isEmpty(),v=s.get("origin"),y=function(t,e,i){if(!i.valueDim)return[];for(var n=[],o=0,a=e.count();oh[c-1].coord&&(h.reverse(),d.reverse());var f=h[0].coord-10,p=h[c-1].coord+10,g=p-f;if(g<.001)return"transparent";R(h,function(t){t.offset=(t.coord-f)/g}),h.push({offset:c?h[c-1].offset:.5,color:d[1]||"transparent"}),h.unshift({offset:c?h[0].offset:.5,color:d[0]||"transparent"});var m=new gs(0,0,0,0,h,!0);return m[n]=f,m[n+"2"]=p,m}}}(a,n)||a.getVisual("color");d.useStyle(D(r.getLineStyle(),{fill:"none",stroke:M,lineJoin:"bevel"}));var I=t.get("smooth");if(I=Tm(t.get("smooth")),d.setShape({smooth:I,smoothMonotone:t.get("smoothMonotone"),connectNulls:t.get("connectNulls")}),f){var T=a.getCalculationInfo("stackedOnSeries"),A=0;f.useStyle(D(s.getAreaStyle(),{fill:M,opacity:.7,lineJoin:"bevel"})),T&&(A=Tm(T.get("smooth"))),f.setShape({smooth:I,stackedOnSmooth:A,smoothMonotone:t.get("smoothMonotone"),connectNulls:t.get("connectNulls")})}this._data=a,this._coordSys=n,this._stackedOnPoints=y,this._points=l,this._step=S,this._valueOrigin=v},dispose:function(){},highlight:function(t,e,i,n){var o=t.getData(),a=Yo(o,n);if(!(a instanceof Array)&&null!=a&&0<=a){var r=o.getItemGraphicEl(a);if(!r){var s=o.getItemLayout(a);if(!s)return;if(this._clipShapeForSymbol&&!this._clipShapeForSymbol.contain(s[0],s[1]))return;(r=new Xg(o,a)).position=s,r.setZ(t.get("zlevel"),t.get("z")),r.ignore=isNaN(s[0])||isNaN(s[1]),r.__temp=!0,o.setItemGraphicEl(a,r),r.stopSymbolAnimation(!0),this.group.add(r)}r.highlight()}else _c.prototype.highlight.call(this,t,e,i,n)},downplay:function(t,e,i,n){var o=t.getData(),a=Yo(o,n);if(null!=a&&0<=a){var r=o.getItemGraphicEl(a);r&&(r.__temp?(o.setItemGraphicEl(a,null),this.group.remove(r)):r.downplay())}else _c.prototype.downplay.call(this,t,e,i,n)},_newPolyline:function(t){var e=this._polyline;return e&&this._lineGroup.remove(e),e=new xm({shape:{points:t},silent:!0,z2:10}),this._lineGroup.add(e),this._polyline=e},_newPolygon:function(t,e){var i=this._polygon;return i&&this._lineGroup.remove(i),i=new _m({shape:{points:t,stackedOnPoints:e},silent:!0}),this._lineGroup.add(i),this._polygon=i},_updateAnimation:function(t,e,i,n,o,a){var r=this._polyline,s=this._polygon,l=t.hostModel,u=function(t,e,i,n,o,a,r,s){for(var l=function(t,e){var i=[];return e.diff(t).add(function(t){i.push({cmd:"+",idx:t})}).update(function(t,e){i.push({cmd:"=",idx:e,idx1:t})}).remove(function(t){i.push({cmd:"-",idx:t})}).execute(),i}(t,e),u=[],h=[],c=[],d=[],f=[],p=[],g=[],m=sm(o,e,r),v=sm(a,t,s),y=0;ye&&(e=t[i]);return isFinite(e)?e:NaN},min:function(t){for(var e=1/0,i=0;ie[1]&&e.reverse(),e},getOtherAxis:function(){this.grid.getOtherAxis()},pointToData:function(t,e){return this.coordToData(this.toLocalCoord(t["x"===this.dim?0:1]),e)},toLocalCoord:null,toGlobalCoord:null},w(zm,Gg);var Bm={show:!0,zlevel:0,z:0,inverse:!1,name:"",nameLocation:"end",nameRotate:null,nameTruncate:{maxWidth:null,ellipsis:"...",placeholder:"."},nameTextStyle:{},nameGap:15,silent:!1,triggerEvent:!1,tooltip:{show:!1},axisPointer:{},axisLine:{show:!0,onZero:!0,onZeroAxisIndex:null,lineStyle:{color:"#333",width:1,type:"solid"},symbol:["none","none"],symbolSize:[10,15]},axisTick:{show:!0,inside:!1,length:5,lineStyle:{width:1}},axisLabel:{show:!0,inside:!1,rotate:0,showMinLabel:null,showMaxLabel:null,margin:8,fontSize:12},splitLine:{show:!0,lineStyle:{color:["#ccc"],width:1,type:"solid"}},splitArea:{show:!1,areaStyle:{color:["rgba(250,250,250,0.3)","rgba(200,200,200,0.3)"]}}},Vm={};Vm.categoryAxis=m({boundaryGap:!0,deduplication:null,splitLine:{show:!1},axisTick:{alignWithLabel:!1,interval:"auto"},axisLabel:{interval:"auto"}},Bm),Vm.valueAxis=m({boundaryGap:[0,0],splitNumber:5,minorTick:{show:!1,splitNumber:5,length:3,lineStyle:{}},minorSplitLine:{show:!1,lineStyle:{color:"#eee",width:1}}},Bm),Vm.timeAxis=D({scale:!0,min:"dataMin",max:"dataMax"},Vm.valueAxis),Vm.logAxis=D({scale:!0,logBase:10},Vm.valueAxis);function Gm(a,t,r,e){R(Fm,function(o){t.extend({type:a+"Axis."+o,mergeDefaultAndTheme:function(t,e){var i=this.layoutMode,n=i?Iu(t):{};m(t,e.getTheme().get(o+"Axis")),m(t,this.getDefaultOption()),t.type=r(a,t),i&&Mu(t,n,i)},optionUpdated:function(){"category"===this.option.type&&(this.__ordinalMeta=vp.createByAxisModel(this))},getCategories:function(t){var e=this.option;if("category"===e.type)return t?e.data:this.__ordinalMeta.categories},getOrdinalMeta:function(){return this.__ordinalMeta},defaultOption:p([{},Vm[o+"Axis"],e],!0)})}),ku.registerSubTypeDefaulter(a+"Axis",T(r,a))}var Fm=["value","category","time","log"],Wm=ku.extend({type:"cartesian2dAxis",axis:null,init:function(){Wm.superApply(this,"init",arguments),this.resetRange()},mergeOption:function(){Wm.superApply(this,"mergeOption",arguments),this.resetRange()},restoreData:function(){Wm.superApply(this,"restoreData",arguments),this.resetRange()},getCoordSysModel:function(){return this.ecModel.queryComponents({mainType:"grid",index:this.option.gridIndex,id:this.option.gridId})[0]}});function Hm(t,e){return e.type||(e.data?"category":"value")}m(Wm.prototype,dg);var Zm={offset:0};function Um(t,e){return t.getCoordSysModel()===e}function Xm(t,e,i){this._coordsMap={},this._coordsList=[],this._axesMap={},this._axesList=[],this._initCartesian(t,e,i),this.model=t}Gm("x",Wm,Hm,Zm),Gm("y",Wm,Hm,Zm),ku.extend({type:"grid",dependencies:["xAxis","yAxis"],layoutMode:"box",coordinateSystem:null,defaultOption:{show:!1,zlevel:0,z:0,left:"10%",top:60,right:"10%",bottom:60,containLabel:!1,backgroundColor:"rgba(0,0,0,0)",borderWidth:1,borderColor:"#ccc"}});var Ym=Xm.prototype;function jm(t,e,i,n){i.getAxesOnZeroOf=function(){return o?[o]:[]};var o,a=t[e],r=i.model,s=r.get("axisLine.onZero"),l=r.get("axisLine.onZeroAxisIndex");if(s){if(null!=l)qm(a[l])&&(o=a[l]);else for(var u in a)if(a.hasOwnProperty(u)&&qm(a[u])&&!n[h(a[u])]){o=a[u];break}o&&(n[h(o)]=!0)}function h(t){return t.dim+"_"+t.index}}function qm(t){return t&&"category"!==t.type&&"time"!==t.type&&function(t){var e=t.scale.getExtent(),i=e[0],n=e[1];return!(0u[1]?-1:1,c=["start"===a?u[0]-h*l:"end"===a?u[1]+h*l:(u[0]+u[1])/2,sv(a)?t.labelOffset+r*l:0],d=e.get("nameRotate");null!=d&&(d=d*tv/180),sv(a)?n=nv(t.rotation,null!=d?d:t.rotation,r):(n=function(t,e,i,n){var o,a,r=Zl(i-t.rotation),s=n[0]>n[1],l="start"===e&&!s||"start"!==e&&s;o=Ul(r-tv/2)?(a=l?"bottom":"top","center"):Ul(r-1.5*tv)?(a=l?"top":"bottom","center"):(a="middle",r<1.5*tv&&tv/2l[1]&&l.reverse(),(null==r||r>l[1])&&(r=l[1]),r=i.r0}}});var ny=Math.PI/180;function oy(o,t,e,i,n,a,r,s,l,u){function h(t,e,i){for(var n=t;nl+r);n++)if(o[n].y+=i,to[n].y+o[n].height)return void c(n,i/2);c(e-1,i/2)}function c(t,e){for(var i=t;0<=i&&!(o[i].y-eo[i-1].y+o[i-1].height));i--);}function d(t,e,i,n,o,a){for(var r=e?Number.MAX_VALUE:0,s=0,l=t.length;s=e?v.push(o[y]):m.push(o[y]);d(m,!1,t,e,i,n),d(v,!0,t,e,i,n)}function ay(t){return"center"===t.position}function ry(L,k,P,t,N,e){var O,R,E=L.getData(),z=[],B=!1,V=(L.get("minShowLabelAngle")||0)*ny;E.each(function(t){var e=E.getItemLayout(t),i=E.getItemModel(t),n=i.getModel("label"),o=n.get("position")||i.get("emphasis.label.position"),a=n.get("distanceToLabelLine"),r=n.get("alignTo"),s=El(n.get("margin"),P),l=n.get("bleedMargin"),u=n.getFont(),h=i.getModel("labelLine"),c=h.get("length");c=El(c,P);var d=h.get("length2");if(d=El(d,P),!(e.anglei[0]&&isFinite(h)&&isFinite(i[0]););else{var l=o.getTicks().length-1;c":"\n";return au(""===r?this.name:r)+s+O(a,function(t,e){var i=o.get(o.mapDimension(t.dim),n);return au(t.name+" : "+i)}).join(s)},getTooltipPosition:function(t){if(null!=t)for(var e=this.getData(),i=this.coordinateSystem,n=e.getValues(O(i.dimensions,function(t){return e.mapDimension(t)}),t,!0),o=0,a=n.length;o":"\n";return l.join(", ")+d+au(r+" : "+a)},getTooltipPosition:function(t){if(null!=t){var e=this.getData().getName(t),i=this.coordinateSystem,n=i.getRegion(e);return n&&i.dataToPoint(n.center)}},setZoom:function(t){this.option.zoom=t},setCenter:function(t){this.option.center=t},defaultOption:{zlevel:0,z:2,coordinateSystem:"geo",map:"",left:"center",top:"center",aspectScale:.75,showLegendSymbol:!0,dataRangeHoverLink:!0,boundingCoords:null,center:null,zoom:1,scaleLimit:null,label:{show:!1,color:"#000"},itemStyle:{borderWidth:.5,borderColor:"#444",areaColor:"#eee"},emphasis:{label:{show:!0,color:"rgb(100,0,0)"},itemStyle:{areaColor:"rgba(255,215,0,0.8)"}},nameProperty:"name"}}),jv);var Ey="\0_ec_interaction_mutex";function zy(t,e){return!!By(t)[e]}function By(t){return t[Ey]||(t[Ey]={})}function Vy(i){this.pointerChecker,this._zr=i,this._opt={};var t=A,n=t(Gy,this),o=t(Fy,this),a=t(Wy,this),r=t(Hy,this),s=t(Zy,this);Ct.call(this),this.setPointerChecker=function(t){this.pointerChecker=t},this.enable=function(t,e){this.disable(),this._opt=D(k(e)||{},{zoomOnMouseWheel:!0,moveOnMouseMove:!0,moveOnMouseWheel:!1,preventDefaultMouseMove:!0}),null==t&&(t=!0),!0!==t&&"move"!==t&&"pan"!==t||(i.on("mousedown",n),i.on("mousemove",o),i.on("mouseup",a)),!0!==t&&"scale"!==t&&"zoom"!==t||(i.on("mousewheel",r),i.on("pinch",s))},this.disable=function(){i.off("mousedown",n),i.off("mousemove",o),i.off("mouseup",a),i.off("mousewheel",r),i.off("pinch",s)},this.dispose=this.disable,this.isDragging=function(){return this._dragging},this.isPinching=function(){return this._pinching}}function Gy(t){if(!(Yt(t)||t.target&&t.target.draggable)){var e=t.offsetX,i=t.offsetY;this.pointerChecker&&this.pointerChecker(t,e,i)&&(this._x=e,this._y=i,this._dragging=!0)}}function Fy(t){if(this._dragging&&Yy("moveOnMouseMove",t,this._opt)&&"pinch"!==t.gestureEvent&&!zy(this._zr,"globalPan")){var e=t.offsetX,i=t.offsetY,n=this._x,o=this._y,a=e-n,r=i-o;this._x=e,this._y=i,this._opt.preventDefaultMouseMove&&Xt(t.event),Xy(this,"pan","moveOnMouseMove",t,{dx:a,dy:r,oldX:n,oldY:o,newX:e,newY:i})}}function Wy(t){Yt(t)||(this._dragging=!1)}function Hy(t){var e=Yy("zoomOnMouseWheel",t,this._opt),i=Yy("moveOnMouseWheel",t,this._opt),n=t.wheelDelta,o=Math.abs(n),a=t.offsetX,r=t.offsetY;if(0!==n&&(e||i)){if(e){var s=3e&&(e=n.height)}this.height=e+1},getNodeById:function(t){if(this.getId()===t)return this;for(var e=0,i=this.children,n=i.length;ei&&(i=t.depth)});var a=t.expandAndCollapse&&0<=t.initialTreeDepth?t.initialTreeDepth:i;return o.root.eachNode("preorder",function(t){var e=t.hostTree.data.getRawDataItem(t.dataIndex);t.isExpand=e&&null!=e.collapsed?!e.collapsed:t.depth<=a}),o.data},getOrient:function(){var t=this.get("orient");return"horizontal"===t?t="LR":"vertical"===t&&(t="TB"),t},setZoom:function(t){this.option.zoom=t},setCenter:function(t){this.option.center=t},formatTooltip:function(t){for(var e=this.getData().tree,i=e.root.children[0],n=e.getNodeByDataIndex(t),o=n.getValue(),a=n.name;n&&n!==i;)a=n.parentNode.name+"."+a,n=n.parentNode;return au(a+(isNaN(o)||null==o?"":" : "+o))},defaultOption:{zlevel:0,z:2,coordinateSystem:"view",left:"12%",top:"12%",right:"12%",bottom:"12%",layout:"orthogonal",edgeShape:"curve",edgeForkPosition:"50%",roam:!1,nodeScaleRatio:.4,center:null,zoom:1,orient:"LR",symbol:"emptyCircle",symbolSize:7,expandAndCollapse:!0,initialTreeDepth:2,lineStyle:{color:"#ccc",width:1.5,curveness:.5},itemStyle:{color:"lightsteelblue",borderColor:"#c23531",borderWidth:1.5},label:{show:!0,color:"#555"},leaves:{label:{show:!0}},animationEasing:"linear",animationDuration:700,animationDurationUpdate:1e3}});var zx=Cs({shape:{parentPoint:[],childPoints:[],orient:"",forkPosition:""},style:{stroke:"#000",fill:null},buildPath:function(t,e){var i=e.childPoints,n=i.length,o=e.parentPoint,a=i[0],r=i[n-1];if(1===n)return t.moveTo(o[0],o[1]),void t.lineTo(a[0],a[1]);var s=e.orient,l="TB"===s||"BT"===s?0:1,u=1-l,h=El(e.forkPosition,1),c=[];c[l]=o[l],c[u]=o[u]+(r[u]-o[u])*h,t.moveTo(o[0],o[1]),t.lineTo(c[0],c[1]),t.moveTo(a[0],a[1]),c[l]=a[l],t.lineTo(c[0],c[1]),c[l]=r[l],t.lineTo(c[0],c[1]),t.lineTo(r[0],r[1]);for(var d=1;dx.x)||(m-=Math.PI);var b=v?"left":"right",S=a.labelModel.get("rotate"),M=S*(Math.PI/180);g.setStyle({textPosition:a.labelModel.get("position")||b,textRotation:null==S?-m:M,textOrigin:"center",verticalAlign:"middle"})}!function(t,e,i,n,o,a,r,s,l){var u=l.edgeShape,h=n.__edge;if("curve"===u)e.parentNode&&e.parentNode!==i&&cl(h=h||(n.__edge=new ds({shape:Wx(l,o,o),style:D({opacity:0,strokeNoScale:!0},l.lineStyle)})),{shape:Wx(l,a,r),style:D({opacity:1},l.lineStyle)},t);else if("polyline"===u&&"orthogonal"===l.layout&&e!==i&&e.children&&0!==e.children.length&&!0===e.isExpand){for(var c=e.children,d=[],f=0;fh.getLayout().x&&(h=t),t.depth>c.depth&&(c=t)});var d=u===h?1:r(u,h)/2,f=d-u.getLayout().x,p=0,g=0,m=0,v=0;if("radial"===n)p=o/(h.getLayout().x+d+f),g=a/(c.depth-1||1),Hx(l,function(t){m=(t.getLayout().x+f)*p,v=(t.depth-1)*g;var e=Px(m,v);t.setLayout({x:e.x,y:e.y,rawX:m,rawY:v},!0)});else{var y=t.getOrient();"RL"===y||"LR"===y?(g=a/(h.getLayout().x+d+f),p=o/(c.depth-1||1),Hx(l,function(t){v=(t.getLayout().x+f)*g,m="LR"===y?(t.depth-1)*p:o-(t.depth-1)*p,t.setLayout({x:m,y:v},!0)})):"TB"!==y&&"BT"!==y||(p=o/(h.getLayout().x+d+f),g=a/(c.depth-1||1),Hx(l,function(t){m=(t.getLayout().x+f)*p,v="TB"===y?(t.depth-1)*g:a-(t.depth-1)*g,t.setLayout({x:m,y:v},!0)}))}}}(t,e)})}),sc.extend({type:"series.treemap",layoutMode:"box",dependencies:["grid","polar"],preventUsingHoverLayer:!0,_viewRoot:null,defaultOption:{progressive:0,left:"center",top:"middle",right:null,bottom:null,width:"80%",height:"80%",sort:!0,clipWindow:"origin",squareRatio:.5*(1+Math.sqrt(5)),leafDepth:null,drillDownIcon:"▶",zoomToNodeRatio:.1024,roam:!0,nodeClick:"zoomToNode",animation:!0,animationDurationUpdate:900,animationEasing:"quinticInOut",breadcrumb:{show:!0,height:22,left:"center",top:"bottom",emptyItemWidth:25,itemStyle:{color:"rgba(0,0,0,0.7)",borderColor:"rgba(255,255,255,0.7)",borderWidth:1,shadowColor:"rgba(150,150,150,1)",shadowBlur:3,shadowOffsetX:0,shadowOffsetY:0,textStyle:{color:"#fff"}},emphasis:{textStyle:{}}},label:{show:!0,distance:0,padding:5,position:"inside",color:"#fff",ellipsis:!0},upperLabel:{show:!1,position:[0,"50%"],height:20,color:"#fff",ellipsis:!0,verticalAlign:"middle"},itemStyle:{color:null,colorAlpha:null,colorSaturation:null,borderWidth:0,gapWidth:0,borderColor:"#fff",borderColorSaturation:null},emphasis:{upperLabel:{show:!0,position:[0,"50%"],color:"#fff",ellipsis:!0,verticalAlign:"middle"}},visualDimension:0,visualMin:null,visualMax:null,color:[],colorAlpha:null,colorSaturation:null,colorMappingBy:"index",visibleMin:10,childrenVisibleMin:null,levels:[]},getInitialData:function(t,e){var i={name:t.name,children:t.data};!function i(t){var n=0;R(t.children,function(t){i(t);var e=t.value;L(e)&&(e=e[0]),n+=e});var e=t.value;L(e)&&(e=e[0]);null!=e&&!isNaN(e)||(e=n);e<0&&(e=0);L(t.value)?t.value[0]=e:t.value=e}(i);var n=t.levels||[],o=new Cl({itemStyle:this.designatedVisualItemStyle={}},this,e),a=O((n=t.levels=function(t,e){var n,i=e.get("color");if(!i)return;if(R(t=t||[],function(t){var e=new Cl(t),i=e.get("color");(e.get("itemStyle.color")||i&&"none"!==i)&&(n=!0)}),!n){(t[0]||(t[0]={})).color=i.slice()}return t}(n,e))||[],function(t){return new Cl(t,o,e)},this),r=Ax.createTree(i,this,function(t){t.wrapMethod("getItemModel",function(t,e){var i=r.getNodeByDataIndex(e),n=a[i.depth];return t.parentModel=n||o,t})});return r.data},optionUpdated:function(){this.resetViewRoot()},formatTooltip:function(t){var e=this.getData(),i=this.getRawValue(t),n=L(i)?tu(i[0]):tu(i);return au(e.getName(t)+": "+n)},getDataParams:function(t){var e=sc.prototype.getDataParams.apply(this,arguments),i=this.getData().tree.getNodeByDataIndex(t);return e.treePathInfo=Yx(i,this),e},setLayoutInfo:function(t){this.layoutInfo=this.layoutInfo||{},P(this.layoutInfo,t)},mapIdToIndex:function(t){var e=this._idIndexMap;e||(e=this._idIndexMap=Q(),this._idIndexMapCount=0);var i=e.get(t);return null==i&&e.set(t,i=this._idIndexMapCount++),i},getViewRoot:function(){return this._viewRoot},resetViewRoot:function(t){t?this._viewRoot=t:t=this._viewRoot;var e=this.getRawData().tree.root;t&&(t===e||e.contains(t))||(this._viewRoot=e)}});var jx=5;function qx(t){this.group=new Ci,t.add(this.group)}function Kx(t,e,i,n,o,a){var r=[[o?t:t-jx,e],[t+i,e],[t+i,e+n],[o?t:t-jx,e+n]];return a||r.splice(2,0,[t+i+jx,e+n/2]),o||r.push([t,e+n/2]),r}qx.prototype={constructor:qx,render:function(t,e,i,n){var o=t.getModel("breadcrumb"),a=this.group;if(a.removeAll(),o.get("show")&&i){var r=o.getModel("itemStyle"),s=r.getModel("textStyle"),l={pos:{left:o.get("left"),right:o.get("right"),top:o.get("top"),bottom:o.get("bottom")},box:{width:e.getWidth(),height:e.getHeight()},emptyItemWidth:o.get("emptyItemWidth"),totalWidth:0,renderList:[]};this._prepare(i,l,s),this._renderContent(t,l,r,s,n),Su(a,l.pos,l.box)}},_prepare:function(t,e,i){for(var n=t;n;n=n.parentNode){var o=n.getModel().get("name"),a=i.getTextRect(o),r=Math.max(a.width+16,e.emptyItemWidth);e.totalWidth+=r+8,e.renderList.push({node:n,text:o,width:r})}},_renderContent:function(t,e,i,n,o){for(var a,r,s=0,l=e.emptyItemWidth,u=t.get("breadcrumb.height"),h=function(t,e,i){var n=e.width,o=e.height,a=El(t.x,n),r=El(t.y,o),s=El(t.x2,n),l=El(t.y2,o);return(isNaN(a)||isNaN(parseFloat(t.x)))&&(a=0),(isNaN(s)||isNaN(parseFloat(t.x2)))&&(s=n),(isNaN(r)||isNaN(parseFloat(t.y)))&&(r=0),(isNaN(l)||isNaN(parseFloat(t.y2)))&&(l=o),i=iu(i||0),{width:Math.max(s-a-i[1]-i[3],0),height:Math.max(l-r-i[0]-i[2],0)}}(e.pos,e.box),c=e.totalWidth,d=e.renderList,f=d.length-1;0<=f;f--){var p=d[f],g=p.node,m=p.width,v=p.text;c>h.width&&(c-=m-l,m=l,v=null);var y=new Qr({shape:{points:Kx(s,0,m,u,f===d.length-1,0===f)},style:D(i.getItemStyle(),{lineJoin:"bevel",text:v,textFill:n.getTextColor(),textFont:n.getFont()}),z:10,onclick:T(o,g)});this.group.add(y),a=t,r=g,y.eventData={componentType:"series",componentSubType:"treemap",componentIndex:a.componentIndex,seriesIndex:a.componentIndex,seriesName:a.name,seriesType:"treemap",selfType:"breadcrumb",nodeData:{dataIndex:r&&r.dataIndex,name:r&&r.name},treePathInfo:r&&Yx(r,a)},s+=m+8}},remove:function(){this.group.removeAll()}};function $x(t){var e=s_(t);return e.stroke=e.fill=e.lineWidth=null,e}var Jx=A,Qx=Ci,t_=rs,e_=R,i_=["label"],n_=["emphasis","label"],o_=["upperLabel"],a_=["emphasis","upperLabel"],r_=10,s_=ha([["fill","color"],["stroke","strokeColor"],["lineWidth","strokeWidth"],["shadowBlur"],["shadowOffsetX"],["shadowOffsetY"],["shadowColor"]]);function l_(h,r,s,l,u,e,c,t,i,n){if(c){var d=c.getLayout(),o=h.getData();if(o.setItemGraphicEl(c.dataIndex,null),d&&d.isInView){var f=d.width,p=d.height,g=d.borderWidth,m=d.invisible,v=c.getRawIndex(),y=t&&t.getRawIndex(),a=c.viewChildren,x=d.upperHeight,_=a&&a.length,w=c.getModel("itemStyle"),b=c.getModel("emphasis.itemStyle"),S=L("nodeGroup",Qx);if(S){if(i.add(S),S.attr("position",[d.x||0,d.y||0]),S.__tmNodeWidth=f,S.__tmNodeHeight=p,d.isAboveViewRoot)return S;var M=c.getModel(),I=L("background",t_,n,1);if(I&&function(t,e,i){if(e.dataIndex=c.dataIndex,e.seriesIndex=h.seriesIndex,e.setShape({x:0,y:0,width:f,height:p}),m)A(e);else{e.invisible=!1;var n=c.getVisual("borderColor",!0),o=b.get("borderColor"),a=$x(w);a.fill=n;var r=s_(b);if(r.fill=o,i){var s=f-2*g;D(a,r,n,s,x,{x:g,y:0,width:s,height:x})}else a.text=r.text=null;e.setStyle(a),Us(e,r)}t.add(e)}(S,I,_&&d.upperLabelHeight),_)Qs(S)&&Js(S,!1),I&&(Js(I,!0),o.setItemGraphicEl(c.dataIndex,I));else{var T=L("content",t_,n,2);T&&function(t,e){e.dataIndex=c.dataIndex,e.seriesIndex=h.seriesIndex;var i=Math.max(f-2*g,0),n=Math.max(p-2*g,0);if(e.culling=!0,e.setShape({x:g,y:g,width:i,height:n}),m)A(e);else{e.invisible=!1;var o=c.getVisual("color",!0),a=$x(w);a.fill=o;var r=s_(b);D(a,r,o,i,n),e.setStyle(a),Us(e,r)}t.add(e)}(S,T),I&&Qs(I)&&Js(I,!1),Js(S,!0),o.setItemGraphicEl(c.dataIndex,S)}return S}}}function A(t){t.invisible||e.push(t)}function D(t,e,i,n,o,a){var r=M.get("name"),s=M.getModel(a?o_:i_),l=M.getModel(a?a_:n_),u=s.getShallow("show");el(t,e,s,l,{defaultText:u?r:null,autoColor:i,isRectText:!0,labelFetcher:h,labelDataIndex:c.dataIndex,labelProp:a?"upperLabel":"label"}),C(t,a,d),C(e,a,d),a&&(t.textRect=k(a)),t.truncate=u&&s.get("ellipsis")?{outerWidth:n,outerHeight:o,minChar:2}:null}function C(t,e,i){var n=t.text;if(!e&&i.isLeafRoot&&null!=n){var o=h.get("drillDownIcon",!0);t.text=o?o+" "+n:n}}function L(t,e,i,n){var o=null!=y&&s[t][y],a=u[t];return o?(s[t][y]=null,function(t,e,i){(t[v]={}).old="nodeGroup"===i?e.position.slice():P({},e.shape)}(a,o,t)):m||((o=new e({z:function(t,e){var i=t*r_+e;return(i-1)/i}(i,n)})).__tmDepth=i,function(t,e,i){var n=t[v]={},o=c.parentNode;if(o&&(!l||"drillDown"===l.direction)){var a=0,r=0,s=u.background[o.getRawIndex()];!l&&s&&s.old&&(a=s.old.width,r=s.old.height),n.old="nodeGroup"===i?[0,r]:{x:a,y:r,width:0,height:0}}n.fadein="nodeGroup"!==i}(a,0,o.__tmStorageName=t)),r[t][v]=o}}Cf({type:"treemap",init:function(t,e){this._containerGroup,this._storage={nodeGroup:[],background:[],content:[]},this._oldTree,this._breadcrumb,this._controller,this._state="ready"},render:function(t,e,i,n){if(!(_(e.findComponents({mainType:"series",subType:"treemap",query:n}),t)<0)){this.seriesModel=t,this.api=i,this.ecModel=e;var o=Zx(n,["treemapZoomToNode","treemapRootToNode"],t),a=n&&n.type,r=t.layoutInfo,s=!this._oldTree,l=this._storage,u="treemapRootToNode"===a&&o&&l?{rootNodeGroup:l.nodeGroup[o.node.getRawIndex()],direction:n.direction}:null,h=this._giveContainerGroup(r),c=this._doRender(h,t,u);s||a&&"treemapZoomToNode"!==a&&"treemapRootToNode"!==a?c.renderFinally():this._doAnimation(h,c,t,u),this._resetController(i),this._renderBreadcrumb(t,i,o)}},_giveContainerGroup:function(t){var e=this._containerGroup;return e||(e=this._containerGroup=new Qx,this._initEvents(e),this.group.add(e)),e.attr("position",[t.x,t.y]),e},_doRender:function(t,e,i){var n=e.getData().tree,o=this._oldTree,a={nodeGroup:[],background:[],content:[]},r={nodeGroup:[],background:[],content:[]},s=this._storage,l=[],c=T(l_,e,r,s,i,a,l);!function a(r,s,l,u,h){u?e_(s=r,function(t,e){t.isRemoved()||i(e,e)}):new kf(s,r,t,t).add(i).update(i).remove(T(i,null)).execute();function t(t){return t.getId()}function i(t,e){var i=null!=t?r[t]:null,n=null!=e?s[e]:null,o=c(i,n,l,h);o&&a(i&&i.viewChildren||[],n&&n.viewChildren||[],o,u,h+1)}}(n.root?[n.root]:[],o&&o.root?[o.root]:[],t,n===o||!o,0);var u,h,d=(h={nodeGroup:[],background:[],content:[]},(u=s)&&e_(u,function(t,e){var i=h[e];e_(t,function(t){t&&(i.push(t),t.__tmWillDelete=1)})}),h);return this._oldTree=n,this._storage=r,{lastsForAnimation:a,willDeleteEls:d,renderFinally:function(){e_(d,function(t){e_(t,function(t){t.parent&&t.parent.remove(t)})}),e_(l,function(t){t.invisible=!0,t.dirty()})}}},_doAnimation:function(t,a,e,s){if(e.get("animation")){var l=e.get("animationDurationUpdate"),u=e.get("animationEasing"),h=function(){var a,r=[],s={};return{add:function(t,e,i,n,o){return E(n)&&(o=n,n=0),!s[t.id]&&(s[t.id]=1,r.push({el:t,target:e,time:i,delay:n,easing:o}),!0)},done:function(t){return a=t,this},start:function(){for(var t=r.length,e=0,i=r.length;e=o.length||t===o[t.depth]){var i=E_(r,l,t,e,g,a);n(t,i,o,a)}})}else c=P_(l),t.setVisual("color",c)}(o,{},t.getViewRoot().getAncestors(),t)}};function k_(i,n,t){var o=P({},n),a=t.designatedVisualItemStyle;return R(["color","colorAlpha","colorSaturation"],function(t){a[t]=n[t];var e=i.get(t);(a[t]=null)!=e&&(o[t]=e)}),o}function P_(t){var e=N_(t,"color");if(e){var i=N_(t,"colorAlpha"),n=N_(t,"colorSaturation");return n&&(e=qe(e,null,null,n)),i&&(e=Ke(e,i)),e}}function N_(t,e){var i=t[e];if(null!=i&&"none"!==i)return i}function O_(t,e,i,n,o,a){if(a&&a.length){var r=R_(e,"color")||null!=o.color&&"none"!==o.color&&(R_(e,"colorAlpha")||R_(e,"colorSaturation"));if(r){var s=e.get("visualMin"),l=e.get("visualMax"),u=i.dataExtent.slice();null!=s&&su[1]&&(u[1]=l);var h=e.get("colorMappingBy"),c={type:r.name,dataExtent:u,visual:r.range};"color"!==c.type||"index"!==h&&"id"!==h?c.mappingMethod="linear":(c.mappingMethod="category",c.loop=!0);var d=new g_(c);return d.__drColorMappingBy=h,d}}}function R_(t,e){var i=t.get(e);return D_(i)&&i.length?{name:e,range:i}:null}function E_(t,e,i,n,o,a){var r=P({},e);if(o){var s=o.type,l="color"===s&&o.__drColorMappingBy,u="index"===l?n:"id"===l?a.mapIdToIndex(i.getId()):i.getValue(t.get("visualDimension"));r[s]=o.mapValueToVisual(u)}return r}var z_=Math.max,B_=Math.min,V_=W,G_=R,F_=["itemStyle","borderWidth"],W_=["itemStyle","gapWidth"],H_=["upperLabel","show"],Z_=["upperLabel","height"],U_={seriesType:"treemap",reset:function(t,e,i,n){var o=i.getWidth(),a=i.getHeight(),r=t.option,s=bu(t.getBoxLayoutParams(),{width:i.getWidth(),height:i.getHeight()}),l=r.size||[],u=El(V_(s.width,l[0]),o),h=El(V_(s.height,l[1]),a),c=n&&n.type,d=Zx(n,["treemapZoomToNode","treemapRootToNode"],t),f="treemapRender"===c||"treemapMove"===c?n.rootRect:null,p=t.getViewRoot(),g=Ux(p);if("treemapMove"!==c){var m="treemapZoomToNode"===c?function(t,e,i,n,o){var a,r=(e||{}).node,s=[n,o];if(!r||r===i)return s;var l=n*o,u=l*t.option.zoomToNodeRatio;for(;a=r.parentNode;){for(var h=0,c=a.children,d=0,f=c.length;ds[1]&&(s[1]=e)})}else s=[NaN,NaN];return{sum:n,dataExtent:s}}(e,r,s);if(0===u.sum)return t.viewChildren=[];if(u.sum=function(t,e,i,n,o){if(!n)return i;for(var a=t.get("visibleMin"),r=o.length,s=r,l=r-1;0<=l;l--){var u=o["asc"===n?r-l-1:l].getValue();u/i*ei[l[r]])&&(h=i[l[r]]);for(var c=0,d=t.length;c "+d)),u++)}var f,p=i.get("coordinateSystem");if("cartesian2d"===p||"polar"===p)f=gp(t,i);else{var g=lh.get(p),m=g&&"view"!==g.type&&g.dimensions||[];_(m,"value")<0&&m.concat(["value"]);var v=lp(t,{coordDimensions:m});(f=new Yf(v,i)).initData(t)}var y=new Yf(["value"],i);return y.initData(l,s),o&&o(f,y),yx({mainData:f,struct:a,structAttr:"graph",datas:{node:f,edge:y},datasAttr:{node:"data",edge:"edgeData"}}),a.update(),a}var nw="--\x3e",ow=function(t){return t.get("autoCurveness")||null},aw=function(t,e){var i=ow(t),n=20,o=[];if("number"==typeof i)n=i;else if(L(i))return void(t.__curvenessList=i);n ")),o.value&&(l+=" : "+au(o.value)),l},_updateCategoriesData:function(){var t=O(this.option.categories||[],function(t){return null!=t.value?t:P({value:0},t)}),e=new Yf(["value"],this);e.initData(t),this._categoriesData=e,this._categoriesModels=e.mapArray(function(t){return e.getItemModel(t,!0)})},setZoom:function(t){this.option.zoom=t},setCenter:function(t){this.option.center=t},isAnimationEnabled:function(){return dw.superCall(this,"isAnimationEnabled")&&!("force"===this.get("layout")&&this.get("force.layoutAnimation"))},defaultOption:{zlevel:0,z:2,coordinateSystem:"view",legendHoverLink:!0,hoverAnimation:!0,layout:null,focusNodeAdjacency:!1,circular:{rotateLabel:!1},force:{initLayout:null,repulsion:[0,50],gravity:.1,friction:.6,edgeLength:30,layoutAnimation:!0},left:"center",top:"center",symbol:"circle",symbolSize:10,edgeSymbol:["none","none"],edgeSymbolSize:10,edgeLabel:{position:"middle",distance:5},draggable:!1,roam:!1,center:null,zoom:1,nodeScaleRatio:.6,label:{show:!1,formatter:"{b}"},itemStyle:{},lineStyle:{color:"#aaa",width:1,opacity:.5},emphasis:{label:{show:!0}}}}),fw=ls.prototype,pw=ds.prototype;function gw(t){return isNaN(+t.cpx1)||isNaN(+t.cpy1)}var mw=Cs({type:"ec-line",style:{stroke:"#000",fill:null},shape:{x1:0,y1:0,x2:0,y2:0,percent:1,cpx1:null,cpy1:null},buildPath:function(t,e){this[gw(e)?"_buildPathLine":"_buildPathCurve"](t,e)},_buildPathLine:fw.buildPath,_buildPathCurve:pw.buildPath,pointAt:function(t){return this[gw(this.shape)?"_pointAtLine":"_pointAtCurve"](t)},_pointAtLine:fw.pointAt,_pointAtCurve:pw.pointAt,tangentAt:function(t){var e=this.shape,i=gw(e)?[e.x2-e.x1,e.y2-e.y1]:this._tangentAtCurve(t);return mt(i,i)},_tangentAtCurve:pw.tangentAt}),vw=["fromSymbol","toSymbol"];function yw(t){return"_"+t+"Type"}function xw(t,e,i){var n=e.getItemVisual(i,t);if(n&&"none"!==n){var o=e.getItemVisual(i,"color"),a=e.getItemVisual(i,t+"Size"),r=e.getItemVisual(i,t+"Rotate");L(a)||(a=[a,a]);var s=wg(n,-a[0]/2,-a[1]/2,a[0],a[1],o);return s.__specifiedRotation=null==r||isNaN(r)?void 0:+r*Math.PI/180||0,s.name=t,s}}function _w(t,e){t.x1=e[0][0],t.y1=e[0][1],t.x2=e[1][0],t.y2=e[1][1],t.percent=1;var i=e[2];i?(t.cpx1=i[0],t.cpy1=i[1]):(t.cpx1=NaN,t.cpy1=NaN)}function ww(t,e,i){Ci.call(this),this._createLine(t,e,i)}var bw=ww.prototype;function Sw(t){this._ctor=t||ww,this.group=new Ci}bw.beforeUpdate=function(){var t=this.childOfName("fromSymbol"),e=this.childOfName("toSymbol"),i=this.childOfName("label");if(t||e||!i.ignore){for(var n=1,o=this.parent;o;)o.scale&&(n/=o.scale[0]),o=o.parent;var a=this.childOfName("line");if(this.__dirty||a.__dirty){var r=a.shape.percent,s=a.pointAt(0),l=a.pointAt(r),u=ht([],l,s);if(mt(u,u),t){if(t.attr("position",s),null==(c=t.__specifiedRotation)){var h=a.tangentAt(0);t.attr("rotation",Math.PI/2-Math.atan2(h[1],h[0]))}else t.attr("rotation",c);t.attr("scale",[n*r,n*r])}if(e){var c;if(e.attr("position",l),null==(c=e.__specifiedRotation)){h=a.tangentAt(1);e.attr("rotation",-Math.PI/2-Math.atan2(h[1],h[0]))}else e.attr("rotation",c);e.attr("scale",[n*r,n*r])}if(!i.ignore){var d,f,p,g;i.attr("position",l);var m=i.__labelDistance,v=m[0]*n,y=m[1]*n,x=r/2,_=[(h=a.tangentAt(x))[1],-h[0]],w=a.pointAt(x);0<_[1]&&(_[0]=-_[0],_[1]=-_[1]);var b,S=h[0]<0?-1:1;if("start"!==i.__position&&"end"!==i.__position){var M=-Math.atan2(h[1],h[0]);l[0]=t&&(0===e?0:n[e-1][0])a&&(e[1-n]=e[n]+c.sign*a),e}function lb(t,e){var i=t[e]-t[1-e];return{span:Math.abs(i),sign:0o*(1-h[0])?(l="jump",r=s-o*(1-h[2])):0<=(r=s-o*h[1])&&(r=s-o*(1-h[1]))<=0&&(r=0),(r*=e.axisExpandWidth/u)?sb(r,n,a,"all"):l="none";else{o=n[1]-n[0];(n=[db(0,a[1]*s/o-o/2)])[1]=cb(a[1],n[0]+o),n[0]=n[1]-o}return{axisExpandWindow:n,behavior:l}}},lh.register("parallel",{create:function(n,o){var a=[];return n.eachComponent("parallel",function(t,e){var i=new vb(t,n,o);i.name="parallel_"+e,i.resize(t,o),(t.coordinateSystem=i).model=t,a.push(i)}),n.eachSeries(function(t){if("parallel"===t.get("coordinateSystem")){var e=n.queryComponents({mainType:"parallel",index:t.get("parallelIndex"),id:t.get("parallelId")})[0];t.coordinateSystem=e.coordinateSystem}}),a}});var xb=ku.extend({type:"baseParallelAxis",axis:null,activeIntervals:[],getAreaSelectStyle:function(){return ha([["fill","color"],["lineWidth","borderWidth"],["stroke","borderColor"],["width","width"],["opacity","opacity"]])(this.getModel("areaSelectStyle"))},setActiveIntervals:function(t){var e=this.activeIntervals=k(t);if(e)for(var i=e.length-1;0<=i;i--)Bl(e[i])},getActiveState:function(t){var e=this.activeIntervals;if(!e.length)return"normal";if(null==t||isNaN(t))return"inactive";if(1===e.length){var i=e[0];if(i[0]<=t&&t<=i[1])return"active"}else for(var n=0,o=e.length;nn.getWidth()||i<0||i>n.getHeight()}(t,e)){var n=t._zr,o=t._covers,a=Fb(t,e,i);if(!t._dragging)for(var r=0;rf&&(f=m.depth),g.setLayout({depth:v?m.depth:c},!0),"vertical"===a?g.setLayout({dy:i},!0):g.setLayout({dx:i},!0);for(var y=0;y "))},preventIncremental:function(){return!!this.get("effect.show")},getProgressive:function(){var t=this.option.progressive;return null==t?this.option.large?1e4:this.get("progressive"):t},getProgressiveThreshold:function(){var t=this.option.progressiveThreshold;return null==t?this.option.large?2e4:this.get("progressiveThreshold"):t},defaultOption:{coordinateSystem:"geo",zlevel:0,z:2,legendHoverLink:!0,hoverAnimation:!0,xAxisIndex:0,yAxisIndex:0,symbol:["none","none"],symbolSize:[10,10],geoIndex:0,effect:{show:!1,period:4,constantSpeed:0,symbol:"circle",symbolSize:3,loop:!0,trailLength:.2},large:!1,largeThreshold:2e3,polyline:!1,clip:!0,label:{show:!1,position:"end"},lineStyle:{opacity:.5}}});function bM(t,e,i){Ci.call(this),this.add(this.createLine(t,e,i)),this._updateEffectSymbol(t,e)}var SM=bM.prototype;function MM(t,e,i){Ci.call(this),this._createPolyline(t,e,i)}SM.createLine=function(t,e,i){return new ww(t,e,i)},SM._updateEffectSymbol=function(t,e){var i=t.getItemModel(e).getModel("effect"),n=i.get("symbolSize"),o=i.get("symbol");L(n)||(n=[n,n]);var a=i.get("color")||t.getItemVisual(e,"color"),r=this.childAt(1);this._symbolType!==o&&(this.remove(r),(r=wg(o,-.5,-.5,1,1,a)).z2=100,r.culling=!0,this.add(r)),r&&(r.setStyle("shadowColor",a),r.setStyle(i.getItemStyle(["color"])),r.attr("scale",n),r.setColor(a),r.attr("scale",n),this._symbolType=o,this._symbolScale=n,this._updateEffectAnimation(t,i,e))},SM._updateEffectAnimation=function(e,t,i){var n=this.childAt(1);if(n){var o=this,a=e.getItemLayout(i),r=1e3*t.get("period"),s=t.get("loop"),l=t.get("constantSpeed"),u=W(t.get("delay"),function(t){return t/e.count()*r/3}),h="function"==typeof u;if(n.ignore=!0,this.updateAnimationPoints(n,a),0e);r++);r=Math.min(r-1,o-2)}wt(t.position,i[r],i[r+1],(e-n[r])/(n[r+1]-n[r]));var s=i[r+1][0]-i[r][0],l=i[r+1][1]-i[r][1];t.rotation=-Math.atan2(l,s)-Math.PI/2,this._lastFrame=r,this._lastFramePercent=e,t.ignore=!1}},w(TM,bM);var DM=Cs({shape:{polyline:!1,curveness:0,segs:[]},buildPath:function(t,e){var i=e.segs,n=e.curveness;if(e.polyline)for(var o=0;o=e[0]&&t<=e[1]}}(y,e.option.range):function(e,n,o){var i=e[1]-e[0],a=(n=O(n,function(t){return{interval:[(t.interval[0]-e[0])/i,(t.interval[1]-e[0])/i]}})).length,r=0;return function(t){for(var e=r;e=e.y&&t[1]<=e.y+e.height:i.contain(i.toLocalCoord(t[1]))&&t[0]>=e.y&&t[0]<=e.y+e.height},pointToData:function(t){var e=this.getAxis();return[e.coordToData(e.toLocalCoord(t["horizontal"===e.orient?0:1]))]},dataToPoint:function(t){var e=this.getAxis(),i=this.getRect(),n=[],o="horizontal"===e.orient?0:1;return t instanceof Array&&(t=t[0]),n[o]=e.toGlobalCoord(e.dataToCoord(+t)),n[1-o]=0==o?i.y+i.height/2:i.x+i.width/2,n}}).dimensions});var sI=["axisLine","axisTickLabel","axisName"],lI=["splitArea","splitLine"],uI=mv.extend({type:"singleAxis",axisPointerClass:"SingleAxisPointer",render:function(e,t,i,n){var o=this.group;o.removeAll();var a=this._axisGroup;this._axisGroup=new Ci;var r=rI(e),s=new Qm(e,r);R(sI,s.add,s),o.add(this._axisGroup),o.add(s.getGroup()),R(lI,function(t){e.get(t+".show")&&this["_"+t](e)},this),ml(a,this._axisGroup,e),uI.superCall(this,"render",e,t,i,n)},remove:function(){bv(this)},_splitLine:function(t){var e=t.axis;if(!e.scale.isBlank()){var i=t.getModel("splitLine"),n=i.getModel("lineStyle"),o=n.get("width"),a=n.get("color");a=a instanceof Array?a:[a];for(var r=t.coordinateSystem.getRect(),s=e.isHorizontal(),l=[],u=0,h=e.getTicksCoords({tickModel:i}),c=[],d=[],f=0;fr)return!0;if(a){var s=fv(t).seriesDataCount,l=n.getExtent();return Math.abs(l[0]-l[1])/s>r}return!1},makeElOption:function(t,e,i,n,o){},createPointerEl:function(t,e,i,n){var o=e.pointer;if(o){var a=AI(t).pointerEl=new bl[o.type](DI(e.pointer));t.add(a)}},createLabelEl:function(t,e,i,n){if(e.label){var o=AI(t).labelEl=new rs(DI(e.label));t.add(o),PI(o,n)}},updatePointerEl:function(t,e,i){var n=AI(t).pointerEl;n&&e.pointer&&(n.setStyle(e.pointer.style),i(n,{shape:e.pointer.shape}))},updateLabelEl:function(t,e,i,n){var o=AI(t).labelEl;o&&(o.setStyle(e.label.style),i(o,{shape:e.label.shape,position:e.label.position}),PI(o,n))},_renderHandle:function(t){if(!this._dragging&&this.updateHandleTransform){var e,i=this._axisPointerModel,n=this._api.getZr(),o=this._handle,a=i.getModel("handle"),r=i.get("status");if(!a.get("show")||!r||"hide"===r)return o&&n.remove(o),void(this._handle=null);this._handle||(e=!0,o=this._handle=yl(a.get("icon"),{cursor:"move",draggable:!0,onmousemove:function(t){Xt(t.event)},onmousedown:CI(this._onHandleDragMove,this,0,0),drift:CI(this._onHandleDragMove,this),ondragend:CI(this._onHandleDragEnd,this)}),n.add(o)),OI(o,i,!1);o.setStyle(a.getItemStyle(null,["color","borderColor","borderWidth","opacity","shadowColor","shadowBlur","shadowOffsetX","shadowOffsetY"]));var s=a.get("size");L(s)||(s=[s,s]),o.attr("scale",[s[0]/2,s[1]/2]),kc(this,"_doDispatchAxisPointer",a.get("throttle")||0,"fixRate"),this._moveHandleToValue(t,e)}},_moveHandleToValue:function(t,e){kI(this._axisPointerModel,!e&&this._moveAnimation,this._handle,NI(this.getHandleTransform(t,this._axisModel,this._axisPointerModel)))},_onHandleDragMove:function(t,e){var i=this._handle;if(i){this._dragging=!0;var n=this.updateHandleTransform(NI(i),[t,e],this._axisModel,this._axisPointerModel);this._payloadInfo=n,i.stopAnimation(),i.attr(NI(n)),AI(i).lastProp=null,this._doDispatchAxisPointer()}},_doDispatchAxisPointer:function(){if(this._handle){var t=this._payloadInfo,e=this._axisModel;this._api.dispatchAction({type:"updateAxisPointer",x:t.cursorPoint[0],y:t.cursorPoint[1],tooltipOption:t.tooltipOption,axesInfo:[{axisDim:e.axis.dim,axisIndex:e.componentIndex}]})}},_onHandleDragEnd:function(t){if(this._dragging=!1,this._handle){var e=this._axisPointerModel.get("value");this._moveHandleToValue(e),this._api.dispatchAction({type:"hideTip"})}},getHandleTransform:null,updateHandleTransform:null,clear:function(t){this._lastValue=null,this._lastStatus=null;var e=t.getZr(),i=this._group,n=this._handle;e&&i&&(this._lastGraphicKey=null,i&&e.remove(i),n&&e.remove(n),this._group=null,this._handle=null,this._payloadInfo=null)},doClear:function(){},buildLabel:function(t,e,i){return{x:t[i=i||0],y:t[1-i],width:e[i],height:e[1-i]}}}).constructor=LI);var HI=LI.extend({makeElOption:function(t,e,i,n,o){var a=i.axis,r=a.grid,s=n.get("type"),l=ZI(r,a).getOtherAxis(a).getGlobalExtent(),u=a.toGlobalCoord(a.dataToCoord(e,!0));if(s&&"none"!==s){var h=RI(n),c=UI[s](a,u,l);c.style=h,t.graphicKey=c.type,t.pointer=c}VI(e,t,_v(r.model,i),i,n,o)},getHandleTransform:function(t,e,i){var n=_v(e.axis.grid.model,e,{labelInside:!1});return n.labelMargin=i.get("handle.margin"),{position:BI(e.axis,t,n),rotation:n.rotation+(n.labelDirection<0?Math.PI:0)}},updateHandleTransform:function(t,e,i,n){var o=i.axis,a=o.grid,r=o.getGlobalExtent(!0),s=ZI(a,o).getOtherAxis(o).getGlobalExtent(),l="x"===o.dim?0:1,u=t.position;u[l]+=e[l],u[l]=Math.min(r[1],u[l]),u[l]=Math.max(r[0],u[l]);var h=(s[1]+s[0])/2,c=[h,h];c[l]=u[l];return{position:u,rotation:t.rotation,cursorPoint:c,tooltipOption:[{verticalAlign:"middle"},{align:"center"}][l]}}});function ZI(t,e){var i={};return i[e.dim+"AxisIndex"]=e.index,t.getCartesian(i)}var UI={line:function(t,e,i){return{type:"Line",subPixelOptimize:!0,shape:GI([e,i[0]],[e,i[1]],XI(t))}},shadow:function(t,e,i){var n=Math.max(1,t.getBandWidth()),o=i[1]-i[0];return{type:"Rect",shape:FI([e-n/2,i[0]],[n,o],XI(t))}}};function XI(t){return"x"===t.dim?0:1}mv.registerAxisPointerClass("CartesianAxisPointer",HI),yf(function(t){if(t){t.axisPointer&&0!==t.axisPointer.length||(t.axisPointer={});var e=t.axisPointer.link;e&&!L(e)&&(t.axisPointer.link=[e])}}),xf(Ld.PROCESSOR.STATISTIC,function(t,e){t.getComponent("axisPointer").coordSysAxesInfo=cv(t,e)}),_f({type:"updateAxisPointer",event:"updateAxisPointer",update:":updateAxisPointer"},function(t,e,i){var n=t.currTrigger,r=[t.x,t.y],o=t,a=t.dispatchAction||A(i.dispatchAction,i),s=e.getComponent("axisPointer").coordSysAxesInfo;if(s){xI(r)&&(r=cI({seriesIndex:o.seriesIndex,dataIndex:o.dataIndex},e).point);var l=xI(r),u=o.axesInfo,h=s.axesInfo,c="leave"===n||xI(r),d={},f={},p={list:[],map:{}},g={showPointer:fI(mI,f),showTooltip:fI(vI,p)};dI(s.coordSysMap,function(t,e){var a=l||t.containPoint(r);dI(s.coordSysAxesInfo[e],function(t,e){var i=t.axis,n=function(t,e){for(var i=0;i<(t||[]).length;i++){var n=t[i];if(e.axis.dim===n.axisDim&&e.axis.model.componentIndex===n.axisIndex)return n}}(u,t);if(!c&&a&&(!u||n)){var o=n&&n.value;null!=o||l||(o=i.pointToData(r)),null!=o&&gI(t,o,g,!1,d)}})});var m={};return dI(h,function(o,t){var a=o.linkGroup;a&&!f[t]&&dI(a.axesInfo,function(t,e){var i=f[e];if(t!==o&&i){var n=i.value;a.mapper&&(n=o.axis.scale.parse(a.mapper(n,yI(t),yI(o)))),m[o.key]=n}})}),dI(m,function(t,e){gI(h[e],t,g,!0,d)}),function(o,t,e){var a=e.axesInfo=[];dI(t,function(t,e){var i=t.axisPointerModel.option,n=o[e];n?(t.useHandle||(i.status="show"),i.value=n.value,i.seriesDataIndices=(n.payloadBatch||[]).slice()):t.useHandle||(i.status="hide"),"show"===i.status&&a.push({axisDim:t.axis.dim,axisIndex:t.axis.model.componentIndex,value:i.value})})}(f,h,d),function(t,e,i,n){if(xI(e)||!t.list.length)return n({type:"hideTip"});var o=((t.list[0].dataByAxis[0]||{}).seriesDataIndices||[])[0]||{};n({type:"showTip",escapeConnect:!0,x:e[0],y:e[1],tooltipOption:i.tooltipOption,position:i.position,dataIndexInside:o.dataIndexInside,dataIndex:o.dataIndex,seriesIndex:o.seriesIndex,dataByCoordSys:t.list})}(p,r,t,a),function(t,e,i){var n=i.getZr(),o="axisPointerLastHighlights",a=pI(n)[o]||{},r=pI(n)[o]={};dI(t,function(t,e){var i=t.axisPointerModel.option;"show"===i.status&&dI(i.seriesDataIndices,function(t){var e=t.seriesIndex+" | "+t.dataIndex;r[e]=t})});var s=[],l=[];R(a,function(t,e){r[e]||l.push(t)}),R(r,function(t,e){a[e]||s.push(t)}),l.length&&i.dispatchAction({type:"downplay",escapeConnect:!0,batch:l}),s.length&&i.dispatchAction({type:"highlight",escapeConnect:!0,batch:s})}(h,0,i),d}});var YI=["x","y"],jI=["width","height"],qI=LI.extend({makeElOption:function(t,e,i,n,o){var a=i.axis,r=a.coordinateSystem,s=JI(r,1-$I(a)),l=r.dataToPoint(e)[0],u=n.get("type");if(u&&"none"!==u){var h=RI(n),c=KI[u](a,l,s);c.style=h,t.graphicKey=c.type,t.pointer=c}VI(e,t,rI(i),i,n,o)},getHandleTransform:function(t,e,i){var n=rI(e,{labelInside:!1});return n.labelMargin=i.get("handle.margin"),{position:BI(e.axis,t,n),rotation:n.rotation+(n.labelDirection<0?Math.PI:0)}},updateHandleTransform:function(t,e,i,n){var o=i.axis,a=o.coordinateSystem,r=$I(o),s=JI(a,r),l=t.position;l[r]+=e[r],l[r]=Math.min(s[1],l[r]),l[r]=Math.max(s[0],l[r]);var u=JI(a,1-r),h=(u[1]+u[0])/2,c=[h,h];return c[r]=l[r],{position:l,rotation:t.rotation,cursorPoint:c,tooltipOption:{verticalAlign:"middle"}}}}),KI={line:function(t,e,i){return{type:"Line",subPixelOptimize:!0,shape:GI([e,i[0]],[e,i[1]],$I(t))}},shadow:function(t,e,i){var n=t.getBandWidth(),o=i[1]-i[0];return{type:"Rect",shape:FI([e-n/2,i[0]],[n,o],$I(t))}}};function $I(t){return t.isHorizontal()?0:1}function JI(t,e){var i=t.getRect();return[i[YI[e]],i[YI[e]]+i[jI[e]]]}mv.registerAxisPointerClass("SingleAxisPointer",qI),Af({type:"single"});var QI=sc.extend({type:"series.themeRiver",dependencies:["singleAxis"],nameMap:null,init:function(t){QI.superApply(this,"init",arguments),this.legendVisualProvider=new qv(A(this.getData,this),A(this.getRawData,this))},fixData:function(t){var e=t.length,i={},n=ta(t,function(t){return i.hasOwnProperty(t[0])||(i[t[0]]=-1),t[2]}),o=[];n.buckets.each(function(t,e){o.push({name:e,dataList:t})});for(var a=o.length,r=0;rMath.PI/2?"right":"left"):x&&"center"!==x?"left"===x?(f=u.r0+y,p>Math.PI/2&&(x="right")):"right"===x&&(f=u.r-y,p>Math.PI/2&&(x="left")):(f=(u.r+u.r0)/2,x="center"),d.attr("style",{text:l,textAlign:x,textVerticalAlign:M("verticalAlign")||"middle",opacity:M("opacity")});var _=f*g+u.cx,w=f*m+u.cy;d.attr("position",[_,w]);var b=M("rotate"),S=0;function M(t){var e=a.get(t);return null==e?o.get(t):e}"radial"===b?(S=-p)<-Math.PI/2&&(S+=Math.PI):"tangential"===b?(S=Math.PI/2-p)>Math.PI/2?S-=Math.PI:S<-Math.PI/2&&(S+=Math.PI):"number"==typeof b&&(S=b*Math.PI/180),d.attr("rotation",S)},sT._initEvents=function(t,e,i,n){t.off("mouseover").off("mouseout").off("emphasis").off("normal");function o(){r.onEmphasis(n)}function a(){r.onNormal()}var r=this;i.isAnimationEnabled()&&t.on("mouseover",o).on("mouseout",a).on("emphasis",o).on("normal",a).on("downplay",function(){r.onDownplay()}).on("highlight",function(){r.onHighlight()})},w(rT,Ci);_c.extend({type:"sunburst",init:function(){},render:function(o,a,t,e){var n=this;this.seriesModel=o,this.api=t,this.ecModel=a;var r=o.getData(),s=r.tree.root,i=o.getViewRoot(),l=this.group,u=o.get("renderLabelForZeroData"),h=[];i.eachNode(function(t){h.push(t)});var c=this._oldChildren||[];if(function(i,n){if(0===i.length&&0===n.length)return;function t(t){return t.getId()}function e(t,e){!function(t,e){u||!t||t.getValue()||(t=null);if(t!==s&&e!==s)if(e&&e.piece)t?(e.piece.updateData(!1,t,"normal",o,a),r.setItemGraphicEl(t.dataIndex,e.piece)):function(t){if(!t)return;t.piece&&(l.remove(t.piece),t.piece=null)}(e);else if(t){var i=new rT(t,o,a);l.add(i),r.setItemGraphicEl(t.dataIndex,i)}}(null==t?null:i[t],null==e?null:n[e])}new kf(n,i,t,t).add(e).update(e).remove(T(e,null)).execute()}(h,c),function(t,e){if(0=i.r0}}});var lT="sunburstRootToNode";_f({type:lT,update:"updateView"},function(o,t){t.eachComponent({mainType:"series",subType:"sunburst",query:o},function(t,e){var i=Zx(o,[lT],t);if(i){var n=t.getViewRoot();n&&(o.direction=Xx(n,i.node)?"rollUp":"drillDown"),t.resetViewRoot(i.node)}})});var uT="sunburstHighlight";_f({type:uT,update:"updateView"},function(n,t){t.eachComponent({mainType:"series",subType:"sunburst",query:n},function(t,e){var i=Zx(n,[uT],t);i&&(n.highlight=i.node)})});_f({type:"sunburstUnhighlight",update:"updateView"},function(i,t){t.eachComponent({mainType:"series",subType:"sunburst",query:i},function(t,e){i.unhighlight=!0})});var hT=Math.PI/180;function cT(t,e){if("function"==typeof e)return t.sort(e);var n="asc"===e;return t.sort(function(t,e){var i=(t.getValue()-e.getValue())*(n?1:-1);return 0==i?(t.dataIndex-e.dataIndex)*(n?-1:1):i})}function dT(a,r){return r=r||[0,0],O(["x","y"],function(t,e){var i=this.getAxis(t),n=r[e],o=a[e]/2;return"category"===i.type?i.getBandWidth():Math.abs(i.dataToCoord(n-o)-i.dataToCoord(n+o))},this)}Sf(T(iy,"sunburst")),bf(T(function(t,e,C,i){e.eachSeriesByType(t,function(t){var e=t.get("center"),i=t.get("radius");L(i)||(i=[0,i]),L(e)||(e=[e,e]);var n=C.getWidth(),o=C.getHeight(),h=Math.min(n,o),c=El(e[0],n),d=El(e[1],o),f=El(i[0],h/2),a=El(i[1],h/2),r=-t.get("startAngle")*hT,p=t.get("minAngle")*hT,g=t.getData().tree.root,s=t.getViewRoot(),m=s.depth,l=t.get("sort");null!=l&&!function e(t,i){var n=t.children||[];t.children=cT(n,i);n.length&&R(t.children,function(t){e(t,i)})}(s,l);var u=0;R(s.children,function(t){isNaN(t.getValue())||u++});var v=s.getValue(),y=Math.PI/(v||u)*2,x=0t[1]&&t.reverse(),{coordSys:{type:"polar",cx:o.cx,cy:o.cy,r:t[1],r0:t[0]},api:{coord:A(function(t){var e=a.dataToRadius(t[0]),i=r.dataToAngle(t[1]),n=o.coordToPoint([e,i]);return n.push(e,i*Math.PI/180),n}),size:A(gT,o)}}},calendar:function(i){var t=i.getRect(),e=i.getRangeInfo();return{coordSys:{type:"calendar",x:t.x,y:t.y,width:t.width,height:t.height,cellWidth:i.getCellWidth(),cellHeight:i.getCellHeight(),rangeInfo:{start:e.start,end:e.end,weeks:e.weeks,dayCount:e.allDay}},api:{coord:function(t,e){return i.dataToPoint(t,e)}}}}};function ST(t,e,i,n,o){null==i[t]||o||(e[t]=i[t],i[t]=n[t])}function MT(a,r,e,t){var i=a.get("renderItem"),n=a.coordinateSystem,o={};n&&(o=n.prepareCustoms?n.prepareCustoms():bT[n.type](n));var s,l,u,h,c,d=D({getWidth:t.getWidth,getHeight:t.getHeight,getZr:t.getZr,getDevicePixelRatio:t.getDevicePixelRatio,value:function(t,e){return null==e&&(e=s),r.get(r.getDimension(t||0),e)},style:function(t,e){null==e&&(e=s),g(e);var i=l.getModel(vT).getItemStyle();null!=c&&(i.fill=c);var n=r.getItemVisual(e,"opacity");null!=n&&(i.opacity=n);var o=t?CT(t,u):u;return nl(i,o,null,{autoColor:c,isRectText:!0}),i.text=o.getShallow("show")?H(a.getFormattedLabel(e,"normal"),Ug(r,e)):null,t&<(i,t),i},styleEmphasis:function(t,e){null==e&&(e=s),g(e);var i=l.getModel(yT).getItemStyle(),n=t?CT(t,h):h;return nl(i,n,null,{isRectText:!0},!0),i.text=n.getShallow("show")?Z(a.getFormattedLabel(e,"emphasis"),a.getFormattedLabel(e,"normal"),Ug(r,e)):null,t&<(i,t),i},visual:function(t,e){return null==e&&(e=s),r.getItemVisual(e,t)},barLayout:function(t){if(n.getBaseAxis){return function(t){var e=[],i=t.axis;if("category"===i.type){for(var n=i.getBandWidth(),o=0;oe[1]&&e.reverse();var i=t.getExtent(),n=Math.PI/180;return{cx:this.cx,cy:this.cy,r0:e[0],r:e[1],startAngle:-i[0]*n,endAngle:-i[1]*n,clockwise:t.inverse,contain:function(t,e){var i=t-this.cx,n=e-this.cy,o=i*i+n*n,a=this.r,r=this.r0;return o<=a*a&&r*r<=o}}}};var GT=ku.extend({type:"polarAxis",axis:null,getCoordSysModel:function(){return this.ecModel.queryComponents({mainType:"polar",index:this.option.polarIndex,id:this.option.polarId})[0]}});m(GT.prototype,dg);var FT={splitNumber:5};function WT(t,e){return e.type||(e.data?"category":"value")}function HT(t,e){var i=this,n=i.getAngleAxis(),o=i.getRadiusAxis();if(n.scale.setExtent(1/0,-1/0),o.scale.setExtent(1/0,-1/0),t.eachSeries(function(t){if(t.coordinateSystem===i){var e=t.getData();R(e.mapDimension("radius",!0),function(t){o.scale.unionExtentFromData(e,pp(e,t))}),R(e.mapDimension("angle",!0),function(t){n.scale.unionExtentFromData(e,pp(e,t))})}}),rg(n.scale,n.model),rg(o.scale,o.model),"category"===n.type&&!n.onBand){var a=n.getExtent(),r=360/n.scale.count();n.inverse?a[1]+=r:a[1]-=r,n.setExtent(a[0],a[1])}}function ZT(t,e){if(t.type=e.get("type"),t.scale=sg(e),t.onBand=e.get("boundaryGap")&&"category"===t.type,t.inverse=e.get("inverse"),"angleAxis"===e.mainType){t.inverse^=e.get("clockwise");var i=e.get("startAngle");t.setExtent(i,i+(t.inverse?-360:360))}(e.axis=t).model=e}Gm("angle",GT,WT,{startAngle:90,clockwise:!0,splitNumber:12,axisLabel:{rotate:!1}}),Gm("radius",GT,WT,FT),Tf({type:"polar",dependencies:["polarAxis","angleAxis"],coordinateSystem:null,findAxisModel:function(t){var e;return this.ecModel.eachComponent(t,function(t){t.getCoordSysModel()===this&&(e=t)},this),e},defaultOption:{zlevel:0,z:0,center:["50%","50%"],radius:"80%"}}),lh.register("polar",{dimensions:VT.prototype.dimensions,create:function(i,s){var l=[];return i.eachComponent("polar",function(t,e){var i=new VT(e);i.update=HT;var n=i.getRadiusAxis(),o=i.getAngleAxis(),a=t.findAxisModel("radiusAxis"),r=t.findAxisModel("angleAxis");ZT(n,a),ZT(o,r),function(t,e,i){var n=e.get("center"),o=i.getWidth(),a=i.getHeight();t.cx=El(n[0],o),t.cy=El(n[1],a);var r=t.getRadiusAxis(),s=Math.min(o,a)/2,l=e.get("radius");null==l?l=[0,"100%"]:L(l)||(l=[0,l]),l=[El(l[0],s),El(l[1],s)],r.inverse?r.setExtent(l[1],l[0]):r.setExtent(l[0],l[1])}(i,t,s),l.push(i),(t.coordinateSystem=i).model=t}),i.eachSeries(function(t){if("polar"===t.get("coordinateSystem")){var e=i.queryComponents({mainType:"polar",index:t.get("polarIndex"),id:t.get("polarId")})[0];t.coordinateSystem=e.coordinateSystem}}),l}});var UT=["axisLine","axisLabel","axisTick","minorTick","splitLine","minorSplitLine","splitArea"];function XT(t,e,i){e[1]>e[0]&&(e=e.slice().reverse());var n=t.coordToPoint([e[0],i]),o=t.coordToPoint([e[1],i]);return{x1:n[0],y1:n[1],x2:o[0],y2:o[1]}}function YT(t){return t.getRadiusAxis().inverse?0:1}function jT(t){var e=t[0],i=t[t.length-1];e&&i&&Math.abs(Math.abs(e.coord-i.coord)-360)<1e-4&&t.pop()}mv.extend({type:"angleAxis",axisPointerClass:"PolarAxisPointer",render:function(e,t){if(this.group.removeAll(),e.get("show")){var i=e.axis,n=i.polar,o=n.getRadiusAxis().getExtent(),a=i.getTicksCoords(),r=i.getMinorTicksCoords(),s=O(i.getViewLabels(),function(t){return(t=k(t)).coord=i.dataToCoord(t.tickValue),t});jT(s),jT(a),R(UT,function(t){!e.get(t+".show")||i.scale.isBlank()&&"axisLine"!==t||this["_"+t](e,n,a,r,o,s)},this)}},_axisLine:function(t,e,i,n,o){var a,r=t.getModel("axisLine.lineStyle"),s=YT(e),l=s?0:1;(a=0===o[l]?new Yr({shape:{cx:e.cx,cy:e.cy,r:o[s]},style:r.getLineStyle(),z2:1,silent:!0}):new Kr({shape:{cx:e.cx,cy:e.cy,r:o[s],r0:o[l]},style:r.getLineStyle(),z2:1,silent:!0})).style.fill=null,this.group.add(a)},_axisTick:function(t,e,i,n,o){var a=t.getModel("axisTick"),r=(a.get("inside")?-1:1)*a.get("length"),s=o[YT(e)],l=O(i,function(t){return new ls({shape:XT(e,[s,s+r],t.coord)})});this.group.add(Rs(l,{style:D(a.getModel("lineStyle").getLineStyle(),{stroke:t.get("axisLine.lineStyle.color")})}))},_minorTick:function(t,e,i,n,o){if(n.length){for(var a=t.getModel("axisTick"),r=t.getModel("minorTick"),s=(a.get("inside")?-1:1)*r.get("length"),l=o[YT(e)],u=[],h=0;hr?"left":"right",u=Math.abs(a[1]-s)/o<.3?"middle":a[1]>s?"top":"bottom";p&&p[n]&&p[n].textStyle&&(i=new Cl(p[n].textStyle,g,g.ecModel));var h=new Ur({silent:Qm.isLabelSilent(c)});this.group.add(h),nl(h.style,i,{x:a[0],y:a[1],textFill:i.getTextColor()||c.get("axisLine.lineStyle.color"),text:t.formattedLabel,textAlign:l,textVerticalAlign:u}),v&&(h.eventData=Qm.makeAxisEventDataBase(c),h.eventData.targetType="axisLabel",h.eventData.value=t.rawLabel)},this)},_splitLine:function(t,e,i,n,o){var a=t.getModel("splitLine").getModel("lineStyle"),r=a.get("color"),s=0;r=r instanceof Array?r:[r];for(var l=[],u=0;um?"left":"right",h=Math.abs(l[1]-v)/g<.3?"middle":l[1]>v?"top":"bottom"}return{position:l,align:u,verticalAlign:h}}(e,i,0,s,d))}});var JT={line:function(t,e,i,n,o){return"angle"===t.dim?{type:"Line",shape:GI(e.coordToPoint([n[0],i]),e.coordToPoint([n[1],i]))}:{type:"Circle",shape:{cx:e.cx,cy:e.cy,r:i}}},shadow:function(t,e,i,n,o){var a=Math.max(1,t.getBandWidth()),r=Math.PI/180;return"angle"===t.dim?{type:"Sector",shape:WI(e.cx,e.cy,n[0],n[1],(-i-a/2)*r,(a/2-i)*r)}:{type:"Sector",shape:WI(e.cx,e.cy,i-a/2,i+a/2,0,2*Math.PI)}}};function QT(n,t){t.update="updateView",_f(t,function(t,e){var i={};return e.eachComponent({mainType:"geo",query:t},function(e){e[n](t.name),R(e.coordinateSystem.regions,function(t){i[t.name]=e.isSelected(t.name)||!1})}),{selected:i,name:t.name}})}mv.registerAxisPointerClass("PolarAxisPointer",$T),bf(T(function(t,e,i){var N={},O=function(t){var g={};R(t,function(t,e){var i=t.getData(),n=t.coordinateSystem,o=n.getBaseAxis(),a=RT(n,o),r=o.getExtent(),s="category"===o.type?o.getBandWidth():Math.abs(r[1]-r[0])/i.count(),l=g[a]||{bandWidth:s,remainedWidth:s,autoWidthCount:0,categoryGap:"20%",gap:"30%",stacks:{}},u=l.stacks;g[a]=l;var h=OT(t);u[h]||l.autoWidthCount++,u[h]=u[h]||{width:0,maxWidth:0};var c=El(t.get("barWidth"),s),d=El(t.get("barMaxWidth"),s),f=t.get("barGap"),p=t.get("barCategoryGap");c&&!u[h].width&&(c=Math.min(l.remainedWidth,c),u[h].width=c,l.remainedWidth-=c),d&&(u[h].maxWidth=d),null!=f&&(l.gap=f),null!=p&&(l.categoryGap=p)});var d={};return R(g,function(t,i){d[i]={};var e=t.stacks,n=t.bandWidth,o=El(t.categoryGap,n),a=El(t.gap,1),r=t.remainedWidth,s=t.autoWidthCount,l=(r-o)/(s+(s-1)*a);l=Math.max(l,0),R(e,function(t,e){var i=t.maxWidth;i&&i=n.start.time&&i.timea.end.time&&t.reverse(),t},_getRangeInfo:function(t){var e;(t=[this.getDateInfo(t[0]),this.getDateInfo(t[1])])[0].time>t[1].time&&(e=!0,t.reverse());var i=Math.floor(t[1].time/864e5)-Math.floor(t[0].time/864e5)+1,n=new Date(t[0].time),o=n.getDate(),a=t[1].date.getDate();n.setDate(o+i-1);var r=n.getDate();if(r!==a)for(var s=0n.weeks||0===t&&en.lweek)return!1;var o=7*(t-1)-n.fweek+e,a=new Date(n.start.time);return a.setDate(n.start.d+o),this.getDateInfo(a)}},tA.dimensions=tA.prototype.dimensions,tA.getDimensionsInfo=tA.prototype.getDimensionsInfo,tA.create=function(i,n){var o=[];return i.eachComponent("calendar",function(t){var e=new tA(t,i,n);o.push(e),t.coordinateSystem=e}),i.eachSeries(function(t){"calendar"===t.get("coordinateSystem")&&(t.coordinateSystem=o[t.get("calendarIndex")||0])}),o},lh.register("calendar",tA);var iA=ku.extend({type:"calendar",coordinateSystem:null,defaultOption:{zlevel:0,z:2,left:80,top:60,cellSize:20,orient:"horizontal",splitLine:{show:!0,lineStyle:{color:"#000",width:1,type:"solid"}},itemStyle:{color:"#fff",borderWidth:1,borderColor:"#ccc"},dayLabel:{show:!0,firstDay:0,position:"start",margin:"50%",nameMap:"en",color:"#000"},monthLabel:{show:!0,position:"start",margin:5,align:"center",nameMap:"en",formatter:null,color:"#000"},yearLabel:{show:!0,position:null,margin:30,formatter:null,color:"#ccc",fontFamily:"sans-serif",fontWeight:"bolder",fontSize:20}},init:function(t,e,i,n){var o=Iu(t);iA.superApply(this,"init",arguments),nA(t,o)},mergeOption:function(t,e){iA.superApply(this,"mergeOption",arguments),nA(this.option,t)}});function nA(t,e){var i=t.cellSize;L(i)?1===i.length&&(i[1]=i[0]):i=t.cellSize=[i,i];var n=O([0,1],function(t){return function(t,e){return null!=t[xu[e][0]]||null!=t[xu[e][1]]&&null!=t[xu[e][2]]}(e,t)&&(i[t]="auto"),null!=i[t]&&"auto"!==i[t]});Mu(t,e,{type:"box",ignoreSize:n})}var oA={EN:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],CN:["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"]},aA={EN:["S","M","T","W","T","F","S"],CN:["日","一","二","三","四","五","六"]};Af({type:"calendar",_tlpoints:null,_blpoints:null,_firstDayOfMonth:null,_firstDayPoints:null,render:function(t,e,i){var n=this.group;n.removeAll();var o=t.coordinateSystem,a=o.getRangeInfo(),r=o.getOrient();this._renderDayRect(t,a,n),this._renderLines(t,a,r,n),this._renderYearText(t,a,r,n),this._renderMonthText(t,r,n),this._renderWeekText(t,a,r,n)},_renderDayRect:function(t,e,i){for(var n=t.coordinateSystem,o=t.getModel("itemStyle").getItemStyle(),a=n.getCellWidth(),r=n.getCellHeight(),s=e.start.time;s<=e.end.time;s=n.getNextNDay(s,1).time){var l=n.dataToRect([s],!1).tl,u=new rs({shape:{x:l[0],y:l[1],width:a,height:r},cursor:"default",style:o});i.add(u)}},_renderLines:function(i,t,n,o){var a=this,r=i.coordinateSystem,s=i.getModel("splitLine.lineStyle").getLineStyle(),l=i.get("splitLine.show"),e=s.lineWidth;this._tlpoints=[],this._blpoints=[],this._firstDayOfMonth=[],this._firstDayPoints=[];for(var u=t.start,h=0;u.time<=t.end.time;h++){d(u.formatedDate),0===h&&(u=r.getDateInfo(t.start.y+"-"+t.start.m));var c=u.date;c.setMonth(c.getMonth()+1),u=r.getDateInfo(c)}function d(t){a._firstDayOfMonth.push(r.getDateInfo(t)),a._firstDayPoints.push(r.dataToRect([t],!1).tl);var e=a._getLinePointsOfOneWeek(i,t,n);a._tlpoints.push(e[0]),a._blpoints.push(e[e.length-1]),l&&a._drawSplitline(e,s,o)}d(r.getNextNDay(t.end.time,1).formatedDate),l&&this._drawSplitline(a._getEdgesPoints(a._tlpoints,e,n),s,o),l&&this._drawSplitline(a._getEdgesPoints(a._blpoints,e,n),s,o)},_getEdgesPoints:function(t,e,i){var n=[t[0].slice(),t[t.length-1].slice()],o="horizontal"===i?0:1;return n[0][o]=n[0][o]-e/2,n[1][o]=n[1][o]+e/2,n},_drawSplitline:function(t,e,i){var n=new ts({z2:20,shape:{points:t},style:e});i.add(n)},_getLinePointsOfOneWeek:function(t,e,i){var n=t.coordinateSystem;e=n.getDateInfo(e);for(var o=[],a=0;a<7;a++){var r=n.getNextNDay(e.time,a),s=n.dataToRect([r.time],!1);o[2*r.day]=s.tl,o[2*r.day+1]=s["horizontal"===i?"bl":"tr"]}return o},_formatterLabel:function(t,e){return"string"==typeof t&&t?uu(t,e):"function"==typeof t?t(e):e.nameMap},_yearTextPositionControl:function(t,e,i,n,o){e=e.slice();var a=["center","bottom"];"bottom"===n?(e[1]+=o,a=["center","top"]):"left"===n?e[0]-=o:"right"===n?(e[0]+=o,a=["center","top"]):e[1]-=o;var r=0;return"left"!==n&&"right"!==n||(r=Math.PI/2),{rotation:r,position:e,style:{textAlign:a[0],textVerticalAlign:a[1]}}},_renderYearText:function(t,e,i,n){var o=t.getModel("yearLabel");if(o.get("show")){var a=o.get("margin"),r=o.get("position");r=r||("horizontal"!==i?"top":"left");var s=[this._tlpoints[this._tlpoints.length-1],this._blpoints[0]],l=(s[0][0]+s[1][0])/2,u=(s[0][1]+s[1][1])/2,h="horizontal"===i?0:1,c={top:[l,s[h][1]],bottom:[l,s[1-h][1]],left:[s[1-h][0],u],right:[s[h][0],u]},d=e.start.y;+e.end.y>+e.start.y&&(d=d+"-"+e.end.y);var f=o.get("formatter"),p={start:e.start.y,end:e.end.y,nameMap:d},g=this._formatterLabel(f,p),m=new Ur({z2:30});nl(m.style,o,{text:g}),m.attr(this._yearTextPositionControl(m,c[r],i,r,a)),n.add(m)}},_monthTextPositionControl:function(t,e,i,n,o){var a="left",r="top",s=t[0],l=t[1];return"horizontal"===i?(l+=o,e&&(a="center"),"start"===n&&(r="bottom")):(s+=o,e&&(r="middle"),"start"===n&&(a="right")),{x:s,y:l,textAlign:a,textVerticalAlign:r}},_renderMonthText:function(t,e,i){var n=t.getModel("monthLabel");if(n.get("show")){var o=n.get("nameMap"),a=n.get("margin"),r=n.get("position"),s=n.get("align"),l=[this._tlpoints,this._blpoints];E(o)&&(o=oA[o.toUpperCase()]||[]);var u="start"===r?0:1,h="horizontal"===e?0:1;a="start"===r?-a:a;for(var c="center"===s,d=0;dd.getHeight()&&(i.textPosition="top",a=!0);var r=a?-5-n.height:p+8;o+n.width/2>d.getWidth()?(i.textPosition=["100%",r],i.textAlign="right"):o-n.width/2<0&&(i.textPosition=[0,r],i.textAlign="left")}})}function t(t,e){var i,n=m[t],o=m[e],a=u[n],r=new Cl(a,h,h.ecModel);if(l&&null!=l.newTitle&&l.featureName===n&&(a.title=l.newTitle),n&&!o){if(function(t){return 0===t.indexOf("my")}(n))i={model:r,onclick:r.option.onclick,featureName:n};else{var s=fA(n);if(!s)return;i=new s(r,c,d)}g[n]=i}else{if(!(i=g[o]))return;i.model=r,i.ecModel=c,i.api=d}n||!o?r.get("show")&&!i.unusable?(function(o,a,t){var r=o.getModel("iconStyle"),s=o.getModel("emphasis.iconStyle"),e=a.getIcons?a.getIcons():o.get("icon"),l=o.get("title")||{};if("string"==typeof e){var i=e,n=l;l={},(e={})[t]=i,l[t]=n}var u=o.iconPaths={};R(e,function(t,e){var i=yl(t,{},{x:-p/2,y:-p/2,width:p,height:p});i.setStyle(r.getItemStyle()),i.hoverStyle=s.getItemStyle(),i.setStyle({text:l[e],textAlign:s.get("textAlign"),textBorderRadius:s.get("textBorderRadius"),textPadding:s.get("textPadding"),textFill:null});var n=h.getModel("tooltip");n&&n.get("show")&&i.attr("tooltip",P({content:l[e],formatter:n.get("formatter",!0)||function(){return l[e]},formatterParams:{componentType:"toolbox",name:e,title:l[e],$vars:["name","title"]},position:n.get("position",!0)||"bottom"},n.option)),$s(i),h.get("showTitle")&&(i.__title=l[e],i.on("mouseover",function(){var t=s.getItemStyle(),e="vertical"===h.get("orient")?null==h.get("right")?"right":"left":null==h.get("bottom")?"bottom":"top";i.setStyle({textFill:s.get("textFill")||t.fill||t.stroke||"#000",textBackgroundColor:s.get("textBackgroundColor"),textPosition:s.get("textPosition")||e})}).on("mouseout",function(){i.setStyle({textFill:null,textBackgroundColor:null})})),i.trigger(o.get("iconStatus."+e)||"normal"),f.add(i),i.on("click",A(a.onclick,a,c,d,e)),u[e]=i})}(r,i,n),r.setIconStatus=function(t,e){var i=this.option,n=this.iconPaths;i.iconStatus=i.iconStatus||{},i.iconStatus[t]=e,n[t]&&n[t].trigger(e)},i.render&&i.render(r,c,d,l)):i.remove&&i.remove(c,d):i.dispose&&i.dispose(c,d)}},updateView:function(t,e,i,n){R(this._features,function(t){t.updateView&&t.updateView(t.model,e,i,n)})},remove:function(e,i){R(this._features,function(t){t.remove&&t.remove(e,i)}),this.group.removeAll()},dispose:function(e,i){R(this._features,function(t){t.dispose&&t.dispose(e,i)})}});var mA=Oc.toolbox.saveAsImage;function vA(t){this.model=t}vA.defaultOption={show:!0,icon:"M4.7,22.9L29.3,45.5L54.7,23.4M4.6,43.6L4.6,58L53.8,58L53.8,43.6M29.2,45.1L29.2,0",title:mA.title,type:"png",connectedBackgroundColor:"#fff",name:"",excludeComponents:["toolbox"],pixelRatio:1,lang:mA.lang.slice()},vA.prototype.unusable=!v.canvasSupported,vA.prototype.onclick=function(t,e){var i=this.model,n=i.get("name")||t.get("title.0.text")||"echarts",o="svg"===e.getZr().painter.getType()?"svg":i.get("type",!0)||"png",a=e.getConnectedDataURL({type:o,backgroundColor:i.get("backgroundColor",!0)||t.get("backgroundColor")||"#fff",connectedBackgroundColor:i.get("connectedBackgroundColor"),excludeComponents:i.get("excludeComponents"),pixelRatio:i.get("pixelRatio")});if("function"!=typeof MouseEvent||v.browser.ie||v.browser.edge)if(window.navigator.msSaveOrOpenBlob){for(var r=atob(a.split(",")[1]),s=r.length,l=new Uint8Array(s);s--;)l[s]=r.charCodeAt(s);var u=new Blob([l]);window.navigator.msSaveOrOpenBlob(u,n+"."+o)}else{var h=i.get("lang"),c='';window.open().document.write(c)}else{var d=document.createElement("a");d.download=n+"."+o,d.target="_blank",d.href=a;var f=new MouseEvent("click",{view:document.defaultView,bubbles:!0,cancelable:!1});d.dispatchEvent(f)}},dA("saveAsImage",vA);var yA=Oc.toolbox.magicType,xA="__ec_magicType_stack__";function _A(t){this.model=t}_A.defaultOption={show:!0,type:[],icon:{line:"M4.1,28.9h7.1l9.3-22l7.4,38l9.7-19.7l3,12.8h14.9M4.1,58h51.4",bar:"M6.7,22.9h10V48h-10V22.9zM24.9,13h10v35h-10V13zM43.2,2h10v46h-10V2zM3.1,58h53.7",stack:"M8.2,38.4l-8.4,4.1l30.6,15.3L60,42.5l-8.1-4.1l-21.5,11L8.2,38.4z M51.9,30l-8.1,4.2l-13.4,6.9l-13.9-6.9L8.2,30l-8.4,4.2l8.4,4.2l22.2,11l21.5-11l8.1-4.2L51.9,30z M51.9,21.7l-8.1,4.2L35.7,30l-5.3,2.8L24.9,30l-8.4-4.1l-8.3-4.2l-8.4,4.2L8.2,30l8.3,4.2l13.9,6.9l13.4-6.9l8.1-4.2l8.1-4.1L51.9,21.7zM30.4,2.2L-0.2,17.5l8.4,4.1l8.3,4.2l8.4,4.2l5.5,2.7l5.3-2.7l8.1-4.2l8.1-4.2l8.1-4.1L30.4,2.2z"},title:k(yA.title),option:{},seriesIndex:{}};var wA=_A.prototype;wA.getIcons=function(){var t=this.model,e=t.get("icon"),i={};return R(t.get("type"),function(t){e[t]&&(i[t]=e[t])}),i};var bA={line:function(t,e,i,n){if("bar"===t)return m({id:e,type:"line",data:i.get("data"),stack:i.get("stack"),markPoint:i.get("markPoint"),markLine:i.get("markLine")},n.get("option.line")||{},!0)},bar:function(t,e,i,n){if("line"===t)return m({id:e,type:"bar",data:i.get("data"),stack:i.get("stack"),markPoint:i.get("markPoint"),markLine:i.get("markLine")},n.get("option.bar")||{},!0)},stack:function(t,e,i,n){var o=i.get("stack")===xA;if("line"===t||"bar"===t)return n.setIconStatus("stack",o?"normal":"emphasis"),m({id:e,stack:o?"":xA},n.get("option.stack")||{},!0)}},SA=[["line","bar"],["stack"]];wA.onclick=function(u,t,h){var c=this.model,e=c.get("seriesIndex."+h);if(bA[h]){var i,d={series:[]};if(R(SA,function(t){0<=_(t,h)&&R(t,function(t){c.setIconStatus(t,"normal")})}),c.setIconStatus(h,"emphasis"),u.eachComponent({mainType:"series",query:null==e?null:{seriesIndex:e}},function(t){var e=t.subType,i=t.id,n=bA[h](e,i,t,c);n&&(D(n,t.option),d.series.push(n));var o=t.coordinateSystem;if(o&&"cartesian2d"===o.type&&("line"===h||"bar"===h)){var a=o.getAxesByScale("ordinal")[0];if(a){var r=a.dim+"Axis",s=u.queryComponents({mainType:r,index:t.get(name+"Index"),id:t.get(name+"Id")})[0].componentIndex;d[r]=d[r]||[];for(var l=0;l<=s;l++)d[r][s]=d[r][s]||{};d[r][s].boundaryGap="bar"===h}}}),"stack"===h)i=d.series&&d.series[0]&&d.series[0].stack===xA?m({stack:yA.title.tiled},yA.title):k(yA.title);t.dispatchAction({type:"changeMagicType",currentType:h,newOption:d,newTitle:i,featureName:"magicType"})}},_f({type:"changeMagicType",event:"magicTypeChanged",update:"prepareAndUpdate"},function(t,e){e.mergeOption(t.newOption)}),dA("magicType",_A);var MA=Oc.toolbox.dataView,IA=new Array(60).join("-"),TA="\t";function AA(t){var e=function(t){var o={},a=[],r=[];return t.eachRawSeries(function(t){var e=t.coordinateSystem;if(!e||"cartesian2d"!==e.type&&"polar"!==e.type)a.push(t);else{var i=e.getBaseAxis();if("category"===i.type){var n=i.dim+"_"+i.index;o[n]||(o[n]={categoryAxis:i,valueAxis:e.getOtherAxis(i),series:[]},r.push({axisDim:i.dim,axisIndex:i.index})),o[n].series.push(t)}else a.push(t)}}),{seriesGroupByCategoryAxis:o,other:a,meta:r}}(t);return{value:M([function(t){var h=[];return R(t,function(t,e){var i=t.categoryAxis,n=t.valueAxis.dim,o=[" "].concat(O(t.series,function(t){return t.name})),a=[i.model.getCategories()];R(t.series,function(t){var e=t.getRawData();a.push(t.getRawData().mapArray(e.mapDimension(n),function(t){return t}))});for(var r=[o.join(TA)],s=0;st[1]&&t.reverse(),t}function GA(t,e){return Ko(t,e,{includeMainTypes:EA})}BA.setOutputRanges=function(t,e){this.matchOutputRanges(t,e,function(t,e,i){if((t.coordRanges||(t.coordRanges=[])).push(e),!t.coordRange){t.coordRange=e;var n=ZA[t.brushType](0,i,e);t.__rangeOffset={offset:XA[t.brushType](n.values,t.range,[1,1]),xyMinMax:n.xyMinMax}}})},BA.matchOutputRanges=function(t,n,o){PA(t,function(i){var t=this.findTargetInfo(i,n);t&&!0!==t&&R(t.coordSyses,function(t){var e=ZA[i.brushType](1,t,i.range);o(i,e.values,t,n)})},this)},BA.setInputRanges=function(t,o){PA(t,function(t){var e=this.findTargetInfo(t,o);if(t.range=t.range||[],e&&!0!==e){t.panelId=e.panelId;var i=ZA[t.brushType](0,e.coordSys,t.coordRange),n=t.__rangeOffset;t.range=n?XA[t.brushType](i.values,n.offset,function(t,e){var i=jA(t),n=jA(e),o=[i[0]/n[0],i[1]/n[1]];return isNaN(o[0])&&(o[0]=1),isNaN(o[1])&&(o[1]=1),o}(i.xyMinMax,n.xyMinMax)):i.values}},this)},BA.makePanelOpts=function(i,n){return O(this._targetInfoList,function(t){var e=t.getPanelRect();return{panelId:t.panelId,defaultBrushType:n&&n(t),clipPath:hS(e),isTargetByCursor:dS(e,i,t.coordSysModel),getLinearBrushOtherExtent:cS(e)}})},BA.controlSeries=function(t,e,i){var n=this.findTargetInfo(t,i);return!0===n||n&&0<=NA(n.coordSyses,e.coordinateSystem)},BA.findTargetInfo=function(t,e){for(var i=this._targetInfoList,n=GA(e,t),o=0;on[1]&&(n[1]=e[1])})}),n[1]c[1];if(r&&!s&&!l)return!0;r&&(n=!0),s&&(e=!0),l&&(i=!0)}return n&&e&&i}):rD(h,function(t){if("empty"===o)i.setData(u=u.map(t,function(t){return function(t){return t>=c[0]&&t<=c[1]}(t)?t:NaN}));else{var e={};e[t]=c,u.selectRange(e)}}),rD(h,function(t){u.setApproximateExtent(c,t)}))})}}};var uD=R,hD=nD,cD=Tf({type:"dataZoom",dependencies:["xAxis","yAxis","zAxis","radiusAxis","angleAxis","singleAxis","series"],defaultOption:{zlevel:0,z:4,orient:null,xAxisIndex:null,yAxisIndex:null,filterMode:"filter",throttle:null,start:0,end:100,startValue:null,endValue:null,minSpan:null,maxSpan:null,minValueSpan:null,maxValueSpan:null,rangeMode:null},init:function(t,e,i){this._dataIntervalByAxis={},this._dataInfo={},this._axisProxies={},this.textStyleModel,this._autoThrottle=!0,this._rangePropMode=["percent","percent"];var n=dD(t);this.settledOption=n,this.mergeDefaultAndTheme(t,i),this.doInit(n)},mergeOption:function(t){var e=dD(t);m(this.option,t,!0),m(this.settledOption,e,!0),this.doInit(e)},doInit:function(t){var i=this.option;v.canvasSupported||(i.realtime=!1),this._setDefaultThrottle(t),fD(this,t);var n=this.settledOption;uD([["start","startValue"],["end","endValue"]],function(t,e){"value"===this._rangePropMode[e]&&(i[t[0]]=n[t[0]]=null)},this),this.textStyleModel=this.getModel("textStyle"),this._resetTarget(),this._giveAxisProxies()},_giveAxisProxies:function(){var r=this._axisProxies;this.eachTargetAxis(function(t,e,i,n){var o=this.dependentModels[t.axis][e],a=o.__dzAxisProxy||(o.__dzAxisProxy=new aD(t.name,e,this,n));r[t.name+"_"+e]=a},this)},_resetTarget:function(){var i=this.option,t=this._judgeAutoMode();hD(function(t){var e=t.axisIndex;i[e]=Vo(i[e])},this),"axisIndex"===t?this._autoSetAxisIndex():"orient"===t&&this._autoSetOrient()},_judgeAutoMode:function(){var e=this.option,i=!1;hD(function(t){null!=e[t.axisIndex]&&(i=!0)},this);var t=e.orient;return null==t&&i?"orient":i?void 0:(null==t&&(e.orient="horizontal"),"axisIndex")},_autoSetAxisIndex:function(){var a=!0,e=this.get("orient",!0),r=this.option,t=this.dependentModels;if(a){var i="vertical"===e?"y":"x";t[i+"Axis"].length?(r[i+"AxisIndex"]=[0],a=!1):uD(t.singleAxis,function(t){a&&t.get("orient",!0)===e&&(r.singleAxisIndex=[t.componentIndex],a=!1)})}a&&hD(function(t){if(a){var e=[],i=this.dependentModels[t.axis];if(i.length&&!e.length)for(var n=0,o=i.length;ne[0][1]&&(e[0][1]=a[0]),a[1]e[1][1]&&(e[1][1]=a[1])}return e&&eC(e)}};function eC(t){return new Di(t[0][0],t[1][0],t[0][1]-t[0][0],t[1][1]-t[1][0])}var iC=["#ddd"];Tf({type:"brush",dependencies:["geo","grid","xAxis","yAxis","parallel","series"],defaultOption:{toolbox:null,brushLink:null,seriesIndex:"all",geoIndex:null,xAxisIndex:null,yAxisIndex:null,brushType:"rect",brushMode:"single",transformable:!0,brushStyle:{borderWidth:1,color:"rgba(120,140,180,0.3)",borderColor:"rgba(120,140,180,0.8)"},throttleType:"fixRate",throttleDelay:0,removeOnClick:!0,z:1e4},areas:[],brushType:null,brushOption:{},coordInfoList:[],optionUpdated:function(t,e){var i=this.option;e||WD(i,t,["inBrush","outOfBrush"]);var n=i.inBrush=i.inBrush||{};i.outOfBrush=i.outOfBrush||{color:iC},n.hasOwnProperty("liftZ")||(n.liftZ=5)},setAreas:function(t){t&&(this.areas=O(t,function(t){return nC(this.option,t)},this))},setBrushOption:function(t){this.brushOption=nC(this.option,t),this.brushType=this.brushOption.brushType}});function nC(t,e){return m({brushType:t.brushType,brushMode:t.brushMode,transformable:t.transformable,brushStyle:new Cl(t.brushStyle).getItemStyle(),removeOnClick:t.removeOnClick,z:t.z},e,!0)}function oC(t,e,i,n){n&&n.$from===t.id||this._brushController.setPanels(t.brushTargetManager.makePanelOpts(i)).enableBrush(t.brushOption).updateCovers(t.areas.slice())}Af({type:"brush",init:function(t,e){this.ecModel=t,this.api=e,this.model,(this._brushController=new Ob(e.getZr())).on("brush",A(this._onBrush,this)).mount()},render:function(t){return this.model=t,oC.apply(this,arguments)},updateTransform:function(t,e){return KD(e),oC.apply(this,arguments)},updateView:oC,dispose:function(){this._brushController.dispose()},_onBrush:function(t,e){var i=this.model.id;this.model.brushTargetManager.setOutputRanges(t,this.ecModel),e.isEnd&&!e.removeOnClick||this.api.dispatchAction({type:"brush",brushId:i,areas:k(t),$from:i}),e.isEnd&&this.api.dispatchAction({type:"brushEnd",brushId:i,areas:k(t),$from:i})}}),_f({type:"brush",event:"brush"},function(e,t){t.eachComponent({mainType:"brush",query:e},function(t){t.setAreas(e.areas)})}),_f({type:"brushSelect",event:"brushSelected",update:"none"},function(){}),_f({type:"brushEnd",event:"brushEnd",update:"none"},function(){});var aC=Oc.toolbox.brush;function rC(t,e,i){this.model=t,this.ecModel=e,this.api=i,this._brushType,this._brushMode}rC.defaultOption={show:!0,type:["rect","polygon","lineX","lineY","keep","clear"],icon:{rect:"M7.3,34.7 M0.4,10V-0.2h9.8 M89.6,10V-0.2h-9.8 M0.4,60v10.2h9.8 M89.6,60v10.2h-9.8 M12.3,22.4V10.5h13.1 M33.6,10.5h7.8 M49.1,10.5h7.8 M77.5,22.4V10.5h-13 M12.3,31.1v8.2 M77.7,31.1v8.2 M12.3,47.6v11.9h13.1 M33.6,59.5h7.6 M49.1,59.5 h7.7 M77.5,47.6v11.9h-13",polygon:"M55.2,34.9c1.7,0,3.1,1.4,3.1,3.1s-1.4,3.1-3.1,3.1 s-3.1-1.4-3.1-3.1S53.5,34.9,55.2,34.9z M50.4,51c1.7,0,3.1,1.4,3.1,3.1c0,1.7-1.4,3.1-3.1,3.1c-1.7,0-3.1-1.4-3.1-3.1 C47.3,52.4,48.7,51,50.4,51z M55.6,37.1l1.5-7.8 M60.1,13.5l1.6-8.7l-7.8,4 M59,19l-1,5.3 M24,16.1l6.4,4.9l6.4-3.3 M48.5,11.6 l-5.9,3.1 M19.1,12.8L9.7,5.1l1.1,7.7 M13.4,29.8l1,7.3l6.6,1.6 M11.6,18.4l1,6.1 M32.8,41.9 M26.6,40.4 M27.3,40.2l6.1,1.6 M49.9,52.1l-5.6-7.6l-4.9-1.2",lineX:"M15.2,30 M19.7,15.6V1.9H29 M34.8,1.9H40.4 M55.3,15.6V1.9H45.9 M19.7,44.4V58.1H29 M34.8,58.1H40.4 M55.3,44.4 V58.1H45.9 M12.5,20.3l-9.4,9.6l9.6,9.8 M3.1,29.9h16.5 M62.5,20.3l9.4,9.6L62.3,39.7 M71.9,29.9H55.4",lineY:"M38.8,7.7 M52.7,12h13.2v9 M65.9,26.6V32 M52.7,46.3h13.2v-9 M24.9,12H11.8v9 M11.8,26.6V32 M24.9,46.3H11.8v-9 M48.2,5.1l-9.3-9l-9.4,9.2 M38.9-3.9V12 M48.2,53.3l-9.3,9l-9.4-9.2 M38.9,62.3V46.4",keep:"M4,10.5V1h10.3 M20.7,1h6.1 M33,1h6.1 M55.4,10.5V1H45.2 M4,17.3v6.6 M55.6,17.3v6.6 M4,30.5V40h10.3 M20.7,40 h6.1 M33,40h6.1 M55.4,30.5V40H45.2 M21,18.9h62.9v48.6H21V18.9z",clear:"M22,14.7l30.9,31 M52.9,14.7L22,45.7 M4.7,16.8V4.2h13.1 M26,4.2h7.8 M41.6,4.2h7.8 M70.3,16.8V4.2H57.2 M4.7,25.9v8.6 M70.3,25.9v8.6 M4.7,43.2v12.6h13.1 M26,55.8h7.8 M41.6,55.8h7.8 M70.3,43.2v12.6H57.2"},title:k(aC.title)};var sC=rC.prototype;sC.render=sC.updateView=function(e,t,i){var n,o,a;t.eachComponent({mainType:"brush"},function(t){n=t.brushType,o=t.brushOption.brushMode||"single",a|=t.areas.length}),this._brushType=n,this._brushMode=o,R(e.get("type",!0),function(t){e.setIconStatus(t,("keep"===t?"multiple"===o:"clear"===t?a:t===n)?"emphasis":"normal")})},sC.getIcons=function(){var t=this.model,e=t.get("icon",!0),i={};return R(t.get("type",!0),function(t){e[t]&&(i[t]=e[t])}),i},sC.onclick=function(t,e,i){var n=this._brushType,o=this._brushMode;"clear"===i?(e.dispatchAction({type:"axisAreaSelect",intervals:[]}),e.dispatchAction({type:"brush",command:"clear",areas:[]})):e.dispatchAction({type:"takeGlobalCursor",key:"brush",brushOption:{brushType:"keep"===i?n:n!==i&&i,brushMode:"keep"===i?"multiple"===o?"single":"multiple":o}})},dA("brush",rC),yf(function(t,e){var i=t&&t.brush;if(L(i)||(i=i?[i]:[]),i.length){var n=[];R(i,function(t){var e=t.hasOwnProperty("toolbox")?t.toolbox:[];e instanceof Array&&(n=n.concat(e))});var o=t&&t.toolbox;L(o)&&(o=o[0]),o||(o={feature:{}},t.toolbox=[o]);var a=o.feature||(o.feature={}),r=a.brush||(a.brush={}),s=r.type||(r.type=[]);s.push.apply(s,n),function(i){var e={};R(i,function(t){e[t]=1}),i.length=0,R(e,function(t,e){i.push(e)})}(s),e&&!s.length&&s.push.apply(s,BD)}}),Tf({type:"title",layoutMode:{type:"box",ignoreSize:!0},defaultOption:{zlevel:0,z:6,show:!0,text:"",target:"blank",subtext:"",subtarget:"blank",left:0,top:0,backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,padding:5,itemGap:10,textStyle:{fontSize:18,fontWeight:"bolder",color:"#333"},subtextStyle:{color:"#aaa"}}}),Af({type:"title",render:function(t,e,i){if(this.group.removeAll(),t.get("show")){var n=this.group,o=t.getModel("textStyle"),a=t.getModel("subtextStyle"),r=t.get("textAlign"),s=H(t.get("textBaseline"),t.get("textVerticalAlign")),l=new Ur({style:nl({},o,{text:t.get("text"),textFill:o.getTextColor()},{disableBox:!0}),z2:10}),u=l.getBoundingRect(),h=t.get("subtext"),c=new Ur({style:nl({},a,{text:h,textFill:a.getTextColor(),y:u.height+t.get("itemGap"),textVerticalAlign:"top"},{disableBox:!0}),z2:10}),d=t.get("link"),f=t.get("sublink"),p=t.get("triggerEvent",!0);l.silent=!d&&!p,c.silent=!f&&!p,d&&l.on("click",function(){gu(d,"_"+t.get("target"))}),f&&c.on("click",function(){gu(f,"_"+t.get("subtarget"))}),l.eventData=c.eventData=p?{componentType:"title",componentIndex:t.componentIndex}:null,n.add(l),h&&n.add(c);var g=n.getBoundingRect(),m=t.getBoxLayoutParams();m.width=g.width,m.height=g.height;var v=bu(m,{width:i.getWidth(),height:i.getHeight()},t.get("padding"));r||("middle"===(r=t.get("left")||t.get("right"))&&(r="center"),"right"===r?v.x+=v.width:"center"===r&&(v.x+=v.width/2)),s||("center"===(s=t.get("top")||t.get("bottom"))&&(s="middle"),"bottom"===s?v.y+=v.height:"middle"===s&&(v.y+=v.height/2),s=s||"top"),n.attr("position",[v.x,v.y]);var y={textAlign:r,textVerticalAlign:s};l.setStyle(y),c.setStyle(y),g=n.getBoundingRect();var x=v.margin,_=t.getItemStyle(["color","opacity"]);_.fill=t.get("backgroundColor");var w=new rs({shape:{x:g.x-x[3],y:g.y-x[0],width:g.width+x[1]+x[3],height:g.height+x[0]+x[2],r:t.get("borderRadius")},style:_,subPixelOptimize:!0,silent:!0});n.add(w)}}});function lC(t){var e=t.itemStyle||(t.itemStyle={}),i=e.emphasis||(e.emphasis={}),n=t.label||t.label||{},o=n.normal||(n.normal={}),a={normal:1,emphasis:1};R(n,function(t,e){a[e]||uC(o,e)||(o[e]=t)}),i.label&&!uC(n,"emphasis")&&(n.emphasis=i.label,delete i.label)}function uC(t,e){return t.hasOwnProperty(e)}ku.registerSubTypeDefaulter("timeline",function(){return"slider"}),_f({type:"timelineChange",event:"timelineChanged",update:"prepareAndUpdate"},function(t,e){var i=e.getComponent("timeline");return i&&null!=t.currentIndex&&(i.setCurrentIndex(t.currentIndex),!i.get("loop",!0)&&i.isIndexMax()&&i.setPlayState(!1)),e.resetOption("timeline"),D({currentIndex:i.option.currentIndex},t)}),_f({type:"timelinePlayChange",event:"timelinePlayChanged",update:"update"},function(t,e){var i=e.getComponent("timeline");i&&null!=t.playState&&i.setPlayState(t.playState)});var hC=ku.extend({type:"timeline",layoutMode:"box",defaultOption:{zlevel:0,z:4,show:!0,axisType:"time",realtime:!0,left:"20%",top:null,right:"20%",bottom:0,width:null,height:40,padding:5,controlPosition:"left",autoPlay:!1,rewind:!1,loop:!0,playInterval:2e3,currentIndex:0,itemStyle:{},label:{color:"#000"},data:[]},init:function(t,e,i){this._data,this._names,this.mergeDefaultAndTheme(t,i),this._initData()},mergeOption:function(t){hC.superApply(this,"mergeOption",arguments),this._initData()},setCurrentIndex:function(t){null==t&&(t=this.option.currentIndex);var e=this._data.count();this.option.loop?t=(t%e+e)%e:(e<=t&&(t=e-1),t<0&&(t=0)),this.option.currentIndex=t},getCurrentIndex:function(){return this.option.currentIndex},isIndexMax:function(){return this.getCurrentIndex()>=this._data.count()-1},setPlayState:function(t){this.option.autoPlay=!!t},getPlayState:function(){return!!this.option.autoPlay},_initData:function(){var t=this.option,e=t.data||[],i=t.axisType,o=this._names=[];if("category"===i){var a=[];R(e,function(t,e){var i,n=Wo(t);z(t)?(i=k(t)).value=e:i=e,a.push(i),E(n)||null!=n&&!isNaN(n)||(n=""),o.push(n+"")}),e=a}var n={category:"ordinal",time:"time"}[i]||"number";(this._data=new Yf([{name:"value",type:n}],this)).initData(e,o)},getData:function(){return this._data},getCategories:function(){if("category"===this.get("axisType"))return this._names.slice()}});b(hC.extend({type:"timeline.slider",defaultOption:{backgroundColor:"rgba(0,0,0,0)",borderColor:"#ccc",borderWidth:0,orient:"horizontal",inverse:!1,tooltip:{trigger:"item"},symbol:"emptyCircle",symbolSize:10,lineStyle:{show:!0,width:2,color:"#304654"},label:{position:"auto",show:!0,interval:"auto",rotate:0,color:"#304654"},itemStyle:{color:"#304654",borderWidth:1},checkpointStyle:{symbol:"circle",symbolSize:13,color:"#c23531",borderWidth:5,borderColor:"rgba(194,53,49, 0.5)",animation:!0,animationDuration:300,animationEasing:"quinticInOut"},controlStyle:{show:!0,showPlayBtn:!0,showPrevBtn:!0,showNextBtn:!0,itemSize:22,itemGap:12,position:"left",playIcon:"path://M31.6,53C17.5,53,6,41.5,6,27.4S17.5,1.8,31.6,1.8C45.7,1.8,57.2,13.3,57.2,27.4S45.7,53,31.6,53z M31.6,3.3 C18.4,3.3,7.5,14.1,7.5,27.4c0,13.3,10.8,24.1,24.1,24.1C44.9,51.5,55.7,40.7,55.7,27.4C55.7,14.1,44.9,3.3,31.6,3.3z M24.9,21.3 c0-2.2,1.6-3.1,3.5-2l10.5,6.1c1.899,1.1,1.899,2.9,0,4l-10.5,6.1c-1.9,1.1-3.5,0.2-3.5-2V21.3z",stopIcon:"path://M30.9,53.2C16.8,53.2,5.3,41.7,5.3,27.6S16.8,2,30.9,2C45,2,56.4,13.5,56.4,27.6S45,53.2,30.9,53.2z M30.9,3.5C17.6,3.5,6.8,14.4,6.8,27.6c0,13.3,10.8,24.1,24.101,24.1C44.2,51.7,55,40.9,55,27.6C54.9,14.4,44.1,3.5,30.9,3.5z M36.9,35.8c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H36c0.5,0,0.9,0.4,0.9,1V35.8z M27.8,35.8 c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H27c0.5,0,0.9,0.4,0.9,1L27.8,35.8L27.8,35.8z",nextIcon:"path://M18.6,50.8l22.5-22.5c0.2-0.2,0.3-0.4,0.3-0.7c0-0.3-0.1-0.5-0.3-0.7L18.7,4.4c-0.1-0.1-0.2-0.3-0.2-0.5 c0-0.4,0.3-0.8,0.8-0.8c0.2,0,0.5,0.1,0.6,0.3l23.5,23.5l0,0c0.2,0.2,0.3,0.4,0.3,0.7c0,0.3-0.1,0.5-0.3,0.7l-0.1,0.1L19.7,52 c-0.1,0.1-0.3,0.2-0.5,0.2c-0.4,0-0.8-0.3-0.8-0.8C18.4,51.2,18.5,51,18.6,50.8z",prevIcon:"path://M43,52.8L20.4,30.3c-0.2-0.2-0.3-0.4-0.3-0.7c0-0.3,0.1-0.5,0.3-0.7L42.9,6.4c0.1-0.1,0.2-0.3,0.2-0.5 c0-0.4-0.3-0.8-0.8-0.8c-0.2,0-0.5,0.1-0.6,0.3L18.3,28.8l0,0c-0.2,0.2-0.3,0.4-0.3,0.7c0,0.3,0.1,0.5,0.3,0.7l0.1,0.1L41.9,54 c0.1,0.1,0.3,0.2,0.5,0.2c0.4,0,0.8-0.3,0.8-0.8C43.2,53.2,43.1,53,43,52.8z",color:"#304654",borderColor:"#304654",borderWidth:1},emphasis:{label:{show:!0,color:"#c23531"},itemStyle:{color:"#c23531"},controlStyle:{color:"#c23531",borderColor:"#c23531",borderWidth:2}},data:[]}}),Xh);function cC(t,e,i,n){Gg.call(this,t,e,i),this.type=n||"value",this.model=null}var dC=gc.extend({type:"timeline"});cC.prototype={constructor:cC,getLabelModel:function(){return this.model.getModel("label")},isHorizontal:function(){return"horizontal"===this.model.get("orient")}},w(cC,Gg);var fC=A,pC=R,gC=Math.PI;function mC(t,e,i,n,o,a){var r=e.get("color");o?(o.setColor(r),i.add(o),a&&a.onUpdate(o)):((o=wg(t.get("symbol"),-1,-1,2,2,r)).setStyle("strokeNoScale",!0),i.add(o),a&&a.onCreate(o));var s=e.getItemStyle(["color","symbol","symbolSize"]);o.setStyle(s),n=m({rectHover:!0,z2:100},n,!0);var l=t.get("symbolSize");(l=l instanceof Array?l.slice():[+l,+l])[0]/=2,l[1]/=2,n.scale=l;var u=t.get("symbolOffset");if(u){var h=n.position=n.position||[0,0];h[0]+=El(u[0],l[0]),h[1]+=El(u[1],l[1])}var c=t.get("symbolRotate");return n.rotation=(c||0)*Math.PI/180||0,o.attr(n),o.updateTransform(),o}function vC(t,e,i,n,o){if(!t.dragging){var a=n.getModel("checkpointStyle"),r=i.dataToCoord(n.getData().get(["value"],e));o||!a.get("animation",!0)?t.attr({position:[r,0]}):(t.stopAnimation(!0),t.animateTo({position:[r,0]},a.get("animationDuration",!0),a.get("animationEasing",!0)))}}dC.extend({type:"timeline.slider",init:function(t,e){this.api=e,this._axis,this._viewRect,this._timer,this._currentPointer,this._mainGroup,this._labelGroup},render:function(e,t,i,n){if(this.model=e,this.api=i,this.ecModel=t,this.group.removeAll(),e.get("show",!0)){var o=this._layout(e,i),a=this._createGroup("mainGroup"),r=this._createGroup("labelGroup"),s=this._axis=this._createAxis(o,e);e.formatTooltip=function(t){return au(s.scale.getLabel(t))},pC(["AxisLine","AxisTick","Control","CurrentPointer"],function(t){this["_render"+t](o,a,s,e)},this),this._renderAxisLabel(o,r,s,e),this._position(o,e)}this._doPlayStop()},remove:function(){this._clearTimer(),this.group.removeAll()},dispose:function(){this._clearTimer()},_layout:function(t,e){var i=t.get("label.position"),n=t.get("orient"),o=function(t,e){return bu(t.getBoxLayoutParams(),{width:e.getWidth(),height:e.getHeight()},t.get("padding"))}(t,e);null==i||"auto"===i?i="horizontal"===n?o.y+o.height/2n[1]&&(i=n[1]),i":"\n"),s&&(l+=xC(s),null!=a&&(l+=" : ")),null!=a&&(l+=xC(r)),l},getData:function(){return this._data},setData:function(t){this._data=t}});b(wC,Xh),wC.extend({type:"markPoint",defaultOption:{zlevel:0,z:5,symbol:"pin",symbolSize:50,tooltip:{trigger:"item"},label:{show:!0,position:"inside"},itemStyle:{borderWidth:2},emphasis:{label:{show:!0}}}});var bC=_;function SC(t,e,i,n,o,a){var r=[],s=fp(e,n)?e.getCalculationInfo("stackResultDimension"):n,l=LC(e,s,t),u=e.indicesOfNearest(s,l)[0];r[o]=e.get(i,u),r[a]=e.get(s,u);var h=e.get(n,u),c=Vl(e.get(n,u));return 0<=(c=Math.min(c,20))&&(r[a]=+r[a].toFixed(c)),[r,h]}var MC=T,IC={min:MC(SC,"min"),max:MC(SC,"max"),average:MC(SC,"average")};function TC(t,e){var i=t.getData(),n=t.coordinateSystem;if(e&&!function(t){return!isNaN(parseFloat(t.x))&&!isNaN(parseFloat(t.y))}(e)&&!L(e.coord)&&n){var o=n.dimensions,a=AC(e,i,n,t);if((e=k(e)).type&&IC[e.type]&&a.baseAxis&&a.valueAxis){var r=bC(o,a.baseAxis.dim),s=bC(o,a.valueAxis.dim),l=IC[e.type](i,a.baseDataDim,a.valueDataDim,r,s);e.coord=l[0],e.value=l[1]}else{for(var u=[null!=e.xAxis?e.xAxis:e.radiusAxis,null!=e.yAxis?e.yAxis:e.angleAxis],h=0;h<2;h++)IC[u[h]]&&(u[h]=LC(i,i.mapDimension(o[h]),u[h]));e.coord=u}}return e}function AC(t,e,i,n){var o={};return null!=t.valueIndex||null!=t.valueDim?(o.valueDataDim=null!=t.valueIndex?e.getDimension(t.valueIndex):t.valueDim,o.valueAxis=i.getAxis(function(t,e){var i=t.getData(),n=i.dimensions;e=i.getDimension(e);for(var o=0;oi[o],f=[-h.x,-h.y];e||(f[n]=s.position[n]);var p=[0,0],g=[-c.x,-c.y],m=H(t.get("pageButtonGap",!0),t.get("itemGap",!0));d&&("end"===t.get("pageButtonPosition",!0)?g[n]+=i[o]-c[o]:p[n]+=c[o]+m);g[1-n]+=h[a]/2-c[a]/2,s.attr("position",f),l.attr("position",p),u.attr("position",g);var v={x:0,y:0};if(v[o]=d?i[o]:h[o],v[a]=Math.max(h[a],c[a]),v[r]=Math.min(0,c[r]+g[1-n]),l.__rectSize=i[o],d){var y={x:0,y:0};y[o]=Math.max(i[o]-c[o]-m,0),y[a]=v[a],l.setClipPath(new rs({shape:y})),l.__rectSize=y[o]}else u.eachChild(function(t){t.attr({invisible:!0,silent:!0})});var x=this._getPageInfo(t);return null!=x.pageIndex&&cl(s,{position:x.contentPosition},d&&t),this._updatePageInfoView(t,x),v},_pageGo:function(t,e,i){var n=this._getPageInfo(e)[t];null!=n&&i.dispatchAction({type:"legendScroll",scrollDataIndex:n,legendId:e.id})},_updatePageInfoView:function(n,o){var a=this._controllerGroup;R(["pagePrev","pageNext"],function(t){var e=null!=o[t+"DataIndex"],i=a.childOfName(t);i&&(i.setStyle("fill",e?n.get("pageIconColor",!0):n.get("pageIconInactiveColor",!0)),i.cursor=e?"pointer":"default")});var t=a.childOfName("pageText"),e=n.get("pageFormatter"),i=o.pageIndex,r=null!=i?i+1:0,s=o.pageCount;t&&e&&t.setStyle("text",E(e)?e.replace("{current}",r).replace("{total}",s):e({current:r,total:s}))},_getPageInfo:function(t){var e=t.get("scrollDataIndex",!0),i=this.getContentGroup(),n=this._containerGroup.__rectSize,o=t.getOrient().index,a=aL[o],r=rL[o],s=this._findTargetItemIndex(e),l=i.children(),u=l[s],h=l.length,c=h?1:0,d={contentPosition:i.position.slice(),pageCount:c,pageIndex:c-1,pagePrevDataIndex:null,pageNextDataIndex:null};if(!u)return d;var f=y(u);d.contentPosition[o]=-f.s;for(var p=s+1,g=f,m=f,v=null;p<=h;++p)(!(v=y(l[p]))&&m.e>g.s+n||v&&!x(v,g.s))&&(g=m.i>g.i?m:v)&&(null==d.pageNextDataIndex&&(d.pageNextDataIndex=g.i),++d.pageCount),m=v;for(p=s-1,g=f,m=f,v=null;-1<=p;--p)(v=y(l[p]))&&x(m,v.s)||!(g.i=e&&t.s<=e+n}},_findTargetItemIndex:function(n){return this._showController?(this.getContentGroup().eachChild(function(t,e){var i=t.__legendDataIndex;null==a&&null!=i&&(a=e),i===n&&(o=e)}),null!=o?o:a):0;var o,a}});_f("legendScroll","legendscroll",function(t,e){var i=t.scrollDataIndex;null!=i&&e.eachComponent({mainType:"legend",subType:"scroll",query:t},function(t){t.setScrollDataIndex(i)})});cD.extend({type:"dataZoom.slider",layoutMode:"box",defaultOption:{show:!0,right:"ph",top:"ph",width:"ph",height:"ph",left:null,bottom:null,backgroundColor:"rgba(47,69,84,0)",dataBackground:{lineStyle:{color:"#2f4554",width:.5,opacity:.3},areaStyle:{color:"rgba(47,69,84,0.3)",opacity:.3}},borderColor:"#ddd",fillerColor:"rgba(167,183,204,0.4)",handleIcon:"M8.2,13.6V3.9H6.3v9.7H3.1v14.9h3.3v9.7h1.8v-9.7h3.3V13.6H8.2z M9.7,24.4H4.8v-1.4h4.9V24.4z M9.7,19.1H4.8v-1.4h4.9V19.1z",handleSize:"100%",handleStyle:{color:"#a7b7cc"},labelPrecision:null,labelFormatter:null,showDetail:!0,showDataShadow:"auto",realtime:!0,zoomLock:!1,textStyle:{color:"#333"}}});var lL=rs,uL=Rl,hL=Bl,cL=A,dL=R,fL="horizontal",pL="vertical",gL=["line","bar","candlestick","scatter"],mL=pD.extend({type:"dataZoom.slider",init:function(t,e){this._displayables={},this._orient,this._range,this._handleEnds,this._size,this._handleWidth,this._handleHeight,this._location,this._dragging,this._dataShadowInfo,this.api=e},render:function(t,e,i,n){mL.superApply(this,"render",arguments),kc(this,"_dispatchZoomAction",this.dataZoomModel.get("throttle"),"fixRate"),this._orient=t.get("orient"),!1!==this.dataZoomModel.get("show")?(n&&"dataZoom"===n.type&&n.from===this.uid||this._buildView(),this._updateView()):this.group.removeAll()},remove:function(){mL.superApply(this,"remove",arguments),Pc(this,"_dispatchZoomAction")},dispose:function(){mL.superApply(this,"dispose",arguments),Pc(this,"_dispatchZoomAction")},_buildView:function(){var t=this.group;t.removeAll(),this._resetLocation(),this._resetInterval();var e=this._displayables.barGroup=new Ci;this._renderBackground(),this._renderHandle(),this._renderDataShadow(),t.add(e),this._positionGroup()},_resetLocation:function(){var t=this.dataZoomModel,e=this.api,i=this._findCoordRect(),n={width:e.getWidth(),height:e.getHeight()},o=this._orient===fL?{right:n.width-i.x-i.width,top:n.height-30-7,width:i.width,height:30}:{right:7,top:i.y,width:30,height:i.height},a=Iu(t.option);R(["right","top","width","height"],function(t){"ph"===a[t]&&(a[t]=o[t])});var r=bu(a,n,t.padding);this._location={x:r.x,y:r.y},this._size=[r.width,r.height],this._orient===pL&&this._size.reverse()},_positionGroup:function(){var t=this.group,e=this._location,i=this._orient,n=this.dataZoomModel.getFirstTargetAxisModel(),o=n&&n.get("inverse"),a=this._displayables.barGroup,r=(this._dataShadowInfo||{}).otherAxisInverse;a.attr(i!==fL||o?i===fL&&o?{scale:r?[-1,1]:[-1,-1]}:i!==pL||o?{scale:r?[-1,-1]:[-1,1],rotation:Math.PI/2}:{scale:r?[1,-1]:[1,1],rotation:Math.PI/2}:{scale:r?[1,1]:[1,-1]});var s=t.getBoundingRect([a]);t.attr("position",[e.x-s.x,e.y-s.y])},_getViewExtent:function(){return[0,this._size[0]]},_renderBackground:function(){var t=this.dataZoomModel,e=this._size,i=this._displayables.barGroup;i.add(new lL({silent:!0,shape:{x:0,y:0,width:e[0],height:e[1]},style:{fill:t.get("backgroundColor")},z2:-40})),i.add(new lL({shape:{x:0,y:0,width:e[0],height:e[1]},style:{fill:"transparent"},z2:0,onclick:A(this._onClickPanelClick,this)}))},_renderDataShadow:function(){var t=this._dataShadowInfo=this._prepareDataShadowInfo();if(t){var e=this._size,i=t.series,n=i.getRawData(),o=i.getShadowDim?i.getShadowDim():t.otherDim;if(null!=o){var a=n.getDataExtent(o),r=.3*(a[1]-a[0]);a=[a[0]-r,a[1]+r];var s,l=[0,e[1]],u=[0,e[0]],h=[[e[0],0],[0,0]],c=[],d=u[1]/(n.count()-1),f=0,p=Math.round(n.count()/e[0]);n.each([o],function(t,e){if(0e[0]||i[1]<0||i[1]>e[1])){var n=this._handleEnds,o=(n[0]+n[1])/2,a=this._updateInterval("all",i[0]-o);this._updateView(),a&&this._dispatchZoomAction()}},_dispatchZoomAction:function(){var t=this._range;this.api.dispatchAction({type:"dataZoom",from:this.uid,dataZoomId:this.dataZoomModel.id,start:t[0],end:t[1]})},_findCoordRect:function(){var i;if(dL(this.getTargetCoordInfo(),function(t){if(!i&&t.length){var e=t[0].model.coordinateSystem;i=e.getRect&&e.getRect()}}),!i){var t=this.api.getWidth(),e=this.api.getHeight();i={x:.2*t,y:.2*e,width:.6*t,height:.6*e}}return i}});function vL(t){return"vertical"===t?"ns-resize":"ew-resize"}cD.extend({type:"dataZoom.inside",defaultOption:{disabled:!1,zoomLock:!1,zoomOnMouseWheel:!0,moveOnMouseMove:!0,moveOnMouseWheel:!1,preventDefaultMouseMove:!0}});var yL="\0_ec_dataZoom_roams";function xL(t,n){var e=wL(t),o=n.dataZoomId,a=n.coordId;R(e,function(t,e){var i=t.dataZoomInfos;i[o]&&_(n.allCoordIds,a)<0&&(delete i[o],t.count--)}),bL(e);var i=e[a];i||((i=e[a]={coordId:a,dataZoomInfos:{},count:0}).controller=function(t,r){var e=new Vy(t.getZr());return R(["pan","zoom","scrollMove"],function(a){e.on(a,function(n){var o=[];R(r.dataZoomInfos,function(t){if(n.isAvailableBehavior(t.dataZoomModel.option)){var e=(t.getRange||{})[a],i=e&&e(r.controller,n);!t.dataZoomModel.get("disabled",!0)&&i&&o.push({dataZoomId:t.dataZoomId,start:i[0],end:i[1]})}}),o.length&&r.dispatchAction(o)})}),e}(t,i),i.dispatchAction=T(SL,t)),i.dataZoomInfos[o]||i.count++,i.dataZoomInfos[o]=n;var r=function(t){var n,o={type_true:2,type_move:1,type_false:0,type_undefined:-1},a=!0;return R(t,function(t){var e=t.dataZoomModel,i=!e.get("disabled",!0)&&(!e.get("zoomLock",!0)||"move");o["type_"+n]"],L(t)&&(t=t.slice(),n=!0),o=e?t:n?[u(t[0]),u(t[1])]:u(t),E(l)?l.replace("{value}",n?o[0]:o).replace("{value2}",n?o[1]:o):C(l)?n?l(t[0],t[1]):l(t):n?t[0]===s[0]?i[0]+" "+o[1]:t[1]===s[1]?i[1]+" "+o[0]:o[0]+" - "+o[1]:o;function u(t){return t===s[0]?"min":t===s[1]?"max":(+t).toFixed(Math.min(r,20))}},resetExtent:function(){var t=this.option,e=GL([t.min,t.max]);this._dataExtent=e},getDataDimension:function(t){var e=this.option.dimension,i=t.dimensions;if(null!=e||i.length){if(null!=e)return t.getDimension(e);for(var n=t.dimensions,o=n.length-1;0<=o;o--){var a=n[o];if(!t.getDimensionInfo(a).isCalculationCoord)return a}}},getExtent:function(){return this._dataExtent.slice()},completeVisualOption:function(){var t=this.ecModel,e=this.option,i={inRange:e.inRange,outOfRange:e.outOfRange},n=e.target||(e.target={}),o=e.controller||(e.controller={});m(n,i),m(o,i);var u=this.isCategory();function a(n){BL(e.color)&&!n.inRange&&(n.inRange={color:e.color.slice().reverse()}),n.inRange=n.inRange||{color:t.get("gradientColor")},VL(this.stateList,function(t){var e=n[t];if(E(e)){var i=OL(e,"active",u);i?(n[t]={},n[t][e]=i):delete n[t]}},this)}a.call(this,n),a.call(this,o),function(t,e,i){var n=t[e],o=t[i];n&&!o&&(o=t[i]={},VL(n,function(t,e){if(g_.isValidType(e)){var i=OL(e,"inactive",u);null!=i&&(o[e]=i,"color"!==e||o.hasOwnProperty("opacity")||o.hasOwnProperty("colorAlpha")||(o.opacity=[0,0]))}}))}.call(this,n,"inRange","outOfRange"),function(a){var r=(a.inRange||{}).symbol||(a.outOfRange||{}).symbol,s=(a.inRange||{}).symbolSize||(a.outOfRange||{}).symbolSize,l=this.get("inactiveColor");VL(this.stateList,function(t){var e=this.itemSize,i=a[t];null==(i=i||(a[t]={color:u?l:[l]})).symbol&&(i.symbol=r&&k(r)||(u?"roundRect":["roundRect"])),null==i.symbolSize&&(i.symbolSize=s&&k(s)||(u?e[0]:[e[0],e[0]])),i.symbol=EL(i.symbol,function(t){return"none"===t||"square"===t?"roundRect":t});var n=i.symbolSize;if(null!=n){var o=-1/0;zL(n,function(t){oe[1]&&e.reverse(),e[0]=Math.max(e[0],t[0]),e[1]=Math.min(e[1],t[1]))},completeVisualOption:function(){WL.prototype.completeVisualOption.apply(this,arguments),R(this.stateList,function(t){var e=this.option.controller[t].symbolSize;e&&e[0]!==e[1]&&(e[0]=0)},this)},setSelected:function(t){this.option.range=t.slice(),this._resetRange()},getSelected:function(){var t=this.getExtent(),e=Bl((this.get("range")||[]).slice());return e[0]>t[1]&&(e[0]=t[1]),e[1]>t[1]&&(e[1]=t[1]),e[0]=i[1]||t<=e[1])?"inRange":"outOfRange"},findTargetDataIndices:function(n){var o=[];return this.eachTargetSeries(function(t){var i=[],e=t.getData();e.each(this.getDataDimension(e),function(t,e){n[0]<=t&&t<=n[1]&&i.push(e)},this),o.push({seriesId:t.id,dataIndex:i})},this),o},getVisualMeta:function(i){var t=UL(this,"outOfRange",this.getExtent()),e=UL(this,"inRange",this.option.range.slice()),n=[];function o(t,e){n.push({value:t,color:i(t,e)})}for(var a=0,r=0,s=e.length,l=t.length;rt[1])break;i.push({color:this.getControllerVisual(a,"color",e),offset:o/100})}return i.push({color:this.getControllerVisual(t[1],"color",e),offset:1}),i},_createBarPoints:function(t,e){var i=this.visualMapModel.itemSize;return[[i[0]-e[0],t[0]],[i[0],t[0]],[i[0],t[1]],[i[0]-e[1],t[1]]]},_createBarGroup:function(t){var e=this._orient,i=this.visualMapModel.get("inverse");return new Ci("horizontal"!==e||i?"horizontal"===e&&i?{scale:"bottom"===t?[-1,1]:[1,1],rotation:-Math.PI/2}:"vertical"!==e||i?{scale:"left"===t?[1,1]:[-1,1]}:{scale:"left"===t?[1,-1]:[-1,-1]}:{scale:"bottom"===t?[1,1]:[-1,1],rotation:Math.PI/2})},_updateHandle:function(n,o){if(this._useHandle){var a=this._shapes,r=this.visualMapModel,s=a.handleThumbs,l=a.handleLabels;KL([0,1],function(t){var e=s[t];e.setStyle("fill",o.handlesColor[t]),e.position[1]=n[t];var i=pl(a.handleLabelPoints[t],fl(e,this.group));l[t].setStyle({x:i[0],y:i[1],text:r.formatValueText(this._dataInterval[t]),textVerticalAlign:"middle",textAlign:this._applyTransform("horizontal"===this._orient?0===t?"bottom":"top":"left",a.barGroup)})},this)}},_showIndicator:function(t,e,i,n){var o=this.visualMapModel,a=o.getExtent(),r=o.itemSize,s=[0,r[1]],l=qL(t,a,s,!0),u=this._shapes,h=u.indicator;if(h){h.position[1]=l,h.attr("invisible",!1),h.setShape("points",function(t,e,i,n){return t?[[0,-$L(e,JL(i,0))],[6,0],[0,$L(e,JL(n-i,0))]]:[[0,0],[5,-5],[5,5]]}(!!i,n,l,r[1]));var c=this.getControllerVisual(t,"color",{convertOpacityToAlpha:!0});h.setStyle("fill",c);var d=pl(u.indicatorLabelPoint,fl(h,this.group)),f=u.indicatorLabel;f.attr("invisible",!1);var p=this._applyTransform("left",u.barGroup),g=this._orient;f.setStyle({text:(i||"")+o.formatValueText(e),textVerticalAlign:"horizontal"===g?p:"middle",textAlign:"horizontal"===g?"center":p,x:d[0],y:d[1]})}},_enableHoverLinkToSeries:function(){var n=this;this._shapes.barGroup.on("mousemove",function(t){if(n._hovering=!0,!n._dragging){var e=n.visualMapModel.itemSize,i=n._applyTransform([t.offsetX,t.offsetY],n._shapes.barGroup,!0,!0);i[1]=$L(JL(0,i[1]),e[1]),n._doHoverLinkToSeries(i[1],0<=i[0]&&i[0]<=e[0])}}).on("mouseout",function(){n._hovering=!1,n._dragging||n._clearHoverLinkToSeries()})},_enableHoverLinkFromSeries:function(){var t=this.api.getZr();this.visualMapModel.option.hoverLink?(t.on("mouseover",this._hoverLinkFromSeriesMouseOver,this),t.on("mouseout",this._hideIndicator,this)):this._clearHoverLinkFromSeries()},_doHoverLinkToSeries:function(t,e){var i=this.visualMapModel,n=i.itemSize;if(i.option.hoverLink){var o=[0,n[1]],a=i.getExtent();t=$L(JL(o[0],t),o[1]);var r=function(t,e,i){var n=6,o=t.get("hoverLinkDataSize");o&&(n=qL(o,e,i,!0)/2);return n}(i,a,o),s=[t-r,t+r],l=qL(t,o,a,!0),u=[qL(s[0],o,a,!0),qL(s[1],o,a,!0)];s[0] ",r):this._showIndicator(l,l,"≈ ",r));var h=this._hoverLinkDataIndices,c=[];(e||ek(i))&&(c=this._hoverLinkDataIndices=i.findTargetDataIndices(u));var d=function(t,e){var i={},n={};return o(t||[],i),o(e||[],n,i),[a(i),a(n)];function o(t,e,i){for(var n=0,o=t.length;ni&&n([i,e[0]],"outOfRange"),n(e.slice()),i=e[1])},this),{stops:a,outerColors:r}}function n(t,e){var i=s.getRepresentValue({interval:t});e=e||s.getValueState(i);var n=o(i,e);t[0]===-1/0?r[0]=n:t[1]===1/0?r[1]=n:a.push({value:t[0],color:n},{value:t[1],color:n})}}}),ok={splitNumber:function(){var t=this.option,e=this._pieceList,i=Math.min(t.precision,20),n=this.getExtent(),o=t.splitNumber;o=Math.max(parseInt(o,10),1),t.splitNumber=o;for(var a=(n[1]-n[0])/o;+a.toFixed(i)!==a&&i<5;)i++;t.precision=i,a=+a.toFixed(i),t.minOpen&&e.push({interval:[-1/0,n[0]],close:[0,0]});for(var r=0,s=n[0];r","≥"][e[0]]];t.text=t.text||this.formatValueText(null!=t.value?t.value:t.interval,!1,i)},this)}};function ak(t,e){var i=t.inverse;("vertical"===t.orient?!i:i)&&e.reverse()}XL.extend({type:"visualMap.piecewise",doRender:function(){var a=this.group;a.removeAll();var r=this.visualMapModel,s=r.get("textGap"),t=r.textStyleModel,l=t.getFont(),u=t.getTextColor(),h=this._getItemAlign(),c=r.itemSize,e=this._getViewData(),i=e.endsText,d=W(r.get("showLabel",!0),!i);i&&this._renderEndsText(a,i[0],c,d,h),R(e.viewPieceList,function(t){var e=t.piece,i=new Ci;i.onclick=A(this._onItemClick,this,e),this._enableHoverLink(i,t.indexInModelPieceList);var n=r.getRepresentValue(e);if(this._createItemSymbol(i,n,[0,0,c[0],c[1]]),d){var o=this.visualMapModel.getValueState(n);i.add(new Ur({style:{x:"right"===h?-s:c[0]+s,y:c[1]/2,text:e.text,textVerticalAlign:"middle",textAlign:h,textFont:l,textFill:u,opacity:"outOfRange"===o?.5:1}}))}a.add(i)},this),i&&this._renderEndsText(a,i[1],c,d,h),wu(r.get("orient"),a,r.get("itemGap")),this.renderBackground(a),this.positionGroup(a)},_enableHoverLink:function(t,i){function e(t){var e=this.visualMapModel;e.option.hoverLink&&this.api.dispatchAction({type:t,batch:jL(e.findTargetDataIndices(i),e)})}t.on("mouseover",A(e,this,"highlight")).on("mouseout",A(e,this,"downplay"))},_getItemAlign:function(){var t=this.visualMapModel,e=t.option;if("vertical"===e.orient)return YL(t,this.api,t.itemSize);var i=e.align;return i&&"auto"!==i||(i="left"),i},_renderEndsText:function(t,e,i,n,o){if(e){var a=new Ci,r=this.visualMapModel.textStyleModel;a.add(new Ur({style:{x:n?"right"===o?i[0]:0:i[0]/2,y:i[1]/2,textVerticalAlign:"middle",textAlign:n?o:"center",text:e,textFont:r.getFont(),textFill:r.getTextColor()}})),t.add(a)}},_getViewData:function(){var t=this.visualMapModel,e=O(t.getPieceList(),function(t,e){return{piece:t,indexInModelPieceList:e}}),i=t.get("text"),n=t.get("orient"),o=t.get("inverse");return("horizontal"===n?o:!o)?e.reverse():i=i&&i.slice().reverse(),{viewPieceList:e,endsText:i}},_createItemSymbol:function(t,e,i){t.add(wg(this.getControllerVisual(e,"symbol"),i[0],i[1],i[2],i[3],this.getControllerVisual(e,"color")))},_onItemClick:function(t){var e=this.visualMapModel,i=e.option,n=k(i.selected),o=e.getSelectedMapKey(t);"single"===i.selectedMode?(n[o]=!0,R(n,function(t,e){n[e]=e===o})):n[o]=!n[o],this.api.dispatchAction({type:"selectDataRange",from:this.uid,visualMapId:this.visualMapModel.id,selected:n})}});yf(DL);var rk,sk="urn:schemas-microsoft-com:vml",lk="undefined"==typeof window?null:window,uk=!1,hk=lk&&lk.document;function ck(t){return rk(t)}if(hk&&!v.canvasSupported)try{hk.namespaces.zrvml||hk.namespaces.add("zrvml",sk),rk=function(t){return hk.createElement("')}}catch(t){rk=function(t){return hk.createElement("<"+t+' xmlns="'+sk+'" class="zrvml">')}}var dk,fk=rr.CMD,pk=Math.round,gk=Math.sqrt,mk=Math.abs,vk=Math.cos,yk=Math.sin,xk=Math.max;if(!v.canvasSupported){var _k=",",wk="progid:DXImageTransform.Microsoft",bk=21600,Sk=bk/2,Mk=function(t){t.style.cssText="position:absolute;left:0;top:0;width:1px;height:1px;",t.coordsize=bk+","+bk,t.coordorigin="0,0"},Ik=function(t,e,i){return"rgb("+[t,e,i].join(",")+")"},Tk=function(t,e){e&&t&&e.parentNode!==t&&t.appendChild(e)},Ak=function(t,e){e&&t&&e.parentNode===t&&t.removeChild(e)},Dk=function(t,e,i){return 1e5*(parseFloat(t)||0)+1e3*(parseFloat(e)||0)+i},Ck=Yn,Lk=function(t,e,i){var n=Fe(e);i=+i,isNaN(i)&&(i=1),n&&(t.color=Ik(n[0],n[1],n[2]),t.opacity=i*n[3])},kk=function(t,e,i,n){var o="fill"===e,a=t.getElementsByTagName(e)[0];null!=i[e]&&"none"!==i[e]&&(o||!o&&i.lineWidth)?(t[o?"filled":"stroked"]="true",i[e]instanceof cs&&Ak(t,a),a=a||ck(e),o?function(t,e,i){var n,o,a=e.fill;if(null!=a)if(a instanceof cs){var r,s=0,l=[0,0],u=0,h=1,c=i.getBoundingRect(),d=c.width,f=c.height;if("linear"===a.type){r="gradient";var p=i.transform,g=[a.x*d,a.y*f],m=[a.x2*d,a.y2*f];p&&(bt(g,g,p),bt(m,m,p));var v=m[0]-g[0],y=m[1]-g[1];(s=180*Math.atan2(v,y)/Math.PI)<0&&(s+=360),s<1e-6&&(s=0)}else{r="gradientradial";g=[a.x*d,a.y*f],p=i.transform;var x=i.scale,_=d,w=f;l=[(g[0]-c.x)/_,(g[1]-c.y)/w],p&&bt(g,g,p),_/=x[0]*bk,w/=x[1]*bk;var b=xk(_,w);u=0/b,h=2*a.r/b-u}var S=a.colorStops.slice();S.sort(function(t,e){return t.offset-e.offset});for(var M=S.length,I=[],T=[],A=0;A=c&&d<=i+1){for(var n=[],o=0;o=c&&d<=o+1)return _P(h,e.components,u,l);p[t]=e}else p[t]=void 0}var s;f++}for(;f<=e;){var r=a();if(r)return r}},pushComponent:function(t,e,i){var n=t[t.length-1];n&&n.added===e&&n.removed===i?t[t.length-1]={count:n.count+1,added:e,removed:i}:t.push({count:1,added:e,removed:i})},extractCommon:function(t,e,i,n){for(var o=e.length,a=i.length,r=t.newPos,s=r-n,l=0;r+1\n\r<"))}},R(["getLayer","insertLayer","eachLayer","eachBuiltinLayer","eachOtherLayer","getLayers","modLayer","delLayer","clearLayer","pathToImage"],function(t){OP.prototype[t]=function(t){return function(){vi('In SVG mode painter not support method "'+t+'"')}}(t)}),Po("svg",OP),t.version="4.9.0",t.dependencies={zrender:"4.3.2"},t.PRIORITY=Ld,t.init=function(t,e,i){var n=mf(t);if(n)return n;var o=new Ed(t,e,i);return o.id="ec_"+cf++,uf[o.id]=o,Jo(t,ff,o.id),function(n){var o="__connectUpdateStatus";function a(t,e){for(var i=0;i b.latest_time -end - - -function user_status() - 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 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=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 - - -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 diff --git a/OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/base_setting.lua b/OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/base_setting.lua deleted file mode 100644 index 9458ec1..0000000 --- a/OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/base_setting.lua +++ /dev/null @@ -1,90 +0,0 @@ -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", translate("App Filter"), translate( - "请先关闭所有加速(acc)、广告过滤、多拨等可能冲突的模块")) - -s = m:section(TypedSection, "global", translate("Basic Settings")) -s:option(Flag, "enable", translate("Enable App Filter"), translate("")) -s.anonymous = true - -o=s:option(ListValue, "work_mode", translate("工作模式"),translate("请正确选择模式,一般经过了WAN口转发则为主路由,建议切换模式后重启设备")) -o.default=0 -o:value(0,"主路由模式") -o:value(1,"旁路由模式") - -local rule_count = 0 -local version = "" - -s = m:section(TypedSection, "appfilter", translate("App Filter Rules")) -s.anonymous = true -s.addremove = false - -local class_fd = io.popen("find /tmp/appfilter/ -type f -name '*.class'") -if class_fd then - while true do - local apps - local class - local path = class_fd:read("*l") - if not path then - break - end - - class = path:match("([^/]+)%.class$") - s:tab(class, translate(class)) - apps = s:taboption(class, MultiValue, class .. "apps", translate("")) - apps.rmempty = true - apps.widget = "checkbox" - apps.size = 10 - - local fd = io.open(path) - if fd then - local line - while true do - local cmd - local cmd_fd - line = fd:read("*l") - if not line then - break - end - if string.len(line) < 5 then - break - end - if not string.find(line, "#") then - cmd = "echo " .. line .. "|awk '{print $1}'" - cmd_fd = io.popen(cmd) - id = cmd_fd:read("*l"); - cmd_fd:close() - - cmd = "echo " .. line .. "|awk '{print $2}'" - cmd_fd = io.popen(cmd) - name = cmd_fd:read("*l") - - cmd_fd:close() - if not id then - break - end - if not name then - break - end - apps:value(id, name) - end - end - fd:close() - end - end - class_fd:close() -end - -return m diff --git a/OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/dev_status.lua b/OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/dev_status.lua deleted file mode 100644 index 1d39a22..0000000 --- a/OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/dev_status.lua +++ /dev/null @@ -1,21 +0,0 @@ -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("Data Statistics") .. "(" .. 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", "control", "appfilter") -return m diff --git a/OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/feature.lua b/OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/feature.lua deleted file mode 100644 index 11e744f..0000000 --- a/OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/feature.lua +++ /dev/null @@ -1,91 +0,0 @@ -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", translate(""), - translate("特征库用于描述app特征,app过滤效果和个数依赖特征库")) - -local rule_count = 0 -local version = "" -if nixio.fs.access("/tmp/feature.cfg") then - rule_count = tonumber(SYS.exec("cat /tmp/feature.cfg | wc -l")) - version = SYS.exec("cat /tmp/feature.cfg |grep \"#version\" | awk '{print $2}'") -end - -local display_str = "当前版本: " .. version .. "
特征码个数: " .. - rule_count .. - "
下载地址:https://destan19.github.io" -s = m:section(TypedSection, "feature", translate("Update feature"), display_str) - -fu = s:option(FileUpload, "") -fu.template = "cbi/oaf_upload" -s.anonymous = true - -um = s:option(DummyValue, "rule_data") -um.template = "cbi/oaf_dvalue" - -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 - 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"); - fd2:close() - local ret = string.match(line, "#version") - local lang = m.uci:get_all("luci.main.lang") - local feature_file = "" - if "" == lang or "auto" == lang then - feature_file = "/etc/appfilter/feature.cfg" - else - feature_file = "/etc/appfilter/feature_" .. lang .. ".cfg" - end - if ret ~= nil then - local cmd = "cp /tmp/upload/" .. meta.file .. " " .. feature_file; - os.execute(cmd); - os.execute("chmod 666 " .. feature_file); - os.execute("rm /tmp/appfilter -fr"); - luci.sys.exec("/etc/init.d/appfilter restart &"); - um.value = translate("Update the feature file successfully, please refresh the page") - else - um.value = translate("Failed to update feature file, format error") - end - os.execute("rm /tmp/upload/* -fr"); - 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 diff --git a/OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/time_setting.lua b/OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/time_setting.lua deleted file mode 100644 index b950551..0000000 --- a/OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/time_setting.lua +++ /dev/null @@ -1,49 +0,0 @@ -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", translate(""), translate("")) - -s = m:section(TypedSection, "time", translate("Time Setting"),translate("时间2为选填,开始和结束时间需要同时设置,结束时间要大于开始时间")) -s.anonymous = true - - -o=s:option(ListValue, "time_mode", translate("时间匹配模式:"),translate("")) -o.default=0 -o:value(0,"时间范围内规则生效") -o:value(1,"时间范围外规则生效") - -days = s:option(MultiValue, "days", "", translate("")) -days.widget = "checkbox" -days.size = 10 -days:value("0", translate("Sun")); -days:value("1", translate("Mon")); -days:value("2", translate("Tue")); -days:value("3", translate("Wed")); -days:value("4", translate("Thur")); -days:value("5", translate("Fri")); -days:value("6", translate("Sat")); - -hv = s:option(Value, "start_time", translate("Start Time1"),translate("格式xx:xx,下同")) -hv.optional = false -hv = s:option(Value, "end_time", translate("End Time1")) -hv.optional = false - -hv = s:option(Value, "start_time2", translate("Start Time2")) -hv.optional = false -hv = s:option(Value, "end_time2", translate("End Time2")) -hv.optional = false - - - -return m diff --git a/OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/user_list.lua b/OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/user_list.lua deleted file mode 100644 index 6a0366b..0000000 --- a/OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/user_list.lua +++ /dev/null @@ -1,19 +0,0 @@ -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", translate(""), translate("")) - -m:section(SimpleSection).template = "admin_network/user_status" - -return m diff --git a/OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/user_setting.lua b/OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/user_setting.lua deleted file mode 100644 index f8a4aab..0000000 --- a/OpenAppFilter/luci-app-oaf/luasrc/model/cbi/appfilter/user_setting.lua +++ /dev/null @@ -1,91 +0,0 @@ -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", translate("App Filter"), translate("")) - -function get_hostname_by_mac(dst_mac) - leasefile = "/tmp/dhcp.leases" - local fd = io.open(leasefile, "r") - if not fd then - return - end - while true do - local ln = fd:read("*l") - if not ln then - break - end - local ts, mac, ip, name, duid = ln:match("^(%d+) (%S+) (%S+) (%S+) (%S+)") - print(ln) - if dst_mac == mac then - fd:close() - return name - end - end - fd:close() - return nil -end - -function get_cmd_result(command) - local fd - local result - fd = io.popen(command); - if not fd then - return "" - end - result = fd:read("*l"); - fd:close() - return result -end - -s = m:section(TypedSection, "user", translate("Select users")) -s.anonymous = true -users = s:option(MultiValue, "users", "", translate( - "It takes effect for all users by default, and only takes effect for the selected users when checked")) -users.widget = "checkbox" --- users.widget="select" -users.size = 1 - -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 string.match(line, "^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)) - local hostname = get_cmd_result(string.format("echo '%s' | awk '{print $4}'", line)) - if mac ~= nil then - if not hostname or hostname == "*" then - users:value(mac, mac); - else - users:value(mac, hostname .. "(" .. mac .. ")"); - end - end - end -end -fd:close() - -local config_users = m.uci:get_all("appfilter.user.users") -if config_users ~= nil and config_users ~= false then - local r = utl.split(config_users, "%s+", nil, true) - local max = table.getn(r) - for i = 1, max, 1 do - users:value(r[i], r[i]); - end -end -return m diff --git a/OpenAppFilter/luci-app-oaf/luasrc/view/admin_network/dev_status.htm b/OpenAppFilter/luci-app-oaf/luasrc/view/admin_network/dev_status.htm deleted file mode 100644 index 0bb46ad..0000000 --- a/OpenAppFilter/luci-app-oaf/luasrc/view/admin_network/dev_status.htm +++ /dev/null @@ -1,382 +0,0 @@ - - - - - - - - - -
-
-
-
-
- - - - - - - - - - - - -
- <%:App Name%> - - <%:Hostname%> - - <%:Mac%> - - <%:Start Time%> - - <%:Visit Time%> - - <%:Filter Status%> -

- <%:Collecting data...%> -
- -
\ No newline at end of file diff --git a/OpenAppFilter/luci-app-oaf/luasrc/view/admin_network/user_status.htm b/OpenAppFilter/luci-app-oaf/luasrc/view/admin_network/user_status.htm deleted file mode 100644 index 19b21f0..0000000 --- a/OpenAppFilter/luci-app-oaf/luasrc/view/admin_network/user_status.htm +++ /dev/null @@ -1,82 +0,0 @@ -<% local dsp=require "luci.dispatcher" -%> - - - -
- - - - - - - - - - - - -
- <%:Id%> - - <%:Hostname%> - - <%:Mac%> - - <%:Ip%> - - <%:Common App(TOP5)%> - - <%:Online Status%> -

- <%:Collecting data...%> -
-
\ No newline at end of file diff --git a/OpenAppFilter/luci-app-oaf/luasrc/view/cbi/oaf_dvalue.htm b/OpenAppFilter/luci-app-oaf/luasrc/view/cbi/oaf_dvalue.htm deleted file mode 100644 index 296c61e..0000000 --- a/OpenAppFilter/luci-app-oaf/luasrc/view/cbi/oaf_dvalue.htm +++ /dev/null @@ -1,8 +0,0 @@ -<%+cbi/valueheader%> - -<% - local val = self:cfgvalue(section) or self.default or "" - write(pcdata(val)) -%> - -<%+cbi/valuefooter%> diff --git a/OpenAppFilter/luci-app-oaf/luasrc/view/cbi/oaf_upload.htm b/OpenAppFilter/luci-app-oaf/luasrc/view/cbi/oaf_upload.htm deleted file mode 100644 index aadf01d..0000000 --- a/OpenAppFilter/luci-app-oaf/luasrc/view/cbi/oaf_upload.htm +++ /dev/null @@ -1,5 +0,0 @@ -<%+cbi/valueheader%> - - - -<%+cbi/valuefooter%> diff --git a/OpenAppFilter/luci-app-oaf/po/zh-cn/oaf.po b/OpenAppFilter/luci-app-oaf/po/zh-cn/oaf.po deleted file mode 100644 index 53990b5..0000000 --- a/OpenAppFilter/luci-app-oaf/po/zh-cn/oaf.po +++ /dev/null @@ -1,167 +0,0 @@ - -msgid "website" -msgstr "常用网站" - -msgid "appfilter" -msgstr "应用过滤" - -msgid "App Filter" -msgstr "应用过滤" - -msgid "game" -msgstr "游戏" - -msgid "web" -msgstr "网页" - -msgid "video" -msgstr "视频" - -msgid "chat" -msgstr "聊天" - -msgid "download" -msgstr "下载" - -msgid "p2p" -msgstr "p2p" - -msgid "music" -msgstr "音乐" - -msgid "shopping" -msgstr "购物" - -msgid "working" -msgstr "办公" - -msgid "employee" -msgstr "招聘" - -msgid "Basic Settings" -msgstr "基本设置" - -msgid "App Filter Rules" -msgstr "应用过滤规则" - -msgid "It takes effect for all users by default, and only takes effect for the selected users when checked" -msgstr "默认对所有用户生效,勾选后只对选择的用户生效" - -msgid "Select users" -msgstr "选择用户" - -msgid "Id" -msgstr "编号" - -msgid "Hostname" -msgstr "主机名" - -msgid "Common App(TOP5)" -msgstr "常用APP(TOP5)" - -msgid "Online Status" -msgstr "在线状态" - -msgid "Client List" -msgstr "终端列表" - -msgid "Online" -msgstr "在线" - -msgid "Offline" -msgstr "离线" - -msgid "App Time Statistics" -msgstr "App 时间统计" - -msgid "Filter Status" -msgstr "过滤状态" - -msgid "Data Statistics" -msgstr "数据统计" - - - -msgid "Current Version" -msgstr "当前版本" - -msgid "App Feature Num" -msgstr "特征码个数" - -msgid "Update feature" -msgstr "特征库更新" - -msgid "Time Setting" -msgstr "时间控制" - -msgid "Sun" -msgstr "周日" - -msgid "Mon" -msgstr "周一" - -msgid "Tue" -msgstr "周二" - -msgid "Wed" -msgstr "周三" - -msgid "Thur" -msgstr "周四" - -msgid "Fri" -msgstr "周五" - -msgid "Sat" -msgstr "周六" - -msgid "Update the feature file successfully, please refresh the page" -msgstr "更新特征库成功,请刷新页面!" - -msgid "Failed to update feature file, format error" -msgstr "更新特征库失败,格式错误!" - -msgid "Select feature file:" -msgstr "选择本地特征库文件:" - -msgid "Start Time1" -msgstr "开始时间1" - -msgid "End Time1" -msgstr "结束时间1" - - -msgid "Start Time2" -msgstr "开始时间2" - -msgid "End Time2" -msgstr "结束时间2" - -msgid "App Name" -msgstr "App名称" - -msgid "Visit Time" -msgstr "访问时间" - -msgid "App classification time statistics" -msgstr "App分类时间统计" - -msgid "Percentage" -msgstr "占比" - -msgid "Filtered" -msgstr "已过滤" - -msgid "Unfiltered" -msgstr "未过滤" - -msgid "h" -msgstr "小时" - -msgid "m" -msgstr "分" - -msgid "Enable App Filter" -msgstr "开启应用过滤" - - diff --git a/OpenAppFilter/luci-app-oaf/root/etc/uci-defaults/91_luci-oaf b/OpenAppFilter/luci-app-oaf/root/etc/uci-defaults/91_luci-oaf deleted file mode 100644 index 24bf73a..0000000 --- a/OpenAppFilter/luci-app-oaf/root/etc/uci-defaults/91_luci-oaf +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - del ucitrack.@appfilter[-1] - add ucitrack appfilter - set ucitrack.@appfilter[-1].exec="/usr/bin/oaf_rule reload" - commit ucitrack -EOF - -# remove LuCI cache -rm -rf /tmp/luci-indexcache /tmp/luci-modulecache diff --git a/OpenAppFilter/luci-app-oaf/root/etc/uci-defaults/92_oaf_time b/OpenAppFilter/luci-app-oaf/root/etc/uci-defaults/92_oaf_time deleted file mode 100644 index 75146d3..0000000 --- a/OpenAppFilter/luci-app-oaf/root/etc/uci-defaults/92_oaf_time +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -uci -q batch <<-EOF >/dev/null - set appfilter.time.time_mode="0" - set appfilter.time.start_time2="" - set appfilter.time.end_time2="" - commit appfilter -EOF diff --git a/OpenAppFilter/oaf/Makefile b/OpenAppFilter/oaf/Makefile deleted file mode 100644 index 6a51fc2..0000000 --- a/OpenAppFilter/oaf/Makefile +++ /dev/null @@ -1,39 +0,0 @@ - -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_NAME:=oaf -include $(INCLUDE_DIR)/package.mk - -PKG_AUTOLOAD:=oaf -RSTRIP:=: - -define KernelPackage/oaf - SECTION:=Derry Apps - CATEGORY:=Derry Apps - TITLE:=open app filter kernel module - FILES:=$(PKG_BUILD_DIR)/oaf.ko - DEPENDS:=+kmod-ipt-conntrack - KCONFIG:= - AUTOLOAD:=$(call AutoLoad,0,$(PKG_AUTOLOAD)) -endef - -define KernelPackage/oaf/description - open appfilter kernel module -endef - - -MAKE_OPTS:= \ - $(KERNEL_MAKE_FLAGS) \ - M="$(PKG_BUILD_DIR)" \ - EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ - $(EXTRA_KCONFIG) - -define Build/Compile - $(MAKE) -C "$(LINUX_DIR)" \ - $(MAKE_OPTS) \ - modules -endef - -$(eval $(call KernelPackage,oaf)) - diff --git a/OpenAppFilter/oaf/src/Makefile b/OpenAppFilter/oaf/src/Makefile deleted file mode 100644 index 96c1f61..0000000 --- a/OpenAppFilter/oaf/src/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -oaf-objs := app_filter.o af_utils.o regexp.o cJSON.o app_filter_config.o af_log.o af_client.o af_client_fs.o -obj-m += oaf.o diff --git a/OpenAppFilter/oaf/src/af_client.c b/OpenAppFilter/oaf/src/af_client.c deleted file mode 100644 index 971446d..0000000 --- a/OpenAppFilter/oaf/src/af_client.c +++ /dev/null @@ -1,438 +0,0 @@ -/* - Author:Derry - Date: 2019/11/12 -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "af_client.h" -#include "af_client_fs.h" -#include "af_log.h" -#include "af_utils.h" -#include "app_filter.h" -#include "cJSON.h" - -DEFINE_RWLOCK(af_client_lock); - -u32 total_client = 0; -struct list_head af_client_list_table[MAX_AF_CLIENT_HASH_SIZE]; - -int af_send_msg_to_user(char *pbuf, uint16_t len); - -static void -nf_client_list_init(void) -{ - int i; - AF_CLIENT_LOCK_W(); - for (i = 0; i < MAX_AF_CLIENT_HASH_SIZE; i++) - { - INIT_LIST_HEAD(&af_client_list_table[i]); - } - AF_CLIENT_UNLOCK_W(); - AF_INFO("client list init......ok\n"); -} - -static void -nf_client_list_clear(void) -{ - int i; - af_client_info_t *p = NULL; - char mac_str[32] = {0}; - - AF_DEBUG("clean list\n"); - AF_CLIENT_LOCK_W(); - for (i = 0; i < MAX_AF_CLIENT_HASH_SIZE; i++) - { - while (!list_empty(&af_client_list_table[i])) - { - p = list_first_entry(&af_client_list_table[i], af_client_info_t, hlist); - memset(mac_str, 0x0, sizeof(mac_str)); - sprintf(mac_str, MAC_FMT, MAC_ARRAY(p->mac)); - AF_DEBUG("clean mac:%s\n", mac_str); - list_del(&(p->hlist)); - kfree(p); - } - } - AF_CLIENT_UNLOCK_W(); -} - -void af_client_list_reset_report_num(void) -{ - int i; - af_client_info_t *node = NULL; - AF_CLIENT_LOCK_W(); - for (i = 0; i < MAX_AF_CLIENT_HASH_SIZE; i++) - { - list_for_each_entry(node, &af_client_list_table[i], hlist) - { - node->report_count = 0; - } - } - AF_CLIENT_UNLOCK_W(); -} - -int get_mac_hash_code(unsigned char *mac) -{ - if (!mac) - return 0; - else - return mac[5] & (MAX_AF_CLIENT_HASH_SIZE - 1); -} - -af_client_info_t *find_af_client(unsigned char *mac) -{ - af_client_info_t *node; - unsigned int index; - - index = get_mac_hash_code(mac); - list_for_each_entry(node, &af_client_list_table[index], hlist) - { - if (0 == memcmp(node->mac, mac, 6)) - { - return node; - } - } - return NULL; -} - -af_client_info_t *find_and_add_af_client(unsigned char *mac) -{ - af_client_info_t *nfc; - nfc = find_af_client(mac); - if (!nfc){ - nfc = nf_client_add(mac); - } - return nfc; -} - - -af_client_info_t *find_af_client_by_ip(unsigned int ip) -{ - af_client_info_t *node; - int i; - - for (i = 0; i < MAX_AF_CLIENT_HASH_SIZE; i++) - { - list_for_each_entry(node, &af_client_list_table[i], hlist) - { - if (node->ip == ip) - { - AF_LMT_DEBUG("match node->ip=%pI4, ip=%pI4\n", &node->ip, &ip); - return node; - } - } - } - return NULL; -} - -af_client_info_t * -nf_client_add(unsigned char *mac) -{ - af_client_info_t *node; - int index = 0; - - node = (af_client_info_t *)kmalloc(sizeof(af_client_info_t), GFP_ATOMIC); - if (node == NULL) - { - AF_ERROR("kmalloc failed\n"); - return NULL; - } - - memset(node, 0, sizeof(af_client_info_t)); - memcpy(node->mac, mac, MAC_ADDR_LEN); - - node->create_jiffies = jiffies; - node->update_jiffies = jiffies; - index = get_mac_hash_code(mac); - - AF_LMT_INFO("new client mac=" MAC_FMT "\n", MAC_ARRAY(node->mac)); - total_client++; - list_add(&(node->hlist), &af_client_list_table[index]); - return node; -} - - - - -void check_client_expire(void) -{ - af_client_info_t *node; - int i; - AF_CLIENT_LOCK_W(); - for (i = 0; i < MAX_AF_CLIENT_HASH_SIZE; i++) - { - list_for_each_entry(node, &af_client_list_table[i], hlist) - { - AF_DEBUG("mac:" MAC_FMT " update:%lu interval:%lu\n", MAC_ARRAY(node->mac), - node->update_jiffies, (jiffies - node->update_jiffies) / HZ); - if (jiffies > (node->update_jiffies + MAX_CLIENT_ACTIVE_TIME * HZ)) - { - AF_INFO("del client:" MAC_FMT "\n", MAC_ARRAY(node->mac)); - list_del(&(node->hlist)); - kfree(node); - AF_CLIENT_UNLOCK_W(); - return; - } - } - } - AF_CLIENT_UNLOCK_W(); -} - -#define MAX_EXPIRED_VISIT_INFO_COUNT 10 -void flush_expired_visit_info(af_client_info_t *node) -{ - int i; - int count = 0; - u_int32_t cur_timep = 0; - int timeout = 0; - cur_timep = af_get_timestamp_sec(); - for (i = 0; i < MAX_RECORD_APP_NUM; i++) - { - if (node->visit_info[i].app_id == 0) - { - return; - } - } - for (i = 0; i < MAX_RECORD_APP_NUM; i++) - { - if (count >= MAX_EXPIRED_VISIT_INFO_COUNT) - break; - - if (node->visit_info[i].total_num > 3) - { - timeout = 180; - } - else - { - timeout = 60; - } - - if (cur_timep - node->visit_info[i].latest_time > timeout) - { - // 3?��o?��??3y???? - memset(&node->visit_info[i], 0x0, sizeof(app_visit_info_t)); - count++; - } - } -} - -int __af_visit_info_report(af_client_info_t *node) -{ - unsigned char mac_str[32] = {0}; - unsigned char ip_str[32] = {0}; - int i; - int count = 0; - char *out = NULL; - cJSON *visit_obj = NULL; - cJSON *visit_info_array = NULL; - cJSON *root_obj = NULL; - - root_obj = cJSON_CreateObject(); - if (!root_obj) - { - AF_ERROR("create json obj failed"); - return 0; - } - sprintf(mac_str, MAC_FMT, MAC_ARRAY(node->mac)); - sprintf(ip_str, "%pI4", &node->ip); - cJSON_AddStringToObject(root_obj, "mac", mac_str); - cJSON_AddStringToObject(root_obj, "ip", ip_str); - cJSON_AddNumberToObject(root_obj, "app_num", node->visit_app_num); - visit_info_array = cJSON_CreateArray(); - for (i = 0; i < MAX_RECORD_APP_NUM; i++) - { - if (node->visit_info[i].app_id == 0) - continue; - count++; - visit_obj = cJSON_CreateObject(); - cJSON_AddNumberToObject(visit_obj, "appid", node->visit_info[i].app_id); - cJSON_AddNumberToObject(visit_obj, "latest_action", node->visit_info[i].latest_action); - cJSON_AddNumberToObject(visit_obj, "up_bytes", node->visit_info[i].total_up_bytes); - cJSON_AddNumberToObject(visit_obj, "down_bytes", node->visit_info[i].total_down_bytes); - memset((char *)&node->visit_info[i], 0x0, sizeof(app_visit_info_t)); - cJSON_AddItemToArray(visit_info_array, visit_obj); - } - - cJSON_AddItemToObject(root_obj, "visit_info", visit_info_array); - out = cJSON_Print(root_obj); - if (!out) - return 0; - cJSON_Minify(out); - if (count > 0 || node->report_count == 0) - { - AF_INFO("report:%s count=%d\n", out, node->report_count); - node->report_count++; - af_send_msg_to_user(out, strlen(out)); - } - cJSON_Delete(root_obj); - kfree(out); - return 0; -} -void af_visit_info_report(void) -{ - af_client_info_t *node; - int i; - AF_CLIENT_LOCK_W(); - for (i = 0; i < MAX_AF_CLIENT_HASH_SIZE; i++) - { - list_for_each_entry(node, &af_client_list_table[i], hlist) - { - // flush_expired_visit_info(node); - AF_INFO("report %s\n", node->mac); - __af_visit_info_report(node); - } - } - AF_CLIENT_UNLOCK_W(); -} -static inline int get_packet_dir(struct net_device *in) -{ - if (0 == strncmp(in->name, "br", 2)) - { - return PKT_DIR_UP; - } - else - { - return PKT_DIR_DOWN; - } -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) -static u_int32_t af_client_hook(void *priv, - struct sk_buff *skb, - const struct nf_hook_state *state) -{ -#else -static u_int32_t af_client_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) -{ -#endif - struct ethhdr *ethhdr = NULL; - unsigned char smac[ETH_ALEN]; - af_client_info_t *nfc = NULL; - int pkt_dir = 0; - struct iphdr *iph = NULL; - -// 4.10-->4.11 nfct-->_nfct -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) - struct nf_conn *ct = (struct nf_conn *)skb->_nfct; -#else - struct nf_conn *ct = (struct nf_conn *)skb->nfct; -#endif - if (ct == NULL) - { - return NF_ACCEPT; - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) - if (!skb->dev) - return NF_ACCEPT; - - pkt_dir = get_packet_dir(skb->dev); -#else - if (!in) - { - AF_ERROR("in is NULL\n"); - return NF_ACCEPT; - } - pkt_dir = get_packet_dir(in); -#endif - - if (PKT_DIR_UP != pkt_dir) - return NF_ACCEPT; - - ethhdr = eth_hdr(skb); - if (ethhdr) - { - memcpy(smac, ethhdr->h_source, ETH_ALEN); - } - else - { - memcpy(smac, &skb->cb[40], ETH_ALEN); - } - - iph = ip_hdr(skb); - if (!iph) - { - return NF_ACCEPT; - } - - AF_CLIENT_LOCK_W(); - nfc = find_af_client(smac); - if (!nfc) - { - if (skb->dev) - AF_DEBUG("from dev:%s [%s] %pI4--->%pI4", skb->dev->name, (iph->protocol == IPPROTO_TCP ? "TCP" : "UDP"), - &iph->saddr, &iph->daddr); - nfc = nf_client_add(smac); - } - if (nfc && nfc->ip != iph->saddr) - { - AF_DEBUG("update node " MAC_FMT " ip %pI4--->%pI4\n", MAC_ARRAY(nfc->mac), &nfc->ip, &iph->saddr); - nfc->update_jiffies = jiffies; - nfc->ip = iph->saddr; - } - AF_CLIENT_UNLOCK_W(); - - return NF_ACCEPT; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) -static struct nf_hook_ops af_client_ops[] = { - { - .hook = af_client_hook, - .pf = PF_INET, - .hooknum = NF_INET_FORWARD, - .priority = NF_IP_PRI_FIRST + 1, - }, -}; -#else -static struct nf_hook_ops af_client_ops[] = { - { - .hook = af_client_hook, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_INET_FORWARD, - .priority = NF_IP_PRI_FIRST + 1, - }, -}; -#endif - -int af_client_init(void) -{ - nf_client_list_init(); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) - nf_register_net_hooks(&init_net, af_client_ops, ARRAY_SIZE(af_client_ops)); -#else - nf_register_hooks(af_client_ops, ARRAY_SIZE(af_client_ops)); -#endif - AF_INFO("init app afclient ........ok\n"); - - return 0; -} - -void af_client_exit(void) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) - nf_unregister_net_hooks(&init_net, af_client_ops, ARRAY_SIZE(af_client_ops)); -#else - nf_unregister_hooks(af_client_ops, ARRAY_SIZE(af_client_ops)); -#endif - nf_client_list_clear(); - return; -} diff --git a/OpenAppFilter/oaf/src/af_client.h b/OpenAppFilter/oaf/src/af_client.h deleted file mode 100644 index ed83565..0000000 --- a/OpenAppFilter/oaf/src/af_client.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef __AF_CLIENT_H__ -#define __AF_CLIENT_H__ -#include "app_filter.h" - -extern rwlock_t af_client_lock; - -extern u32 nfc_debug_level; - -#define MAX_AF_CLIENT_HASH_SIZE 64 -#define NF_CLIENT_TIMER_EXPIRE 1 -#define MAX_CLIENT_ACTIVE_TIME 90 - -#define AF_CLIENT_LOCK_R() read_lock_bh(&af_client_lock); -#define AF_CLIENT_UNLOCK_R() read_unlock_bh(&af_client_lock); -#define AF_CLIENT_LOCK_W() write_lock_bh(&af_client_lock); -#define AF_CLIENT_UNLOCK_W() write_unlock_bh(&af_client_lock); - -#define NIPQUAD(addr) \ - ((unsigned char *)&addr)[0], \ - ((unsigned char *)&addr)[1], \ - ((unsigned char *)&addr)[2], \ - ((unsigned char *)&addr)[3] -#define NIPQUAD_FMT "%u.%u.%u.%u" - -enum NFC_PKT_DIR -{ - PKT_DIR_DOWN, - PKT_DIR_UP -}; - -#define MAX_VISIT_HISTORY_TIME 24 -#define MAX_RECORD_APP_NUM 64 - -typedef struct app_visit_info -{ - unsigned int app_id; - unsigned int total_num; - unsigned int drop_num; - unsigned long latest_time; - unsigned int latest_action; - unsigned int total_down_bytes; - unsigned int total_up_bytes; - unsigned long history_time[MAX_VISIT_HISTORY_TIME]; - unsigned int action[MAX_VISIT_HISTORY_TIME]; -} app_visit_info_t; - -typedef struct af_client_info -{ - struct list_head hlist; - unsigned char mac[MAC_ADDR_LEN]; - unsigned int ip; - unsigned long create_jiffies; - unsigned long update_jiffies; - unsigned int visit_app_num; - int report_count; - app_visit_info_t visit_info[MAX_RECORD_APP_NUM]; -} af_client_info_t; - -int af_client_init(void); - -void af_client_exit(void); -af_client_info_t *find_af_client_by_ip(unsigned int ip); -af_client_info_t *find_af_client(unsigned char *mac); - -void check_client_expire(void); - -void af_visit_info_report(void); - -void af_client_list_reset_report_num(void); -af_client_info_t *nf_client_add(unsigned char *mac); -af_client_info_t *find_and_add_af_client(unsigned char *mac); - -#endif diff --git a/OpenAppFilter/oaf/src/af_client_fs.c b/OpenAppFilter/oaf/src/af_client_fs.c deleted file mode 100644 index 6037988..0000000 --- a/OpenAppFilter/oaf/src/af_client_fs.c +++ /dev/null @@ -1,194 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cJSON.h" -#include "af_log.h" -#include "af_client.h" - -extern struct list_head af_client_list_table[MAX_AF_CLIENT_HASH_SIZE]; -struct af_client_iter_state -{ - unsigned int bucket; - void *head; -}; - -static void *af_client_get_first(struct seq_file *seq) -{ - struct af_client_iter_state *st = seq->private; - for (st->bucket = 0; st->bucket < MAX_AF_CLIENT_HASH_SIZE; st->bucket++) - { - if (!list_empty(&(af_client_list_table[st->bucket]))) - { - st->head = &(af_client_list_table[st->bucket]); - return af_client_list_table[st->bucket].next; - } - } - return NULL; -} - -static void *af_client_get_next(struct seq_file *seq, - void *head) -{ - struct af_client_iter_state *st = seq->private; - struct hlist_node *node = (struct hlist_node *)head; - - node = node->next; - if (node != st->head) - { - return node; - } - else - { - st->bucket++; - for (; st->bucket < MAX_AF_CLIENT_HASH_SIZE; st->bucket++) - { - if (!list_empty(&(af_client_list_table[st->bucket]))) - { - st->head = &(af_client_list_table[st->bucket]); - return af_client_list_table[st->bucket].next; - } - } - return NULL; - } -} - -static void *af_client_get_idx(struct seq_file *seq, loff_t pos) -{ - void *head = af_client_get_first(seq); - - if (head) - while (pos && (head = af_client_get_next(seq, head))) - pos--; - - return pos ? NULL : head; -} - -static void *af_client_seq_start(struct seq_file *s, loff_t *pos) -{ - AF_CLIENT_LOCK_R(); - if (*pos == 0) - { - return SEQ_START_TOKEN; - } - - return af_client_get_idx(s, *pos - 1); -} - -static void *af_client_seq_next(struct seq_file *s, void *v, loff_t *pos) -{ - (*pos)++; - if (v == SEQ_START_TOKEN) - return af_client_get_idx(s, 0); - - return af_client_get_next(s, v); -} - -static void af_client_seq_stop(struct seq_file *s, void *v) -{ - AF_CLIENT_UNLOCK_R(); -} - -static int af_client_seq_show(struct seq_file *s, void *v) -{ - unsigned char mac_str[32] = {0}; - unsigned char ip_str[32] = {0}; - static int index = 0; - af_client_info_t *node = (af_client_info_t *)v; - if (v == SEQ_START_TOKEN) - { - index = 0; - seq_printf(s, "%-4s %-20s %-20s\n", "Id", "Mac", "Ip"); - return 0; - } - index++; - sprintf(mac_str, MAC_FMT, MAC_ARRAY(node->mac)); - sprintf(ip_str, "%pI4", &node->ip); - seq_printf(s, "%-4d %-20s %-20s\n", index, mac_str, ip_str); - return 0; -} - -static const struct seq_operations nf_client_seq_ops = { - .start = af_client_seq_start, - .next = af_client_seq_next, - .stop = af_client_seq_stop, - .show = af_client_seq_show}; - -static int af_client_open(struct inode *inode, struct file *file) -{ - struct seq_file *seq; - struct af_client_iter_state *iter; - int err; - - iter = kzalloc(sizeof(*iter), GFP_KERNEL); - if (!iter) - return -ENOMEM; - - err = seq_open(file, &nf_client_seq_ops); - if (err) - { - kfree(iter); - return err; - } - - seq = file->private_data; - seq->private = iter; - return 0; -} - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 5, 0) -static const struct file_operations af_client_fops = { - .owner = THIS_MODULE, - .open = af_client_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release_private, -}; -#else -static const struct proc_ops af_client_fops = { - .proc_flags = PROC_ENTRY_PERMANENT, - .proc_read = seq_read, - .proc_open = af_client_open, - .proc_lseek = seq_lseek, - .proc_release = seq_release_private, -}; -#endif - -#define AF_CLIENT_PROC_STR "af_client" - -int init_af_client_procfs(void) -{ - struct proc_dir_entry *pde; - struct net *net = &init_net; - pde = proc_create(AF_CLIENT_PROC_STR, 0440, net->proc_net, &af_client_fops); - - if (!pde) - { - AF_ERROR("nf_client proc file created error\n"); - return -1; - } - return 0; -} - -void finit_af_client_procfs(void) -{ - struct net *net = &init_net; - remove_proc_entry(AF_CLIENT_PROC_STR, net->proc_net); -} diff --git a/OpenAppFilter/oaf/src/af_client_fs.h b/OpenAppFilter/oaf/src/af_client_fs.h deleted file mode 100644 index 0140c27..0000000 --- a/OpenAppFilter/oaf/src/af_client_fs.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __AF_CLIENT_FS_H__ -#define __AF_CLIENT_FS_H__ - -int init_af_client_procfs(void); -void finit_af_client_procfs(void); - -#endif diff --git a/OpenAppFilter/oaf/src/af_log.c b/OpenAppFilter/oaf/src/af_log.c deleted file mode 100644 index dba9c10..0000000 --- a/OpenAppFilter/oaf/src/af_log.c +++ /dev/null @@ -1,87 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "app_filter.h" -#include "af_log.h" -int af_log_lvl = 1; -int af_test_mode = 0; -// todo: rename af_log.c -int g_oaf_enable __read_mostly = 0; -int af_work_mode = AF_MODE_GATEWAY; -/* - cat /proc/sys/oaf/debug -*/ -static struct ctl_table oaf_table[] = { - { - .procname = "debug", - .data = &af_log_lvl, - .maxlen = sizeof(int), - .mode = 0666, - .proc_handler = proc_dointvec, - }, - { - .procname = "test_mode", - .data = &af_test_mode, - .maxlen = sizeof(int), - .mode = 0666, - .proc_handler = proc_dointvec, - }, - { - .procname = "enable", - .data = &g_oaf_enable, - .maxlen = sizeof(int), - .mode = 0666, - .proc_handler = proc_dointvec, - }, - { - .procname = "work_mode", - .data = &af_work_mode, - .maxlen = sizeof(int), - .mode = 0666, - .proc_handler = proc_dointvec, - }, - { - } -}; - -static struct ctl_table oaf_root_table[] = { - { - .procname = "oaf", - .mode = 0555, - .child = oaf_table, - }, - {} -}; -static struct ctl_table_header *oaf_table_header; - - -static int af_init_log_sysctl(void) -{ - oaf_table_header = register_sysctl_table(oaf_root_table); - if (oaf_table_header == NULL){ - printk("init log sysctl...failed\n"); - return -ENOMEM; - } - printk("init oaf sysctl...ok\n"); - return 0; -} - -static int af_fini_log_sysctl(void) -{ - if (oaf_table_header) - unregister_sysctl_table(oaf_table_header); - return 0; -} - -int af_log_init(void){ - af_init_log_sysctl(); - return 0; -} - -int af_log_exit(void){ - af_fini_log_sysctl(); - return 0; -} diff --git a/OpenAppFilter/oaf/src/af_log.h b/OpenAppFilter/oaf/src/af_log.h deleted file mode 100644 index f37b8d6..0000000 --- a/OpenAppFilter/oaf/src/af_log.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef __AF_DEBUG_H__ -#define __AF_DEBUG_H__ -extern int af_log_lvl; -extern int af_test_mode; -extern int af_work_mode; -#define LOG(level, fmt, ...) do { \ - if ((level) <= af_log_lvl) { \ - printk(fmt, ##__VA_ARGS__); \ - } \ -} while (0) - -#define LLOG(level, fmt, ...) do { \ - if ((level) <= af_log_lvl) { \ - pr_info_ratelimited(fmt, ##__VA_ARGS__); \ - } \ -} while (0) - - -#define AF_ERROR(...) LOG(0, ##__VA_ARGS__) -#define AF_WARN(...) LOG(1, ##__VA_ARGS__) -#define AF_INFO(...) LOG(2, ##__VA_ARGS__) -#define AF_DEBUG(...) LOG(3, ##__VA_ARGS__) - -#define AF_LMT_ERROR(...) LLOG(0, ##__VA_ARGS__) -#define AF_LMT_WARN(...) LLOG(1, ##__VA_ARGS__) -#define AF_LMT_INFO(...) LLOG(2, ##__VA_ARGS__) -#define AF_LMT_DEBUG(...) LLOG(3, ##__VA_ARGS__) - - -#define TEST_MODE() (af_test_mode) -int af_log_init(void); -int af_log_exit(void); -#endif diff --git a/OpenAppFilter/oaf/src/af_utils.c b/OpenAppFilter/oaf/src/af_utils.c deleted file mode 100644 index cb8103b..0000000 --- a/OpenAppFilter/oaf/src/af_utils.c +++ /dev/null @@ -1,330 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "af_utils.h" -u_int32_t af_get_timestamp_sec(void) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0) - struct timespec64 ts; - ktime_get_real_ts64(&ts); - return (u_int32_t)ts.tv_sec; -#else - struct timespec ts; - ts = current_kernel_time(); - return ts.tv_sec; -#endif - -} -char *k_trim(char *s) -{ - char *start, *last, *bk; - int len; - - start = s; - while (isspace(*start)) - start++; - - bk = last = s + strlen(s) - 1; - while (last > start && isspace(*last)) - last--; - - if ((s != start) || (bk != last)) - { - len = last - start + 1; - strncpy(s, start, len); - s[len] = '\0'; - } - return s; -} - -int check_local_network_ip(unsigned int ip) -{ - if ((ip & 0xffff0000) == 0xc0a80000) - return 1; - else if ((ip & 0xfff00000) == 0xac100000) - return 1; - else if ((ip & 0xff000000) == 0x0a000000) - return 1; - else - return 0; -} - -void dump_str(char *name, unsigned char *p, int len) -{ - #define MAX_DUMP_STR_LEN 64 - char buf[MAX_DUMP_STR_LEN] = {0}; - if (len > MAX_DUMP_STR_LEN) { - len = MAX_DUMP_STR_LEN - 1; - } - printk("%s: ",name); - strncpy(buf, p, len); - printk("[%s]\n", buf); -} - -void dump_hex(char *name, unsigned char *p, int len) -{ - #define MAX_DUMP_STR_LEN 64 - int i; - if (len > MAX_DUMP_STR_LEN) { - len = MAX_DUMP_STR_LEN - 1; - } - printk("%s: ",name); - for (i = 0; i < len; i++) { - if (i % 16 == 0) - printk("\n"); - printk("%02X ",*(p + i)); - } - printk("\n"); -} - -#ifndef va_arg -typedef signed int acpi_native_int; -#ifndef _VALIST -#define _VALIST -typedef char *va_list; -#endif - -#define _AUPBND (sizeof (acpi_native_int) - 1) -#define _ADNBND (sizeof (acpi_native_int) - 1) - - -#define _bnd(X, bnd) (((sizeof (X)) + (bnd)) & (~(bnd))) -#define va_arg(ap, T) (*(T *)(((ap) += (_bnd (T, _AUPBND))) - (_bnd (T,_ADNBND)))) -#define va_end(ap) (void) 0 -#define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_bnd (A,_AUPBND)))) - -#endif - -#ifndef TOLOWER -#define TOLOWER(x) ((x) | 0x20) -#endif - - -static long long k_simple_strtoll(const char *cp, char **endp, unsigned int base) -{ - if (*cp == '-') - return -simple_strtoull(cp + 1, endp, base); - - return simple_strtoull(cp, endp, base); -} - -static int skip_atoi(const char **s) -{ - int i=0; - while (isdigit(**s)) - i = i*10 + *((*s)++) - '0'; - return i; -} - -char *skip_spaces(const char *str) -{ - while (isspace(*str) && ((unsigned char )*str != 0xa0)) - ++str; - return (char *)str; -} -static int k_vsscanf(const char *buf, const char *fmt, va_list args) -{ - const char *str = buf; - char *next; - char digit; - int num = 0; - u8 qualifier; - u8 base; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22) - int field_width; -#else - s16 field_width; -#endif - bool is_sign; - while (*fmt && *str) { - if (isspace(*fmt)) { - fmt = skip_spaces(++fmt); - str = skip_spaces(str); - } - - if (*fmt != '%' && *fmt) { - if (*fmt++ != *str++) - break; - continue; - } - if (!*fmt) - break; - ++fmt; - - if (*fmt == '*') { - while (!isspace(*fmt) && *fmt != '%' && *fmt) - fmt++; - while (!isspace(*str) && *str) - str++; - continue; - } - field_width = -1; - if (isdigit(*fmt)) - field_width = skip_atoi(&fmt); - qualifier = -1; - if (*fmt == 'h' || TOLOWER(*fmt) == 'l' || - TOLOWER(*fmt) == 'z') { - qualifier = *fmt++; - if (unlikely(qualifier == *fmt)) { - if (qualifier == 'h') { - qualifier = 'H'; - fmt++; - } else if (qualifier == 'l') { - qualifier = 'L'; - fmt++; - } - } - } - if (!*fmt || !*str) - break; - base = 10; - is_sign = 0; - switch (*fmt++) { - case 'c': - { - char *s = (char *)va_arg(args, char*); - if (field_width == -1) - field_width = 1; - do { - *s++ = *str++; - } while (--field_width > 0 && *str); - num++; - } - continue; - case 's': - { - char *s = (char *)va_arg(args, char *); -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22) - if(field_width == -1) - field_width = INT_MAX; -#else - if (field_width == -1) - field_width = SHRT_MAX; -#endif - str = skip_spaces(str); - - while (*str && (!isspace(*str) || ((unsigned char )*str == 0xA0) )&& field_width--) - *s++ = *str++; - *s = '\0'; - num++; - } - continue; - case 'n': - { - int *i = (int *)va_arg(args, int*); - *i = str - buf; - } - continue; - case 'o': - base = 8; - break; - case 'x': - case 'X': - base = 16; - break; - case 'i': - base = 0; - case 'd': - is_sign = 1; - case 'u': - break; - case '%': - if (*str++ != '%') - return num; - continue; - default: - return num; - } - str = skip_spaces(str); - digit = *str; - if (is_sign && digit == '-') - digit = *(str + 1); - if (!digit - || (base == 16 && !isxdigit(digit)) - || (base == 10 && !isdigit(digit)) - || (base == 8 && (!isdigit(digit) || digit > '7')) - || (base == 0 && !isdigit(digit))) - break; - - switch (qualifier) { - case 'H': - if (is_sign) { - signed char *s = (signed char *)va_arg(args, signed char *); - *s = (signed char)simple_strtol(str, &next, base); - } else { - unsigned char *s = (unsigned char *)va_arg(args, unsigned char *); - *s = (unsigned char)simple_strtoul(str, &next, base); - } - break; - case 'h': - if (is_sign) { - short *s = (short *)va_arg(args, short *); - *s = (short)simple_strtol(str, &next, base); - } else { - unsigned short *s = (unsigned short *)va_arg(args, unsigned short *); - *s = (unsigned short)simple_strtoul(str, &next, base); - } - break; - case 'l': - if (is_sign) { - long *l = (long *)va_arg(args, long *); - *l = simple_strtol(str, &next, base); - } else { - unsigned long *l = (unsigned long *)va_arg(args, unsigned long *); - *l = simple_strtoul(str, &next, base); - } - break; - case 'L': - if (is_sign) { - long long *l = (long long *)va_arg(args, long long *); - *l = k_simple_strtoll(str, &next, base); - } else { - unsigned long long *l = (unsigned long long *)va_arg(args, unsigned long long *); - *l = simple_strtoull(str, &next, base); - } - break; - case 'Z': - case 'z': - { - size_t *s = (size_t *)va_arg(args, size_t *); - *s = (size_t)simple_strtoul(str, &next, base); - } - break; - default: - if (is_sign) { - int *i = (int *)va_arg(args, int *); - *i = (int)simple_strtol(str, &next, base); - } else { - unsigned int *i = (unsigned int *)va_arg(args, unsigned int*); - *i = (unsigned int)simple_strtoul(str, &next, base); - } - break; - } - num++; - if (!next) - break; - str = next; - } - if (*fmt == '%' && *(fmt + 1) == 'n') { - int *p = (int *)va_arg(args, int *); - *p = str - buf; - } - return num; -} - - -int k_sscanf(const char *buf, const char *fmt, ...) -{ - va_list args; - int i; - va_start(args, fmt); - i = k_vsscanf(buf, fmt, args); - va_end(args); - return i; -} - - diff --git a/OpenAppFilter/oaf/src/af_utils.h b/OpenAppFilter/oaf/src/af_utils.h deleted file mode 100644 index f2f7be0..0000000 --- a/OpenAppFilter/oaf/src/af_utils.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef AF_UTILS_H -#define AF_UTILS_H -u_int32_t af_get_timestamp_sec(void); - -char *k_trim(char *s); - -int check_local_network_ip(unsigned int ip); - -void dump_str(char *name, unsigned char *p, int len); - -void dump_hex(char *name, unsigned char *p, int len); - -int k_sscanf(const char *buf, const char *fmt, ...); - -#endif - diff --git a/OpenAppFilter/oaf/src/app_filter.c b/OpenAppFilter/oaf/src/app_filter.c deleted file mode 100644 index e9ca013..0000000 --- a/OpenAppFilter/oaf/src/app_filter.c +++ /dev/null @@ -1,1255 +0,0 @@ - -/* - author: derry - date:2019/1/10 -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "app_filter.h" -#include "af_utils.h" -#include "af_log.h" -#include "af_client.h" -#include "af_client_fs.h" -#include "cJSON.h" - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("destan19@126.com"); -MODULE_DESCRIPTION("app filter module"); -MODULE_VERSION("5.0"); -struct list_head af_feature_head = LIST_HEAD_INIT(af_feature_head); - -DEFINE_RWLOCK(af_feature_lock); - -#define feature_list_read_lock() read_lock_bh(&af_feature_lock); -#define feature_list_read_unlock() read_unlock_bh(&af_feature_lock); -#define feature_list_write_lock() write_lock_bh(&af_feature_lock); -#define feature_list_write_unlock() write_unlock_bh(&af_feature_lock); - -#define SET_APPID(mark, appid) (mark = appid) -#define GET_APPID(mark) (mark) -#define MAX_OAF_NETLINK_MSG_LEN 1024 - -int __add_app_feature(int appid, char *name, int proto, int src_port, - port_info_t dport_info, char *host_url, char *request_url, char *dict) -{ - af_feature_node_t *node = NULL; - char *p = dict; - char *begin = dict; - char pos[32] = {0}; - int index = 0; - int value = 0; - node = kzalloc(sizeof(af_feature_node_t), GFP_KERNEL); - if (node == NULL) - { - printk("malloc feature memory error\n"); - return -1; - } - else - { - node->app_id = appid; - strcpy(node->app_name, name); - node->proto = proto; - node->dport_info = dport_info; - node->sport = src_port; - strcpy(node->host_url, host_url); - strcpy(node->request_url, request_url); - // 00:0a-01:11 - p = dict; - begin = dict; - index = 0; - value = 0; - while (*p++) - { - if (*p == '|') - { - memset(pos, 0x0, sizeof(pos)); - strncpy(pos, begin, p - begin); - k_sscanf(pos, "%d:%x", &index, &value); - begin = p + 1; - node->pos_info[node->pos_num].pos = index; - node->pos_info[node->pos_num].value = value; - node->pos_num++; - } - } - - if (begin != dict) - strncpy(pos, begin, p - begin); - else - strcpy(pos, dict); - - k_sscanf(pos, "%d:%x", &index, &value); - node->pos_info[node->pos_num].pos = index; - node->pos_info[node->pos_num].value = value; - node->pos_num++; - feature_list_write_lock(); - list_add(&(node->head), &af_feature_head); - feature_list_write_unlock(); - } - return 0; -} -int validate_range_value(char *range_str){ - if (!range_str) - return 0; - char *p = range_str; - while(*p){ - if (*p == ' ' || *p == '!' || *p == '-' || - ((*p >= '0') && (*p <= '9'))){ - p++; - continue; - } - else{ - printk("error, invalid char %x\n", *p); - return 0; - } - } - return 1; -} - -int parse_range_value(char *range_str, range_value_t *range){ - char pure_range[128] = {0}; - if (!validate_range_value(range_str)){ - printk("validate range str failed, value = %s\n", range_str); - return -1; - } - k_trim(range_str); - if (range_str[0] == '!'){ - range->not = 1; - strcpy(pure_range, range_str + 1); - } - else{ - range->not = 0; - strcpy(pure_range, range_str); - } - k_trim(pure_range); - int start, end; - if (strstr(pure_range, "-")){ - if (2 != sscanf(pure_range, "%d-%d",&start, &end)) - return -1; - } - else{ - if (1 != sscanf(pure_range, "%d", &start)) - return -1; - end = start; - } - range->start = start; - range->end = end; - return 0; -} - -int parse_port_info(char *port_str, port_info_t *info){ - char *p = port_str; - char *begin = port_str; - int param_num = 0; - char one_port_buf[128] = {0}; - k_trim(port_str); - if (strlen(port_str) == 0) - return -1; - - while(*p++) { - if (*p != '|') - continue; - memset(one_port_buf, 0x0, sizeof(one_port_buf)); - strncpy(one_port_buf, begin, p - begin); - if (0 == parse_range_value(one_port_buf, &info->range_list[info->num])){ - info->num++; - } - param_num++; - begin = p + 1; - } - memset(one_port_buf, 0x0, sizeof(one_port_buf)); - strncpy(one_port_buf, begin, p - begin); - if (0 == parse_range_value(one_port_buf, &info->range_list[info->num])){ - info->num++; - } - return 0; -} - -int af_match_port(port_info_t *info, int port){ - int i; - int with_not = 0; - if (info->num == 0) - return 1; - for (i = 0; i < info->num; i++){ - if (info->range_list[i].not){ - with_not = 1; - break; - } - } - for (i = 0; i < info->num; i++){ - if (with_not){ - if (info->range_list[i].not && port >= info->range_list[i].start - && port <= info->range_list[i].end){ - return 0; - } - } - else{ - if (port >= info->range_list[i].start - && port <= info->range_list[i].end){ - return 1; - } - } - } - if (with_not) - return 1; - else - return 0; -} -//[tcp;;443;baidu.com;;] -int add_app_feature(int appid, char *name, char *feature) -{ - char proto_str[16] = {0}; - char src_port_str[16] = {0}; - port_info_t dport_info; - char dst_port_str[16] = {0}; - char host_url[32] = {0}; - char request_url[128] = {0}; - char dict[128] = {0}; - int proto = IPPROTO_TCP; - char *p = feature; - char *begin = feature; - int param_num = 0; - int dst_port = 0; - int src_port = 0; - - if (!name || !feature) - { - AF_ERROR("error, name or feature is null\n"); - return -1; - } - // tcp;8000;www.sina.com;0:get_name;00:0a-01:11 - memset(&dport_info, 0x0, sizeof(dport_info)); - while (*p++) - { - if (*p != ';') - continue; - - switch (param_num) - { - - case AF_PROTO_PARAM_INDEX: - strncpy(proto_str, begin, p - begin); - break; - case AF_SRC_PORT_PARAM_INDEX: - strncpy(src_port_str, begin, p - begin); - break; - case AF_DST_PORT_PARAM_INDEX: - strncpy(dst_port_str, begin, p - begin); - break; - - case AF_HOST_URL_PARAM_INDEX: - strncpy(host_url, begin, p - begin); - break; - - case AF_REQUEST_URL_PARAM_INDEX: - strncpy(request_url, begin, p - begin); - break; - } - param_num++; - begin = p + 1; - } - if (AF_DICT_PARAM_INDEX != param_num && strlen(feature) > MIN_FEATURE_STR_LEN) - { - AF_ERROR("invalid feature:%s\n", feature); - return -1; - } - strncpy(dict, begin, p - begin); - - if (0 == strcmp(proto_str, "tcp")) - proto = IPPROTO_TCP; - else if (0 == strcmp(proto_str, "udp")) - proto = IPPROTO_UDP; - else - { - AF_DEBUG("proto %s is not support\n", proto_str); - return -1; - } - sscanf(src_port_str, "%d", &src_port); -// sscanf(dst_port_str, "%d", &dst_port); - parse_port_info(dst_port_str, &dport_info); - - __add_app_feature(appid, name, proto, src_port, dport_info, host_url, request_url, dict); - return 0; -} - -void af_init_feature(char *feature_str) -{ - int app_id; - char app_name[128] = {0}; - char feature_buf[MAX_FEATURE_LINE_LEN] = {0}; - char *p = feature_str; - char *pos = NULL; - int len = 0; - char *begin = NULL; - char feature[MAX_FEATURE_STR_LEN]; - - if (strstr(feature_str, "#")) - return; - - k_sscanf(feature_str, "%d%[^:]", &app_id, app_name); - while (*p++) - { - if (*p == '[') - { - pos = p + 1; - continue; - } - if (*p == ']' && pos != NULL) - { - len = p - pos; - } - } - - if (pos && len) - strncpy(feature_buf, pos, len); - memset(feature, 0x0, sizeof(feature)); - p = feature_buf; - begin = feature_buf; - - while (*p++) - { - if (*p == ',') - { - memset(feature, 0x0, sizeof(feature)); - strncpy((char *)feature, begin, p - begin); - - add_app_feature(app_id, app_name, feature); - begin = p + 1; - } - } - if (p != begin) - { - memset(feature, 0x0, sizeof(feature)); - strncpy((char *)feature, begin, p - begin); - add_app_feature(app_id, app_name, feature); - } -} - -void load_feature_buf_from_file(char **config_buf) -{ - struct inode *inode = NULL; - struct file *fp = NULL; -#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 7, 19) - mm_segment_t fs; -#endif - off_t size; - fp = filp_open(AF_FEATURE_CONFIG_FILE, O_RDONLY, 0); - - if (IS_ERR(fp)) - { - printk("open feature file failed\n"); - return; - } - - inode = fp->f_inode; - size = inode->i_size; - if (size == 0) - { - return; - } - *config_buf = (char *)kzalloc(sizeof(char) * size, GFP_KERNEL); - if (NULL == *config_buf) - { - AF_ERROR("alloc buf fail\n"); - filp_close(fp, NULL); - return; - } - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 7, 19) - fs = get_fs(); - set_fs(KERNEL_DS); -#endif -// 4.14rc3 vfs_read-->kernel_read -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 14, 0) - kernel_read(fp, *config_buf, size, &(fp->f_pos)); -#else - vfs_read(fp, *config_buf, size, &(fp->f_pos)); -#endif - -#if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 7, 19) - set_fs(fs); -#endif - filp_close(fp, NULL); -} - -int load_feature_config(void) -{ - char *feature_buf = NULL; - char *p; - char *begin; - char line[MAX_FEATURE_LINE_LEN] = {0}; - - load_feature_buf_from_file(&feature_buf); - if (!feature_buf) - { - AF_ERROR("error, feature buf is null\n"); - return -1; - } - p = begin = feature_buf; - while (*p++) - { - if (*p == '\n') - { - if (p - begin < MIN_FEATURE_LINE_LEN || p - begin > MAX_FEATURE_LINE_LEN) - { - begin = p + 1; - continue; - } - memset(line, 0x0, sizeof(line)); - strncpy(line, begin, p - begin); - af_init_feature(line); - begin = p + 1; - } - } - if (p != begin) - { - if (p - begin < MIN_FEATURE_LINE_LEN || p - begin > MAX_FEATURE_LINE_LEN) - return 0; - memset(line, 0x0, sizeof(line)); - strncpy(line, begin, p - begin); - af_init_feature(line); - begin = p + 1; - } - if (feature_buf) - kfree(feature_buf); - return 0; -} - -static void af_clean_feature_list(void) -{ - af_feature_node_t *node; - feature_list_write_lock(); - while (!list_empty(&af_feature_head)) - { - node = list_first_entry(&af_feature_head, af_feature_node_t, head); - list_del(&(node->head)); - kfree(node); - } - feature_list_write_unlock(); -} - -int parse_flow_proto(struct sk_buff *skb, flow_info_t *flow) -{ - struct tcphdr *tcph = NULL; - struct udphdr *udph = NULL; - struct nf_conn *ct = NULL; - struct iphdr *iph = NULL; - if (!skb) - return -1; - iph = ip_hdr(skb); - if (!iph) - return -1; - flow->src = iph->saddr; - flow->dst = iph->daddr; - flow->l4_protocol = iph->protocol; - switch (iph->protocol) - { - case IPPROTO_TCP: - tcph = (struct tcphdr *)(iph + 1); - flow->l4_data = skb->data + iph->ihl * 4 + tcph->doff * 4; - flow->l4_len = ntohs(iph->tot_len) - iph->ihl * 4 - tcph->doff * 4; - flow->dport = htons(tcph->dest); - flow->sport = htons(tcph->source); - return 0; - case IPPROTO_UDP: - udph = (struct udphdr *)(iph + 1); - flow->l4_data = skb->data + iph->ihl * 4 + 8; - flow->l4_len = ntohs(udph->len) - 8; - flow->dport = htons(udph->dest); - flow->sport = htons(udph->source); - return 0; - case IPPROTO_ICMP: - break; - default: - return -1; - } - return -1; -} - -int dpi_https_proto(flow_info_t *flow) -{ - int i; - short url_len = 0; - char *p = flow->l4_data; - int data_len = flow->l4_len; - - if (NULL == flow) - { - AF_ERROR("flow is NULL\n"); - return -1; - } - if (NULL == p || data_len == 0) - { - return -1; - } - if (!(p[0] == 0x16 && p[1] == 0x03 && p[2] == 0x01)) - return -1; - - - for (i = 0; i < data_len; i++) - { - if (i + HTTPS_URL_OFFSET >= data_len) - { - return -1; - } - - if (p[i] == 0x0 && p[i + 1] == 0x0 && p[i + 2] == 0x0 && p[i + 3] != 0x0) - { - // 2 bytes - memcpy(&url_len, p + i + HTTPS_LEN_OFFSET, 2); - if (ntohs(url_len) <= 0 || ntohs(url_len) > data_len) - { - continue; - } - if (i + HTTPS_URL_OFFSET + ntohs(url_len) < data_len) - { - flow->https.match = AF_TRUE; - flow->https.url_pos = p + i + HTTPS_URL_OFFSET; - flow->https.url_len = ntohs(url_len); - return 0; - } - } - } - return -1; -} - -void dpi_http_proto(flow_info_t *flow) -{ - int i = 0; - int start = 0; - char *data = NULL; - int data_len = 0; - if (!flow) - { - AF_ERROR("flow is null\n"); - return; - } - if (flow->l4_protocol != IPPROTO_TCP) - { - return; - } - - data = flow->l4_data; - data_len = flow->l4_len; - if (data_len < MIN_HTTP_DATA_LEN) - { - return; - } - if (flow->sport != 80 && flow->dport != 80) - return; - for (i = 0; i < data_len; i++) - { - if (data[i] == 0x0d && data[i + 1] == 0x0a) - { - if (0 == memcmp(&data[start], "POST ", 5)) - { - flow->http.match = AF_TRUE; - flow->http.method = HTTP_METHOD_POST; - flow->http.url_pos = data + start + 5; - flow->http.url_len = i - start - 5; - } - else if (0 == memcmp(&data[start], "GET ", 4)) - { - flow->http.match = AF_TRUE; - flow->http.method = HTTP_METHOD_GET; - flow->http.url_pos = data + start + 4; - flow->http.url_len = i - start - 4; - } - else if (0 == memcmp(&data[start], "Host:", 5)) - { - flow->http.host_pos = data + start + 6; - flow->http.host_len = i - start - 6; - } - if (data[i + 2] == 0x0d && data[i + 3] == 0x0a) - { - flow->http.data_pos = data + i + 4; - flow->http.data_len = data_len - i - 4; - break; - } - // 0x0d 0x0a - start = i + 2; - } - } -} - -static void dump_http_flow_info(http_proto_t *http) -{ - if (!http) - { - AF_ERROR("http ptr is NULL\n"); - return; - } - if (!http->match) - return; - if (http->method == HTTP_METHOD_GET) - { - printk("Http method: " HTTP_GET_METHOD_STR "\n"); - } - else if (http->method == HTTP_METHOD_POST) - { - printk("Http method: " HTTP_POST_METHOD_STR "\n"); - } - if (http->url_len > 0 && http->url_pos) - { - dump_str("Request url", http->url_pos, http->url_len); - } - - if (http->host_len > 0 && http->host_pos) - { - dump_str("Host", http->host_pos, http->host_len); - } - - printk("--------------------------------------------------------\n\n\n"); -} - -static void dump_https_flow_info(https_proto_t *https) -{ - if (!https) - { - AF_ERROR("https ptr is NULL\n"); - return; - } - if (!https->match) - return; - - if (https->url_len > 0 && https->url_pos) - { - dump_str("https server name", https->url_pos, https->url_len); - } - - printk("--------------------------------------------------------\n\n\n"); -} -static void dump_flow_info(flow_info_t *flow) -{ - if (!flow) - { - AF_ERROR("flow is null\n"); - return; - } - if (flow->l4_len > 0) - { - AF_LMT_INFO("src=" NIPQUAD_FMT ",dst=" NIPQUAD_FMT ",sport: %d, dport: %d, data_len: %d\n", - NIPQUAD(flow->src), NIPQUAD(flow->dst), flow->sport, flow->dport, flow->l4_len); - } - - if (flow->l4_protocol == IPPROTO_TCP) - { - if (AF_TRUE == flow->http.match) - { - printk("-------------------http protocol-------------------------\n"); - printk("protocol:TCP , sport: %-8d, dport: %-8d, data_len: %-8d\n", - flow->sport, flow->dport, flow->l4_len); - dump_http_flow_info(&flow->http); - } - if (AF_TRUE == flow->https.match) - { - printk("-------------------https protocol-------------------------\n"); - dump_https_flow_info(&flow->https); - } - } -} -int af_match_by_pos(flow_info_t *flow, af_feature_node_t *node) -{ - int i; - unsigned int pos = 0; - - if (!flow || !node) - return AF_FALSE; - if (node->pos_num > 0) - { - for (i = 0; i < node->pos_num; i++) - { - // -1 - if (node->pos_info[i].pos < 0) - { - pos = flow->l4_len + node->pos_info[i].pos; - } - else - { - pos = node->pos_info[i].pos; - } - if (pos >= flow->l4_len) - { - return AF_FALSE; - } - if (flow->l4_data[pos] != node->pos_info[i].value) - { - return AF_FALSE; - } - } - AF_DEBUG("match by pos, appid=%d\n", node->app_id); - return AF_TRUE; - } - return AF_FALSE; -} - -int af_match_by_url(flow_info_t *flow, af_feature_node_t *node) -{ - char reg_url_buf[MAX_URL_MATCH_LEN] = {0}; - - if (!flow || !node) - return AF_FALSE; - // match host or https url - if (flow->https.match == AF_TRUE && flow->https.url_pos) - { - if (flow->https.url_len >= MAX_URL_MATCH_LEN) - strncpy(reg_url_buf, flow->https.url_pos, MAX_URL_MATCH_LEN - 1); - else - strncpy(reg_url_buf, flow->https.url_pos, flow->https.url_len); - } - else if (flow->http.match == AF_TRUE && flow->http.host_pos) - { - if (flow->http.host_len >= MAX_URL_MATCH_LEN) - strncpy(reg_url_buf, flow->http.host_pos, MAX_URL_MATCH_LEN - 1); - else - strncpy(reg_url_buf, flow->http.host_pos, flow->http.host_len); - } - if (strlen(reg_url_buf) > 0 && strlen(node->host_url) > 0 && regexp_match(node->host_url, reg_url_buf)) - { - AF_DEBUG("match url:%s reg = %s, appid=%d\n", - reg_url_buf, node->host_url, node->app_id); - return AF_TRUE; - } - - // match request url - if (flow->http.match == AF_TRUE && flow->http.url_pos) - { - memset(reg_url_buf, 0x0, sizeof(reg_url_buf)); - if (flow->http.url_len >= MAX_URL_MATCH_LEN) - strncpy(reg_url_buf, flow->http.url_pos, MAX_URL_MATCH_LEN - 1); - else - strncpy(reg_url_buf, flow->http.url_pos, flow->http.url_len); - if (strlen(reg_url_buf) > 0 && strlen(node->request_url) && regexp_match(node->request_url, reg_url_buf)) - { - AF_DEBUG("match request:%s reg:%s appid=%d\n", - reg_url_buf, node->request_url, node->app_id); - return AF_TRUE; - } - } - return AF_FALSE; -} - -int af_match_one(flow_info_t *flow, af_feature_node_t *node) -{ - int ret = AF_FALSE; - if (!flow || !node) - { - AF_ERROR("node or flow is NULL\n"); - return AF_FALSE; - } - if (node->proto > 0 && flow->l4_protocol != node->proto) - return AF_FALSE; - if (flow->l4_len == 0) - return AF_FALSE; - - if (node->sport != 0 && flow->sport != node->sport) - { - return AF_FALSE; - } - - if (!af_match_port(&node->dport_info, flow->dport)){ - return AF_FALSE; - } - - if (strlen(node->request_url) > 0 || - strlen(node->host_url) > 0) - { - ret = af_match_by_url(flow, node); - } - else if (node->pos_num > 0) - { - ret = af_match_by_pos(flow, node); - } - else - { - AF_DEBUG("node is empty, match sport:%d,dport:%d, appid = %d\n", - node->sport, node->dport, node->app_id); - return AF_TRUE; - } - return ret; -} - -int app_filter_match(flow_info_t *flow) -{ - af_feature_node_t *n, *node; - af_client_info_t *client = NULL; - feature_list_read_lock(); - if (!list_empty(&af_feature_head)) - { - list_for_each_entry_safe(node, n, &af_feature_head, head) - { - if (af_match_one(flow, node)) - { - flow->app_id = node->app_id; - strncpy(flow->app_name, node->app_name, sizeof(flow->app_name) - 1); - client = find_af_client_by_ip(flow->src); - if (!client) - { - goto EXIT; - } - if (is_user_match_enable() && !find_af_mac(client->mac)) - { - goto EXIT; - } - if (af_get_app_status(node->app_id)) - { - flow->drop = AF_TRUE; - feature_list_read_unlock(); - return AF_TRUE; - } - else - { - goto EXIT; - } - } - } - } -EXIT: - flow->drop = AF_FALSE; - feature_list_read_unlock(); - return AF_FALSE; -} - -#define NF_DROP_BIT 0x80000000 - -static int af_get_visit_index(af_client_info_t *node, int app_id) -{ - int i; - for (i = 0; i < MAX_RECORD_APP_NUM; i++) - { - if (node->visit_info[i].app_id == app_id || node->visit_info[i].app_id == 0) - { - return i; - } - } - // default 0 - return 0; -} - -int af_update_client_app_info(af_client_info_t *node, int app_id, int drop) -{ - int index = -1; - if (!node) - return -1; - - index = af_get_visit_index(node, app_id); - if (index < 0 || index >= MAX_RECORD_APP_NUM) - return 0; - node->visit_info[index].total_num++; - if (drop) - node->visit_info[index].drop_num++; - node->visit_info[index].app_id = app_id; - node->visit_info[index].latest_time = af_get_timestamp_sec(); - node->visit_info[index].latest_action = drop; - return 0; -} - -int af_send_msg_to_user(char *pbuf, uint16_t len); -int af_match_bcast_packet(flow_info_t *f){ - if (!f) - return 0; - if (0 == f->src || 0 == f->dst - || 0xffffffff == f->dst || 0 == f->dst) - return 1; - return 0; -} - -int af_match_local_packet(flow_info_t *f){ - if (!f) - return 0; - if (0x0100007f == f->src || 0x0100007f == f->dst){ - return 1; - } - return 0; -} - -int dpi_main(struct sk_buff *skb, flow_info_t *flow){ - dpi_http_proto(flow); - dpi_https_proto(flow); - if (TEST_MODE()) - dump_flow_info(flow); - return 0; -} - -void af_get_smac(struct sk_buff *skb, u_int8_t *smac){ - struct ethhdr *ethhdr = NULL; - ethhdr = eth_hdr(skb); - if (ethhdr) - memcpy(smac, ethhdr->h_source, ETH_ALEN); - else - memcpy(smac, &skb->cb[40], ETH_ALEN); -} - -u_int32_t app_filter_hook_bypass_handle(struct sk_buff *skb, struct net_device *dev){ - flow_info_t flow; - u_int8_t smac[ETH_ALEN]; - af_client_info_t *client = NULL; - - if (!skb || !dev) - return NF_ACCEPT; - - if (skb->len > MAX_BYPASS_DPI_PKT_LEN) - return NF_ACCEPT; - - memset((char *)&flow, 0x0, sizeof(flow_info_t)); - if (parse_flow_proto(skb, &flow) < 0) - return NF_ACCEPT; - if (af_match_bcast_packet(&flow) || af_match_local_packet(&flow)) - return NF_ACCEPT; - - af_get_smac(skb, smac); - - AF_CLIENT_LOCK_W(); - client = find_and_add_af_client(smac); - if (!client){ - AF_CLIENT_UNLOCK_W(); - return NF_ACCEPT; - } - client->update_jiffies = jiffies; - AF_CLIENT_UNLOCK_W(); - - if (0 != dpi_main(skb, &flow)) - return NF_ACCEPT; - - client->ip = flow.src; - app_filter_match(&flow); - if (flow.app_id != 0){ - af_update_client_app_info(client, flow.app_id, flow.drop); - } - if (flow.drop) - { - return NF_DROP; - } - return NF_ACCEPT; -} - -u_int32_t app_filter_hook_gateway_handle(struct sk_buff *skb, struct net_device *dev){ - unsigned long long total_packets = 0; - flow_info_t flow; - enum ip_conntrack_info ctinfo; - struct nf_conn *ct = NULL; - struct nf_conn_acct *acct; - af_client_info_t *client = NULL; - int app_id = 0; - int drop = 0; - - memset((char *)&flow, 0x0, sizeof(flow_info_t)); - if (parse_flow_proto(skb, &flow) < 0) - return NF_ACCEPT; - - ct = nf_ct_get(skb, &ctinfo); - if (ct == NULL || !nf_ct_is_confirmed(ct)) - return NF_ACCEPT; - - AF_CLIENT_LOCK_R(); - client = find_af_client_by_ip(flow.src); - if (!client){ - AF_CLIENT_UNLOCK_R(); - return NF_ACCEPT; - } - client->update_jiffies = jiffies; - AF_CLIENT_UNLOCK_R(); - - if (ct->mark != 0) - { - app_id = ct->mark & (~NF_DROP_BIT); - if (app_id > 1000 && app_id < 9999){ - if (NF_DROP_BIT == (ct->mark & NF_DROP_BIT)) - drop = 1; - AF_CLIENT_LOCK_W(); - af_update_client_app_info(client, app_id, drop); - AF_CLIENT_UNLOCK_W(); - - if (drop){ - return NF_DROP; - } - } - } - acct = nf_conn_acct_find(ct); - if(!acct) - return NF_ACCEPT; - total_packets = (unsigned long long)atomic64_read(&acct->counter[IP_CT_DIR_ORIGINAL].packets) - + (unsigned long long)atomic64_read(&acct->counter[IP_CT_DIR_REPLY].packets); - - if(total_packets > MAX_DPI_PKT_NUM) - return NF_ACCEPT; - - if (0 != dpi_main(skb, &flow)) - return NF_ACCEPT; - - app_filter_match(&flow); - - if (flow.app_id != 0) - { - ct->mark = flow.app_id; - AF_CLIENT_LOCK_W(); - af_update_client_app_info(client, flow.app_id, flow.drop); - AF_CLIENT_UNLOCK_W(); - AF_LMT_INFO("match %s %pI4(%d)--> %pI4(%d) len = %d, %d\n ", IPPROTO_TCP == flow.l4_protocol ? "tcp" : "udp", - &flow.src, flow.sport, &flow.dst, flow.dport, skb->len, flow.app_id); - } - if (flow.drop) - { - ct->mark |= NF_DROP_BIT; - AF_LMT_INFO("##Drop app %s flow, appid is %d\n", flow.app_name, flow.app_id); - return NF_DROP; - } - return NF_ACCEPT; -} - - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) -static u_int32_t app_filter_hook(void *priv, - struct sk_buff *skb, - const struct nf_hook_state *state) -{ -#else -static u_int32_t app_filter_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) -{ -#endif - if (!g_oaf_enable) - return NF_ACCEPT; - if (AF_MODE_BYPASS == af_work_mode) - return NF_ACCEPT; - return app_filter_hook_gateway_handle(skb, skb->dev); -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) -static u_int32_t app_filter_by_pass_hook(void *priv, - struct sk_buff *skb, - const struct nf_hook_state *state) -{ -#else -static u_int32_t app_filter_by_pass_hook(unsigned int hook, - struct sk_buff *skb, - const struct net_device *in, - const struct net_device *out, - int (*okfn)(struct sk_buff *)) -{ -#endif - if (!g_oaf_enable) - return NF_ACCEPT; - if (AF_MODE_GATEWAY == af_work_mode) - return NF_ACCEPT; - return app_filter_hook_bypass_handle(skb, skb->dev); -} - - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0) -static struct nf_hook_ops app_filter_ops[] __read_mostly = { - { - .hook = app_filter_hook, - .pf = PF_INET, - .hooknum = NF_INET_FORWARD, - .priority = NF_IP_PRI_MANGLE + 1, - - }, - { - .hook = app_filter_by_pass_hook, - .pf = PF_INET, - .hooknum = NF_INET_PRE_ROUTING, - .priority = NF_IP_PRI_MANGLE + 1, - }, -}; -#else -static struct nf_hook_ops app_filter_ops[] __read_mostly = { - { - .hook = app_filter_hook, - .owner = THIS_MODULE, - .pf = PF_INET, - .hooknum = NF_INET_FORWARD, - .priority = NF_IP_PRI_MANGLE + 1, - }, -}; -#endif - - -struct timer_list oaf_timer; -int report_flag = 0; -#define OAF_TIMER_INTERVAL 1 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) -static void oaf_timer_func(struct timer_list *t) -#else -static void oaf_timer_func(unsigned long ptr) -#endif -{ - static int count = 0; - if (count % 60 == 0) - check_client_expire(); - if (count % 60 == 0 || report_flag) - { - report_flag = 0; - af_visit_info_report(); - } - count++; - mod_timer(&oaf_timer, jiffies + OAF_TIMER_INTERVAL * HZ); -} - -void init_oaf_timer(void) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) - timer_setup(&oaf_timer, oaf_timer_func, 0); -#else - setup_timer(&oaf_timer, oaf_timer_func, OAF_TIMER_INTERVAL * HZ); -#endif - mod_timer(&oaf_timer, jiffies + OAF_TIMER_INTERVAL * HZ); - AF_INFO("init oaf timer...ok"); -} - -void fini_oaf_timer(void) -{ - del_timer_sync(&oaf_timer); - AF_INFO("del oaf timer...ok"); -} - -static struct sock *oaf_sock = NULL; - -int af_send_msg_to_user(char *pbuf, uint16_t len) -{ - struct sk_buff *nl_skb; - struct nlmsghdr *nlh; - //todo: kmalloc - char msg_buf[MAX_OAF_NL_MSG_LEN] = {0}; - struct af_msg_hdr *hdr = NULL; - char *p_data = NULL; - int ret; - if (len >= MAX_OAF_NL_MSG_LEN) - return -1; - - memset(msg_buf, 0x0, sizeof(msg_buf)); - nl_skb = nlmsg_new(len + sizeof(struct af_msg_hdr), GFP_ATOMIC); - if (!nl_skb) - { - return -1; - } - - nlh = nlmsg_put(nl_skb, 0, 0, OAF_NETLINK_ID, len + sizeof(struct af_msg_hdr), 0); - if (nlh == NULL) - { - nlmsg_free(nl_skb); - return -1; - } - - hdr = (struct af_msg_hdr *)msg_buf; - hdr->magic = 0xa0b0c0d0; - hdr->len = len; - p_data = msg_buf + sizeof(struct af_msg_hdr); - memcpy(p_data, pbuf, len); - memcpy(nlmsg_data(nlh), msg_buf, len + sizeof(struct af_msg_hdr)); - ret = netlink_unicast(oaf_sock, nl_skb, 999, MSG_DONTWAIT); - return ret; -} - -static void oaf_user_msg_handle(af_msg_t *msg) -{ - switch (msg->action) - { - case AF_MSG_INIT: - af_client_list_reset_report_num(); - report_flag = 1; - break; - default: - break; - } -} -static void oaf_msg_rcv(struct sk_buff *skb) -{ - struct nlmsghdr *nlh = NULL; - char *umsg = NULL; - void *udata = NULL; - struct af_msg_hdr *af_hdr = NULL; - if (skb->len >= nlmsg_total_size(0)) - { - nlh = nlmsg_hdr(skb); - umsg = NLMSG_DATA(nlh); - af_hdr = (struct af_msg_hdr *)umsg; - if (af_hdr->magic != 0xa0b0c0d0) - return; - if (af_hdr->len <= 0 || af_hdr->len >= MAX_OAF_NETLINK_MSG_LEN) - return; - udata = umsg + sizeof(struct af_msg_hdr); - - if (udata) - oaf_user_msg_handle((af_msg_t *)udata); - } -} - -int netlink_oaf_init(void) -{ - struct netlink_kernel_cfg nl_cfg = {0}; - nl_cfg.input = oaf_msg_rcv; - oaf_sock = netlink_kernel_create(&init_net, OAF_NETLINK_ID, &nl_cfg); - - if (NULL == oaf_sock) - { - AF_ERROR("init oaf netlink failed, id=%d\n", OAF_NETLINK_ID); - return -1; - } - AF_INFO("init oaf netlink ok, id = %d\n", OAF_NETLINK_ID); - return 0; -} - -static int __init app_filter_init(void) -{ - printk("appfilter version:" AF_VERSION "\n"); - if (0 != load_feature_config()) - { - printk("load feature failed\n"); - return -1; - } - - netlink_oaf_init(); - af_log_init(); - af_register_dev(); - af_mac_list_init(); - af_init_app_status(); - init_af_client_procfs(); - af_client_init(); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) - nf_register_net_hooks(&init_net, app_filter_ops, ARRAY_SIZE(app_filter_ops)); -#else - nf_register_hooks(app_filter_ops, ARRAY_SIZE(app_filter_ops)); -#endif - init_oaf_timer(); - AF_INFO("init app filter ........ok\n"); - return 0; -} - -static void app_filter_fini(void) -{ - AF_INFO("app filter module exit\n"); - fini_oaf_timer(); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) - nf_unregister_net_hooks(&init_net, app_filter_ops, ARRAY_SIZE(app_filter_ops)); -#else - nf_unregister_hooks(app_filter_ops, ARRAY_SIZE(app_filter_ops)); -#endif - - af_clean_feature_list(); - af_mac_list_clear(); - af_unregister_dev(); - af_log_exit(); - af_client_exit(); - finit_af_client_procfs(); - if (oaf_sock) - netlink_kernel_release(oaf_sock); - return; -} - -module_init(app_filter_init); -module_exit(app_filter_fini); diff --git a/OpenAppFilter/oaf/src/app_filter.h b/OpenAppFilter/oaf/src/app_filter.h deleted file mode 100644 index 2577fea..0000000 --- a/OpenAppFilter/oaf/src/app_filter.h +++ /dev/null @@ -1,172 +0,0 @@ -#ifndef APP_FILTER_H -#define APP_FILTER_H - -#define AF_VERSION "5.0" -#define AF_FEATURE_CONFIG_FILE "/tmp/feature.cfg" - -#define MAX_DPI_PKT_NUM 64 -#define MIN_HTTP_DATA_LEN 16 -#define MAX_APP_NAME_LEN 64 -#define MAX_FEATURE_NUM_PER_APP 16 -#define MIN_FEATURE_STR_LEN 16 -#define MAX_FEATURE_STR_LEN 128 -#define MAX_HOST_URL_LEN 128 -#define MAX_REQUEST_URL_LEN 128 -#define MAX_FEATURE_BITS 16 -#define MAX_POS_INFO_PER_FEATURE 16 -#define MAX_FEATURE_LINE_LEN 256 -#define MIN_FEATURE_LINE_LEN 16 -#define MAX_URL_MATCH_LEN 64 -#define MAX_BYPASS_DPI_PKT_LEN 600 - -//#define CONFIG_KERNEL_FUNC_TEST 1 - -#define HTTP_GET_METHOD_STR "GET" -#define HTTP_POST_METHOD_STR "POST" -#define HTTP_HEADER "HTTP" -#define NIPQUAD(addr) \ - ((unsigned char *)&addr)[0], \ - ((unsigned char *)&addr)[1], \ - ((unsigned char *)&addr)[2], \ - ((unsigned char *)&addr)[3] -#define NIPQUAD_FMT "%u.%u.%u.%u" -#define MAC_ARRAY(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] -#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x" - -#define AF_TRUE 1 -#define AF_FALSE 0 - -#define AF_APP_TYPE(a) (a) / 1000 -#define AF_APP_ID(a) (a) % 1000 -#define MAC_ADDR_LEN 6 - -#define HTTPS_URL_OFFSET 9 -#define HTTPS_LEN_OFFSET 7 - -enum AF_FEATURE_PARAM_INDEX{ - AF_PROTO_PARAM_INDEX, - AF_SRC_PORT_PARAM_INDEX, - AF_DST_PORT_PARAM_INDEX, - AF_HOST_URL_PARAM_INDEX, - AF_REQUEST_URL_PARAM_INDEX, - AF_DICT_PARAM_INDEX, -}; - - -#define OAF_NETLINK_ID 29 -#define MAX_OAF_NL_MSG_LEN 1024 - -enum E_MSG_TYPE{ - AF_MSG_INIT, - AF_MSG_MAX -}; -enum AF_WORK_MODE { - AF_MODE_GATEWAY, - AF_MODE_BYPASS, - AF_MODE_BRIDGE, -}; - -typedef struct af_msg{ - int action; - void *data; -}af_msg_t; - -struct af_msg_hdr{ - int magic; - int len; -}; - -enum e_http_method{ - HTTP_METHOD_GET = 1, - HTTP_METHOD_POST, -}; -typedef struct http_proto{ - int match; - int method; - char *url_pos; - int url_len; - char *host_pos; - int host_len; - char *data_pos; - int data_len; -}http_proto_t; - -typedef struct https_proto{ - int match; - char *url_pos; - int url_len; -}https_proto_t; - -typedef struct flow_info{ - struct nf_conn *ct; - u_int32_t src; - u_int32_t dst; - int l4_protocol; - u_int16_t sport; - u_int16_t dport; - unsigned char *l4_data; - int l4_len; - http_proto_t http; - https_proto_t https; - u_int32_t app_id; - u_int8_t app_name[MAX_APP_NAME_LEN]; - u_int8_t drop; - u_int8_t dir; - u_int16_t total_len; -}flow_info_t; - - - -typedef struct af_pos_info{ - int pos; - unsigned char value; -}af_pos_info_t; - -#define MAX_PORT_RANGE_NUM 5 - -typedef struct range_value -{ - int not ; - int start; - int end; -} range_value_t; - -typedef struct port_info -{ - u_int8_t mode; // 0: match, 1: not match - int num; - range_value_t range_list[MAX_PORT_RANGE_NUM]; -} port_info_t; - -typedef struct af_feature_node{ - struct list_head head; - u_int32_t app_id; - char app_name[MAX_APP_NAME_LEN]; - char feature_str[MAX_FEATURE_NUM_PER_APP][MAX_FEATURE_STR_LEN]; - u_int32_t proto; - u_int32_t sport; - u_int32_t dport; - port_info_t dport_info; - char host_url[MAX_HOST_URL_LEN]; - char request_url[MAX_REQUEST_URL_LEN]; - int pos_num; - af_pos_info_t pos_info[MAX_POS_INFO_PER_FEATURE]; -}af_feature_node_t; - -typedef struct af_mac_info { - struct list_head hlist; - unsigned char mac[MAC_ADDR_LEN]; -}af_mac_info_t; - -int af_register_dev(void); -void af_unregister_dev(void); -void af_init_app_status(void); -int af_get_app_status(int appid); -int regexp_match(char *reg, char *text); -void af_mac_list_init(void); -void af_mac_list_clear(void); -af_mac_info_t * find_af_mac(unsigned char *mac); -int is_user_match_enable(void); -extern int g_oaf_enable; - -#endif diff --git a/OpenAppFilter/oaf/src/app_filter_config.c b/OpenAppFilter/oaf/src/app_filter_config.c deleted file mode 100644 index 58a07d9..0000000 --- a/OpenAppFilter/oaf/src/app_filter_config.c +++ /dev/null @@ -1,455 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "cJSON.h" -#include "app_filter.h" -#include "af_utils.h" -#include "af_log.h" -#define AF_MAX_APP_TYPE_NUM 16 -#define AF_MAX_APP_NUM 256 -#define AF_DEV_NAME "appfilter" - -DEFINE_RWLOCK(af_rule_lock); - -#define af_rule_read_lock() read_lock_bh(&af_rule_lock); -#define af_rule_read_unlock() read_unlock_bh(&af_rule_lock); -#define af_rule_write_lock() write_lock_bh(&af_rule_lock); -#define af_rule_write_unlock() write_unlock_bh(&af_rule_lock); - -static struct mutex af_cdev_mutex; -struct af_config_dev -{ - dev_t id; - struct cdev char_dev; - struct class *c; -}; -struct af_config_dev g_af_dev; - -struct af_cdev_file -{ - size_t size; - char buf[256 << 10]; -}; - -enum AF_CONFIG_CMD -{ - AF_CMD_ADD_APPID = 1, - AF_CMD_DEL_APPID, - AF_CMD_CLEAN_APPID, - AF_CMD_SET_MAC_LIST, -}; - -char g_app_id_array[AF_MAX_APP_TYPE_NUM][AF_MAX_APP_NUM] = {0}; - -void af_show_app_status(void) -{ - int i, j; - AF_DEBUG("#########show app status##########\n"); - for (i = 0; i < AF_MAX_APP_TYPE_NUM; i++) - { - for (j = 0; j < AF_MAX_APP_NUM; j++) - { - - af_rule_read_lock(); - if (g_app_id_array[i][j] == AF_TRUE) - { - AF_DEBUG("%d, %d\n", i, j); - } - af_rule_read_unlock(); - } - } - - AF_DEBUG("\n\n\n"); -} - -int af_change_app_status(cJSON *data_obj, int status) -{ - int i; - int id; - int type; - cJSON *appid_arr = NULL; - if (!data_obj) - { - AF_ERROR("data obj is null\n"); - return -1; - } - appid_arr = cJSON_GetObjectItem(data_obj, "apps"); - if (!appid_arr) - { - AF_ERROR("apps obj is null\n"); - return -1; - } - for (i = 0; i < cJSON_GetArraySize(appid_arr); i++) - { - cJSON *appid_obj = cJSON_GetArrayItem(appid_arr, i); - if (!appid_obj) - return -1; - id = AF_APP_ID(appid_obj->valueint); - type = AF_APP_TYPE(appid_obj->valueint); - af_rule_write_lock(); - g_app_id_array[type][id] = status; - af_rule_write_unlock(); - } - - return 0; -} -DEFINE_RWLOCK(af_mac_lock); -#define MAX_AF_MAC_HASH_SIZE 64 -#define AF_MAC_LOCK_R() read_lock_bh(&af_mac_lock); -#define AF_MAC_UNLOCK_R() read_unlock_bh(&af_mac_lock); -#define AF_MAC_LOCK_W() write_lock_bh(&af_mac_lock); -#define AF_MAC_UNLOCK_W() write_unlock_bh(&af_mac_lock); - -u32 total_mac = 0; -struct list_head af_mac_list_table[MAX_AF_MAC_HASH_SIZE]; - -void af_mac_list_init(void) -{ - int i; - AF_MAC_LOCK_W(); - for (i = 0; i < MAX_AF_MAC_HASH_SIZE; i++) - { - INIT_LIST_HEAD(&af_mac_list_table[i]); - } - AF_MAC_UNLOCK_W(); - AF_INFO("client list init......ok\n"); -} - -void af_mac_list_clear(void) -{ - int i; - af_mac_info_t *p = NULL; - char mac_str[32] = {0}; - - AF_DEBUG("clean list\n"); - AF_MAC_LOCK_W(); - for (i = 0; i < MAX_AF_MAC_HASH_SIZE; i++) - { - while (!list_empty(&af_mac_list_table[i])) - { - p = list_first_entry(&af_mac_list_table[i], af_mac_info_t, hlist); - memset(mac_str, 0x0, sizeof(mac_str)); - sprintf(mac_str, MAC_FMT, MAC_ARRAY(p->mac)); - AF_DEBUG("clean mac:%s\n", mac_str); - list_del(&(p->hlist)); - kfree(p); - } - } - total_mac = 0; - AF_MAC_UNLOCK_W(); -} - -int hash_mac(unsigned char *mac) -{ - if (!mac) - return 0; - else - return mac[5] & (MAX_AF_MAC_HASH_SIZE - 1); -} - -af_mac_info_t *find_af_mac(unsigned char *mac) -{ - af_mac_info_t *node; - unsigned int index; - - index = hash_mac(mac); - list_for_each_entry(node, &af_mac_list_table[index], hlist) - { - if (0 == memcmp(node->mac, mac, 6)) - { - AF_DEBUG("match mac:" MAC_FMT "\n", MAC_ARRAY(node->mac)); - return node; - } - } - return NULL; -} - -static af_mac_info_t * -af_mac_add(unsigned char *mac) -{ - af_mac_info_t *node; - int index = 0; - - node = (af_mac_info_t *)kmalloc(sizeof(af_mac_info_t), GFP_ATOMIC); - if (node == NULL) - { - AF_ERROR("kmalloc failed\n"); - return NULL; - } - - memset(node, 0, sizeof(af_mac_info_t)); - memcpy(node->mac, mac, MAC_ADDR_LEN); - - index = hash_mac(mac); - - AF_LMT_INFO("new client mac=" MAC_FMT "\n", MAC_ARRAY(node->mac)); - total_mac++; - list_add(&(node->hlist), &af_mac_list_table[index]); - return node; -} - -int is_user_match_enable(void) -{ - return total_mac > 0; -} -int mac_to_hex(u8 *mac, u8 *mac_hex) -{ - u32 mac_tmp[MAC_ADDR_LEN]; - int ret = 0, i = 0; - ret = sscanf(mac, "%02x:%02x:%02x:%02x:%02x:%02x", - (unsigned int *)&mac_tmp[0], - (unsigned int *)&mac_tmp[1], - (unsigned int *)&mac_tmp[2], - (unsigned int *)&mac_tmp[3], - (unsigned int *)&mac_tmp[4], - (unsigned int *)&mac_tmp[5]); - if (MAC_ADDR_LEN != ret) - return -1; - for (i = 0; i < MAC_ADDR_LEN; i++) - { - mac_hex[i] = mac_tmp[i]; - } - return 0; -} -int af_set_mac_list(cJSON *data_obj) -{ - int i; - cJSON *mac_arr = NULL; - u8 mac_hex[MAC_ADDR_LEN] = {0}; - if (!data_obj) - { - AF_ERROR("data obj is null\n"); - return -1; - } - mac_arr = cJSON_GetObjectItem(data_obj, "mac_list"); - if (!mac_arr) - { - AF_ERROR("apps obj is null\n"); - return -1; - } - af_mac_list_clear(); - for (i = 0; i < cJSON_GetArraySize(mac_arr); i++) - { - cJSON *mac_obj = cJSON_GetArrayItem(mac_arr, i); - if (!mac_obj) - { - AF_ERROR("appid obj is null\n"); - return -1; - } - if (-1 == mac_to_hex(mac_obj->valuestring, mac_hex)) - { - continue; - } - af_mac_add(mac_hex); - } - AF_DEBUG("## mac num = %d\n", total_mac); - return 0; -} - -void af_init_app_status(void) -{ - int i, j; - - for (i = 0; i < AF_MAX_APP_TYPE_NUM; i++) - { - for (j = 0; j < AF_MAX_APP_NUM; j++) - { - af_rule_write_lock(); - g_app_id_array[i][j] = AF_FALSE; - af_rule_write_unlock(); - } - } -} -int af_get_app_status(int appid) -{ - int status = 0; - int id = AF_APP_ID(appid); - int type = AF_APP_TYPE(appid); - af_rule_read_lock(); - status = g_app_id_array[type][id]; - af_rule_read_unlock(); - return status; -} -/* -add: -{ - "op":1, - "data"{ - "apps":[] - } -} -clean -{ - "op":3, -} - -*/ -int af_config_handle(char *config, unsigned int len) -{ - cJSON *config_obj = NULL; - cJSON *cmd_obj = NULL; - cJSON *data_obj = NULL; - if (!config || len == 0) - { - AF_ERROR("config or len is invalid\n"); - return -1; - } - config_obj = cJSON_Parse(config); - if (!config_obj) - { - AF_ERROR("config_obj is NULL\n"); - return -1; - } - cmd_obj = cJSON_GetObjectItem(config_obj, "op"); - if (!cmd_obj) - { - AF_ERROR("not find op object\n"); - return -1; - } - data_obj = cJSON_GetObjectItem(config_obj, "data"); - - switch (cmd_obj->valueint) - { - case AF_CMD_ADD_APPID: - if (!data_obj) - break; - af_change_app_status(data_obj, AF_TRUE); - break; - case AF_CMD_DEL_APPID: - if (!data_obj) - break; - af_change_app_status(data_obj, AF_FALSE); - break; - case AF_CMD_CLEAN_APPID: - af_init_app_status(); - break; - case AF_CMD_SET_MAC_LIST: - af_set_mac_list(data_obj); - break; - default: - AF_ERROR("invalid cmd %d\n", cmd_obj->valueint); - return -1; - } - af_show_app_status(); - return 0; -} - -static int af_cdev_open(struct inode *inode, struct file *filp) -{ - struct af_cdev_file *file; - file = vzalloc(sizeof(*file)); - if (!file) - return -EINVAL; - - mutex_lock(&af_cdev_mutex); - filp->private_data = file; - return 0; -} - -static ssize_t af_cdev_read(struct file *filp, char *buf, size_t count, loff_t *off) -{ - return 0; -} - -static int af_cdev_release(struct inode *inode, struct file *filp) -{ - struct af_cdev_file *file = filp->private_data; - AF_DEBUG("config size: %d,data = %s\n", (int)file->size, file->buf); - af_config_handle(file->buf, file->size); - filp->private_data = NULL; - mutex_unlock(&af_cdev_mutex); - vfree(file); - return 0; -} - -static ssize_t af_cdev_write(struct file *filp, const char *buffer, size_t count, loff_t *off) -{ - struct af_cdev_file *file = filp->private_data; - int ret; - if (file->size + count > sizeof(file->buf)) - { - AF_ERROR("config overflow, cur_size: %d, block_size: %d, max_size: %d", - (int)file->size, (int)count, (int)sizeof(file->buf)); - return -EINVAL; - } - - ret = copy_from_user(file->buf + file->size, buffer, count); - if (ret != 0) - return -EINVAL; - - file->size += count; - return count; -} - -static struct file_operations af_cdev_ops = { - owner : THIS_MODULE, - release : af_cdev_release, - open : af_cdev_open, - write : af_cdev_write, - read : af_cdev_read, -}; - -int af_register_dev(void) -{ - struct device *dev; - int res; - mutex_init(&af_cdev_mutex); - - res = alloc_chrdev_region(&g_af_dev.id, 0, 1, AF_DEV_NAME); - if (res != 0) - { - return -EINVAL; - } - - cdev_init(&g_af_dev.char_dev, &af_cdev_ops); - res = cdev_add(&g_af_dev.char_dev, g_af_dev.id, 1); - if (res < 0) - { - goto REGION_OUT; - } - - g_af_dev.c = class_create(THIS_MODULE, AF_DEV_NAME); - if (IS_ERR_OR_NULL(g_af_dev.c)) - { - goto CDEV_OUT; - } - - dev = device_create(g_af_dev.c, NULL, g_af_dev.id, NULL, AF_DEV_NAME); - if (IS_ERR_OR_NULL(dev)) - { - goto CLASS_OUT; - } - AF_INFO("register char dev....ok\n"); - - return 0; - -CLASS_OUT: - class_destroy(g_af_dev.c); -CDEV_OUT: - cdev_del(&g_af_dev.char_dev); -REGION_OUT: - unregister_chrdev_region(g_af_dev.id, 1); - - AF_ERROR("register char dev....fail\n"); - return -EINVAL; -} - -void af_unregister_dev(void) -{ - device_destroy(g_af_dev.c, g_af_dev.id); - class_destroy(g_af_dev.c); - cdev_del(&g_af_dev.char_dev); - unregister_chrdev_region(g_af_dev.id, 1); - AF_INFO("unregister char dev....ok\n"); -} diff --git a/OpenAppFilter/oaf/src/cJSON.c b/OpenAppFilter/oaf/src/cJSON.c deleted file mode 100644 index 7dcb2e5..0000000 --- a/OpenAppFilter/oaf/src/cJSON.c +++ /dev/null @@ -1,519 +0,0 @@ -/* - Copyright (c) 2009 Dave Gamble - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -// cJSON -// JSON parser in C. - -#if 0 -#include -#include -#include -#include -#include -#endif - -#include "cJSON.h" - -#include -#include - -#if 0 -#if defined(WINDOWS) || defined(__WIN32__) || defined(WIN32) || defined(_WIN32) -#define strcasecmp stricmp -#define strdup _strdup -#endif -#endif - - -#if 0 -static void *(*cJSON_malloc)(size_t sz) = malloc; -static void *(*cJSON_realloc)(void *ptr, size_t sz) = realloc; -static void (*cJSON_free)(void *ptr) = free; -#endif - -static void *cJSON_malloc(size_t sz) { - return kmalloc(sz, GFP_KERNEL); -} - -static void *cJSON_realloc(void *ptr, size_t sz) -{ - return krealloc(ptr, sz, GFP_KERNEL); -} - -static void cJSON_free(void *ptr) -{ - kfree(ptr); -} - -static char* cJSON_strdup(const char* str) -{ - size_t len; - char* copy; - - len = strlen(str) + 1; - if (!(copy = (char*)cJSON_malloc(len))) return 0; - memcpy(copy,str,len); - return copy; -} - -#if 0 -void cJSON_InitHooks(cJSON_Hooks* hooks) -{ - if (!hooks) { /* Reset hooks */ - cJSON_malloc = malloc; - cJSON_realloc = realloc; - cJSON_free = free; - return; - } - - cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; - cJSON_realloc= (hooks->realloc_fn)?hooks->realloc_fn:realloc; - cJSON_free = (hooks->free_fn)?hooks->free_fn:free; -} -#endif - -// Internal constructor. -static cJSON *cJSON_New_Item(void) -{ - cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); - if (node) memset(node,0,sizeof(cJSON)); - return node; -} - -// Delete a cJSON structure. -void cJSON_Delete(cJSON *c) -{ - cJSON *next; - while (c) - { - next=c->next; - if (c->child) cJSON_Delete(c->child); - if (c->valuestring) cJSON_free(c->valuestring); - if (c->string) cJSON_free(c->string); - cJSON_free(c); - c=next; - } -} - - -/* Parse the input text to generate a number, and populate the result into item. */ -static const char *parse_number(cJSON *item,const char *num) -{ - int n=0,sign=1; - - if (*num=='-') sign=-1,num++; /* Has sign? */ - if (*num=='0') num++; /* is zero */ - if (*num>='1' && *num<='9') do n=(n*10)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */ - item->valueint=(int)n; - item->type=cJSON_Number; - return num; -} - -/* Render the number nicely from the given item into a string. */ -static char *print_number(cJSON *item) -{ - char *str; - str=(char*)cJSON_malloc(21); - if (str) - sprintf(str,"%d",item->valueint); - return str; -} - - -// Parse the input text into an unescaped cstring, and populate item. -static const char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; -static const char *parse_string(cJSON *item,const char *str) -{ - const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc; - if (*str!='\"') return 0; // not a string! - - while (*ptr!='\"' && *ptr>31 && ++len) if (*ptr++ == '\\') ptr++; // Skip escaped quotes. - - out=(char*)cJSON_malloc(len+1); // This is how long we need for the string, roughly. - if (!out) return 0; - - ptr=str+1;ptr2=out; - while (*ptr!='\"' && *ptr>31) - { - if (*ptr!='\\') *ptr2++=*ptr++; - else - { - ptr++; - switch (*ptr) - { - case 'b': *ptr2++='\b'; break; - case 'f': *ptr2++='\f'; break; - case 'n': *ptr2++='\n'; break; - case 'r': *ptr2++='\r'; break; - case 't': *ptr2++='\t'; break; - case 'u': // transcode utf16 to utf8. DOES NOT SUPPORT SURROGATE PAIRS CORRECTLY. - sscanf(ptr+1,"%4x",&uc); // get the unicode char. - len=3;if (uc<0x80) len=1;else if (uc<0x800) len=2;ptr2+=len; - - switch (len) { - case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; - case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; - case 1: *--ptr2 =(uc | firstByteMark[len]); - } - ptr2+=len;ptr+=4; - break; - default: *ptr2++=*ptr; break; - } - ptr++; - } - } - *ptr2=0; - if (*ptr=='\"') ptr++; - item->valuestring=out; - item->type=cJSON_String; - return ptr; -} - -// Render the cstring provided to an escaped version that can be printed. -static char *print_string_ptr(const char *str) -{ - const char *ptr;char *ptr2,*out;int len=0; - - ptr=str;while (*ptr && ++len) {if (*ptr<32 || *ptr=='\"' || *ptr=='\\') len++;ptr++;} - - out=(char*)cJSON_malloc(len+3); - ptr2=out;ptr=str; - *ptr2++='\"'; - while (*ptr) - { - if (*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++; - else - { - *ptr2++='\\'; - switch (*ptr++) - { - case '\\': *ptr2++='\\'; break; - case '\"': *ptr2++='\"'; break; - case '\b': *ptr2++='b'; break; - case '\f': *ptr2++='f'; break; - case '\n': *ptr2++='n'; break; - case '\r': *ptr2++='r'; break; - case '\t': *ptr2++='t'; break; - default: ptr2--; break; // eviscerate with prejudice. - } - } - } - *ptr2++='\"';*ptr2++=0; - return out; -} -// Invote print_string_ptr (which is useful) on an item. -static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);} - -// Predeclare these prototypes. -static const char *parse_value(cJSON *item,const char *value); -static char *print_value(cJSON *item,int depth); -static const char *parse_array(cJSON *item,const char *value); -static char *print_array(cJSON *item,int depth); -static const char *parse_object(cJSON *item,const char *value); -static char *print_object(cJSON *item,int depth); - -// Utility to jump whitespace and cr/lf -static const char *skip(const char *in) {while (in && *in<=32) in++; return in;} - -// Parse an object - create a new root, and populate. -cJSON *cJSON_Parse(const char *value) -{ - cJSON *c=cJSON_New_Item(); - if (!c) return 0; /* memory fail */ - - if (!parse_value(c,skip(value))) {cJSON_Delete(c);return 0;} - return c; -} - -// Render a cJSON item/entity/structure to text. -char *cJSON_Print(cJSON *item) {return print_value(item,0);} - -// Parser core - when encountering text, process appropriately. -static const char *parse_value(cJSON *item,const char *value) -{ - if (!value) return 0; // Fail on null. - if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; } - if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } - if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; } - if (*value=='\"') { return parse_string(item,value); } - if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); } - if (*value=='[') { return parse_array(item,value); } - if (*value=='{') { return parse_object(item,value); } - - return 0; // failure. -} - -// Render a value to text. -static char *print_value(cJSON *item,int depth) -{ - char *out=0; - switch (item->type) - { - case cJSON_NULL: out=cJSON_strdup("null"); break; - case cJSON_False: out=cJSON_strdup("false");break; - case cJSON_True: out=cJSON_strdup("true"); break; - case cJSON_Number: out=print_number(item);break; - case cJSON_String: out=print_string(item);break; - case cJSON_Array: out=print_array(item,depth);break; - case cJSON_Object: out=print_object(item,depth);break; - } - return out; -} - -// Build an array from input text. -static const char *parse_array(cJSON *item,const char *value) -{ - cJSON *child; - if (*value!='[') return 0; // not an array! - - item->type=cJSON_Array; - value=skip(value+1); - if (*value==']') return value+1; // empty array. - - item->child=child=cJSON_New_Item(); - if (!item->child) return 0; // memory fail - value=skip(parse_value(child,skip(value))); // skip any spacing, get the value. - if (!value) return 0; - - while (*value==',') - { - cJSON *new_item; - if (!(new_item=cJSON_New_Item())) return 0; // memory fail - child->next=new_item;new_item->prev=child;child=new_item; - value=skip(parse_value(child,skip(value+1))); - if (!value) return 0; // memory fail - } - - if (*value==']') return value+1; // end of array - return 0; // malformed. -} - -// Render an array to text -static char *print_array(cJSON *item,int depth) -{ - char *out,*ptr,*ret;int len=5; - cJSON *child=item->child; - - out=(char*)cJSON_malloc(len);*out='['; - ptr=out+1;*ptr=0; - while (child) - { - ret=print_value(child,depth+1); - if (!ret) {cJSON_free(out);return 0;} // Check for failure! - len+=strlen(ret)+3; - out=(char*)cJSON_realloc(out,len); - ptr=out+strlen(out); - ptr+=sprintf(ptr,ret); - if (child->next) {*ptr++=',';*ptr++=' ';*ptr=0;} - child=child->next; - cJSON_free(ret); - } - *ptr++=']';*ptr++=0; - return out; -} - -// Build an object from the text. -static const char *parse_object(cJSON *item,const char *value) -{ - cJSON *child; - if (*value!='{') return 0; // not an object! - - item->type=cJSON_Object; - value=skip(value+1); - if (*value=='}') return value+1; // empty array. - - item->child=child=cJSON_New_Item(); - value=skip(parse_string(child,skip(value))); - if (!value) return 0; - child->string=child->valuestring;child->valuestring=0; - if (*value!=':') return 0; // fail! - value=skip(parse_value(child,skip(value+1))); // skip any spacing, get the value. - if (!value) return 0; - - while (*value==',') - { - cJSON *new_item; - if (!(new_item=cJSON_New_Item())) return 0; // memory fail - child->next=new_item;new_item->prev=child;child=new_item; - value=skip(parse_string(child,skip(value+1))); - if (!value) return 0; - child->string=child->valuestring;child->valuestring=0; - if (*value!=':') return 0; // fail! - value=skip(parse_value(child,skip(value+1))); // skip any spacing, get the value. - if (!value) return 0; - } - - if (*value=='}') return value+1; // end of array - return 0; // malformed. -} - -// Render an object to text. -static char *print_object(cJSON *item,int depth) -{ - char *out,*ptr,*ret,*str;int len=7,i; - cJSON *child=item->child; - - depth++;len+=depth;out=(char*)cJSON_malloc(len);*out='{'; - ptr=out+1;*ptr++='\n';*ptr=0; - while (child) - { - str=print_string_ptr(child->string); - if (!str) {cJSON_free(out);return 0;} - ret=print_value(child,depth); - if (!ret) {cJSON_free(str);cJSON_free(out);return 0;} // Check for failure! - len+=strlen(ret)+strlen(str)+4+depth; - out=(char*)cJSON_realloc(out,len); - ptr=out+strlen(out); - for (i=0;inext) *ptr++=','; - *ptr++='\n';*ptr=0; - child=child->next; - cJSON_free(str);cJSON_free(ret); - } - for (i=0;ichild;int i=0;while(c)i++,c=c->next;return i;} -cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item) item--,c=c->next; return c;} -cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && strcasecmp(c->string,string)) c=c->next; return c;} - -// Utility for array list handling. -static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} - -// Add item to array/object. -void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}} -void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);} - -// Create basic types: -cJSON *cJSON_CreateNull() {cJSON *item=cJSON_New_Item();item->type=cJSON_NULL;return item;} -cJSON *cJSON_CreateTrue() {cJSON *item=cJSON_New_Item();item->type=cJSON_True;return item;} -cJSON *cJSON_CreateFalse() {cJSON *item=cJSON_New_Item();item->type=cJSON_False;return item;} -cJSON *cJSON_CreateNumber(int num) {cJSON *item=cJSON_New_Item();item->type=cJSON_Number;item->valueint=(int)num;return item;} -cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();item->type=cJSON_String;item->valuestring=cJSON_strdup(string);return item;} -cJSON *cJSON_CreateArray() {cJSON *item=cJSON_New_Item();item->type=cJSON_Array;return item;} -cJSON *cJSON_CreateObject() {cJSON *item=cJSON_New_Item();item->type=cJSON_Object;return item;} - -// Create Arrays: -cJSON *cJSON_CreateIntArray(int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;ichild=n;else suffix_object(p,n);p=n;}return a;} -cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;ichild=n;else suffix_object(p,n);p=n;}return a;} diff --git a/OpenAppFilter/oaf/src/cJSON.h b/OpenAppFilter/oaf/src/cJSON.h deleted file mode 100644 index 97b701c..0000000 --- a/OpenAppFilter/oaf/src/cJSON.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - Copyright (c) 2009 Dave Gamble - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#ifndef cJSON__h -#define cJSON__h -#include - -// cJSON Types: -#define cJSON_False 0 -#define cJSON_True 1 -#define cJSON_NULL 2 -#define cJSON_Number 3 -#define cJSON_String 4 -#define cJSON_Array 5 -#define cJSON_Object 6 - -// The cJSON structure: -typedef struct cJSON { - struct cJSON *next,*prev; // next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem - struct cJSON *child; // An array or object item will have a child pointer pointing to a chain of the items in the array/object. - - int type; // The type of the item, as above. - - char *valuestring; // The item's string, if type==cJSON_String - int valueint; // The item's number, if type==cJSON_Number - char *string; // The item's name string, if this item is the child of, or is in the list of subitems of an object. -} cJSON; - -typedef struct cJSON_Hooks { - void *(*malloc_fn)(size_t sz); - void *(*realloc_fn)(void *ptr, size_t sz); - void (*free_fn)(void *ptr); -} cJSON_Hooks; - -// Supply malloc, realloc and free functions to cJSON -extern void cJSON_InitHooks(cJSON_Hooks* hooks); - - -// Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. -extern cJSON *cJSON_Parse(const char *value); -// Render a cJSON entity to text for transfer/storage. Free the char* when finished. -extern char *cJSON_Print(cJSON *item); -// Delete a cJSON entity and all subentities. -extern void cJSON_Delete(cJSON *c); - -// Returns the number of items in an array (or object). -extern int cJSON_GetArraySize(cJSON *array); -// Retrieve item number "item" from array "array". Returns NULL if unsuccessful. -extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); -// Get item "string" from object. Case insensitive. -extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); - -// These calls create a cJSON item of the appropriate type. -extern cJSON *cJSON_CreateNull(void); -extern cJSON *cJSON_CreateTrue(void); -extern cJSON *cJSON_CreateFalse(void); -extern cJSON *cJSON_CreateNumber(int num); -extern cJSON *cJSON_CreateString(const char *string); -extern cJSON *cJSON_CreateArray(void); -extern cJSON *cJSON_CreateObject(void); -extern void cJSON_Minify(char *json); -// These utilities create an Array of count items. -extern cJSON *cJSON_CreateIntArray(int *numbers,int count); - -// Append item to the specified array/object. -extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); -extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); - -#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) -#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) -#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) -#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) -#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) - -#endif diff --git a/OpenAppFilter/oaf/src/regexp.c b/OpenAppFilter/oaf/src/regexp.c deleted file mode 100644 index bd8ef4a..0000000 --- a/OpenAppFilter/oaf/src/regexp.c +++ /dev/null @@ -1,302 +0,0 @@ -#include -#include -#include -#include -#include -//#include "regexp.h" - -typedef enum{CHAR, DOT, BEGIN, END, STAR, PLUS, QUES, LIST, TYPENUM}TYPE; - -typedef struct RE{ - TYPE type; - int ch; - char *ccl; - int nccl; - struct RE *next; -}RE; - -int match_longest = 0; -char *match_first = NULL; - - -static void * getmem(size_t size) -{ - void *tmp; - if((tmp = kmalloc(size, GFP_ATOMIC))==NULL) - { - printk("malloc failed"); - return NULL; - } - return tmp; -} - -static size_t creat_list(char *str, int start, int end) -{ - size_t cnt = end - start + 1; - for(; start <= end ;start++) - *str++ = start; - return (cnt > 0)?cnt:0; -} - -static int in_list(char ch, RE *regexp) -{ - char *str = regexp->ccl; - if(regexp->type != LIST) - return 0; - for(; *str && ch != *str; str++) - ; - return (*str != '\0') ^ regexp->nccl; -} - -static void regexp_free(RE *regexp) -{ - RE *tmp; - for(; regexp; regexp = tmp) - { - tmp = regexp->next; - kfree(regexp); - } -} - -static RE* compile(char *regexp) -{ - RE head, *tail, *tmp; - char *pstr; - int err_flag = 0; - - for(tail = &head; *regexp != '\0' && err_flag == 0; regexp++) - { - tmp = getmem(sizeof(RE)); - switch(*regexp){ - case '\\': - regexp++; - if(*regexp == 'd') - { - tmp->type = LIST; - tmp->nccl = 0; - tmp->ccl = getmem(11); - creat_list(tmp->ccl, '0','9'); - tmp->ccl[11] = '\0'; - }else if(*regexp == 'D') - { - tmp->type = LIST; - tmp->nccl = 1; - tmp->ccl = getmem(11); - creat_list(tmp->ccl, '0','9'); - tmp->ccl[11] = '\0'; - }else - { - tmp->type = CHAR; - tmp->ch = *(regexp + 1); - } - break; - case '.': - tmp->type = DOT; - break; - case '^': - tmp->type = BEGIN; - tmp->ch = '^'; - break; - case '$': - tmp->type = END; - tmp->ch = '$'; - break; - case '*': - tmp->type = STAR; - break; - case '+': - tmp->type = PLUS; - break; - case '?': - tmp->type = QUES; - break; - case '[': - pstr = tmp->ccl = getmem(256); - tmp->nccl = 0; - if(*++regexp == '^') - { - tmp->nccl = 1; - regexp++; - } - while(*regexp != '\0' && *regexp != ']') - { - if(*regexp != '-') - { - *pstr++ = *regexp++; - continue; - } - if(pstr == tmp->ccl || *(regexp + 1) == ']') - { - err_flag = 1; - break; - } - pstr += creat_list(pstr, *(regexp - 1) + 1, *(regexp + 1)); - regexp += 2; - } - *pstr = '\0'; - if(*regexp == '\0') - err_flag = 1; - tmp->type = LIST; - break; - default: - tmp->type = CHAR; - tmp->ch = *regexp; - } - - tail->next = tmp; - tail = tmp; - } - - tail->next = NULL; - if(err_flag) - { - regexp_free(head.next); - return NULL; - } - return head.next; -} - -#define MATCH_ONE(reg, text) \ - (reg->type == DOT || in_list(*text, reg) || *text == reg->ch) -#define MATCH_ONE_P(reg, text) \ - (in_list(*text++, reg) || *(text - 1) == reg->ch || reg->type == DOT) - -static int matchhere(RE *regexp, char *text); - -static int matchstar(RE *cur, RE *regexp, char *text) -{ - do{ - if(matchhere(regexp, text)) - return 1; - }while(*text != '\0' && MATCH_ONE_P(cur, text)); - return 0; -} - -static int matchstar_l(RE *cur, RE *regexp, char *text) -{ - char *t; - for(t = text; *t != '\0' && MATCH_ONE(cur, t); t++) - ; - do{ - if(matchhere(regexp, t)) - return 1; - }while(t-- > text); - return 0; -} - -static int matchplus(RE *cur, RE *regexp, char *text) -{ - while(*text != '\0' && MATCH_ONE_P(cur, text)) - { - if(matchhere(regexp, text)) - return 1; - } - return 0; -} - -static int matchplus_l(RE *cur, RE *regexp, char *text) -{ - char *t; - for(t = text; *t != '\0' && MATCH_ONE(cur, t); t++) - ; - for(; t > text; t--) - { - if(matchhere(regexp, t)) - return 1; - } - return 0; -} - -static int matchques(RE *cur, RE *regexp, char *text) -{ - int cnt = 1; - char *t = text; - if(*t != '\0' && cnt-- && MATCH_ONE(cur, t)) - t++; - do{ - if(matchhere(regexp, t)) - return 1; - }while(t-- > text); - return 0; -} - -static int (*matchfun[TYPENUM][2])(RE *, RE *, char *) = { - 0, 0, 0, 0, 0, 0, 0, 0, - matchstar, matchstar_l, - matchplus, matchplus_l, - matchques, matchques, -}; - -static int matchhere(RE *regexp, char *text) -{ - if(regexp == NULL) - return 1; - if(regexp->type == END && regexp->next == NULL) - return *text == '\0'; - if(regexp->next && matchfun[regexp->next->type][match_longest]) - return matchfun[regexp->next->type][match_longest](regexp, regexp->next->next, text); - - if(*text != '\0' && MATCH_ONE(regexp, text)) - return matchhere(regexp->next, text + 1); - return 0; -} - -/* - * return value: - * -1 error - * 0 not match - * 1 matched - */ -int regexp_match(char *reg, char *text) -{ - int ret; - RE *regexp = compile(reg); - if(regexp == NULL) - return -1; - - if(regexp->type == BEGIN) - { - ret = matchhere(regexp->next, text); - goto out; - } - - do{ - if(ret = matchhere(regexp, text)) - { - goto out; - } - }while(*text++ != '\0'); - -out: - regexp_free(regexp); - return ret; -} - - -void TEST_reg_func(char *reg, char * str, int ret) -{ - - if (ret != regexp_match(reg, str)) { - if (reg) - printk("reg = %s,", reg); - else - printk("reg = null"); - if (str) - printk("str = %s ", str); - else - printk("str= null"); - printk("error, unit test.... failed, ret = %d\n",ret); - } - else { - if (reg && str) - printk("[unit test] %s %s......ok,ret = %d\n", reg, str, ret); - } -} - -void TEST_regexp(void) -{ - TEST_reg_func(".*baidu.com$", "www.baidu.com", 1); - TEST_reg_func("^sina.com", "www.sina.com.cn", 0); - TEST_reg_func("^sina.com", "sina.com.cn", 1); - TEST_reg_func(".*baidu.com$", "www.baidu.com223", 0); -} diff --git a/OpenAppFilter/open-app-filter/Makefile b/OpenAppFilter/open-app-filter/Makefile deleted file mode 100644 index 9d574be..0000000 --- a/OpenAppFilter/open-app-filter/Makefile +++ /dev/null @@ -1,60 +0,0 @@ - -include $(TOPDIR)/rules.mk - -PKG_NAME:=appfilter -PKG_VERSION:=5.0 -PKG_RELEASE:=1 - -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) - - -include $(INCLUDE_DIR)/package.mk -#include $(INCLUDE_DIR)/kernel.mk - -define Package/appfilter - SECTION:=Derry Apps - CATEGORY:=Derry Apps - DEPENDS:=+libubox +libubus +libuci +libpthread +libjson-c +libblobmsg-json - TITLE:=App filter userspace module -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - cp -rf ./src/* $(PKG_BUILD_DIR) -endef - -define Build/Compile - $(MAKE) -C $(PKG_BUILD_DIR)/ \ - CC="$(TARGET_CROSS)gcc" \ - CFLAGS="$(TARGET_CFLAGS)" \ - LIBS="$(TARGET_LDFLAGS) -lm -lpthread -lubox -luci -lubus -ljson-c -lblobmsg_json" \ - all -endef - - -define Build/Compile/Default - -endef - -define Package/appfilter/description - open appfilter app -endef - - -define Package/appfilter/install - echo "install" - $(INSTALL_DIR) $(1)/usr/bin $(1)/etc/init.d - $(INSTALL_DIR) $(1)/etc/appfilter - $(INSTALL_DIR) $(1)/etc/config - $(CP) ./files/*.cfg $(1)/etc/appfilter/ - $(CP) ./files/*.txt $(1)/etc/appfilter/ - $(INSTALL_BIN) ./files/appfilter.init $(1)/etc/init.d/appfilter - $(INSTALL_BIN) ./files/oaf_rule $(1)/usr/bin - $(INSTALL_BIN) ./files/gen_class.sh $(1)/usr/bin - $(INSTALL_BIN) ./files/appfilter.config $(1)/etc/config/appfilter - $(INSTALL_BIN) $(PKG_BUILD_DIR)/oafd $(1)/usr/bin -endef - - -$(eval $(call BuildPackage,appfilter)) - diff --git a/OpenAppFilter/open-app-filter/files/app_class.txt b/OpenAppFilter/open-app-filter/files/app_class.txt deleted file mode 100644 index 8e2a09d..0000000 --- a/OpenAppFilter/open-app-filter/files/app_class.txt +++ /dev/null @@ -1,8 +0,0 @@ -1 聊天 -2 游戏 -3 视频 -4 购物 -5 音乐 -6 招聘 -7 下载 -8 常用网站 \ No newline at end of file diff --git a/OpenAppFilter/open-app-filter/files/app_class_en.txt b/OpenAppFilter/open-app-filter/files/app_class_en.txt deleted file mode 100644 index 0b89f4e..0000000 --- a/OpenAppFilter/open-app-filter/files/app_class_en.txt +++ /dev/null @@ -1,8 +0,0 @@ -1 chat -2 game -3 video -4 shopping -5 music -6 recruitment -7 download -8 website \ No newline at end of file diff --git a/OpenAppFilter/open-app-filter/files/appfilter.config b/OpenAppFilter/open-app-filter/files/appfilter.config deleted file mode 100644 index e28cb39..0000000 --- a/OpenAppFilter/open-app-filter/files/appfilter.config +++ /dev/null @@ -1,16 +0,0 @@ -config global global - option enable '0' - option work_mode '0' - -config appfilter appfilter - -config feature feature - -config time 'time' - option time_mode '0' - option days '0 1 2 3 4 5 6' - option start_time '00:00' - option end_time '23:59' - option start_time2 '' - option end_time2 '' -config user user diff --git a/OpenAppFilter/open-app-filter/files/appfilter.init b/OpenAppFilter/open-app-filter/files/appfilter.init deleted file mode 100644 index 0624a37..0000000 --- a/OpenAppFilter/open-app-filter/files/appfilter.init +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/sh /etc/rc.common -. /usr/share/libubox/jshn.sh -. /lib/functions.sh - -START=96 -USE_PROCD=1 -OAFD_BIN="/usr/bin/oafd" -FEATURE_FILE="/tmp/feature.cfg" -CLASS_FILE="/tmp/app_class.txt" -service_triggers() -{ - procd_add_reload_trigger "appfilter" -} - -stop_service(){ - killall -9 oafd - rmmod oaf -} - -start_service(){ - lang=`uci get luci.main.lang` - test -f $FEATURE_FILE && rm $FEATURE_FILE - test -f $CLASS_FILE && rm $CLASS_FILE - if [ x"" == x"$lang" -o x"auto" == x"$lang" ];then - ln -s /etc/appfilter/feature.cfg $FEATURE_FILE - ln -s /etc/appfilter/app_class.txt $CLASS_FILE - else - if [ -f "/etc/appfilter/feature_$lang.cfg" ];then - ln -s /etc/appfilter/feature_$lang.cfg $FEATURE_FILE - else - ln -s /etc/appfilter/feature.cfg $FEATURE_FILE - fi - - if [ -f "/etc/appfilter/app_class_$lang.txt" ];then - ln -s /etc/appfilter/app_class_$lang.txt $CLASS_FILE - else - ln -s /etc/appfilter/app_class.txt $CLASS_FILE - fi - fi - gen_class.sh /tmp/feature.cfg - insmod oaf - /usr/bin/oaf_rule reload - procd_open_instance - procd_set_param respawn 60 5 5 - procd_set_param stderr 1 - procd_set_param command "$OAFD_BIN" - procd_close_instance -} diff --git a/OpenAppFilter/open-app-filter/files/appfilter.lua b/OpenAppFilter/open-app-filter/files/appfilter.lua deleted file mode 100644 index 8cea896..0000000 --- a/OpenAppFilter/open-app-filter/files/appfilter.lua +++ /dev/null @@ -1,262 +0,0 @@ -#!/usr/bin/lua - -local libubus = require "ubus" -local uloop = require "uloop" - -local UBUS_STATUS_OK = 0 -local UBUS_STATUS_INVALID_COMMAND = 1 -local UBUS_STATUS_INVALID_ARGUMENT = 2 -local UBUS_STATUS_METHOD_NOT_FOUND = 3 -local UBUS_STATUS_NOT_FOUND = 4 -local UBUS_STATUS_NO_DATA = 5 -local UBUS_STATUS_PERMISSION_DENIED = 6 -local UBUS_STATUS_TIMEOUT = 7 -local UBUS_STATUS_NOT_SUPPORTED = 8 -local UBUS_STATUS_UNKNOWN_ERROR = 9 -local UBUS_STATUS_CONNECTION_FAILED = 10 -local UBUS_STATUS_ALREADY_EXISTS = 11 - -local cfg_file = "/etc/appfilter/feature.cfg" - -local cfg = {} -local class = {} -local ubus - -cfg.__index = cfg -class.__index = class -function cfg:init(file) - local f = io.open(file, "r") - local t = {} - local t2 = {} - if f then - for line in f:lines() do - table.insert(t, line) - local tt = line:match("#class (%S+)") - if tt then - table.insert(t2, tt) - end - end - setmetatable(t, self) - setmetatable(t2, self) - return t,t2 - end - return nil -end - -function cfg:lookup(o) - if not o then return UBUS_STATUS_INVALID_ARGUMENT end - local tab = self - for _, v in ipairs(tab) do - if v:match(o) then - if v:match("#class") then - local tt = {} - local t2 = {} - local found - for _, t in ipairs(tab) do - repeat - if t:match(o) then - found = true - table.insert(tt, t) - break - end - - if t:match("#class") then - found = false - table.insert(t2, t) - break - end - - if found then - table.insert(tt, t) - else - table.insert(t2, t) - end - until true - end - setmetatable(tt, self) - setmetatable(t2, self) - return tt, t2 - else - return v - end - end - end - return nil -end - -function cfg:lookup_class(m) - if not m then return UBUS_STATUS_INVALID_ARGUMENT end - local t1, t2 = self:lookup(m) - if type(t1) ~= "table" then return nil end - return t1, t2 -end - -function cfg:add_class(m) - if not m then return UBUS_STATUS_INVALID_ARGUMENT end - local f = io.open(cfg_file, "r+") - local tab = self - if f then - io.output(f) - for _, v in ipairs(tab) do - io.write(v) - io.write("\n") - end - io.write("#class "..m) - f:flush() - f:close() - return UBUS_STATUS_OK - else - return UBUS_STATUS_NOT_FOUND - end -end - -function cfg:add_app(m, name, proto, sport, dport, url, request, dict) - if not name then return UBUS_STATUS_INVALID_ARGUMENT end - local id - local offset - local f = io.open(cfg_file, "r+") - io.output(f) - local t1,t2 = self:lookup_class(m) - if t1[#t1] == nil or "" then - offset = 0 - id = math.modf(string.match(t1[#t1-1], "(%d+) %S+:") +1) - else - offset = 1 - id = math.modf(string.match(t1[#t1], "(%d+) %S+:") +1) - end - - local str = string.format("%d %s:[%s;%s;%s;%s;%s;%s]", id, name, proto, sport or "", dport or "", url or "", request or "", dict or "") - table.insert(t1, #t1+offset, str) - if f then - for _, v in ipairs(t2) do - if v then - io.write(v) - io.write("\n") - end - end - for _, v in ipairs(t1) do - if v then - io.write(v) - io.write("\n") - end - end - f:flush() - f:close() - end - return id -end - -function cfg:del_app(id, name) - local t = self - local f = io.open(cfg_file, "r+") - local ret - if id then - for i, v in ipairs(t) do - if v:match(id) then - table.remove(t, i) - ret = i - end - end - - end - - if name then - for i, v in ipairs(t) do - if v:match(name) then - table.remove(t, i) - ret = i - end - end - end - - if f then - io.output(f) - for _, v in ipairs(t) do - io.write(v) - io.write("\n") - end - f:flush() - f:close() - end - return ret -end - -local methods = { - ["appfilter"] = { - add_class = { - function(req, msg) - if not msg.class then return UBUS_STATUS_INVALID_ARGUMENT end - local t = cfg:init(cfg_file) - local ret - if t:lookup_class(msg.class) then return ubus.reply(req, {ret = UBUS_STATUS_ALREADY_EXISTS}) end - ret = t:add_class(msg.class) - ubus.reply(req, {msg = ret}) - end, {class = libubus.STRING} - }, - add_app = { - function (req, msg) - if not msg.class then return UBUS_STATUS_INVALID_ARGUMENT end - if not msg.name then return UBUS_STATUS_INVALID_ARGUMENT end - if not msg.proto then return UBUS_STATUS_INVALID_ARGUMENT end - local t = cfg:init(cfg_file) - local ret - if t:lookup(msg.name) then return ubus.reply(req, {ret = UBUS_STATUS_ALREADY_EXISTS}) end - ret = t:add_app(msg.class, msg.name, msg.proto, msg.sport, msg.dport, msg.url, msg.request, msg.dict) - ubus.reply(req, {ret = ret}) - end,{class = libubus.STRING, name = libubus.STRING, proto = libubus.STRING, sport = libubus.INT32, dport = libubus.INT32, url = libubus.STRING, request = libubus.STRING, dict = libubus.STRING} - }, - del_app = { - function(req, msg) - local t = cfg:init(cfg_file) - local ret = t:del_app(msg.id, msg.name) - ubus.reply(req, {ret = ret}) - end,{id = libubus.INT32, name = libubus.STRING} - }, - list_class = { - function (req, msg) - local _, c = cfg:init(cfg_file) - ubus.reply(req, {result = c}) - end,{} - }, - list_app = { - function (req, msg) - if not msg.class then return UBUS_STATUS_INVALID_ARGUMENT end - local t = cfg:init(cfg_file) - local ret = {} - for i, v in ipairs(t:lookup_class(msg.class)) do - if not v:match("#class") then - local id, name = v:match("(%d+) (%S+):%[") - ret[i-1] = {id = id, name = name} - end - end - ubus.reply(req, {result = ret}) - end,{class = libubus.STRING} - } - } -} - -function ubus_init() - local conn = libubus.connect() - if not conn then - error("Failed to connect to ubus") - end - - conn:add(methods) - - return { - call = function(object, method, params) - return conn:call(object, method, params or {}) - end, - reply = function(req, msg) - conn:reply(req, msg) - end - } -end - -local function main() - uloop.init() - ubus = ubus_init() - uloop.run() -end - -main() \ No newline at end of file diff --git a/OpenAppFilter/open-app-filter/files/appfilter.sh b/OpenAppFilter/open-app-filter/files/appfilter.sh deleted file mode 100644 index b096c9f..0000000 --- a/OpenAppFilter/open-app-filter/files/appfilter.sh +++ /dev/null @@ -1,88 +0,0 @@ -. /usr/share/libubox/jshn.sh -. /lib/functions.sh - -config_apply() -{ - test -z "$1" && return 1 - - if [ -e "/dev/appfilter" ];then - echo "config json str=$1" - echo "$1" >/dev/appfilter - fi -} - -clean_rule() -{ - json_init - echo "clean appfilter rule..." - - json_add_int "op" 3 - json_add_object "data" - json_str=`json_dump` - - config_apply "$json_str" - - json_cleanup -} - -load_rule() -{ - json_init - - config_load appfilter - config_get enable "global" enable - echo "enable = $enable" - if [ x"$enable" != x"1" ];then - echo "appfilter is disabled" - echo 0 >/proc/sys/oaf/enable>/dev/null - return 0 - else - insmod oaf >/dev/null - echo 1 >/proc/sys/oaf/enable - fi - echo "appfilter is enabled" - json_add_int "op" 1 - - json_add_object "data" - json_add_array "apps" - - for file in `ls /tmp/appfilter/*.class` - do - class_name=`echo "$file" | awk -F/ '{print $4}'| awk -F. '{print $1}'` - config_get appid_list "appfilter" "${class_name}apps" - echo "appid_list=$appid_list" - - if ! test -z "$appid_list";then - for appid in $appid_list: - do - json_add_int "" $appid - done - fi - done - - json_str=`json_dump` - config_apply "$json_str" - json_cleanup -} -load_mac_list() -{ - json_init - config_load appfilter - json_add_int "op" 4 - json_add_object "data" - json_add_array "mac_list" - config_get appid_list "user" "users" - echo "appid list=$appid_list" - for appid in $appid_list: - do - echo "appid=$appid" - json_add_string "" $appid - done - json_str=`json_dump` - config_apply "$json_str" - echo "json str=$json_str" - json_cleanup -} -clean_rule -load_rule -load_mac_list diff --git a/OpenAppFilter/open-app-filter/files/feature.cfg b/OpenAppFilter/open-app-filter/files/feature.cfg deleted file mode 100644 index ab4c104..0000000 --- a/OpenAppFilter/open-app-filter/files/feature.cfg +++ /dev/null @@ -1,216 +0,0 @@ -#version v22.3.24 -#id name:[proto;sport;dport;host url;request;dict] -#class chat -1001 QQ:[tcp;;;;;00:02|-1:03,tcp;;;;;02:02|-1:03,tcp;;14000;;;,tcp;;8080;;;00:ca|01:3c,tcp;;;;;00:00|01:00|02:00|03:15] -1002 微信:[tcp;;;;;01:f1|02:03,tcp;;;;;00:ab|01:00|02:00,tcp;;80;;/mmtls;] -1003 微博:[tcp;;443;weibo;;] -1004 陌陌:[tcp;;;momo;;,tcp;;;;;04:2f|05:66|06:65|07:65,tcp;;;;;00:03|01:03|02:00] -1005 支付宝:[tcp;;443;alipay.com;;] -1006 钉钉:[tcp;;;dingtalk;;,tcp;;;;d?host=;,tcp;;;;/man/api;,tcp;;;;/beacon;] -1007 Soul:[tcp;;;soulapp;;] -1008 伊对:[tcp;;;520yidui;;] -1009 探探:[tcp;;;tancdn;;,tcp;;;tantanapp;;] -1010 多闪:[tcp;;;ppkankan;;] - -#class game -2001 王者荣耀:[tcp;;;;;00:33|01:66|02:00|03:09,udp;;;;;00:01|01:02|02:00|03:00] -2003 英雄联盟:[udp;;;;;44:00|45:00|46:00|47:02] -2015 我的世界:[tcp;;443;g79mclobt.nie.netease;;] -2005 欢乐斗地主:[tcp;;8000;;;00:74|01:67|02:77|03:5f] -2006 梦幻西游:[tcp;;;;;00:0e|01:00|02:fe|03:ff] -2007 明日之后:[udp;;;;;00:05|01:09|02:00,tcp;;;;;00:02|01:00|02:00|03:00|04:00|05:00] -2008 QQ飞车:[udp;;;;;00:28|01:28,tcp;;10000;;;00:33|01:66|02:00|03:08] -2009 跑跑卡丁车:[tcp;;8888;;;00:33|01:66|02:00|03:08] -2010 开心消消乐:[tcp;;80;happyelements;;] -2011 狂野飙车:[tcp;;;asphalt9;;] -2012 率土之滨:[tcp;;10001;;;00:00|01:00,tcp;;8001;;;00:00|01:00] -2013 一刀传世:[tcp;;8040;;;00:47|01:45] -2014 第五人格:[tcp;;4010;;;,tcp;;4010;;;,tcp;;4020;;;,tcp;;4030;;;,tcp;;4040;;;,tcp;;4050;;;,tcp;;4060;;;,tcp;;4070;;;,tcp;;4080;;;,tcp;;4090;;;] -2016 皇室战争:[udp;;9339;;;] -2017 炉石传说:[tcp;;3724;;;00:73:01:00:02:00] - - -#class video -3001 抖音短视频:[tcp;;;-dy-;;,tcp;;;-dy.;;,tcp;;;douyin;;] -3002 火山小视频:[tcp;;;.huoshan.com;;,tcp;;;hs.pstatp.com;;,tcp;;;hs.ixigua.com;;] -3003 腾讯视频:[tcp;;443;v.qq.com;;,tcp;;443;video.qq.com;;,tcp;;443;btrace.qq.com;;] -3004 爱奇艺:[tcp;;;iqiyi;;,tcp;;;qy.net;;] -3005 微视:[tcp;;80;;;00:34|01:16|02:75,tcp;;80;weishi.qq.com;;] -3006 斗鱼直播:[tcp;;;douyu;;,tcp;;;douyu;;-2:2f|-1:00] -3008 虎牙直播:[tcp;;;huya;;,udp;;;;;01:00|02:00|03:00|04:23,udp;;;;;01:00|02:00|03:00|04:24] -3009 快手:[tcp;;;kuaishou;;,tcp;;;ksyuncdn.com;;,tcp;;;.gifshow.com;;,tcp;;;yximgs.com;;,tcp;;80;;/ksc;,tcp;;;kwaicdn;;,tcp;;;kwimgs;;] -3010 小红书:[tcp;;;xiaohongshu;;,tcp;;;xhscdn;;] -3011 花椒直播:[tcp;;;huajiao;;] -3012 映客直播:[tcp;;;;.inke.cn;] -3013 YY:[udp;;;;;02:00|03:00|04:08,udp;;;;;00:4f|01:00|02:00] -3014 哔哩哔哩:[tcp;;;bilivideo;;,tcp;;;bilibili.com;;,tcp;;;;;00:47|05:75|06:70|07:67,tcp;;;;/bfs/emote/;,,tcp;;;hdslb.com;;] -3016 芒果tv:[tcp;;443;mgtv;;,tcp;;80;mgtv;;,tcp;;443;hitv;;] -3017 西瓜视频:[tcp;;;ixigua;;,tcp;;443;snsdk;;,tcp;;;xg-p.ixigua;;,tcp;;;bdxigua;;] -3018 搜狐视频:[tcp;;;aty.sohu.com;;,tcp;;;tv.itc.cn;;] -3019 播聊:[tcp;;80;randlove.cn;;,tcp;;;yueliao;;,tcp;;;5glive;;] -3020 咪咕视频:[tcp;;;miguvideo;;,tcp;;;migu.cn;;] -3021 韩剧TV:[tcp;;;hanju.koudaibaobao;;] -3022 人人视频:[tcp;;;rr.tv;;] -3023 央视影音:[tcp;;;cntv;;] -3024 土豆视频:[tcp;;;youku;;,tcp;;;ykimg;;] -3025 最右:[tcp;;;izuiyou;;] -3026 风行视频:[tcp;;;funshion;;] -3027 企鹅电竞:[tcp;;;egame.qq;;,tcp;;;liveplay;;,tcp;;;;pggame;] -3028 波波视频:[tcp;;;miaopai;;] -3029 酷狗短酷:[tcp;;;bssdl.kugou;;] -3030 酷狗直播:[tcp;;;rt-m.kugou;;,tcp;;;kgimg.com;;] - - -#class shopping -4001 淘宝:[tcp;;;taobao;;,tcp;;;alicdn.com;;,tcp;;;tmall.com;;,tcp;;;;;00:d3|01:00,,tcp;;;;;00:d4|01:00,,tcp;;;;;00:d3|01:00] -4002 京东:[tcp;;;360buyimg;;,tcp;;;jd.com;;,tcp;;;jdcdn.com;;,tcp;;;;;00:d5|01:00] -4003 唯品会:[tcp;;;vips-mobile;;,tcp;;;vipshop;;,tcp;;;vip.com;;,tcp;;;vipstatic.com;;,tcp;;;appsimg.com;;] -4004 拼多多:[tcp;;;pinduoduo;;,tcp;;;yangkeduo.com;;,tcp;;;s1p.cdntip.com;;] -4010 饿了么:[tcp;;;eleme;;] -4011 美团:[tcp;;;meituan;;] -4012 闲鱼:[tcp;;;xianyu;;] -4021 转转:[tcp;;;zhuanzhuan;;,tcp;;;zhuanstatic;;] -4005 蘑菇街:[tcp;;;mogujie;;,tcp;;;mogucdn;;,tcp;;;;;00:73|01:ea|02:68|03:fb|04:3f] -4006 苏宁易购:[tcp;;;.suning.;;] -4007 当当网:[tcp;;;.dangdang.com;;] -4008 1号店:[tcp;;;.yhd.com;;] -4009 朴朴超市:[tcp;;;pupumall;;,tcp;;;pupuapi;;] -4013 叮咚买菜:[tcp;;;ddxq.mobi;;] -4014 小米有品:[tcp;;;youpin;;,tcp;;;shopapi.io.mi.com;;] -4015 微店:[tcp;;;weidian;;] -4016 折800:[tcp;;;zhe800.com;;] -4017 HM:[tcp;;;www.hm.com;;,tcp;;;measurement.com;;] -4018 好省:[tcp;;;hzhstb.com;;] -4019 什么值得买:[tcp;;;smzdm.com;;] -4020 大众点评:[tcp;;;dianping.com;;] -4022 网易严选:[tcp;;;yanxuan;;] -4023 识货:[tcp;;;shihuo;;] -4024 考拉海购:[tcp;;;kaola;;] -4025 宜家家居:[tcp;;;ikea.cn;;] -4026 小象优品:[tcp;;;xiaoxiangyoupin;;] - -#class music -5001 网易云音乐:[tcp;;;music.163;;,tcp;;;music.126;;] -5002 QQ音乐:[tcp;;;;^/amobile.music.tc.qq.com;,tcp;;;qqmusic;;] -5003 酷狗音乐:[tcp;;;kugou;;,tcp;;;kgimg;;,tcp;;;fanxing;;] -5004 酷我音乐:[tcp;;;.kuwo.cn;;] -5005 喜马拉雅:[tcp;;;.ximalaya.com;;] -5006 千千音乐:[tcp;;;music.taihe.com;;] -5007 虾米音乐:[tcp;;;xiami;;] -5008 音悦台:[tcp;;;yinyuetai.com;;] -5009 豆瓣FM:[tcp;;;douban.fm;;] -5010 唱吧:[tcp;;;changba.com;;] -5011 音乐随心听:[tcp;;;fm.taihe.com;;] -5012 懒人听书:[tcp;;;lrts.me;;] - -#class employee -6001 前程无忧:[tcp;;;51job;;] -6002 智联招聘:[tcp;;;zhaopin;;] -6003 猎聘:[tcp;;;liepin;;] -6004 赶集网:[tcp;;;58.com;;,tcp;;;58cdn;;] -6005 同城急聘:[tcp;;;xiaomei;;] -6006 领英:[tcp;;;linkedin;;] -6007 斗米:[tcp;;;doumi;;] -6008 看准:[tcp;;;kanzhun.com;;] -6009 应届生求职:[tcp;;;yingjiesheng.com;;] -6010 中华英才网:[tcp;;;chinahr.com;;] -6011 拉勾网:[tcp;;;lagou.com;;] -6012 大街网:[tcp;;;dajie.com;;] -6013 boss直聘:[tcp;;;zhipin.com;;] -6014 实习僧:[tcp;;;shixiseng.com;;] - -#class download -7001 迅雷:[udp;12345;;;;,udp;15000;;;;,tcp;;54321;;;,tcp;;12345;;;,udp;6881;;;;,udp;;12346;;;,udp;12346;;;;] -7002 AppStore:[tcp;;;itunes.apple.com;;] HIDE:0 -7003 samba共享:[tcp;;445;;;] HIDE:0 -7004 ftp文件传输:[tcp;;21;;;] HIDE:0 -7005 vivo应用商店:[tcp;;443;appstore.vivo;;,tcp;;443;apkappdefwsdl.vivo;;] HIDE:0 -7006 王者荣耀更新:[tcp;;80;;/sgame/;] -7007 天翼云盘:[tcp;;;ctyunapi;;] -7008 腾讯微云:[tcp;;;weiyun.com;;,tcp;;;aegis.qq.com;;,tcp;;;pingtas.qq.com;;,tcp;;443;;;00:77|01:6e|02:73] -7009 坚果云:[tcp;;;jianguoyun;;] -7010 蓝奏云:[tcp;;;pan.lanzou.com;;] -7011 华为云:[tcp;;;cloud.huawei.com;;,tcp;;;hicloud.com;;,tcp;;;myhuaweicloud.cn;;] -7020 windows更新:[tcp;;80;update.microsoft.com;;,tcp;;;windowsupdate.com;;] -7030 向日葵:[tcp;;;oray.com;;,tcp;;;oray.net;;] -7031 TeamViewer:[tcp;;;teamviewer;;] -7032 阿里云盘:[tcp;;;aliyundrive;;] -7035 SSH:[tcp;;;;;00:53|01:53|02:48] - -#class website -8001 百度:[tcp;;;baidu.com;;] -8002 新浪:[tcp;;;sina.com;;] -8003 搜狐:[tcp;;;sohu.com;;] -8004 网易:[tcp;;;163.com;;,tcp;;443;126.com;;] -8005 凤凰网:[tcp;;;ifeng.com;;] -8006 人民网:[tcp;;;people.com.cn;;] -8007 凤凰网:[tcp;;;ifeng.com;;] -8008 中华网:[tcp;;;china.com;;] -8009 hao123:[tcp;;;hao123.com;;,] -8010 2345:[tcp;;;2345.com;;,] -8011 4399游戏:[tcp;;;4399.com;;] -8012 7k7k游戏:[tcp;;;7k7k.com;;] -8013 17173游戏:[tcp;;;17173.com;;] -8014 37网游:[tcp;;;37.com;;] -8015 游民星空:[tcp;;;gamersky.com;;] -8016 游侠网:[tcp;;;ali213.net;;] -8017 世纪佳缘:[tcp;;;jiayuan.com;;] -8018 珍爱网:[tcp;;;zhenai.com;;] -8019 百合网:[tcp;;;baihe.com;;] -8020 天涯社区:[tcp;;;tianya.cn;;] -8021 携程网:[tcp;;;ctrip.com;;] -8022 飞猪:[tcp;;;fliggy.com;;] -8023 12306:[tcp;;;12306.cn;;] -8024 马蜂窝:[tcp;;;mafengwo.cn;;] -8025 途牛:[tcp;;;tuniu.com;;] -8026 穷游网:[tcp;;;qyer.com;;] -8027 驴妈妈:[tcp;;;lvmama.com;;] -8028 同程旅游:[tcp;;;ly.com;;] -8029 太平洋汽车:[tcp;;;pcauto.com.cn;;] -8030 易车网:[tcp;;;bitauto.com;;] -8031 爱卡汽车:[tcp;;;xcar.com.cn;;] -8032 雪球:[tcp;;;xueqiu.com;;] -8033 东方财富:[tcp;;;eastmoney.com;;] -8034 证券之星:[tcp;;;stockstar.com;;] -8035 和讯:[tcp;;;hexun.com;;] -8036 第一财经:[tcp;;;yicai.com;;] -8037 全景网:[tcp;;;p5w.net;;] -8038 中彩网:[tcp;;;zhcw.com;;] -8039 中国体育彩票:[tcp;;;lottery.gov.cn;;] -8040 竞彩网:[tcp;;;sporttery.cn;;] -8041 豆丁:[tcp;;;docin.com;;] -8042 豆瓣:[tcp;;;douban.com;;] -8043 知乎:[tcp;;;zhihu.com;;] -8044 缤客:[tcp;;;booking.com;;] -8046 猫扑:[tcp;;;mop.com;;] -8047 赶集网:[tcp;;;ganji.com;;] -8048 安居客:[tcp;;;anjuke.com;;] -8049 房天下:[tcp;;;fang.com;;] -8050 链家:[tcp;;;lianjia.com;;] -8051 百姓网:[tcp;;;baixing.com;;] -8052 下厨房:[tcp;;;xiachufang.com;;] -8053 大众点评:[tcp;;;dianping.com;;] -8054 58同城:[tcp;;;58.com;;] -8055 天眼查:[tcp;;;tianyancha.com;;] -8056 千图网:[tcp;;;58pic.com;;] -8057 csdn社区:[tcp;;;csdn.net;;] -8058 有道词典:[tcp;;;dict.youdao.com;;] -8059 动漫之家:[tcp;;;dmzj.com;;] -8060 汽车之家:[tcp;;;autohome.com.cn;;] -8061 纵横中文网:[tcp;;;zongheng.com;;] -8062 起点中文网:[tcp;;;qidian.com;;] -8063 飞卢:[tcp;;;faloo.com;;] -8064 潇湘书院:[tcp;;;xxsy.net;;] -8065 cctv5:[tcp;;;sports.cctv.com;;] -8066 虎扑体育:[tcp;;;www.hupu.com;;] -8067 建设银行:[tcp;;;ccb.com;;] -8068 农业银行:[tcp;;;abchina.com;;] -8069 中国银行:[tcp;;;boc.cn;;] -8070 交通银行:[tcp;;;bankcomm.com;;] -8071 招商银行:[tcp;;;cmbchina.com;;] -8072 邮政储蓄:[tcp;;;psbc.com;;] -8073 兴业银行:[tcp;;;cib.com.cn;;] -8074 浦发银行:[tcp;;;spdb.com.cn;;] -8075 中信银行:[tcp;;;citicbank.com;;] -8076 上海银行:[tcp;;;bosc.cn;;] - diff --git a/OpenAppFilter/open-app-filter/files/feature_en.cfg b/OpenAppFilter/open-app-filter/files/feature_en.cfg deleted file mode 100644 index ba4adf0..0000000 --- a/OpenAppFilter/open-app-filter/files/feature_en.cfg +++ /dev/null @@ -1,51 +0,0 @@ -#version v21.9.1 -#id name:[proto;sport;dport;host url;request;dict] -#class chat -1001 Facebook:[tcp;;;facebook.com;;] -1002 Whatsapp:[tcp;;;whatsapp;;] -1003 Twitter:[tcp;;;twitter.com;;] -1004 Instagram:[tcp;;;instagram.com;;] -1005 VK:[tcp;;;vk.com;;] -1006 Line:[tcp;;;line;;] - -#class video -3001 YouTube:[tcp;;;youtube;;] -3002 NetFlix:[tcp;;;netflix;;] -3003 Vimeo:[tcp;;;vimeo;;] -3004 DailyMotion:[tcp;;;dailymotion;;] -3005 Hulu:[tcp;;;hulu;;] -3006 Vube:[tcp;;;vube;;] -3007 Twitch:[tcp;;;twitch;;] -3008 LiveLeak:[tcp;;;itemfix;;] -3009 LiveLeak:[tcp;;;itemfix;;] -3010 Xvideos:[tcp;;;xvideos.com;;] -3011 Pornhub:[tcp;;;pornhub.com;;] - -#class shopping -4001 Amazon:[tcp;;;amazon.com;;] -4002 eBay:[tcp;;;ebay.com;;] -4003 Etsy:[tcp;;;etsy.com;;] -4004 Wish:[tcp;;;wish.com;;] -4005 Alibaba:[tcp;;;alibaba;;] -4006 Aliexpress:[tcp;;;aliexpress.com;;] -4007 Walmart:[tcp;;;walmart.com;;] -4008 Sears:[tcp;;;sears.com;;] -4009 Kohls:[tcp;;;kohls.com;;] -4010 Costco:[tcp;;;costco.com;;] -4011 Asos:[tcp;;;asos.com;;] -4012 Cuyana:[tcp;;;cuyana.com;;] - -#class download -7001 Google Play:[tcp;;;play.google.com;;] -7002 AppStore:[tcp;;80;iosapps.itunes.apple.com;;] - -#class website -8001 Google:[tcp;;;www.google.com;;] -8002 Wiki:[tcp;;;www.wikipedia.com;;] -8003 Yahoo:[tcp;;;www.yahoo.com;;] -8004 Apple:[tcp;;;www.apple.com;;] -8010 Reddit:[tcp;;;www.reddit.com;;] -8011 Outlook:[tcp;;;www.outlook.live.com;;] -8012 Naver:[tcp;;;www.naver.com;;] -8013 Fandom:[tcp;;;www.fandom.com;;] -8015 Globo:[tcp;;;www.globo.com;;] \ No newline at end of file diff --git a/OpenAppFilter/open-app-filter/files/gen_class.sh b/OpenAppFilter/open-app-filter/files/gen_class.sh deleted file mode 100644 index 80350ca..0000000 --- a/OpenAppFilter/open-app-filter/files/gen_class.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh - -f_file=$1 -test -z "$f_file" && return -test -d /tmp/appfilter && return -cur_class="" -cur_class_file="" -mkdir /tmp/appfilter -while read line -do - echo "$line"| grep "^#class" - if [ $? -eq 0 ];then - class=`echo $line| grep '#class' | awk '{print $2}'` - if ! test -z "$class";then - cur_class=$class - cur_class_file="/tmp/appfilter/${cur_class}.class" - if [ -e "$cur_class_file" ];then - rm $cur_class_file - fi - touch $cur_class_file - fi - fi - test -z "$cur_class" && continue - appid=`echo "$line" |awk '{print $1}'` - appname=`echo "$line" | awk '{print $2}' | awk -F: '{print $1}'` - - echo "$appid $appname" >> $cur_class_file -done < $f_file -echo "ok" - diff --git a/OpenAppFilter/open-app-filter/files/oaf_rule b/OpenAppFilter/open-app-filter/files/oaf_rule deleted file mode 100644 index 0aa57d3..0000000 --- a/OpenAppFilter/open-app-filter/files/oaf_rule +++ /dev/null @@ -1,95 +0,0 @@ -. /usr/share/libubox/jshn.sh -. /lib/functions.sh - - -config_apply() -{ - test -z "$1" && return 1 - - if [ -e "/dev/appfilter" ];then - echo "config json str=$1" - echo "$1" >/dev/appfilter - fi -} - -clean_rule() -{ - json_init - echo "clean appfilter rule..." - - json_add_int "op" 3 - json_add_object "data" - json_str=`json_dump` - - config_apply "$json_str" - - json_cleanup -} - -load_rule() -{ - json_init - json_add_int "op" 1 - json_add_object "data" - json_add_array "apps" - - for file in `ls /tmp/appfilter/*.class` - do - class_name=`echo "$file" | awk -F/ '{print $4}'| awk -F. '{print $1}'` - config_get appid_list "appfilter" "${class_name}apps" - - if ! test -z "$appid_list";then - for appid in $appid_list: - do - json_add_int "" $appid - done - fi - done - - json_str=`json_dump` - config_apply "$json_str" - json_cleanup -} - -load_mac_list() -{ - json_init - config_load appfilter - json_add_int "op" 4 - json_add_object "data" - json_add_array "mac_list" - config_get mac_list "user" "users" - echo "mac list=$mac_list" - if [ x"$mac_list" != x"" ];then - for mac in $mac_list: - do - json_add_string "" $mac - done - fi - json_str=`json_dump` - config_apply "$json_str" - json_cleanup -} - -reload_rule(){ - config_load appfilter - clean_rule - load_rule - load_mac_list -} - -reload_base_config(){ - local old_work_mode - config_load appfilter - config_get work_mode "global" "work_mode" - echo "work mode=$work_mode" - echo "$work_mode" >/proc/sys/oaf/work_mode -} - -case $1 in -"reload") - echo "reload appfilter rule..." - reload_base_config - reload_rule -;; -esac diff --git a/OpenAppFilter/open-app-filter/src/Makefile b/OpenAppFilter/open-app-filter/src/Makefile deleted file mode 100644 index 3f0cdce..0000000 --- a/OpenAppFilter/open-app-filter/src/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -OBJS:=appfilter_user.o appfilter_netlink.o appfilter_ubus.o appfilter_config.o main.o -EXEC:=oafd -all: $(OBJS) - $(CC) -o $(EXEC) $(OBJS) $(LIBS) -clean: - rm $(EXEC) *.o diff --git a/OpenAppFilter/open-app-filter/src/appfilter_config.c b/OpenAppFilter/open-app-filter/src/appfilter_config.c deleted file mode 100644 index 1fcb959..0000000 --- a/OpenAppFilter/open-app-filter/src/appfilter_config.c +++ /dev/null @@ -1,329 +0,0 @@ -/* -Copyright (C) 2020 Derry - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -#include -#include -#include -#include "appfilter_config.h" -#include - -app_name_info_t app_name_table[MAX_SUPPORT_APP_NUM]; -int g_app_count = 0; -int g_cur_class_num = 0; -char CLASS_NAME_TABLE[MAX_APP_TYPE][MAX_CLASS_NAME_LEN]; - -const char *config_path = "./config"; -static struct uci_context *uci_ctx = NULL; -static struct uci_package *uci_appfilter; - - -int uci_get_int_value(struct uci_context *ctx, char *key) -{ - struct uci_element *e; - struct uci_ptr ptr; - int ret = -1; - int dummy; - char *parameters ; - char param_tmp[128] = {0}; - strcpy(param_tmp, key); - if (uci_lookup_ptr(ctx, &ptr, param_tmp, true) != UCI_OK) { - return ret; - } - - if (!(ptr.flags & UCI_LOOKUP_COMPLETE)) { - ctx->err = UCI_ERR_NOTFOUND; - goto done; - } - - e = ptr.last; - switch(e->type) { - case UCI_TYPE_SECTION: - ret = -1; - goto done; - case UCI_TYPE_OPTION: - ret = atoi(ptr.o->v.string); - goto done; - default: - break; - } -done: - - if (ptr.p) - uci_unload(ctx, ptr.p); - return ret; -} - - -int uci_get_value(struct uci_context *ctx, char *key, char *output, int out_len) -{ - struct uci_element *e; - struct uci_ptr ptr; - int ret = UCI_OK; - int dummy; - char *parameters ; - char param_tmp[128] = {0}; - strcpy(param_tmp, key); - if (uci_lookup_ptr(ctx, &ptr, param_tmp, true) != UCI_OK) { - ret = 1; - return ret; - } - - if (!(ptr.flags & UCI_LOOKUP_COMPLETE)) { - ctx->err = UCI_ERR_NOTFOUND; - ret = 1; - goto done; - } - - e = ptr.last; - switch(e->type) { - case UCI_TYPE_SECTION: - snprintf(output, out_len, "%s", ptr.s->type); - break; - case UCI_TYPE_OPTION: - snprintf(output, out_len, "%s", ptr.o->v.string); - break; - default: - ret = 1; - break; - } -done: - if (ptr.p) - uci_unload(ctx, ptr.p); - return ret; -} - -// -static struct uci_package * -config_init_package(const char *config) -{ - struct uci_context *ctx = uci_ctx; - struct uci_package *p = NULL; - - if (!ctx) - { - ctx = uci_alloc_context(); - uci_ctx = ctx; - ctx->flags &= ~UCI_FLAG_STRICT; - //if (config_path) - // uci_set_confdir(ctx, config_path); - } - else - { - p = uci_lookup_package(ctx, config); - if (p) - uci_unload(ctx, p); - } - - if (uci_load(ctx, config, &p)) - return NULL; - - return p; -} -char *get_app_name_by_id(int id) -{ - int i; - for (i = 0; i < g_app_count; i++) - { - if (id == app_name_table[i].id) - return app_name_table[i].name; - } - return ""; -} - -void init_app_name_table(void) -{ - int count = 0; - char line_buf[2048] = {0}; - - FILE *fp = fopen("/tmp/feature.cfg", "r"); - if (!fp) - { - printf("open file failed\n"); - return; - } - - while (fgets(line_buf, sizeof(line_buf), fp)) - { - if (strstr(line_buf, "#")) - continue; - if (strlen(line_buf) < 10) - continue; - if (!strstr(line_buf, ":")) - continue; - char *pos1 = strstr(line_buf, ":"); - char app_info_buf[128] = {0}; - int app_id; - char app_name[64] = {0}; - memset(app_name, 0x0, sizeof(app_name)); - strncpy(app_info_buf, line_buf, pos1 - line_buf); - sscanf(app_info_buf, "%d %s", &app_id, app_name); - app_name_table[g_app_count].id = app_id; - strcpy(app_name_table[g_app_count].name, app_name); - g_app_count++; - } - fclose(fp); -} - -void init_app_class_name_table(void) -{ - char line_buf[2048] = {0}; - int class_id; - char class_name[64] = {0}; - FILE *fp = fopen("/tmp/app_class.txt", "r"); - if (!fp) - { - printf("open file failed\n"); - return; - } - while (fgets(line_buf, sizeof(line_buf), fp)) - { - sscanf(line_buf, "%d %s", &class_id, class_name); - strcpy(CLASS_NAME_TABLE[class_id - 1], class_name); - g_cur_class_num++; - } - fclose(fp); -} -//00:00 9:1 -int check_time_valid(char *t) -{ - if (!t) - return 0; - if (strlen(t) < 3 || strlen(t) > 5 || (!strstr(t, ":"))) - return 0; - else - return 1; -} - -void dump_af_time(af_ctl_time_t *t) -{ - int i; - printf("---------dump af time-------------\n"); - printf("%d:%d ---->%d:%d\n", t->start.hour, t->start.min, - t->end.hour, t->end.min); - for (i = 0; i < 7; i++) - { - printf("%d ", t->days[i]); - } - printf("\n"); -} - -af_ctl_time_t *load_appfilter_ctl_time_config(void) -{ - char start_time_str[64] = {0}; - char end_time_str[64] = {0}; - char start_time_str2[64] = {0}; - char end_time_str2[64] = {0}; - char days_str[64] = {0}; - int value = 0; - int ret = 0; - af_ctl_time_t *t = NULL; - struct uci_context *ctx = uci_alloc_context(); - if (!ctx) - return NULL; - - memset(start_time_str, 0x0, sizeof(start_time_str)); - memset(end_time_str, 0x0, sizeof(end_time_str)); - memset(start_time_str2, 0x0, sizeof(start_time_str2)); - memset(end_time_str2, 0x0, sizeof(end_time_str2)); - - uci_get_value(ctx, "appfilter.time.start_time", start_time_str, sizeof(start_time_str)); - uci_get_value(ctx, "appfilter.time.end_time", end_time_str, sizeof(end_time_str)); - uci_get_value(ctx, "appfilter.time.start_time2", start_time_str2, sizeof(start_time_str2)); - uci_get_value(ctx, "appfilter.time.end_time2", end_time_str2, sizeof(end_time_str2)); - uci_get_value(ctx, "appfilter.time.days", days_str, sizeof(days_str)); - - - t = malloc(sizeof(af_ctl_time_t)); - - value = uci_get_int_value(ctx, "appfilter.time.time_mode"); - if (value < 0) - t->time_mode = 0; - else - t->time_mode = value; - if (check_time_valid(start_time_str) && check_time_valid(end_time_str)){ - sscanf(start_time_str, "%d:%d", &t->start.hour, &t->start.min); - sscanf(end_time_str, "%d:%d", &t->end.hour, &t->end.min); - } - if (check_time_valid(start_time_str2) && check_time_valid(end_time_str2)){ - sscanf(start_time_str2, "%d:%d", &t->start2.hour, &t->start2.min); - sscanf(end_time_str2, "%d:%d", &t->end2.hour, &t->end2.min); - } - - char *p = strtok(days_str, " "); - if (!p) - goto EXIT; - do - { - int day = atoi(p); - if (day >= 0 && day <= 6) - t->days[day] = 1; - else - ret = 0; - } while (p = strtok(NULL, " ")); -EXIT: - uci_free_context(ctx); - return t; -} - - - -int config_get_appfilter_enable(void) -{ - int enable = 0; - struct uci_context *ctx = uci_alloc_context(); - if (!ctx) - return NULL; - enable = uci_get_int_value(ctx, "appfilter.global.enable"); - if (enable < 0) - enable = 0; - - uci_free_context(ctx); - return enable; -} - -int appfilter_config_alloc(void) -{ - char *err; - uci_appfilter = config_init_package("appfilter"); - if (!uci_appfilter) - { - uci_get_errorstr(uci_ctx, &err, NULL); - printf("Failed to load appfilter config (%s)\n", err); - free(err); - return -1; - } - - return 0; -} - -int appfilter_config_free(void) -{ - if (uci_appfilter) - { - uci_unload(uci_ctx, uci_appfilter); - uci_appfilter = NULL; - } - if (uci_ctx) - { - uci_free_context(uci_ctx); - uci_ctx = NULL; - } -} diff --git a/OpenAppFilter/open-app-filter/src/appfilter_config.h b/OpenAppFilter/open-app-filter/src/appfilter_config.h deleted file mode 100644 index 1d29e10..0000000 --- a/OpenAppFilter/open-app-filter/src/appfilter_config.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -Copyright (C) 2020 Derry - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -#ifndef __APPFILTER_CONFIG_H__ -#define __APPFILTER_CONFIG_H__ -#define MAX_SUPPORT_APP_NUM 1024 -#define MAX_CLASS_NAME_LEN 32 -#include "appfilter_user.h" -extern int g_cur_class_num; -extern int g_app_count; -extern char CLASS_NAME_TABLE[MAX_APP_TYPE][MAX_CLASS_NAME_LEN]; -typedef struct af_time -{ - int hour; - int min; -} af_time_t; -typedef struct af_ctl_time -{ - int time_mode; // 0,1 - af_time_t start; - af_time_t end; - af_time_t start2; // todo: time group list - af_time_t end2; - int days[7]; -} af_ctl_time_t; - -typedef struct app_name_info -{ - int id; - char name[64]; -} app_name_info_t; -void init_app_name_table(void); -void init_app_class_name_table(void); -char *get_app_name_by_id(int id); - -int appfilter_config_alloc(void); - -int appfilter_config_free(void); -af_ctl_time_t *load_appfilter_ctl_time_config(void); -int config_get_appfilter_enable(void); - -#endif diff --git a/OpenAppFilter/open-app-filter/src/appfilter_netlink.c b/OpenAppFilter/open-app-filter/src/appfilter_netlink.c deleted file mode 100644 index 33a2442..0000000 --- a/OpenAppFilter/open-app-filter/src/appfilter_netlink.c +++ /dev/null @@ -1,241 +0,0 @@ -/* -Copyright (C) 2020 Derry - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "appfilter_user.h" -#include "appfilter_netlink.h" -#define MAX_NL_RCV_BUF_SIZE 4096 - -#define REPORT_INTERVAL_SECS 60 -void appfilter_nl_handler(struct uloop_fd *u, unsigned int ev) -{ - int ret; - int i; - char buf[MAX_NL_RCV_BUF_SIZE]; - struct sockaddr_nl nladdr; - struct iovec iov = {buf, sizeof(buf)}; - struct nlmsghdr *h; - int type; - int id; - char *mac = NULL; - printf("%s %d\n", __func__, __LINE__); - - struct msghdr msg = { - .msg_name = &nladdr, - .msg_namelen = sizeof(nladdr), - .msg_iov = &iov, - .msg_iovlen = 1, - }; - - do - { - ret = recvmsg(u->fd, &msg, 0); - } while ((-1 == ret) && (EINTR == errno)); - - if (ret < 0) - { - printf("recv msg error\n"); - return; - } - else if (0 == ret) - { - return; - } - - h = (struct nlmsghdr *)buf; - char *kmsg = (char *)NLMSG_DATA(h); - struct af_msg_hdr *af_hdr = (struct af_msg_hdr *)kmsg; - if (af_hdr->magic != 0xa0b0c0d0) - { - printf("magic error %x\n", af_hdr->magic); - return; - } - if (af_hdr->len <= 0 || af_hdr->len >= MAX_OAF_NETLINK_MSG_LEN) - { - printf("data len error\n"); - return; - } - - char *kdata = kmsg + sizeof(struct af_msg_hdr); - struct json_object *root = json_tokener_parse(kdata); - if (!root) - { - printf("parse json failed:%s", kdata); - return; - } - printf("recv msg = %s\n", kdata); - - struct json_object *mac_obj = json_object_object_get(root, "mac"); - - if (!mac_obj) - { - printf("parse mac obj failed\n"); - json_object_put(root); - return; - } - - mac = json_object_get_string(mac_obj); - - dev_node_t *node = find_dev_node(mac); - - if (!node) - { - node = add_dev_node(mac); - if (!node) - { - printf("add dev node failed\n"); - json_object_put(root); - return; - } - } - - struct json_object *ip_obj = json_object_object_get(root, "ip"); - if (ip_obj) - strncpy(node->ip, json_object_get_string(ip_obj), sizeof(node->ip)); - struct json_object *visit_array = json_object_object_get(root, "visit_info"); - if (!visit_array) - { - json_object_put(root); - return; - } - for (i = 0; i < json_object_array_length(visit_array); i++) - { - struct json_object *visit_obj = json_object_array_get_idx(visit_array, i); - struct json_object *appid_obj = json_object_object_get(visit_obj, "appid"); - struct json_object *action_obj = json_object_object_get(visit_obj, "latest_action"); - struct json_object *up_obj = json_object_object_get(visit_obj, "up_bytes"); - struct json_object *down_obj = json_object_object_get(visit_obj, "down_bytes"); - struct timeval cur_time; - - gettimeofday(&cur_time, NULL); - int appid = json_object_get_int(appid_obj); - int action = json_object_get_int(action_obj); - - type = appid / 1000; - id = appid % 1000; - if (id <= 0 || type <= 0) - continue; - node->stat[type - 1][id - 1].total_time += REPORT_INTERVAL_SECS; - - // node->stat[type - 1][id - 1].total_down_bytes += json_object_get_int(down_obj); - // node->stat[type - 1][id - 1].total_up_bytes += json_object_get_int(up_obj); - - int hash = hash_appid(appid); - visit_info_t *head = node->visit_htable[hash]; - - if (head && (cur_time.tv_sec - head->latest_time) < 300) - { - head->latest_time = cur_time.tv_sec; - } - else - { - printf("%s %d\n", __func__, __LINE__); - - visit_info_t *visit_node = (visit_info_t *)calloc(1, sizeof(visit_info_t)); - visit_node->action = action; - visit_node->appid = appid; - visit_node->latest_time = cur_time.tv_sec; - visit_node->first_time = cur_time.tv_sec - MIN_VISIT_TIME; - visit_node->next = NULL; - add_visit_info_node(&node->visit_htable[hash], visit_node); - - //printf("add visit info curtime=%d\n", cur_time.tv_sec); - } - } - - json_object_put(root); -} - -#define MAX_NL_MSG_LEN 1024 -int send_msg_to_kernel(int fd, void *msg, int len) -{ - struct sockaddr_nl saddr, daddr; - memset(&daddr, 0, sizeof(daddr)); - daddr.nl_family = AF_NETLINK; - daddr.nl_pid = 0; // to kernel - daddr.nl_groups = 0; - printf("%s %d\n", __func__, __LINE__); - - int ret = 0; - struct nlmsghdr *nlh = NULL; - nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_NL_MSG_LEN)); - nlh->nlmsg_len = NLMSG_SPACE(MAX_NL_MSG_LEN); - nlh->nlmsg_flags = 0; - nlh->nlmsg_type = 0; - nlh->nlmsg_seq = 0; - nlh->nlmsg_pid = DEFAULT_USR_NL_PID; - - char msg_buf[MAX_NL_MSG_LEN] = {0}; - struct af_msg_hdr *hdr = (struct af_msg_hdr *)msg_buf; - hdr->magic = 0xa0b0c0d0; - hdr->len = len; - char *p_data = msg_buf + sizeof(struct af_msg_hdr); - memcpy(p_data, msg, len); - - // memset(nlh, 0, sizeof(struct nlmsghdr)); - - memcpy(NLMSG_DATA(nlh), msg_buf, len + sizeof(struct af_msg_hdr)); - - ret = sendto(fd, nlh, nlh->nlmsg_len, 0, (struct sockaddr *)&daddr, sizeof(struct sockaddr_nl)); - if (!ret) - { - perror("sendto error\n"); - return -1; - } - printf("%s %d\n", __func__, __LINE__); - - return 0; -} - -int appfilter_nl_init(void) -{ - int fd; - struct sockaddr_nl nls; - fd = socket(AF_NETLINK, SOCK_RAW, OAF_NETLINK_ID); - if (fd < 0) - { - printf("Connect netlink %d failed %s", OAF_NETLINK_ID, strerror(errno)); - exit(1); - } - memset(&nls, 0, sizeof(struct sockaddr_nl)); - nls.nl_pid = DEFAULT_USR_NL_PID; - nls.nl_groups = 0; - nls.nl_family = AF_NETLINK; - - if (bind(fd, (void *)&nls, sizeof(struct sockaddr_nl))) - { - printf("Bind failed %s\n", strerror(errno)); - exit(1); - } - - return fd; -} diff --git a/OpenAppFilter/open-app-filter/src/appfilter_netlink.h b/OpenAppFilter/open-app-filter/src/appfilter_netlink.h deleted file mode 100644 index f88b128..0000000 --- a/OpenAppFilter/open-app-filter/src/appfilter_netlink.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -Copyright (C) 2020 Derry - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -#ifndef __APPFILTER_NETLINK_H__ -#define __APPFILTER_NETLINK_H__ -#define DEFAULT_USR_NL_PID 999 -#define OAF_NETLINK_ID 29 -#define MAX_OAF_NETLINK_MSG_LEN 1024 - -struct af_msg_hdr -{ - int magic; - int len; -}; - -enum E_MSG_TYPE -{ - AF_MSG_INIT, - AF_MSG_MAX -}; - -typedef struct af_msg -{ - int action; - void *data; -} af_msg_t; -int appfilter_nl_init(void); -void appfilter_nl_handler(struct uloop_fd *u, unsigned int ev); -int send_msg_to_kernel(int fd, void *msg, int len); -#endif \ No newline at end of file diff --git a/OpenAppFilter/open-app-filter/src/appfilter_ubus.c b/OpenAppFilter/open-app-filter/src/appfilter_ubus.c deleted file mode 100644 index bbfb500..0000000 --- a/OpenAppFilter/open-app-filter/src/appfilter_ubus.c +++ /dev/null @@ -1,526 +0,0 @@ -/* -Copyright (C) 2020 Derry - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "appfilter_user.h" -#include "appfilter_config.h" - -struct ubus_context *ubus_ctx = NULL; -static struct blob_buf b; - -extern char *format_time(int timetamp); - -void get_hostname_by_mac(char *mac, char *hostname) -{ - if (!mac || !hostname) - return; - FILE *fp = fopen("/tmp/dhcp.leases", "r"); - if (!fp) - { - printf("open dhcp lease file....failed\n"); - return; - } - char line_buf[256] = {0}; - while (fgets(line_buf, sizeof(line_buf), fp)) - { - char hostname_buf[128] = {0}; - char mac_buf[32] = {0}; - sscanf(line_buf, "%*s %s %*s %s", mac_buf, hostname_buf); - if (0 == strcmp(mac, mac_buf)) - { - strcpy(hostname, hostname_buf); - } - } - fclose(fp); -} - -void ubus_dump_visit_list(struct blob_buf *b, char *mac) -{ - int i, j; - void *c, *array; - void *t; - void *s; - - array = blobmsg_open_array(b, "dev_list"); - - for (i = 0; i < MAX_DEV_NODE_HASH_SIZE; i++) - { - dev_node_t *node = dev_hash_table[i]; - while (node) - { - if (mac && strcmp(mac, node->mac)) - { - node = node->next; - continue; - } - t = blobmsg_open_table(b, NULL); - blobmsg_add_string(b, "hostname", "unknown"); - blobmsg_add_string(b, "mac", node->mac); - blobmsg_add_string(b, "ip", node->ip); - void *visit_array; - - visit_array = blobmsg_open_array(b, "visit_info"); - for (j = 0; j < MAX_VISIT_HASH_SIZE; j++) - { - visit_info_t *p_info = node->visit_htable[j]; - while (p_info) - { - char *first_time_str = format_time(p_info->first_time); - char *latest_time_str = format_time(p_info->latest_time); - int total_time = p_info->latest_time - p_info->first_time; - s = blobmsg_open_table(b, NULL); - blobmsg_add_string(b, "appname", "unknown"); - blobmsg_add_u32(b, "appid", p_info->appid); - blobmsg_add_u32(b, "latest_action", p_info->action); - blobmsg_add_u32(b, "first_time", p_info->first_time); - blobmsg_add_u32(b, "latest_time", p_info->latest_time); - blobmsg_close_table(b, s); - if (first_time_str) - free(first_time_str); - if (latest_time_str) - free(latest_time_str); - p_info = p_info->next; - } - } - - blobmsg_close_array(b, visit_array); - blobmsg_close_table(b, t); - node = node->next; - } - } - blobmsg_close_array(b, array); -} - -void update_app_visit_time_list(char *mac, struct app_visit_stat_info *visit_info) -{ - int i, j, s; - int num = 0; - - dev_node_t *node = find_dev_node(mac); - if (!node) - { - printf("not found mac:%s\n", mac); - return; - } - for (i = 0; i < MAX_APP_TYPE; i++) - { - for (j = 0; j < MAX_APP_ID_NUM; j++) - { - unsigned long long min = visit_info->visit_list[0].total_time; - int min_index = 0; - if (node->stat[i][j].total_time == 0) - continue; - if (num < MAX_APP_STAT_NUM) - { - min_index = num; - } - else - { - for (s = 0; s < MAX_APP_STAT_NUM; s++) - { - if (visit_info->visit_list[s].total_time < min) - { - min_index = s; - break; - } - } - } - num++; - if (node->stat[i][j].total_time > visit_info->visit_list[min_index].total_time) - { - visit_info->visit_list[min_index].total_time = node->stat[i][j].total_time; - visit_info->visit_list[min_index].app_id = (i + 1) * 1000 + j + 1; - } - } - } - if (num < MAX_APP_STAT_NUM) - visit_info->num = num; - else - visit_info->num = MAX_APP_STAT_NUM; -} - -void update_app_class_visit_time_list(char *mac, int *visit_time) -{ - int i, j, s; - int num = 0; - - dev_node_t *node = find_dev_node(mac); - if (!node) - { - printf("not found mac:%s\n", mac); - return; - } - for (i = 0; i < MAX_APP_TYPE; i++) - { - for (j = 0; j < MAX_APP_ID_NUM; j++) - { - if (node->stat[i][j].total_time == 0) - continue; - visit_time[i] += node->stat[i][j].total_time; - } - } -} - -void ubus_get_dev_visit_time_info(char *mac, struct blob_buf *b) -{ - int i, j; - void *c, *array; - void *t; - void *s; - struct app_visit_stat_info info; - memset((char *)&info, 0x0, sizeof(info)); - update_app_visit_time_list(mac, &info); -} - -static int -appfilter_handle_visit_list(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - int ret; - blob_buf_init(&b, 0); - char *msg_obj_str = blobmsg_format_json(msg, true); - if (!msg_obj_str) - { - printf("format json failed\n"); - return 0; - } - - struct json_object *req_obj = json_tokener_parse(msg_obj_str); - struct json_object *mac_obj = json_object_object_get(req_obj, "mac"); - - if (!mac_obj) - { - ubus_dump_visit_list(&b, NULL); - } - else - ubus_dump_visit_list(&b, json_object_get_string(mac_obj)); - ubus_send_reply(ctx, req, b.head); - return 0; -} - -typedef struct app_visit_time_info -{ - int app_id; - unsigned long long total_time; -} app_visit_time_info_t; - -int visit_time_compare(const void *a, const void *b) -{ - app_visit_time_info_t *p1 = (app_visit_time_info_t *)a; - app_visit_time_info_t *p2 = (app_visit_time_info_t *)b; - return p1->total_time < p2->total_time ? 1 : -1; -} - -#define MAX_STAT_APP_NUM 128 -void update_top5_app(dev_node_t *node, app_visit_time_info_t top5_app_list[]) -{ - int i, j; - //memset(app_array, 0x0, sizeof(int) *size); - app_visit_time_info_t app_visit_array[MAX_STAT_APP_NUM]; - memset(app_visit_array, 0x0, sizeof(app_visit_array)); - int app_visit_num = 0; - - for (i = 0; i < MAX_APP_TYPE; i++) - { - for (j = 0; j < MAX_APP_ID_NUM; j++) - { - if (node->stat[i][j].total_time == 0) - continue; - app_visit_array[app_visit_num].app_id = (i + 1) * 1000 + j + 1; - app_visit_array[app_visit_num].total_time = node->stat[i][j].total_time; - app_visit_num++; - } - } - - qsort((void *)app_visit_array, app_visit_num, sizeof(app_visit_time_info_t), visit_time_compare); -#if 0 -for (i = 0; i < app_visit_num; i++){ -printf("appid %d-----------total time %llu\n", app_visit_array[i].app_id, -app_visit_array[i].total_time); -} -#endif - for (i = 0; i < 5; i++) - { - top5_app_list[i] = app_visit_array[i]; - //printf("appid %d-----------total time %llu\n", app_visit_array[i].app_id, - // app_visit_array[i].total_time); - } -} - -static int -appfilter_handle_dev_list(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - int i, j; - struct json_object *root_obj = json_object_new_object(); - - struct json_object *dev_array = json_object_new_array(); - int count = 0; - for (i = 0; i < MAX_DEV_NODE_HASH_SIZE; i++) - { - - dev_node_t *node = dev_hash_table[i]; - while (node) - { - if (node->online == 0) - { - - node = node->next; - continue; - } - struct json_object *dev_obj = json_object_new_object(); - struct json_object *app_array = json_object_new_array(); - app_visit_time_info_t top5_app_list[5]; - memset(top5_app_list, 0x0, sizeof(top5_app_list)); - update_top5_app(node, top5_app_list); - - for (j = 0; j < 5; j++) - { - if (top5_app_list[j].app_id == 0) - break; - struct json_object *app_obj = json_object_new_object(); - json_object_object_add(app_obj, "id", json_object_new_int(top5_app_list[j].app_id)); - json_object_object_add(app_obj, "name", json_object_new_string(get_app_name_by_id(top5_app_list[j].app_id))); - json_object_array_add(app_array, app_obj); - } - - json_object_object_add(dev_obj, "applist", app_array); - json_object_object_add(dev_obj, "mac", json_object_new_string(node->mac)); - char hostname[128] = {0}; - get_hostname_by_mac(node->mac, hostname); - json_object_object_add(dev_obj, "ip", json_object_new_string(node->ip)); - - json_object_object_add(dev_obj, "online", json_object_new_int(1)); - json_object_object_add(dev_obj, "hostname", json_object_new_string(hostname)); - json_object_object_add(dev_obj, "latest_app", json_object_new_string("test")); - json_object_array_add(dev_array, dev_obj); - - node = node->next; - count++; - if (count >= MAX_SUPPORT_DEV_NUM) - goto END; - } - } - for (i = 0; i < MAX_DEV_NODE_HASH_SIZE; i++) - { - dev_node_t *node = dev_hash_table[i]; - while (node) - { - if (node->online != 0) - { - - node = node->next; - continue; - } - struct json_object *dev_obj = json_object_new_object(); - struct json_object *app_array = json_object_new_array(); - app_visit_time_info_t top5_app_list[5]; - memset(top5_app_list, 0x0, sizeof(top5_app_list)); - update_top5_app(node, top5_app_list); - - for (j = 0; j < 5; j++) - { - if (top5_app_list[j].app_id == 0) - break; - struct json_object *app_obj = json_object_new_object(); - json_object_object_add(app_obj, "id", json_object_new_int(top5_app_list[j].app_id)); - json_object_object_add(app_obj, "name", json_object_new_string(get_app_name_by_id(top5_app_list[j].app_id))); - json_object_array_add(app_array, app_obj); - } - - json_object_object_add(dev_obj, "applist", app_array); - json_object_object_add(dev_obj, "mac", json_object_new_string(node->mac)); - char hostname[32] = {0}; - get_hostname_by_mac(node->mac, hostname); - json_object_object_add(dev_obj, "ip", json_object_new_string(node->ip)); - - json_object_object_add(dev_obj, "online", json_object_new_int(0)); - json_object_object_add(dev_obj, "hostname", json_object_new_string(hostname)); - json_object_object_add(dev_obj, "latest_app", json_object_new_string("test")); - json_object_array_add(dev_array, dev_obj); - node = node->next; - count++; - if (count >= MAX_SUPPORT_DEV_NUM) - goto END; - } - } - -END: - - json_object_object_add(root_obj, "devlist", dev_array); - blob_buf_init(&b, 0); - blobmsg_add_object(&b, root_obj); - ubus_send_reply(ctx, req, b.head); - json_object_put(root_obj); - return 0; -} - -static int -appfilter_handle_visit_time(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - int ret; - struct app_visit_stat_info info; - blob_buf_init(&b, 0); - memset((char *)&info, 0x0, sizeof(info)); - char *msg_obj_str = blobmsg_format_json(msg, true); - if (!msg_obj_str) - { - printf("format json failed\n"); - return 0; - } - - struct json_object *req_obj = json_tokener_parse(msg_obj_str); - struct json_object *mac_obj = json_object_object_get(req_obj, "mac"); - if (!mac_obj) - { - printf("mac is NULL\n"); - return 0; - } - update_app_visit_time_list(json_object_get_string(mac_obj), &info); - - struct json_object *resp_obj = json_object_new_object(); - struct json_object *app_info_array = json_object_new_array(); - json_object_object_add(resp_obj, "app_list", app_info_array); - int i; - for (i = 0; i < info.num; i++) - { - struct json_object *app_info_obj = json_object_new_object(); - json_object_object_add(app_info_obj, "app_id", - json_object_new_string(get_app_name_by_id(info.visit_list[i].app_id))); - json_object_object_add(app_info_obj, "visit_time", - json_object_new_int(info.visit_list[i].total_time)); - json_object_array_add(app_info_array, app_info_obj); - } - - blobmsg_add_object(&b, resp_obj); - ubus_send_reply(ctx, req, b.head); - json_object_put(resp_obj); - json_object_put(req_obj); - return 0; -} - -static int -handle_app_class_visit_time(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - int ret; - int i; - blob_buf_init(&b, 0); - char *msg_obj_str = blobmsg_format_json(msg, true); - if (!msg_obj_str) - { - printf("format json failed\n"); - return 0; - } - - struct json_object *req_obj = json_tokener_parse(msg_obj_str); - struct json_object *mac_obj = json_object_object_get(req_obj, "mac"); - if (!mac_obj) - { - printf("mac is NULL\n"); - return 0; - } - int app_class_visit_time[MAX_APP_TYPE]; - memset(app_class_visit_time, 0x0, sizeof(app_class_visit_time)); - update_app_class_visit_time_list(json_object_get_string(mac_obj), app_class_visit_time); - - struct json_object *resp_obj = json_object_new_object(); - struct json_object *app_class_array = json_object_new_array(); - json_object_object_add(resp_obj, "class_list", app_class_array); - for (i = 0; i < MAX_APP_TYPE; i++) - { - if (i >= g_cur_class_num) - break; - struct json_object *app_class_obj = json_object_new_object(); - json_object_object_add(app_class_obj, "type", json_object_new_int(i)); - json_object_object_add(app_class_obj, "name", json_object_new_string(CLASS_NAME_TABLE[i])); - json_object_object_add(app_class_obj, "visit_time", json_object_new_int(app_class_visit_time[i])); - json_object_array_add(app_class_array, app_class_obj); - } - - blobmsg_add_object(&b, resp_obj); - ubus_send_reply(ctx, req, b.head); - json_object_put(resp_obj); - json_object_put(req_obj); - return 0; -} - -static const struct blobmsg_policy empty_policy[1] = { - //[DEV_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING }, -}; - -static struct ubus_method appfilter_object_methods[] = { - UBUS_METHOD("visit_list", appfilter_handle_visit_list, empty_policy), - UBUS_METHOD("dev_visit_time", appfilter_handle_visit_time, empty_policy), - UBUS_METHOD("app_class_visit_time", handle_app_class_visit_time, empty_policy), - UBUS_METHOD("dev_list", appfilter_handle_dev_list, empty_policy), -}; - -static struct ubus_object_type main_object_type = - UBUS_OBJECT_TYPE("appfilter", appfilter_object_methods); - -static struct ubus_object main_object = { - .name = "appfilter", - .type = &main_object_type, - .methods = appfilter_object_methods, - .n_methods = ARRAY_SIZE(appfilter_object_methods), -}; - -static void appfilter_add_object(struct ubus_object *obj) -{ - int ret = ubus_add_object(ubus_ctx, obj); - - if (ret != 0) - fprintf(stderr, "Failed to publish object '%s': %s\n", obj->name, ubus_strerror(ret)); -} - -int appfilter_ubus_init(void) -{ - ubus_ctx = ubus_connect("/var/run/ubus/ubus.sock"); - if (!ubus_ctx){ - ubus_ctx = ubus_connect("/var/run/ubus.sock"); - } - if (!ubus_ctx){ - return -EIO; - } - - appfilter_add_object(&main_object); - ubus_add_uloop(ubus_ctx); - return 0; -} diff --git a/OpenAppFilter/open-app-filter/src/appfilter_ubus.h b/OpenAppFilter/open-app-filter/src/appfilter_ubus.h deleted file mode 100644 index c53dde5..0000000 --- a/OpenAppFilter/open-app-filter/src/appfilter_ubus.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - Copyright (C) 2020 Derry - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ -#ifndef __APPFILTER_UBUS_H__ -#define __APPFILTER_UBUS_H__ -int appfilter_ubus_init(void); -#endif \ No newline at end of file diff --git a/OpenAppFilter/open-app-filter/src/appfilter_user.c b/OpenAppFilter/open-app-filter/src/appfilter_user.c deleted file mode 100644 index 6b1e217..0000000 --- a/OpenAppFilter/open-app-filter/src/appfilter_user.c +++ /dev/null @@ -1,516 +0,0 @@ -/* -Copyright (C) 2020 Derry - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "appfilter_user.h" - -dev_node_t *dev_hash_table[MAX_DEV_NODE_HASH_SIZE]; -int g_cur_user_num = 0; -unsigned int hash_mac(unsigned char *mac) -{ - if (!mac) - return 0; - else - return mac[0] & (MAX_DEV_NODE_HASH_SIZE - 1); -} -int get_timestamp(void) -{ - struct timeval cur_time; - gettimeofday(&cur_time, NULL); - return cur_time.tv_sec; -} - -int hash_appid(int appid) -{ - return appid % (MAX_VISIT_HASH_SIZE - 1); -} - -void add_visit_info_node(visit_info_t **head, visit_info_t *node) -{ - if (*head == NULL) - { - *head = node; - } - else - { - node->next = *head; - *head = node; - } -} - -void init_dev_node_htable() -{ - int i; - for (i = 0; i < MAX_DEV_NODE_HASH_SIZE; i++) - { - dev_hash_table[i] = NULL; - } -} - -dev_node_t *add_dev_node(char *mac) -{ - unsigned int hash = 0; - if (g_cur_user_num >= MAX_SUPPORT_USER_NUM) - { - printf("error, user num reach max %d\n", g_cur_user_num); - return NULL; - } - hash = hash_mac(mac); - if (hash >= MAX_DEV_NODE_HASH_SIZE) - { - printf("hash code error %d\n", hash); - return NULL; - } - dev_node_t *node = (dev_node_t *)calloc(1, sizeof(dev_node_t)); - if (!node) - return NULL; - strncpy(node->mac, mac, sizeof(node->mac)); - node->online = 1; - node->online_time = get_timestamp(); - if (dev_hash_table[hash] == NULL) - dev_hash_table[hash] = node; - else - { - node->next = dev_hash_table[hash]; - dev_hash_table[hash] = node; - } - g_cur_user_num++; - printf("add mac:%s to htable[%d]....success\n", mac, hash); - return node; -} - -dev_node_t *find_dev_node(char *mac) -{ - unsigned int hash = 0; - dev_node_t *p = NULL; - hash = hash_mac(mac); - if (hash >= MAX_DEV_NODE_HASH_SIZE) - { - printf("hash code error %d\n", hash); - return NULL; - } - p = dev_hash_table[hash]; - while (p) - { - if (0 == strncmp(p->mac, mac, sizeof(p->mac))) - { - return p; - } - p = p->next; - } - return NULL; -} - -void dev_foreach(void *arg, iter_func iter) -{ - int i, j; - dev_node_t *node = NULL; - - for (i = 0; i < MAX_DEV_NODE_HASH_SIZE; i++) - { - dev_node_t *node = dev_hash_table[i]; - while (node) - { - iter(arg, node); - node = node->next; - } - } -} - -char *format_time(int timetamp) -{ - char time_buf[64] = {0}; - time_t seconds = timetamp; - struct tm *auth_tm = localtime(&seconds); - strftime(time_buf, sizeof(time_buf), "%Y %m %d %H:%M:%S", auth_tm); - return strdup(time_buf); -} - -void update_dev_hostname(void) -{ - char line_buf[256] = {0}; - char hostname_buf[128] = {0}; - char mac_buf[32] = {0}; - char ip_buf[32] = {0}; - - FILE *fp = fopen("/tmp/dhcp.leases", "r"); - if (!fp) - { - printf("open dhcp lease file....failed\n"); - return; - } - while (fgets(line_buf, sizeof(line_buf), fp)) - { - if (strlen(line_buf) <= 16) - continue; - sscanf(line_buf, "%*s %s %s %s", mac_buf, ip_buf, hostname_buf); - dev_node_t *node = find_dev_node(mac_buf); - if (!node) - continue; - if (strlen(hostname_buf) > 0) - { - strncpy(node->hostname, hostname_buf, sizeof(node->hostname)); - } - } - fclose(fp); -} - -void clean_dev_online_status(void) -{ - int i; - for (i = 0; i < MAX_DEV_NODE_HASH_SIZE; i++) - { - dev_node_t *node = dev_hash_table[i]; - while (node) - { - if (node->online){ - node->offline_time = get_timestamp(); - node->online = 0; - } - node = node->next; - } - } -} - -/* -Id Mac Ip -1 10:bf:48:37:0c:94 192.168.66.244 -*/ -void update_dev_online_status(void) -{ - char line_buf[256] = {0}; - char mac_buf[32] = {0}; - char ip_buf[32] = {0}; - - FILE *fp = fopen("/proc/net/af_client", "r"); - if (!fp) - { - printf("open dev file....failed\n"); - return; - } - fgets(line_buf, sizeof(line_buf), fp); // title - while (fgets(line_buf, sizeof(line_buf), fp)) - { - sscanf(line_buf, "%*s %s %s", mac_buf, ip_buf); - if (strlen(mac_buf) < 17) - { - printf("invalid mac:%s\n", mac_buf); - continue; - } - dev_node_t *node = find_dev_node(mac_buf); - if (!node) - { - node = add_dev_node(mac_buf); - if (!node) - continue; - strncpy(node->ip, ip_buf, sizeof(node->ip)); - } - node->online = 1; - } - fclose(fp); -} - - -#define DEV_OFFLINE_TIME (SECONDS_PER_DAY * 3) - -int check_dev_expire(void) -{ - int i, j; - int count = 0; - int cur_time = get_timestamp(); - int offline_time = 0; - int expire_count = 0; - int visit_count = 0; - for (i = 0; i < MAX_DEV_NODE_HASH_SIZE; i++) - { - dev_node_t *node = dev_hash_table[i]; - while (node) - { - if (node->online) - goto NEXT; - visit_count = 0; - offline_time = cur_time - node->offline_time; - if (offline_time > DEV_OFFLINE_TIME) - { - node->expire = 1; - for (j = 0; j < MAX_VISIT_HASH_SIZE; j++) - { - visit_info_t *p_info = node->visit_htable[j]; - while (p_info) - { - p_info->expire = 1; - visit_count++; - p_info = p_info->next; - } - } - expire_count++; - printf("dev:%s expired, offline time = %ds, count=%d, visit_count=%d\n", - node->mac, offline_time, expire_count, visit_count); - } - NEXT: - node = node->next; - } - } - return expire_count; -} - -void flush_dev_expire_node(void) -{ - int i, j; - int count = 0; - dev_node_t *node = NULL; - dev_node_t *prev = NULL; - for (i = 0; i < MAX_DEV_NODE_HASH_SIZE; i++) - { - dev_node_t *node = dev_hash_table[i]; - prev = NULL; - while (node) - { - if (node->expire) - { - if (NULL == prev) - { - dev_hash_table[i] = node->next; - free(node); - node = dev_hash_table[i]; - prev = NULL; - } - else - { - prev->next = node->next; - free(node); - node = prev->next; - } - } - else - { - prev = node; - node = node->next; - } - } - } -} - -void dump_dev_list(void) -{ - int i, j; - int count = 0; - char hostname_buf[MAX_HOSTNAME_SIZE] = {0}; - char ip_buf[MAX_IP_LEN] = {0}; - clean_dev_online_status(); - update_dev_hostname(); - update_dev_online_status(); - FILE *fp = fopen(OAF_DEV_LIST_FILE, "w"); - if (!fp) - { - return; - } - - fprintf(fp, "%-4s %-20s %-20s %-32s %-8s\n", "Id", "Mac Addr", "Ip Addr", "Hostname", "Online"); - for (i = 0; i < MAX_DEV_NODE_HASH_SIZE; i++) - { - dev_node_t *node = dev_hash_table[i]; - while (node) - { - if (node->online != 0) - { - if (strlen(node->hostname) == 0) - strcpy(hostname_buf, "*"); - else - strcpy(hostname_buf, node->hostname); - if (strlen(node->ip) == 0) - strcpy(ip_buf, "*"); - else - strcpy(ip_buf, node->ip); - fprintf(fp, "%-4d %-20s %-20s %-32s %-8d\n", - i + 1, node->mac, ip_buf, hostname_buf, node->online); - count++; - } - if (count >= MAX_SUPPORT_DEV_NUM) - { - goto EXIT; - } - node = node->next; - } - } - for (i = 0; i < MAX_DEV_NODE_HASH_SIZE; i++) - { - dev_node_t *node = dev_hash_table[i]; - while (node) - { - if (node->online == 0) - { - if (strlen(node->hostname) == 0) - strcpy(hostname_buf, "*"); - else - strcpy(hostname_buf, node->hostname); - - if (strlen(node->ip) == 0) - strcpy(ip_buf, "*"); - else - strcpy(ip_buf, node->ip); - - fprintf(fp, "%-4d %-20s %-20s %-32s %-8d\n", - i + 1, node->mac, ip_buf, hostname_buf, node->online); - } - if (count >= MAX_SUPPORT_DEV_NUM) - goto EXIT; - node = node->next; - } - } -EXIT: - fclose(fp); -} -// 记录最大保存时间 todo: support config -#define MAX_RECORD_TIME (7 * 24 * 60 * 60) // 7day -// 超过1天后清除短时间的记录 -#define RECORD_REMAIN_TIME (24 * 60 * 60) // 1day -#define INVALID_RECORD_TIME (5 * 60) // 5min - -void check_dev_visit_info_expire(void) -{ - int i, j; - int count = 0; - int cur_time = get_timestamp(); - for (i = 0; i < MAX_DEV_NODE_HASH_SIZE; i++) - { - dev_node_t *node = dev_hash_table[i]; - while (node) - { - for (j = 0; j < MAX_VISIT_HASH_SIZE; j++) - { - visit_info_t *p_info = node->visit_htable[j]; - while (p_info) - { - int total_time = p_info->latest_time - p_info->first_time; - int interval_time = cur_time - p_info->first_time; - if (interval_time > MAX_RECORD_TIME || interval_time < 0){ - p_info->expire = 1; - } - else if (interval_time > RECORD_REMAIN_TIME){ - if (total_time < INVALID_RECORD_TIME) - p_info->expire = 1; - } - p_info = p_info->next; - } - } - node = node->next; - } - } -} - -void flush_expire_visit_info(void) -{ - int i, j; - int count = 0; - visit_info_t *prev = NULL; - for (i = 0; i < MAX_DEV_NODE_HASH_SIZE; i++) - { - dev_node_t *node = dev_hash_table[i]; - while (node) - { - for (j = 0; j < MAX_VISIT_HASH_SIZE; j++) - { - visit_info_t *p_info = node->visit_htable[j]; - prev = NULL; - while (p_info) - { - if (p_info->expire){ - if (NULL == prev){ - node->visit_htable[j] = p_info->next; - free(p_info); - p_info = node->visit_htable[j]; - prev = NULL; - } - else{ - prev->next = p_info->next; - free(p_info); - p_info = prev->next; - } - } - else{ - prev = p_info; - p_info = p_info->next; - } - - } - } - node = node->next; - } - } -} - - - - -void dump_dev_visit_list(void) -{ - int i, j; - int count = 0; - FILE *fp = fopen(OAF_VISIT_LIST_FILE, "w"); - if (!fp) - { - return; - } - - fprintf(fp, "%-4s %-20s %-20s %-8s %-32s %-32s %-32s %-8s\n", "Id", "Mac Addr", - "Ip Addr", "Appid", "First Time", "Latest Time", "Total Time(s)", "Expire"); - for (i = 0; i < MAX_DEV_NODE_HASH_SIZE; i++) - { - dev_node_t *node = dev_hash_table[i]; - while (node) - { - for (j = 0; j < MAX_VISIT_HASH_SIZE; j++) - { - visit_info_t *p_info = node->visit_htable[j]; - while (p_info) - { - char *first_time_str = format_time(p_info->first_time); - char *latest_time_str = format_time(p_info->latest_time); - int total_time = p_info->latest_time - p_info->first_time; - fprintf(fp, "%-4d %-20s %-20s %-8d %-32s %-32s %-32d %-4d\n", - count, node->mac, node->ip, p_info->appid, first_time_str, - latest_time_str, total_time, p_info->expire); - if (first_time_str) - free(first_time_str); - if (latest_time_str) - free(latest_time_str); - p_info = p_info->next; - count++; - if (count > 50) - goto EXIT; - } - } - node = node->next; - } - } -EXIT: - fclose(fp); -} diff --git a/OpenAppFilter/open-app-filter/src/appfilter_user.h b/OpenAppFilter/open-app-filter/src/appfilter_user.h deleted file mode 100644 index fa88d80..0000000 --- a/OpenAppFilter/open-app-filter/src/appfilter_user.h +++ /dev/null @@ -1,118 +0,0 @@ -/* -Copyright (C) 2020 Derry - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -#ifndef __FILTER_USER_H__ -#define __FILTER_USER_H__ -#define MAX_IP_LEN 32 -#define MAX_MAC_LEN 32 -#define MAX_VISIT_HASH_SIZE 64 -#define MAX_DEV_NODE_HASH_SIZE 64 -#define MAX_HOSTNAME_SIZE 64 -#define MAX_SUPPORT_USER_NUM 64 -#define OAF_VISIT_LIST_FILE "/tmp/visit_list" -#define OAF_DEV_LIST_FILE "/tmp/dev_list" -#define MIN_VISIT_TIME 5 // default 5s -#define MAX_APP_STAT_NUM 8 -#define MAX_VISITLIST_DUMP_NUM 16 -#define MAX_APP_TYPE 16 -#define MAX_APP_ID_NUM 128 -#define MAX_SUPPORT_DEV_NUM 64 -#define SECONDS_PER_DAY (24 * 3600) - -//extern dev_node_t *dev_hash_table[MAX_DEV_NODE_HASH_SIZE]; - -/* -{ -"mac": "10:bf:48:37:0c:94", -"ip": "192.168.100.244", -"app_num": 0, -"visit_info": [{ -"appid": 8002, -"latest_action": 1, -"latest_time": 1602604293, -"total_num": 4, -"drop_num": 4, -"history_info": [] -}] -} -*/ -/* 单个访问记录结构 */ -typedef struct visit_info -{ - int appid; - int first_time; - int latest_time; - int action; - int expire; /*定期清除无效数据*/ - struct visit_info *next; -} visit_info_t; - -/* 用于记录某个app总时间和总流量 */ -typedef struct visit_stat -{ - unsigned long long total_time; - unsigned long long total_down_bytes; - unsigned long long total_up_bytes; -} visit_stat_t; - -typedef struct dev_node -{ - char mac[MAX_MAC_LEN]; - char ip[MAX_IP_LEN]; - char hostname[MAX_HOSTNAME_SIZE]; - int online; - int expire; - int offline_time; - int online_time; - visit_info_t *visit_htable[MAX_VISIT_HASH_SIZE]; - visit_stat_t stat[MAX_APP_TYPE][MAX_APP_ID_NUM]; - struct dev_node *next; -} dev_node_t; - -struct app_visit_info -{ - int app_id; - char app_name[32]; - int total_time; -}; - -struct app_visit_stat_info -{ - int num; - struct app_visit_info visit_list[MAX_APP_STAT_NUM]; -}; -typedef void (*iter_func)(void *arg, dev_node_t *dev); -//todo:dev for each -extern dev_node_t *dev_hash_table[MAX_DEV_NODE_HASH_SIZE]; - -dev_node_t *add_dev_node(char *mac); -void init_dev_node_htable(); -void dump_dev_list(void); -void dump_dev_visit_list(void); -dev_node_t *find_dev_node(char *mac); -void dev_foreach(void *arg, iter_func iter); -void add_visit_info_node(visit_info_t **head, visit_info_t *node); -void check_dev_visit_info_expire(void); -void flush_expire_visit_info(); -int check_dev_expire(void); -void flush_dev_expire_node(void); -void flush_expire_visit_info(void); -#endif diff --git a/OpenAppFilter/open-app-filter/src/main.c b/OpenAppFilter/open-app-filter/src/main.c deleted file mode 100644 index 586db2f..0000000 --- a/OpenAppFilter/open-app-filter/src/main.c +++ /dev/null @@ -1,138 +0,0 @@ -/* -Copyright (C) 2020 Derry - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -#include -#include -#include -#include -#include -#include -#include "appfilter_user.h" -#include "appfilter_netlink.h" -#include "appfilter_ubus.h" -#include "appfilter_config.h" -#include -void check_appfilter_enable(void) -{ - int enable = 1; - struct tm *t; - af_ctl_time_t *af_t = NULL; - time_t tt; - time(&tt); - enable = config_get_appfilter_enable(); - - if (0 == enable) - goto EXIT; - af_t = load_appfilter_ctl_time_config(); - if (!af_t) - { - enable = 0; - goto EXIT; - } - - t = localtime(&tt); - if (af_t->days[t->tm_wday] != 1) - { - if (af_t->time_mode == 0){ - enable = 0; - goto EXIT; - } - } - - int cur_mins = t->tm_hour * 60 + t->tm_min; - if (((af_t->start.hour * 60 + af_t->start.min < cur_mins) && (cur_mins < af_t->end.hour * 60 + af_t->end.min)) - || ((af_t->start2.hour * 60 + af_t->start2.min < cur_mins) && (cur_mins < af_t->end2.hour * 60 + af_t->end2.min)) - ) - { - if (af_t->time_mode == 0){ - enable = 1; - } - else{ - enable = 0; - } - } - else{ - if (af_t->time_mode == 0){ - enable = 0; - } - else{ - enable = 1; - } - } -EXIT: - if (enable) - { - system("echo 1 >/proc/sys/oaf/enable "); - } - else - system("echo 0 >/proc/sys/oaf/enable "); - if (af_t) - free(af_t); -} - -void dev_list_timeout_handler(struct uloop_timeout *t) -{ - dump_dev_list(); - check_dev_visit_info_expire(); - flush_expire_visit_info(); - //dump_dev_visit_list(); - check_appfilter_enable(); - //todo: dev list expire - if (check_dev_expire()){ - flush_expire_visit_info(); - flush_dev_expire_node(); - } - uloop_timeout_set(t, 10000); -} - -struct uloop_timeout dev_tm = { - .cb = dev_list_timeout_handler}; - -static struct uloop_fd appfilter_nl_fd = { - .cb = appfilter_nl_handler, -}; - -int main(int argc, char **argv) -{ - int ret = 0; - uloop_init(); - printf("init appfilter\n"); - init_dev_node_htable(); - init_app_name_table(); - init_app_class_name_table(); - if (appfilter_ubus_init() < 0) - { - fprintf(stderr, "Failed to connect to ubus\n"); - return 1; - } - - - appfilter_nl_fd.fd = appfilter_nl_init(); - uloop_fd_add(&appfilter_nl_fd, ULOOP_READ); - af_msg_t msg; - msg.action = AF_MSG_INIT; - send_msg_to_kernel(appfilter_nl_fd.fd, (void *)&msg, sizeof(msg)); - uloop_timeout_set(&dev_tm, 5000); - uloop_timeout_add(&dev_tm); - uloop_run(); - uloop_done(); - return 0; -}