🐶 Sync 2025-11-02 14:26:26
This commit is contained in:
1
luci-app-mosdns/htdocs/luci-static/resources/codemirror5/addon/display/autorefresh.min.js
vendored
Normal file
1
luci-app-mosdns/htdocs/luci-static/resources/codemirror5/addon/display/autorefresh.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],e):e(CodeMirror)}(function(u){"use strict";function f(e,t){clearTimeout(t.timeout),u.off(window,"mouseup",t.hurry),u.off(window,"keyup",t.hurry)}u.defineOption("autoRefresh",!1,function(e,t){function o(){i.display.wrapper.offsetHeight?(f(0,r),i.display.lastWrapHeight!=i.display.wrapper.clientHeight&&i.refresh()):r.timeout=setTimeout(o,r.delay)}var i,r;e.state.autoRefresh&&(f(0,e.state.autoRefresh),e.state.autoRefresh=null),t&&0==e.display.wrapper.offsetHeight&&((r=(i=e).state.autoRefresh={delay:t.delay||250}).timeout=setTimeout(o,r.delay),r.hurry=function(){clearTimeout(r.timeout),r.timeout=setTimeout(o,50)},u.on(window,"mouseup",r.hurry),u.on(window,"keyup",r.hurry))})});
|
||||
1
luci-app-mosdns/htdocs/luci-static/resources/codemirror5/addon/lint/lint.min.css
vendored
Normal file
1
luci-app-mosdns/htdocs/luci-static/resources/codemirror5/addon/lint/lint.min.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.CodeMirror-lint-markers{width:16px}.CodeMirror-lint-tooltip{background-color:#ffd;border:1px solid #000;border-radius:4px 4px 4px 4px;color:#000;font-family:monospace;font-size:10pt;overflow:hidden;padding:2px 5px;position:fixed;white-space:pre;white-space:pre-wrap;z-index:100;max-width:600px;opacity:0;transition:opacity .4s;-moz-transition:opacity .4s;-webkit-transition:opacity .4s;-o-transition:opacity .4s;-ms-transition:opacity .4s}.CodeMirror-lint-mark{background-position:left bottom;background-repeat:repeat-x}.CodeMirror-lint-mark-warning{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII=)}.CodeMirror-lint-mark-error{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg==)}.CodeMirror-lint-marker{background-position:center center;background-repeat:no-repeat;cursor:pointer;display:inline-block;height:16px;width:16px;vertical-align:middle;position:relative}.CodeMirror-lint-message{padding-left:18px;background-position:top left;background-repeat:no-repeat}.CodeMirror-lint-marker-warning,.CodeMirror-lint-message-warning{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAANlBMVEX/uwDvrwD/uwD/uwD/uwD/uwD/uwD/uwD/uwD6twD/uwAAAADurwD2tQD7uAD+ugAAAAD/uwDhmeTRAAAADHRSTlMJ8mN1EYcbmiixgACm7WbuAAAAVklEQVR42n3PUQqAIBBFUU1LLc3u/jdbOJoW1P08DA9Gba8+YWJ6gNJoNYIBzAA2chBth5kLmG9YUoG0NHAUwFXwO9LuBQL1giCQb8gC9Oro2vp5rncCIY8L8uEx5ZkAAAAASUVORK5CYII=)}.CodeMirror-lint-marker-error,.CodeMirror-lint-message-error{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAHlBMVEW7AAC7AACxAAC7AAC7AAAAAAC4AAC5AAD///+7AAAUdclpAAAABnRSTlMXnORSiwCK0ZKSAAAATUlEQVR42mWPOQ7AQAgDuQLx/z8csYRmPRIFIwRGnosRrpamvkKi0FTIiMASR3hhKW+hAN6/tIWhu9PDWiTGNEkTtIOucA5Oyr9ckPgAWm0GPBog6v4AAAAASUVORK5CYII=)}.CodeMirror-lint-marker-multiple{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAMAAADzjKfhAAAACVBMVEUAAAAAAAC/v7914kyHAAAAAXRSTlMAQObYZgAAACNJREFUeNo1ioEJAAAIwmz/H90iFFSGJgFMe3gaLZ0od+9/AQZ0ADosbYraAAAAAElFTkSuQmCC);background-repeat:no-repeat;background-position:right bottom;width:100%;height:100%}.CodeMirror-lint-line-error{background-color:rgba(183,76,81,.08)}.CodeMirror-lint-line-warning{background-color:rgba(255,211,0,.1)}
|
||||
1
luci-app-mosdns/htdocs/luci-static/resources/codemirror5/addon/lint/lint.min.js
vendored
Normal file
1
luci-app-mosdns/htdocs/luci-static/resources/codemirror5/addon/lint/lint.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(t){"object"==typeof exports&&"object"==typeof module?t(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],t):t(CodeMirror)}(function(p){"use strict";var h="CodeMirror-lint-markers",g="CodeMirror-lint-line-";function u(t){t.parentNode&&t.parentNode.removeChild(t)}function v(t,e,n,o){t=t,e=e,n=n,(i=document.createElement("div")).className="CodeMirror-lint-tooltip cm-s-"+t.options.theme,i.appendChild(n.cloneNode(!0)),(t.state.lint.options.selfContain?t.getWrapperElement():document.body).appendChild(i),p.on(document,"mousemove",a),a(e),null!=i.style.opacity&&(i.style.opacity=1);var i,r=i;function a(t){if(!i.parentNode)return p.off(document,"mousemove",a);var e=Math.max(0,t.clientY-i.offsetHeight-5),t=Math.max(0,Math.min(t.clientX+5,i.ownerDocument.defaultView.innerWidth-i.offsetWidth));i.style.top=e+"px",i.style.left=t+"px"}function l(){var t;p.off(o,"mouseout",l),r&&((t=r).parentNode&&(null==t.style.opacity&&u(t),t.style.opacity=0,setTimeout(function(){u(t)},600)),r=null)}var s=setInterval(function(){if(r)for(var t=o;;t=t.parentNode){if((t=t&&11==t.nodeType?t.host:t)==document.body)return;if(!t){l();break}}if(!r)return clearInterval(s)},400);p.on(o,"mouseout",l)}function a(s,t,e){for(var n in this.marked=[],(t=t instanceof Function?{getAnnotations:t}:t)&&!0!==t||(t={}),this.options={},this.linterOptions=t.options||{},o)this.options[n]=o[n];for(var n in t)o.hasOwnProperty(n)?null!=t[n]&&(this.options[n]=t[n]):t.options||(this.linterOptions[n]=t[n]);this.timeout=null,this.hasGutter=e,this.onMouseOver=function(t){var e=s,n=t.target||t.srcElement;if(/\bCodeMirror-lint-mark-/.test(n.className)){for(var n=n.getBoundingClientRect(),o=(n.left+n.right)/2,n=(n.top+n.bottom)/2,i=e.findMarksAt(e.coordsChar({left:o,top:n},"client")),r=[],a=0;a<i.length;++a){var l=i[a].__annotation;l&&r.push(l)}r.length&&!function(t,e,n){for(var o=n.target||n.srcElement,i=document.createDocumentFragment(),r=0;r<e.length;r++){var a=e[r];i.appendChild(M(a))}v(t,n,i,o)}(e,r,t)}},this.waitingFor=0}var o={highlightLines:!1,tooltips:!0,delay:500,lintOnChange:!0,getAnnotations:null,async:!1,selfContain:null,formatAnnotation:null,onUpdateLinting:null};function C(t){var n,e=t.state.lint;e.hasGutter&&t.clearGutter(h),e.options.highlightLines&&(n=t).eachLine(function(t){var e=t.wrapClass&&/\bCodeMirror-lint-line-\w+\b/.exec(t.wrapClass);e&&n.removeLineClass(t,"wrap",e[0])});for(var o=0;o<e.marked.length;++o)e.marked[o].clear();e.marked.length=0}function M(t){var e=(e=t.severity)||"error",n=document.createElement("div");return n.className="CodeMirror-lint-message CodeMirror-lint-message-"+e,void 0!==t.messageHTML?n.innerHTML=t.messageHTML:n.appendChild(document.createTextNode(t.message)),n}function l(e){var t,n,o,i,r,a,l=e.state.lint;function s(){a=-1,o.off("change",s)}!l||(t=(i=l.options).getAnnotations||e.getHelper(p.Pos(0,0),"lint"))&&(i.async||t.async?(i=t,r=(o=e).state.lint,a=++r.waitingFor,o.on("change",s),i(o.getValue(),function(t,e){o.off("change",s),r.waitingFor==a&&(e&&t instanceof p&&(t=e),o.operation(function(){c(o,t)}))},r.linterOptions,o)):(n=t(e.getValue(),l.linterOptions,e))&&(n.then?n.then(function(t){e.operation(function(){c(e,t)})}):e.operation(function(){c(e,n)})))}function c(t,e){var n=t.state.lint;if(n){for(var o,i,r=n.options,a=(C(t),function(t){for(var e=[],n=0;n<t.length;++n){var o=t[n],i=o.from.line;(e[i]||(e[i]=[])).push(o)}return e}(e)),l=0;l<a.length;++l){var s=a[l];if(s){for(var u=null,c=n.hasGutter&&document.createDocumentFragment(),f=0;f<s.length;++f){var m=s[f],d=m.severity;i=d=d||"error",u="error"==(o=u)?o:i,r.formatAnnotation&&(m=r.formatAnnotation(m)),n.hasGutter&&c.appendChild(M(m)),m.to&&n.marked.push(t.markText(m.from,m.to,{className:"CodeMirror-lint-mark CodeMirror-lint-mark-"+d,__annotation:m}))}n.hasGutter&&t.setGutterMarker(l,h,function(e,n,t,o,i){var r=document.createElement("div"),a=r;return r.className="CodeMirror-lint-marker CodeMirror-lint-marker-"+t,o&&((a=r.appendChild(document.createElement("div"))).className="CodeMirror-lint-marker CodeMirror-lint-marker-multiple"),0!=i&&p.on(a,"mouseover",function(t){v(e,t,n,a)}),r}(t,c,u,1<s.length,r.tooltips)),r.highlightLines&&t.addLineClass(l,"wrap",g+u)}}r.onUpdateLinting&&r.onUpdateLinting(e,a,t)}}function s(t){var e=t.state.lint;e&&(clearTimeout(e.timeout),e.timeout=setTimeout(function(){l(t)},e.options.delay))}p.defineOption("lint",!1,function(t,e,n){if(n&&n!=p.Init&&(C(t),!1!==t.state.lint.options.lintOnChange&&t.off("change",s),p.off(t.getWrapperElement(),"mouseover",t.state.lint.onMouseOver),clearTimeout(t.state.lint.timeout),delete t.state.lint),e){for(var o=t.getOption("gutters"),i=!1,r=0;r<o.length;++r)o[r]==h&&(i=!0);n=t.state.lint=new a(t,e,i);n.options.lintOnChange&&t.on("change",s),0!=n.options.tooltips&&"gutter"!=n.options.tooltips&&p.on(t.getWrapperElement(),"mouseover",n.onMouseOver),l(t)}}),p.defineExtension("performLint",function(){l(this)})});
|
||||
1
luci-app-mosdns/htdocs/luci-static/resources/codemirror5/addon/lint/yaml-lint.min.js
vendored
Normal file
1
luci-app-mosdns/htdocs/luci-static/resources/codemirror5/addon/lint/yaml-lint.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(o){"object"==typeof exports&&"object"==typeof module?o(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],o):o(CodeMirror)}(function(n){"use strict";n.registerHelper("lint","yaml",function(e){var r=[];if(!window.jsyaml)return window.console&&window.console.error("Error: window.jsyaml not defined, CodeMirror YAML linting cannot run."),r;try{jsyaml.loadAll(e)}catch(o){e=o.mark,e=e?n.Pos(e.line,e.column):n.Pos(0,0);r.push({from:e,to:e,message:o.message})}return r})});
|
||||
1
luci-app-mosdns/htdocs/luci-static/resources/codemirror5/codemirror.min.css
vendored
Normal file
1
luci-app-mosdns/htdocs/luci-static/resources/codemirror5/codemirror.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
luci-app-mosdns/htdocs/luci-static/resources/codemirror5/codemirror.min.js
vendored
Normal file
1
luci-app-mosdns/htdocs/luci-static/resources/codemirror5/codemirror.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
luci-app-mosdns/htdocs/luci-static/resources/codemirror5/libs/js-yaml.min.js
vendored
Normal file
2
luci-app-mosdns/htdocs/luci-static/resources/codemirror5/libs/js-yaml.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
luci-app-mosdns/htdocs/luci-static/resources/codemirror5/mode/yaml/yaml.min.js
vendored
Normal file
1
luci-app-mosdns/htdocs/luci-static/resources/codemirror5/mode/yaml/yaml.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],e):e(CodeMirror)}(function(e){"use strict";e.defineMode("yaml",function(){var n=new RegExp("\\b(("+["true","false","on","off","yes","no"].join(")|(")+"))$","i");return{token:function(e,i){var t=e.peek(),r=i.escaped;if(i.escaped=!1,"#"==t&&(0==e.pos||/\s/.test(e.string.charAt(e.pos-1))))return e.skipToEnd(),"comment";if(e.match(/^('([^']|\\.)*'?|"([^"]|\\.)*"?)/))return"string";if(i.literal&&e.indentation()>i.keyCol)return e.skipToEnd(),"string";if(i.literal&&(i.literal=!1),e.sol()){if(i.keyCol=0,i.pair=!1,i.pairStart=!1,e.match("---"))return"def";if(e.match("..."))return"def";if(e.match(/\s*-\s+/))return"meta"}if(e.match(/^(\{|\}|\[|\])/))return"{"==t?i.inlinePairs++:"}"==t?i.inlinePairs--:"["==t?i.inlineList++:i.inlineList--,"meta";if(0<i.inlineList&&!r&&","==t)return e.next(),"meta";if(0<i.inlinePairs&&!r&&","==t)return i.keyCol=0,i.pair=!1,i.pairStart=!1,e.next(),"meta";if(i.pairStart){if(e.match(/^\s*(\||\>)\s*/))return i.literal=!0,"meta";if(e.match(/^\s*(\&|\*)[a-z0-9\._-]+\b/i))return"variable-2";if(0==i.inlinePairs&&e.match(/^\s*-?[0-9\.\,]+\s?$/))return"number";if(0<i.inlinePairs&&e.match(/^\s*-?[0-9\.\,]+\s?(?=(,|}))/))return"number";if(e.match(n))return"keyword"}return!i.pair&&e.match(/^\s*(?:[,\[\]{}&*!|>'"%@`][^\s'":]|[^\s,\[\]{}#&*!|>'"%@`])[^#:]*(?=:($|\s))/)?(i.pair=!0,i.keyCol=e.indentation(),"atom"):i.pair&&e.match(/^:\s*/)?(i.pairStart=!0,"meta"):(i.pairStart=!1,i.escaped="\\"==t,e.next(),null)},startState:function(){return{pair:!1,pairStart:!1,keyCol:0,inlinePairs:0,inlineList:0,literal:!1,escaped:!1}},lineComment:"#",fold:"indent"}}),e.defineMIME("text/x-yaml","yaml"),e.defineMIME("text/yaml","yaml")});
|
||||
1
luci-app-mosdns/htdocs/luci-static/resources/codemirror5/theme/dracula.min.css
vendored
Normal file
1
luci-app-mosdns/htdocs/luci-static/resources/codemirror5/theme/dracula.min.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.cm-s-dracula .CodeMirror-gutters,.cm-s-dracula.CodeMirror{background-color:#282a36!important;color:#f8f8f2!important;border:none}.cm-s-dracula .CodeMirror-gutters{color:#282a36}.cm-s-dracula .CodeMirror-cursor{border-left:solid thin #f8f8f0}.cm-s-dracula .CodeMirror-linenumber{color:#6d8a88}.cm-s-dracula .CodeMirror-selected{background:rgba(255,255,255,.1)}.cm-s-dracula .CodeMirror-line::selection,.cm-s-dracula .CodeMirror-line>span::selection,.cm-s-dracula .CodeMirror-line>span>span::selection{background:rgba(255,255,255,.1)}.cm-s-dracula .CodeMirror-line::-moz-selection,.cm-s-dracula .CodeMirror-line>span::-moz-selection,.cm-s-dracula .CodeMirror-line>span>span::-moz-selection{background:rgba(255,255,255,.1)}.cm-s-dracula span.cm-comment{color:#6272a4}.cm-s-dracula span.cm-string,.cm-s-dracula span.cm-string-2{color:#f1fa8c}.cm-s-dracula span.cm-number{color:#bd93f9}.cm-s-dracula span.cm-variable{color:#50fa7b}.cm-s-dracula span.cm-variable-2{color:#fff}.cm-s-dracula span.cm-def{color:#50fa7b}.cm-s-dracula span.cm-operator{color:#ff79c6}.cm-s-dracula span.cm-keyword{color:#ff79c6}.cm-s-dracula span.cm-atom{color:#bd93f9}.cm-s-dracula span.cm-meta{color:#f8f8f2}.cm-s-dracula span.cm-tag{color:#ff79c6}.cm-s-dracula span.cm-attribute{color:#50fa7b}.cm-s-dracula span.cm-qualifier{color:#50fa7b}.cm-s-dracula span.cm-property{color:#66d9ef}.cm-s-dracula span.cm-builtin{color:#50fa7b}.cm-s-dracula span.cm-type,.cm-s-dracula span.cm-variable-3{color:#ffb86c}.cm-s-dracula .CodeMirror-activeline-background{background:rgba(255,255,255,.1)}.cm-s-dracula .CodeMirror-matchingbracket{text-decoration:underline;color:#fff!important}
|
||||
@@ -0,0 +1,457 @@
|
||||
'use strict';
|
||||
'require form';
|
||||
'require fs';
|
||||
'require poll';
|
||||
'require rpc';
|
||||
'require uci';
|
||||
'require ui';
|
||||
'require view';
|
||||
|
||||
var callServiceList = rpc.declare({
|
||||
object: 'service',
|
||||
method: 'list',
|
||||
params: ['name'],
|
||||
expect: { '': {} }
|
||||
});
|
||||
|
||||
function getServiceStatus() {
|
||||
return L.resolveDefault(callServiceList('mosdns'), {}).then(function (res) {
|
||||
var isRunning = false;
|
||||
try {
|
||||
isRunning = res['mosdns']['instances']['mosdns']['running'];
|
||||
} catch (e) { }
|
||||
return isRunning;
|
||||
});
|
||||
}
|
||||
|
||||
function renderStatus(isRunning) {
|
||||
var spanTemp = '<em><span style="color:%s"><strong>%s %s</strong></span></em>';
|
||||
var renderHTML;
|
||||
if (isRunning) {
|
||||
renderHTML = spanTemp.format('green', _('MosDNS'), _('RUNNING'));
|
||||
} else {
|
||||
renderHTML = spanTemp.format('red', _('MosDNS'), _('NOT RUNNING'));
|
||||
}
|
||||
|
||||
return renderHTML;
|
||||
}
|
||||
|
||||
async function loadCodeMirrorResources() {
|
||||
const styles = [
|
||||
'/luci-static/resources/codemirror5/theme/dracula.min.css',
|
||||
'/luci-static/resources/codemirror5/addon/lint/lint.min.css',
|
||||
'/luci-static/resources/codemirror5/codemirror.min.css',
|
||||
];
|
||||
const scripts = [
|
||||
'/luci-static/resources/codemirror5/libs/js-yaml.min.js',
|
||||
'/luci-static/resources/codemirror5/codemirror.min.js',
|
||||
'/luci-static/resources/codemirror5/addon/display/autorefresh.min.js',
|
||||
'/luci-static/resources/codemirror5/mode/yaml/yaml.min.js',
|
||||
'/luci-static/resources/codemirror5/addon/lint/lint.min.js',
|
||||
'/luci-static/resources/codemirror5/addon/lint/yaml-lint.min.js',
|
||||
];
|
||||
const loadStyles = async () => {
|
||||
for (const href of styles) {
|
||||
const link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
link.href = href;
|
||||
document.head.appendChild(link);
|
||||
}
|
||||
};
|
||||
const loadScripts = async () => {
|
||||
for (const src of scripts) {
|
||||
const script = document.createElement('script');
|
||||
script.src = src;
|
||||
document.head.appendChild(script);
|
||||
await new Promise(resolve => script.onload = resolve);
|
||||
}
|
||||
};
|
||||
await loadStyles();
|
||||
await loadScripts();
|
||||
}
|
||||
|
||||
return view.extend({
|
||||
load: function () {
|
||||
return Promise.all([
|
||||
L.resolveDefault(fs.exec('/usr/bin/mosdns', ['version']), null),
|
||||
]);
|
||||
},
|
||||
|
||||
handleFlushCache: function (m, section_id, ev) {
|
||||
return fs.exec('/usr/share/mosdns/mosdns.sh', ['flush'])
|
||||
.then(function (lazy_cache) {
|
||||
var res = lazy_cache.code;
|
||||
if (res === 0) {
|
||||
ui.addNotification(null, E('p', _('Flushing DNS Cache Success.')), 'info');
|
||||
} else {
|
||||
ui.addNotification(null, E('p', _('Flushing DNS Cache Failed, Please check if MosDNS is running.')), 'error');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
render: function (basic) {
|
||||
var m, s, o, v;
|
||||
v = '';
|
||||
|
||||
if (basic[0] && basic[0].code === 0) {
|
||||
v = basic[0].stdout.trim();
|
||||
}
|
||||
m = new form.Map('mosdns', _('MosDNS') + ' ' + v,
|
||||
_('MosDNS is a plugin-based DNS forwarder/traffic splitter.'));
|
||||
|
||||
s = m.section(form.TypedSection);
|
||||
s.anonymous = true;
|
||||
s.render = function () {
|
||||
setTimeout(function () {
|
||||
poll.add(function () {
|
||||
return L.resolveDefault(getServiceStatus()).then(function (res) {
|
||||
var view = document.getElementById('service_status');
|
||||
if (view) {
|
||||
view.innerHTML = renderStatus(res);
|
||||
} else {
|
||||
console.error('Element #service_status not found.');
|
||||
}
|
||||
});
|
||||
});
|
||||
}, 100);
|
||||
|
||||
/* dynamically loading Codemirror resources */
|
||||
loadCodeMirrorResources();
|
||||
|
||||
return E('div', { class: 'cbi-section', id: 'status_bar' }, [
|
||||
E('p', { id: 'service_status' }, _('Collecting data...'))
|
||||
]);
|
||||
}
|
||||
|
||||
s = m.section(form.NamedSection, 'config', 'mosdns');
|
||||
|
||||
s.tab('basic', _('Basic Options'));
|
||||
s.tab("advanced", _("Advanced Options"));
|
||||
s.tab("cloudflare", _("Cloudflare Options"));
|
||||
s.tab("api", _("API Options"));
|
||||
s.tab('geodata', _('GeoData Export'));
|
||||
|
||||
/* basic */
|
||||
o = s.taboption('basic', form.Flag, 'enabled', _('Enabled'));
|
||||
o.default = o.disabled;
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.taboption('basic', form.ListValue, 'configfile', _('Config File'));
|
||||
o.value('/var/etc/mosdns.json', _('Default Config'));
|
||||
o.value('/etc/mosdns/config_custom.yaml', _('Custom Config'));
|
||||
o.default = '/var/etc/mosdns.json';
|
||||
|
||||
o = s.taboption('basic', form.Value, 'listen_port', _('Listen port'));
|
||||
o.default = '5335';
|
||||
o.datatype = 'port';
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
|
||||
o = s.taboption('basic', form.ListValue, 'log_level', _('Log Level'));
|
||||
o.value('debug', _('Debug'));
|
||||
o.value('info', _('Info'));
|
||||
o.value('warn', _('Warning'));
|
||||
o.value('error', _('Error'));
|
||||
o.default = 'info';
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
|
||||
o = s.taboption('basic', form.Value, 'log_file', _('Log File'));
|
||||
o.placeholder = '/var/log/mosdns.log';
|
||||
o.default = '/var/log/mosdns.log';
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
|
||||
o = s.taboption('basic', form.Flag, 'redirect', _('DNS Forward'), _('Forward Dnsmasq Domain Name resolution requests to MosDNS'));
|
||||
o.default = false;
|
||||
|
||||
if (L.hasSystemFeature('firewall4')) {
|
||||
o = s.taboption('basic', form.Flag, 'local_dns_redirect', _('DNS redirect'), _('Force redirect all local DNS queries to MosDNS, a.k.a. DNS Hijacking'));
|
||||
o.default = false;
|
||||
o.depends('redirect', '1');
|
||||
}
|
||||
|
||||
o = s.taboption('basic', form.Flag, 'prefer_ipv4_cn', _('China DNS prefer IPv4'),
|
||||
_('IPv4 is preferred for China DNS resolution of dual-stack addresses, and is not affected when the destination is IPv6 only'));
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
o.default = false;
|
||||
|
||||
o = s.taboption('basic', form.Flag, 'prefer_ipv4', _('Remote DNS prefer IPv4'),
|
||||
_('IPv4 is preferred for Remote / Streaming Media DNS resolution of dual-stack addresses, and is not affected when the destination is IPv6 only'));
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
o.default = false;
|
||||
|
||||
o = s.taboption('basic', form.Flag, 'custom_local_dns', _('Custom China DNS'), _('Follow WAN interface DNS if not enabled'));
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
o.default = false;
|
||||
|
||||
o = s.taboption('basic', form.Flag, 'apple_optimization', _('Apple domains optimization'),
|
||||
_('For Apple domains equipped with Chinese mainland CDN, always responsive to Chinese CDN IP addresses'));
|
||||
o.depends('custom_local_dns', '1');
|
||||
o.default = false;
|
||||
|
||||
o = s.taboption('basic', form.DynamicList, 'local_dns', _('China DNS server'));
|
||||
o.value('119.29.29.29', _('Tencent Public DNS (119.29.29.29)'));
|
||||
o.value('119.28.28.28', _('Tencent Public DNS (119.28.28.28)'));
|
||||
o.value('223.5.5.5', _('Aliyun Public DNS (223.5.5.5)'));
|
||||
o.value('223.6.6.6', _('Aliyun Public DNS (223.6.6.6)'));
|
||||
o.value('180.184.1.1', _('TrafficRoute Public DNS (180.184.1.1)'));
|
||||
o.value('180.184.2.2', _('TrafficRoute Public DNS (180.184.2.2)'));
|
||||
o.value('114.114.114.114', _('Xinfeng Public DNS (114.114.114.114)'));
|
||||
o.value('114.114.115.115', _('Xinfeng Public DNS (114.114.115.115)'));
|
||||
o.value('180.76.76.76', _('Baidu Public DNS (180.76.76.76)'));
|
||||
o.value('https://doh.pub/dns-query', _('Tencent Public DNS (DNS over HTTPS)'));
|
||||
o.value('quic://dns.alidns.com', _('Aliyun Public DNS (DNS over QUIC)'));
|
||||
o.value('https://dns.alidns.com/dns-query', _('Aliyun Public DNS (DNS over HTTPS)'));
|
||||
o.value('h3://dns.alidns.com/dns-query', _('Aliyun Public DNS (DNS over HTTPS/3)'));
|
||||
o.value('https://doh.360.cn/dns-query', _('360 Public DNS (DNS over HTTPS)'));
|
||||
o.default = '119.29.29.29';
|
||||
o.depends('custom_local_dns', '1');
|
||||
|
||||
o = s.taboption('basic', form.DynamicList, 'remote_dns', _('Remote DNS server'));
|
||||
o.value('tls://1.1.1.1', _('CloudFlare Public DNS (1.1.1.1)'));
|
||||
o.value('tls://1.0.0.1', _('CloudFlare Public DNS (1.0.0.1)'));
|
||||
o.value('tls://8.8.8.8', _('Google Public DNS (8.8.8.8)'));
|
||||
o.value('tls://8.8.4.4', _('Google Public DNS (8.8.4.4)'));
|
||||
o.value('tls://9.9.9.9', _('Quad9 Public DNS (9.9.9.9)'));
|
||||
o.value('tls://149.112.112.112', _('Quad9 Public DNS (149.112.112.112)'));
|
||||
o.value('tls://208.67.222.222', _('Cisco Public DNS (208.67.222.222)'));
|
||||
o.value('tls://208.67.220.220', _('Cisco Public DNS (208.67.220.220)'));
|
||||
o.default = 'tls://8.8.8.8';
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
|
||||
o = s.taboption('basic', form.Flag, 'custom_stream_media_dns', _('Custom Stream Media DNS'),
|
||||
_('Netflix, Disney+, Hulu and streaming media rules list will use this DNS'));
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
o.default = false;
|
||||
|
||||
o = s.taboption('basic', form.DynamicList, 'stream_media_dns', _('Streaming Media DNS server'));
|
||||
o.value('tls://1.1.1.1', _('CloudFlare Public DNS (1.1.1.1)'));
|
||||
o.value('tls://1.0.0.1', _('CloudFlare Public DNS (1.0.0.1)'));
|
||||
o.value('tls://8.8.8.8', _('Google Public DNS (8.8.8.8)'));
|
||||
o.value('tls://8.8.4.4', _('Google Public DNS (8.8.4.4)'));
|
||||
o.value('tls://9.9.9.9', _('Quad9 Public DNS (9.9.9.9)'));
|
||||
o.value('tls://149.112.112.112', _('Quad9 Public DNS (149.112.112.112)'));
|
||||
o.value('tls://208.67.222.222', _('Cisco Public DNS (208.67.222.222)'));
|
||||
o.value('tls://208.67.220.220', _('Cisco Public DNS (208.67.220.220)'));
|
||||
o.default = 'tls://8.8.8.8';
|
||||
o.depends('custom_stream_media_dns', '1');
|
||||
|
||||
o = s.taboption('basic', form.Value, 'bootstrap_dns', _('Bootstrap DNS servers'),
|
||||
_('Bootstrap DNS servers are used to resolve IP addresses of the DoH/DoT resolvers you specify as upstreams'));
|
||||
o.value('119.29.29.29', _('Tencent Public DNS (119.29.29.29)'));
|
||||
o.value('119.28.28.28', _('Tencent Public DNS (119.28.28.28)'));
|
||||
o.value('223.5.5.5', _('Aliyun Public DNS (223.5.5.5)'));
|
||||
o.value('223.6.6.6', _('Aliyun Public DNS (223.6.6.6)'));
|
||||
o.value('114.114.114.114', _('Xinfeng Public DNS (114.114.114.114)'));
|
||||
o.value('114.114.115.115', _('Xinfeng Public DNS (114.114.115.115)'));
|
||||
o.value('180.76.76.76', _('Baidu Public DNS (180.76.76.76)'));
|
||||
o.value('8.8.8.8', _('Google Public DNS (8.8.8.8)'));
|
||||
o.value('1.1.1.1', _('CloudFlare Public DNS (1.1.1.1)'));
|
||||
o.default = '119.29.29.29';
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
|
||||
/* advanced */
|
||||
o = s.taboption('advanced', form.Value, 'concurrent', _('Concurrent'),
|
||||
_('DNS query request concurrency, The number of upstream DNS servers that are allowed to initiate requests at the same time'));
|
||||
o.datatype = 'and(uinteger,min(1),max(3))';
|
||||
o.default = '2';
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'idle_timeout', _('Idle Timeout'),
|
||||
_('DoH/TCP/DoT Connection Multiplexing idle timeout (default 30 seconds)'))
|
||||
o.datatype = 'and(uinteger,min(1))';
|
||||
o.default = '30';
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'enable_pipeline', _('TCP/DoT Connection Multiplexing'),
|
||||
_('Enable TCP/DoT RFC 7766 new Query Pipelining connection multiplexing mode'))
|
||||
o.rmempty = false;
|
||||
o.default = false;
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'insecure_skip_verify', _('Disable TLS Certificate'),
|
||||
_('Disable TLS Servers certificate validation, Can be useful if system CA certificate expires or the system time is out of order'));
|
||||
o.rmempty = false;
|
||||
o.default = false;
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'enable_ecs_remote',
|
||||
_('Enable EDNS client subnet'));
|
||||
o.rmempty = false;
|
||||
o.default = false;
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'remote_ecs_ip', _('IP Address'),
|
||||
_('Please provide the IP address you use when accessing foreign websites. This IP subnet (0/24) will be used as the ECS address for Remote / Streaming Media DNS requests') +
|
||||
_('This feature is typically used when using a self-built DNS server as an Remote / Streaming Media DNS upstream (requires support from the upstream server)'));
|
||||
o.datatype = 'ipaddr';
|
||||
o.depends('enable_ecs_remote', '1');
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'dns_leak', _('Prevent DNS Leaks'),
|
||||
_('Enable this option fallback policy forces forwarding to remote DNS'));
|
||||
o.rmempty = false;
|
||||
o.default = false;
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'cache', _('Enable DNS Cache'));
|
||||
o.rmempty = false;
|
||||
o.default = false;
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'cache_size', _('DNS Cache Size'));
|
||||
o.datatype = 'and(uinteger,min(0))';
|
||||
o.default = 8000;
|
||||
o.depends('cache', '1');
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'lazy_cache_ttl', _('Lazy Cache TTL'),
|
||||
_('Lazy cache survival time (in second). To disable Lazy Cache, please set to 0.'));
|
||||
o.datatype = 'and(uinteger,min(0))';
|
||||
o.default = 86400;
|
||||
o.depends('cache', '1');
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'dump_file', _('Cache Dump'),
|
||||
_('Save the cache locally and reload the cache dump on the next startup'));
|
||||
o.rmempty = false;
|
||||
o.default = false;
|
||||
o.depends('cache', '1');
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'dump_interval',
|
||||
_('Auto Save Cache Interval'));
|
||||
o.datatype = 'and(uinteger,min(0))';
|
||||
o.default = 3600;
|
||||
o.depends('dump_file', '1');
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'minimal_ttl', _('Minimum TTL'),
|
||||
_('Modify the Minimum TTL value (seconds) for DNS answer results, 0 indicating no modification'));
|
||||
o.datatype = 'and(uinteger,min(0),max(604800))';
|
||||
o.default = 0;
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
|
||||
o = s.taboption('advanced', form.Value, 'maximum_ttl', _('Maximum TTL'),
|
||||
_('Modify the Maximum TTL value (seconds) for DNS answer results, 0 indicating no modification'));
|
||||
o.datatype = 'and(uinteger,min(0),max(604800))';
|
||||
o.default = 0;
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'reject_type65', _('Disable RR Type 65 (HTTPS/SVCB)'),
|
||||
_('Block DNS RR Type 65 records (HTTPS/SVCB, used for HTTP/3, ECH, etc.), force using only A/AAAA records.'));
|
||||
o.default = 0;
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
|
||||
o = s.taboption('advanced', form.Flag, 'adblock', _('Enable DNS ADblock'));
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
o.default = false;
|
||||
|
||||
o = s.taboption('advanced', form.DynamicList, 'ad_source', _('ADblock Source'),
|
||||
_('When using custom rule sources, please use rule types supported by MosDNS (domain lists).') +
|
||||
'<br>' +
|
||||
_('Support for local files, such as: file:///var/mosdns/example.txt'));
|
||||
o.depends('adblock', '1');
|
||||
o.default = 'geosite.dat';
|
||||
o.value('geosite.dat', 'v2ray-geosite');
|
||||
o.value('https://raw.githubusercontent.com/privacy-protection-tools/anti-AD/master/anti-ad-domains.txt', 'anti-AD')
|
||||
o.value('https://raw.githubusercontent.com/Cats-Team/AdRules/main/mosdns_adrules.txt', 'Cats-Team/AdRules')
|
||||
o.value('https://raw.githubusercontent.com/neodevpro/neodevhost/master/domain', 'NEO DEV HOST')
|
||||
|
||||
/* cloudflare */
|
||||
o = s.taboption('cloudflare', form.Flag, 'cloudflare', _('Enabled'),
|
||||
_('Match the parsing result with the Cloudflare IP ranges, and when there is a successful match, \
|
||||
use the \'Custom IP\' as the parsing result (experimental feature)'));
|
||||
o.rmempty = false;
|
||||
o.default = false;
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
|
||||
o = s.taboption('cloudflare', form.DynamicList, 'cloudflare_ip', _('Custom IP'));
|
||||
o.datatype = 'ipaddr';
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
|
||||
o = s.taboption('cloudflare', form.TextValue, '_cloudflare',
|
||||
_('Cloudflare IP Ranges'),
|
||||
_('IPv4 CIDR: <a href="https://www.cloudflare.com/ips-v4" target="_blank">https://www.cloudflare.com/ips-v4</a> <br /> IPv6 CIDR: <a href="https://www.cloudflare.com/ips-v6" target="_blank">https://www.cloudflare.com/ips-v6</a>'));
|
||||
o.rows = 15;
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
o.cfgvalue = function (section_id) {
|
||||
return fs.trimmed('/etc/mosdns/rule/cloudflare-cidr.txt');
|
||||
};
|
||||
o.write = function (section_id, formvalue) {
|
||||
return this.cfgvalue(section_id).then(function (value) {
|
||||
if (value == formvalue) {
|
||||
return;
|
||||
}
|
||||
return fs.write('/etc/mosdns/rule/cloudflare-cidr.txt', formvalue.trim().replace(/\r\n/g, '\n') + '\n')
|
||||
.then(function (i) {
|
||||
return fs.exec('/etc/init.d/mosdns', ['restart']);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/* api */
|
||||
o = s.taboption('api', form.Value, 'listen_port_api', _('API Listen port'));
|
||||
o.datatype = 'and(port,min(1))';
|
||||
o.default = 9091;
|
||||
o.depends('configfile', '/var/etc/mosdns.json');
|
||||
|
||||
o = s.taboption('api', form.Button, '_flush_cache', null,
|
||||
_('Flushing DNS Cache will clear any IP addresses or DNS records from MosDNS cache.'));
|
||||
o.title = ' ';
|
||||
o.inputtitle = _('Flush DNS Cache');
|
||||
o.inputstyle = 'apply';
|
||||
o.onclick = L.bind(this.handleFlushCache, this, m);
|
||||
o.depends('cache', '1');
|
||||
|
||||
/* configuration */
|
||||
var configeditor = null;
|
||||
setTimeout(function () {
|
||||
var textarea = document.getElementById('widget.cbid.mosdns.config._custom');
|
||||
if (textarea) {
|
||||
configeditor = CodeMirror.fromTextArea(textarea, {
|
||||
autoRefresh: true,
|
||||
lineNumbers: true,
|
||||
lineWrapping: true,
|
||||
lint: true,
|
||||
gutters: ['CodeMirror-lint-markers'],
|
||||
matchBrackets: true,
|
||||
mode: "text/yaml",
|
||||
styleActiveLine: true,
|
||||
theme: "dracula"
|
||||
});
|
||||
}
|
||||
}, 600);
|
||||
o = s.taboption('basic', form.TextValue, '_custom', _('Configuration Editor'),
|
||||
_('This is the content of the file \'/etc/mosdns/config_custom.yaml\' from which your MosDNS configuration will be generated. \
|
||||
Only accepts configuration content in yaml format.'));
|
||||
o.rows = 25;
|
||||
o.depends('configfile', '/etc/mosdns/config_custom.yaml');
|
||||
o.cfgvalue = function (section_id) {
|
||||
return fs.trimmed('/etc/mosdns/config_custom.yaml');
|
||||
};
|
||||
o.write = function (section_id, formvalue) {
|
||||
if (configeditor) {
|
||||
var editorContent = configeditor.getValue();
|
||||
if (editorContent === formvalue) {
|
||||
return;
|
||||
}
|
||||
return fs.write('/etc/mosdns/config_custom.yaml', editorContent.trim().replace(/\r\n/g, '\n') + '\n')
|
||||
.then(function (i) {
|
||||
return fs.exec('/etc/init.d/mosdns', ['restart']);
|
||||
})
|
||||
.then(function () {
|
||||
return window.location.reload();
|
||||
})
|
||||
.catch(function (e) {
|
||||
ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message)));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
o = s.taboption('geodata', form.DynamicList, 'geosite_tags', _('GeoSite Tags'),
|
||||
_('Enter the GeoSite.dat category to be exported, Allow add multiple tags'),
|
||||
_('Export directory: /var/mosdns'));
|
||||
o.depends('configfile', '/etc/mosdns/config_custom.yaml');
|
||||
|
||||
o = s.taboption('geodata', form.DynamicList, 'geoip_tags', _('GeoIP Tags'),
|
||||
_('Enter the GeoIP.dat category to be exported, Allow add multiple tags'),
|
||||
_('Export directory: /var/mosdns'));
|
||||
o.depends('configfile', '/etc/mosdns/config_custom.yaml');
|
||||
|
||||
return m.render();
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,70 @@
|
||||
'use strict';
|
||||
'require dom';
|
||||
'require fs';
|
||||
'require poll';
|
||||
'require view';
|
||||
|
||||
var scrollPosition = 0;
|
||||
var userScrolled = false;
|
||||
var logTextarea;
|
||||
|
||||
function pollLog() {
|
||||
return Promise.all([
|
||||
fs.exec_direct('/usr/share/mosdns/mosdns.sh', ['printlog']).then(function (res) {
|
||||
return res.trim().split(/\n/).join('\n');
|
||||
}),
|
||||
]).then(function (data) {
|
||||
logTextarea.value = data[0] || _('No log data.');
|
||||
|
||||
if (!userScrolled) {
|
||||
logTextarea.scrollTop = logTextarea.scrollHeight;
|
||||
} else {
|
||||
logTextarea.scrollTop = scrollPosition;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return view.extend({
|
||||
handleCleanLogs: function () {
|
||||
return fs.exec('/usr/share/mosdns/mosdns.sh', ['cleanlog'])
|
||||
.catch(function (e) { ui.addNotification(null, E('p', e.message)) });
|
||||
},
|
||||
|
||||
render: function () {
|
||||
logTextarea = E('textarea', {
|
||||
'class': 'cbi-input-textarea',
|
||||
'wrap': 'off',
|
||||
'readonly': 'readonly',
|
||||
'style': 'width: calc(100% - 20px);height: 535px;margin: 10px;overflow-y: scroll;',
|
||||
});
|
||||
|
||||
logTextarea.addEventListener('scroll', function () {
|
||||
userScrolled = true;
|
||||
scrollPosition = logTextarea.scrollTop;
|
||||
});
|
||||
|
||||
var log_textarea_wrapper = E('div', { 'id': 'log_textarea' }, logTextarea);
|
||||
|
||||
poll.add(pollLog);
|
||||
|
||||
var clear_logs_button = E('input', { 'class': 'btn cbi-button-action', 'type': 'button', 'style': 'margin-left: 10px; margin-top: 10px;', 'value': _('Clear logs') });
|
||||
clear_logs_button.addEventListener('click', this.handleCleanLogs.bind(this));
|
||||
|
||||
return E([
|
||||
E('div', { 'class': 'cbi-map' }, [
|
||||
E('h2', { 'name': 'content' }, '%s - %s'.format(_('MosDNS'), _('Log Data'))),
|
||||
E('div', { 'class': 'cbi-section' }, [
|
||||
clear_logs_button,
|
||||
log_textarea_wrapper,
|
||||
E('div', { 'style': 'text-align:right' },
|
||||
E('small', {}, _('Refresh every %s seconds.').format(L.env.pollinterval))
|
||||
)
|
||||
])
|
||||
])
|
||||
]);
|
||||
},
|
||||
|
||||
handleSave: null,
|
||||
handleSaveApply: null,
|
||||
handleReset: null
|
||||
});
|
||||
@@ -0,0 +1,234 @@
|
||||
'use strict';
|
||||
'require form';
|
||||
'require fs';
|
||||
'require ui';
|
||||
'require view';
|
||||
|
||||
return view.extend({
|
||||
render: function () {
|
||||
var m, s, o;
|
||||
|
||||
m = new form.Map("mosdns", _("Rule Settings"),
|
||||
_('The list of rules only apply to \'Default Config\' profiles.'));
|
||||
|
||||
s = m.section(form.TypedSection);
|
||||
s.anonymous = true;
|
||||
s.sortable = true;
|
||||
|
||||
s.tab('whitelist', _('White Lists'));
|
||||
s.tab('blocklist', _('Block Lists'));
|
||||
s.tab('greylist', _('Grey Lists'));
|
||||
s.tab('ddnslist', _('DDNS Lists'));
|
||||
s.tab('hostslist', _('Hosts'));
|
||||
s.tab('redirectlist', _('Redirect'));
|
||||
s.tab('localptrlist', _('Block PTR'));
|
||||
s.tab('streamingmedialist', _('Streaming Media'));
|
||||
|
||||
o = s.taboption('whitelist', form.TextValue, '_whitelist',
|
||||
null,
|
||||
'<font color=\'red\'>'
|
||||
+ _('Added domain names always permit resolution using \'local DNS\' with the highest priority (one domain per line, supports domain matching rules).')
|
||||
+ '</font>'
|
||||
);
|
||||
o.rows = 25;
|
||||
o.cfgvalue = function (section_id) {
|
||||
return fs.trimmed('/etc/mosdns/rule/whitelist.txt').catch(function (e) {
|
||||
return "";
|
||||
});
|
||||
};
|
||||
o.write = function (section_id, formvalue) {
|
||||
return this.cfgvalue(section_id).then(function (value) {
|
||||
if (value == formvalue) {
|
||||
return;
|
||||
}
|
||||
return fs.write('/etc/mosdns/rule/whitelist.txt', formvalue.trim().replace(/\r\n/g, '\n') + '\n')
|
||||
.catch(function (e) {
|
||||
ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message)));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
o = s.taboption('blocklist', form.TextValue, '_blocklist',
|
||||
null,
|
||||
'<font color=\'red\'>'
|
||||
+ _('Added domain names will block DNS resolution (one domain per line, supports domain matching rules).')
|
||||
+ '</font>'
|
||||
);
|
||||
o.rows = 25;
|
||||
o.cfgvalue = function (section_id) {
|
||||
return fs.trimmed('/etc/mosdns/rule/blocklist.txt').catch(function (e) {
|
||||
return "";
|
||||
});
|
||||
};
|
||||
o.write = function (section_id, formvalue) {
|
||||
return this.cfgvalue(section_id).then(function (value) {
|
||||
if (value == formvalue) {
|
||||
return;
|
||||
}
|
||||
return fs.write('/etc/mosdns/rule/blocklist.txt', formvalue.trim().replace(/\r\n/g, '\n') + '\n')
|
||||
.catch(function (e) {
|
||||
ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message)));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
o = s.taboption('greylist', form.TextValue, '_greylist',
|
||||
null,
|
||||
'<font color=\'red\'>'
|
||||
+ _('Added domain names will always use \'Remote DNS\' for resolution (one domain per line, supports domain matching rules).')
|
||||
+ '</font>'
|
||||
);
|
||||
o.rows = 25;
|
||||
o.cfgvalue = function (section_id) {
|
||||
return fs.trimmed('/etc/mosdns/rule/greylist.txt').catch(function (e) {
|
||||
return "";
|
||||
});
|
||||
};
|
||||
o.write = function (section_id, formvalue) {
|
||||
return this.cfgvalue(section_id).then(function (value) {
|
||||
if (value == formvalue) {
|
||||
return;
|
||||
}
|
||||
return fs.write('/etc/mosdns/rule/greylist.txt', formvalue.trim().replace(/\r\n/g, '\n') + '\n')
|
||||
.catch(function (e) {
|
||||
ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message)));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
o = s.taboption('ddnslist', form.TextValue, '_ddnslist',
|
||||
null,
|
||||
'<font color=\'red\'>'
|
||||
+ _('Added domain names will always use \'Local DNS\' for resolution, with a forced TTL of 5 seconds, and results will not be cached (one domain per line, supports domain matching rules).')
|
||||
+ '</font>'
|
||||
);
|
||||
o.rows = 25;
|
||||
o.cfgvalue = function (section_id) {
|
||||
return fs.trimmed('/etc/mosdns/rule/ddnslist.txt').catch(function (e) {
|
||||
return "";
|
||||
});
|
||||
};
|
||||
o.write = function (section_id, formvalue) {
|
||||
return this.cfgvalue(section_id).then(function (value) {
|
||||
if (value == formvalue) {
|
||||
return;
|
||||
}
|
||||
return fs.write('/etc/mosdns/rule/ddnslist.txt', formvalue.trim().replace(/\r\n/g, '\n') + '\n')
|
||||
.catch(function (e) {
|
||||
ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message)));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
o = s.taboption('hostslist', form.TextValue, '_hostslist',
|
||||
null,
|
||||
'<font color=\'red\'>'
|
||||
+ _('Custom Hosts rewrite, for example: baidu.com 10.0.0.1 (one rule per line, supports domain matching rules).')
|
||||
+ '</font>'
|
||||
);
|
||||
o.rows = 25;
|
||||
o.cfgvalue = function (section_id) {
|
||||
return fs.trimmed('/etc/mosdns/rule/hosts.txt').catch(function (e) {
|
||||
return "";
|
||||
});
|
||||
};
|
||||
o.write = function (section_id, formvalue) {
|
||||
return this.cfgvalue(section_id).then(function (value) {
|
||||
if (value == formvalue) {
|
||||
return;
|
||||
}
|
||||
return fs.write('/etc/mosdns/rule/hosts.txt', formvalue.trim().replace(/\r\n/g, '\n') + '\n')
|
||||
.catch(function (e) {
|
||||
ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message)));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
o = s.taboption('redirectlist', form.TextValue, '_redirectlist',
|
||||
null,
|
||||
'<font color=\'red\'>'
|
||||
+ _('Redirecting requests for domain names. Request domain A, but return records for domain B, for example: baidu.com qq.com (one rule per line).')
|
||||
+ '</font>'
|
||||
);
|
||||
o.rows = 25;
|
||||
o.cfgvalue = function (section_id) {
|
||||
return fs.trimmed('/etc/mosdns/rule/redirect.txt').catch(function (e) {
|
||||
return "";
|
||||
});
|
||||
};
|
||||
o.write = function (section_id, formvalue) {
|
||||
return this.cfgvalue(section_id).then(function (value) {
|
||||
if (value == formvalue) {
|
||||
return;
|
||||
}
|
||||
return fs.write('/etc/mosdns/rule/redirect.txt', formvalue.trim().replace(/\r\n/g, '\n') + '\n')
|
||||
.catch(function (e) {
|
||||
ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message)));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
o = s.taboption('localptrlist', form.TextValue, '_localptrlist',
|
||||
null,
|
||||
'<font color=\'red\'>'
|
||||
+ _('Added domain names will block PTR requests (one domain per line, supports domain matching rules).')
|
||||
+ '</font>'
|
||||
);
|
||||
o.rows = 25;
|
||||
o.cfgvalue = function (section_id) {
|
||||
return fs.trimmed('/etc/mosdns/rule/local-ptr.txt').catch(function (e) {
|
||||
return "";
|
||||
});
|
||||
};
|
||||
o.write = function (section_id, formvalue) {
|
||||
return this.cfgvalue(section_id).then(function (value) {
|
||||
if (value == formvalue) {
|
||||
return;
|
||||
}
|
||||
return fs.write('/etc/mosdns/rule/local-ptr.txt', formvalue.trim().replace(/\r\n/g, '\n') + '\n')
|
||||
.catch(function (e) {
|
||||
ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message)));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
o = s.taboption('streamingmedialist', form.TextValue, '_streamingmedialist',
|
||||
null,
|
||||
'<font color=\'red\'>'
|
||||
+ _('When enabling \'Custom Stream Media DNS\', added domains will always use the \'Streaming Media DNS server\' for resolution (one domain per line, supports domain matching rules).')
|
||||
+ '</font>'
|
||||
);
|
||||
o.rows = 25;
|
||||
o.cfgvalue = function (section_id) {
|
||||
return fs.trimmed('/etc/mosdns/rule/streaming.txt').catch(function (e) {
|
||||
return "";
|
||||
});
|
||||
};
|
||||
o.write = function (section_id, formvalue) {
|
||||
return this.cfgvalue(section_id).then(function (value) {
|
||||
if (value == formvalue) {
|
||||
return;
|
||||
}
|
||||
return fs.write('/etc/mosdns/rule/streaming.txt', formvalue.trim().replace(/\r\n/g, '\n') + '\n')
|
||||
.catch(function (e) {
|
||||
ui.addNotification(null, E('p', _('Unable to save contents: %s').format(e.message)));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return m.render();
|
||||
},
|
||||
|
||||
handleSaveApply: function (ev) {
|
||||
var m = this.map;
|
||||
onclick = L.bind(this.handleSave, this, m);
|
||||
return fs.exec('/etc/init.d/mosdns', ['restart'])
|
||||
.then(function () {
|
||||
window.location.reload();
|
||||
})
|
||||
.catch(function (e) {
|
||||
ui.addNotification(null, E('p', _('Failed to restart mosdns: %s').format(e.message)));
|
||||
});
|
||||
},
|
||||
handleReset: null
|
||||
});
|
||||
@@ -0,0 +1,75 @@
|
||||
'use strict';
|
||||
'require form';
|
||||
'require fs';
|
||||
'require ui';
|
||||
'require view';
|
||||
|
||||
return view.extend({
|
||||
handleUpdate: function (m, section_id, ev) {
|
||||
return fs.exec('/usr/share/mosdns/mosdns.sh', ['geodata'])
|
||||
.then(function (i) {
|
||||
var res = i.code;
|
||||
if (res === 0) {
|
||||
ui.addNotification(null, E('p', _('Update success')), 'info');
|
||||
} else {
|
||||
ui.addNotification(null, E('p', i.stderr + '<br />' + i.stdout), 'warn');
|
||||
ui.addNotification(null, E('p', _('Update failed, Please check the network status')), 'error');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
render: function () {
|
||||
var m, s, o;
|
||||
|
||||
m = new form.Map('mosdns', _('Update GeoIP & GeoSite databases'),
|
||||
_('Automatically update GeoIP and GeoSite databases as well as ad filtering rules through scheduled tasks.'));
|
||||
|
||||
s = m.section(form.TypedSection);
|
||||
s.anonymous = true;
|
||||
|
||||
o = s.option(form.Flag, 'geo_auto_update', _('Enable Auto Database Update'));
|
||||
o.rmempty = false;
|
||||
|
||||
o = s.option(form.ListValue, 'geo_update_week_time', _('Update Cycle'));
|
||||
o.value('*', _('Every Day'));
|
||||
o.value('1', _('Every Monday'));
|
||||
o.value('2', _('Every Tuesday'));
|
||||
o.value('3', _('Every Wednesday'));
|
||||
o.value('4', _('Every Thursday'));
|
||||
o.value('5', _('Every Friday'));
|
||||
o.value('6', _('Every Saturday'));
|
||||
o.value('0', _('Every Sunday'));
|
||||
o.default = 3;
|
||||
|
||||
o = s.option(form.ListValue, 'geo_update_day_time', _('Update Time'));
|
||||
for (let t = 0; t < 24; t++) {
|
||||
o.value(t, t + ':00');
|
||||
};
|
||||
o.default = 3;
|
||||
|
||||
o = s.option(form.ListValue, 'geoip_type', _('GeoIP Type'),
|
||||
_('Little: only include Mainland China and Private IP addresses.') +
|
||||
'<br>' +
|
||||
_('Full: includes all Countries and Private IP addresses.')
|
||||
);
|
||||
o.value('geoip', _('Full'));
|
||||
o.value('geoip-only-cn-private', _('Little'));
|
||||
o.rmempty = false;
|
||||
o.default = 'geoip';
|
||||
|
||||
o = s.option(form.Value, 'github_proxy', _('GitHub Proxy'),
|
||||
_('Update data files with GitHub Proxy, leave blank to disable proxy downloads.'));
|
||||
o.value('https://gh-proxy.com', _('https://gh-proxy.com'));
|
||||
o.rmempty = true;
|
||||
o.default = '';
|
||||
|
||||
o = s.option(form.Button, '_udpate', null,
|
||||
_('Check And Update GeoData.'));
|
||||
o.title = _('Database Update');
|
||||
o.inputtitle = _('Check And Update');
|
||||
o.inputstyle = 'apply';
|
||||
o.onclick = L.bind(this.handleUpdate, this, m);
|
||||
|
||||
return m.render();
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user