diff --git a/filebrowser/Makefile b/filebrowser/Makefile index d121281f..3c420928 100644 --- a/filebrowser/Makefile +++ b/filebrowser/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=filebrowser -PKG_VERSION:=0.8.7-beta +PKG_VERSION:=1.2.3-stable PKG_RELEASE=1 ifeq ($(ARCH),aarch64) diff --git a/luci-app-adguardhome/.gitattributes b/luci-app-adguardhome/.gitattributes new file mode 100644 index 00000000..dfe07704 --- /dev/null +++ b/luci-app-adguardhome/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/luci-app-adguardhome/LICENSE b/luci-app-adguardhome/LICENSE new file mode 100644 index 00000000..b09cd785 --- /dev/null +++ b/luci-app-adguardhome/LICENSE @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. diff --git a/luci-app-adguardhome/Makefile b/luci-app-adguardhome/Makefile old mode 100644 new mode 100755 index 8c62bdbb..0ff9b510 --- a/luci-app-adguardhome/Makefile +++ b/luci-app-adguardhome/Makefile @@ -1,58 +1,14 @@ -# This is free software, licensed under the Apache License, Version 2.0 . -# +# Copyright 2024- Douglas Orend +# This is free software, licensed under the Apache License, Version 2.0 include $(TOPDIR)/rules.mk -PKG_NAME:=luci-app-adguardhome -PKG_MAINTAINER:= +PKG_LICENSE:=Apache-2.0 -LUCI_TITLE:=LuCI app for AdGuardHome -LUCI_PKGARCH:=all -LUCI_DEPENDS:=+!wget-ssl&&!curl:wget-ssl +xz-utils +xz -LUCI_DESCRIPTION:=LuCI support for AdGuardHome +LUCI_TITLE:=LuCI support for AdguardHome +LUCI_DEPENDS:=+adguardhome +luci-base +curl - -define Package/$(PKG_NAME)/config -config PACKAGE_$(PKG_NAME)_INCLUDE_binary - bool "Include Binary File" - default n -endef - -PKG_CONFIG_DEPENDS:= CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_binary - -define Package/luci-app-adguardhome/conffiles -/usr/share/AdGuardHome/links.txt -/etc/config/AdGuardHome -/etc/AdGuardHome.yaml -endef - - -define Package/luci-app-adguardhome/postinst -#!/bin/sh - chmod 755 /usr/share/AdGuardHome/* - chmod +x /etc/init.d/AdGuardHome - /etc/init.d/AdGuardHome enable >/dev/null 2>&1 - enable=$(uci get AdGuardHome.AdGuardHome.enabled 2>/dev/null) - if [ "$enable" == "1" ]; then - /etc/init.d/AdGuardHome reload - fi - rm -f /tmp/luci-indexcache - rm -f /tmp/luci-modulecache/* -exit 0 -endef - -define Package/luci-app-adguardhome/prerm -#!/bin/sh -if [ -z "$${IPKG_INSTROOT}" ]; then - /etc/init.d/AdGuardHome disable - /etc/init.d/AdGuardHome stop -uci -q batch <<-EOF >/dev/null 2>&1 - delete ucitrack.@AdGuardHome[-1] - commit ucitrack -EOF -fi -exit 0 -endef +PKG_MAINTAINER:=Douglas Orend include $(TOPDIR)/feeds/luci/luci.mk diff --git a/luci-app-adguardhome/README.md b/luci-app-adguardhome/README.md new file mode 100644 index 00000000..d7bf4af4 --- /dev/null +++ b/luci-app-adguardhome/README.md @@ -0,0 +1,13 @@ +# LuCI App AdGuardHome + +**NOTE:** Original Source found for LUCI app [here](https://github.com/openwrt/luci/tree/3253c2644215a1ea8136199044e06ad5e4fd9de9/applications/luci-app-adguardhome) by Duncan Hill (). + +## Screenshots + +### Configuration Tab +![MAC Filter Tab](https://github.com/kiddin9/luci-app-adguardhome/blob/main/.github/images/config.png?raw=true) + +### Status Tab +![Status Tab](https://github.com/kiddin9/luci-app-adguardhome/blob/main/.github/images/status.png?raw=true) + + diff --git a/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js b/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js new file mode 100644 index 00000000..5e5d3695 --- /dev/null +++ b/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/config.js @@ -0,0 +1,158 @@ +'use strict'; +'require rpc'; +'require form'; +'require view'; +'require poll'; + +const DEFAULT_CONFIG_FILE = '/etc/adguardhome/adguardhome.yaml'; +const DEFAULT_WORK_DIR = '/var/lib/adguardhome'; +const DEFAULT_USER = 'adguardhome'; +const DEFAULT_GROUP = DEFAULT_USER; + +const PATH_REGEX = new RegExp('^/etc(/[^/]+)?/?$'); + +function validateConfigFile(_unused, value) { + if (value == null || value === '') { + return true; + } + if (!value.startsWith('/')) { + return _('Path must be absolute.'); + } + if (value.endsWith('/')) { + return _('Path must not end with a slash.'); + } + if (PATH_REGEX.test(value)) { + return _('Configuration file must be stored in its own directory, and not in \'/etc\'.'); + } + return true; +} + +function validateWorkDir(_unused, value) { + if (value == null || value === '') { + return true; + } + if (!value.startsWith('/')) { + return _('Path must be absolute.'); + } + return true; +} + +function renderStatus(status, agh_config) { + var spanTemp = '%s %s'; + var renderHTML; + if (status.running) { + var button = String.format(' %s', + agh_config.web_url, _('Open Web Interface')); + renderHTML = spanTemp.format('green', _('adguardhome'), _('RUNNING')) + button; + } else { + renderHTML = spanTemp.format('red', _('adguardhome'), _('NOT RUNNING')); + } + + return renderHTML; +} + +return view.extend({ + load_adguardhome_config: rpc.declare({ + object: 'luci.adguardhome', + method: 'get_config' + }), + load_adguardhome_status: rpc.declare({ + object: 'luci.adguardhome', + method: 'get_status' + }), + load: function () { + return Promise.all([ + this.load_adguardhome_status(), + this.load_adguardhome_config() + ]); + }, + render: function (data) { + var status = data[0] || {}; + var agh_config = data[1] || {}; + // A basic configuration form; the luci.adguardhome script that + // powers the other UI pages needs a username and password to + // communicate with the AdguardHome REST API. + var s, o; + var m = new form.Map('adguardhome', _('AdGuard Home Configuration'), + _('默认用户名admin 密码admin') + ); + + s = m.section(form.TypedSection); + s.anonymous = true; + + s.render = function () { + setTimeout(function() { + poll.add(function () { + var view = document.getElementById('service_status'); + view.innerHTML = renderStatus(status, agh_config); + }); + }, 0); + + return E('div', { class: 'cbi-section', id: 'status_bar' }, [ + E('p', { id: 'service_status' }, _('Collecting data...')) + ]); + } + + s = m.section(form.NamedSection, 'config', 'adguardhome', _('General settings')); + o = s.option(form.Flag, 'enabled', _('Enable')); + o.default = o.disabled; + o.rmempty = false; + + o = s.option(form.Value, 'config_file', _('Configuration file')); + o.datatype = 'string'; + o.placeholder = DEFAULT_CONFIG_FILE; + o.validate = validateConfigFile; + + o = s.option(form.Value, 'work_dir', _('Work Dir')); + o.datatype = 'string'; + o.placeholder = DEFAULT_WORK_DIR; + o.validate = validateWorkDir; + + o = s.option(form.Value, 'user', _('Service user'), _('User the service runs under.')); + o.datatype = 'string'; + o.placeholder = DEFAULT_USER; + + o = s.option(form.Value, 'group', _('Service group'), _('Group the service runs under.')); + o.datatype = 'string'; + o.placeholder = DEFAULT_GROUP; + + // 添加重定向模式选择 + o = s.option(form.ListValue, 'redirect', _('Redirect'), _('AdGuardHome redirect mode')); + o.value('none', _('none')); + o.value('dnsmasq-upstream', _('Run as dnsmasq upstream server')); + o.value('redirect', _('Redirect 53 port to AdGuardHome')); + o.value('exchange', _('Use port 53 replace dnsmasq')); + o.default = 'none'; + + o = s.option(form.Value, 'web_username', _('Username for AdGuard Home'), _('The username you configured when you set up AdGuard Home')); + o.default = 'admin'; + + o = s.option(form.Value, 'web_password', _('Password for AdGuard Home'), _('The password you configured when you set up AdGuard Home')); + o.password = true; + o.default = 'admin'; + + var ChangePassword = form.Button.extend({ + set_passwd: rpc.declare({ + object: 'luci.adguardhome', + method: 'set_passwd', + params: [ 'username', 'hash' ], + }), + onclick: function() { + var username = document.getElementById("widget.cbid.adguardhome.config.web_username").value; + var password = document.getElementById("widget.cbid.adguardhome.config.web_password").value; + var hash = TwinBcrypt.hashSync(password); + return Promise.all([ this.set_passwd( username, hash ) ]); + }, + }); + o = s.option(ChangePassword, 'change_password', _('Change Password')); + + var BCryptInclude = form.DummyValue.extend({ + renderWidget: function(section_id, option_index, cfgvalue) { + return E('script', { 'type':'text/javascript', 'src':'/luci-static/resources/view/twin-bcrypt.min.js' }); + } + }); + o = s.option(BCryptInclude, 'misc'); + + return m.render(); + }, +}) diff --git a/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/logs.js b/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/logs.js new file mode 100644 index 00000000..21d04377 --- /dev/null +++ b/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/logs.js @@ -0,0 +1,44 @@ +'use strict'; +'require dom'; +'require fs'; +'require poll'; +'require ui'; +'require view'; + +return view.extend({ + load: function() { + return Promise.all([ + L.resolveDefault(fs.stat('/sbin/logread'), null), + L.resolveDefault(fs.stat('/usr/sbin/logread'), null) + ]).then(function(stat) { + var logger = stat[0] ? stat[0].path : stat[1] ? stat[1].path : null; + + return fs.exec_direct(logger, [ '-e', 'AdGuardHome' ]).catch(function(err) { + ui.addNotification(null, E('p', {}, _('Unable to load log data: ' + err.message))); + return ''; + }); + }); + }, + + render: function(logdata) { + var loglines = logdata.trim().split(/\n/).reverse().slice(0, 50); + + return E([], [ + E('h2', {}, [_('System Log (AdGuard Home)')]), + E('div', {}, [_('Showing last 50 lines')]), + E('div', { 'id': 'content_syslog' }, [ + E('textarea', { + 'id': 'syslog', + 'style': 'font-size:12px', + 'readonly': 'readonly', + 'wrap': 'off', + 'rows': loglines.length + 1 + }, [ loglines.join('\n') ]) + ]) + ]); + }, + + handleSave: null, + handleSaveApply: null, + handleReset: null +}); diff --git a/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/status.js b/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/status.js new file mode 100644 index 00000000..ef045016 --- /dev/null +++ b/luci-app-adguardhome/htdocs/luci-static/resources/view/adguardhome/status.js @@ -0,0 +1,171 @@ +'use strict'; +'require rpc'; +'require view'; + +return view.extend({ + load_adguardhome_config: rpc.declare({ + object: 'luci.adguardhome', + method: 'get_config' + }), + load_adguardhome_status: rpc.declare({ + object: 'luci.adguardhome', + method: 'get_status' + }), + load_adguardhome_statistics: rpc.declare({ + object: 'luci.adguardhome', + method: 'get_statistics' + }), + + generic_failure: function(message) { + return E('div', {'class': 'error'}, [_('RPC call failure: '), message]) + }, + render_list: function ( agh_list ) { + var table = E('ul', {}); + for (var i = 0; i < agh_list.length; i++) { + table.appendChild(E('li', {}, agh_list[i])); + } + return table; + }, + render_status_table: function (status, agh_config) { + if (status.error) { + return this.generic_failure(status.error) + } + // Take a hint from the base LuCI module for the Overview page, + // declare the fields and use a loop to build the tabular status view. + // Written out as key/value pairs, but it's just an iterable of elements. + const weburl = agh_config.web_url; + const listen_addresses = L.isObject(status.dns_addresses) ? this.render_list(status.dns_addresses) : _('Not found'); + const bootstrap_dns = L.isObject(agh_config.dns_bootstrap_dns) ? this.render_list(agh_config.dns_bootstrap_dns) : _('Not found'); + const upstream_dns = L.isObject(agh_config.dns_upstream_dns) ? this.render_list(agh_config.dns_upstream_dns) : _('Not found'); + const fields = [ + _('Running'), status.running ? _('Yes') : _('No'), + _('Protection enabled'), status.protection_enabled ? _('Yes') : _('No'), + _('Statistics period (days)'), agh_config.statistics_interval, + _('Web interface'), E('button', { 'class': "cbi-button cbi-button-button" }, E('a', { 'href': weburl, 'target': '_blank' }, weburl)), + _('DNS listen port'), status.dns_port, + _('DNS listen addresses'), listen_addresses, + _('Bootstrap DNS addresses'), bootstrap_dns, + _('Upstream DNS addresses'), upstream_dns, + _('Version'), status.version, + ]; + + var table = E('table', { 'class': 'table', 'id': 'status' }); + for (var i = 0; i < fields.length; i += 2) { + table.appendChild(E('tr', { 'class': 'tr' }, [ + E('td', { 'class': 'td left', 'width': '33%', 'vertical-align': 'text-top' }, [fields[i]]), + E('td', { 'class': 'td left' }, [(fields[i + 1] != null) ? fields[i + 1] : _('Not found')]) + ])); + } + return table; + }, + render_statistics_table: function (statistics) { + // High level statistics + if (statistics.error) { + return this.generic_failure(statistics.error) + } + const fields = [ + _('DNS queries'), statistics.num_dns_queries, + _('DNS blocks'), statistics.num_blocked_filtering, + _('DNS replacements (safesearch)'), statistics.num_replaced_safesearch, + _('DNS replacements (malware/phishing)'), statistics.num_replaced_safebrowsing, + _('Average processing time (seconds)'), statistics.avg_processing_time, + ]; + + var table = E('table', { 'class': 'table', 'id': 'statistics' }); + for (var i = 0; i < fields.length; i += 2) { + table.appendChild( + E('tr', { 'class': 'tr' }, [ + E('td', { 'class': 'td left', 'width': '33%' }, [fields[i]]), + E('td', { 'class': 'td left' }, [(fields[i + 1] != null) ? fields[i + 1] : _('Not found')]) + ])); + } + return table; + }, + render_top_table: function(table_id, objects) { + var table = E('table', { 'class': 'table', 'id': table_id }); + for (var i = 0; i < objects.length; i++) { + table.appendChild( + E('tr', { 'class': 'tr' }, [ + E('td', { 'class': 'td left', 'width': '33%' }, Object.keys(objects[i])[0]), + E('td', { 'class': 'td left' }, Object.values(objects[i])[0]) + ]) + ); + } + return table; + }, + render_top_queries_table: function (statistics) { + // Top 5 queried domains table view + if (statistics.error) { + return this.generic_failure(statistics.error) + } + if (typeof statistics.top_queried_domains === 'undefined') { return ""; } + const top_queries = statistics.top_queried_domains.slice(0, 5); + return this.render_top_table('top_queries', top_queries) + }, + render_top_blocked_table: function (statistics) { + // Top 5 blocked domains table view + if (statistics.error) { + return this.generic_failure(statistics.error) + } + if (typeof statistics.top_blocked_domains === 'undefined') { return ""; } + const top_blocked = statistics.top_blocked_domains.slice(0, 5); + return this.render_top_table('top_blocked', top_blocked) + }, + // Core LuCI functions from here on. + load: function () { + return Promise.all([ + this.load_adguardhome_status(), + this.load_adguardhome_statistics(), + this.load_adguardhome_config() + ]); + }, + render: function (data) { + // data[0] should be load_adguardhome_status() result + var status = data[0] || {}; + // data[1] should be load_adguardhome_statistics() result + var statistics = data[1] || {}; + // data[2] should be load_adguardhome_config() result + var agh_config = data[2] || {}; + + // status.auth_error is only filled in when the config fetch failed + // to get the credentials. That stops all activity, since the user must + // first configure the username and password. Don't even bother trying + // to make REST API calls without credentials. + if (status.auth_error) { + return E('div', { 'class': 'cbi-map', 'id': 'map' }, [ + E('div', { 'class': 'cbi-section' }, [ + E('div', { 'class': 'left' }, [ + E('h2', _('AdGuard Home Status - Error')), + E('div', { 'class': 'error' }, status.auth_error), + E('div', { 'class': 'info' }, _('Please open the Configuration section, and provide the credentials.')) + ]) + ]), + ]); + } + + // Render all the status tables as one big block. + return E('div', { 'class': 'cbi-map', 'id': 'map' }, [ + E('div', { 'class': 'cbi-section' }, [ + E('div', { 'class': 'left' }, [ + E('h2', _('AdGuard Home Status')), + this.render_status_table(status, agh_config) + ]), + E('div', { 'class': 'left' }, [ + E('h3', _('AdGuard Home Statistics')), + this.render_statistics_table(statistics) + ]), + E('div', { 'class': 'left' }, [ + E('h3', _('Top Queried Domains')), + this.render_top_queries_table(statistics) + ]), + E('div', { 'class': 'left' }, [ + E('h3', _('Top Blocked Domains')), + this.render_top_blocked_table(statistics) + ]) + ]), + ]); + }, + handleSave: null, + handleSaveApply: null, + handleReset: null +}) diff --git a/luci-app-adguardhome/root/www/luci-static/resources/twin-bcrypt.min.js b/luci-app-adguardhome/htdocs/luci-static/resources/view/twin-bcrypt.min.js similarity index 100% rename from luci-app-adguardhome/root/www/luci-static/resources/twin-bcrypt.min.js rename to luci-app-adguardhome/htdocs/luci-static/resources/view/twin-bcrypt.min.js diff --git a/luci-app-adguardhome/luasrc/controller/AdGuardHome.lua b/luci-app-adguardhome/luasrc/controller/AdGuardHome.lua deleted file mode 100644 index 468e6a70..00000000 --- a/luci-app-adguardhome/luasrc/controller/AdGuardHome.lua +++ /dev/null @@ -1,126 +0,0 @@ -module("luci.controller.AdGuardHome", package.seeall) -local fs = require "nixio.fs" -local http = require "luci.http" -local uci = require"luci.model.uci".cursor() -function index() -local page = entry({"admin", "services", "AdGuardHome"},alias("admin", "services", "AdGuardHome", "base"),_("AdGuard Home")) -page.order = 11 -page.dependent = true -page.acl_depends = { "luci-app-adguardhome" } - entry({"admin", "services", "AdGuardHome", "base"}, cbi("AdGuardHome/base"), _("Base Setting"), 1).leaf = true - entry({"admin", "services", "AdGuardHome", "log"}, form("AdGuardHome/log"), _("Log"), 2).leaf = true - entry({"admin", "services", "AdGuardHome", "manual"}, cbi("AdGuardHome/manual"), _("Manual Config"), 3).leaf = true - entry({"admin", "services", "AdGuardHome", "status"}, call("act_status")).leaf = true - entry({"admin", "services", "AdGuardHome", "check"}, call("check_update")) - entry({"admin", "services", "AdGuardHome", "doupdate"}, call("do_update")) - entry({"admin", "services", "AdGuardHome", "getlog"}, call("get_log")) - entry({"admin", "services", "AdGuardHome", "dodellog"}, call("do_dellog")) - entry({"admin", "services", "AdGuardHome", "reloadconfig"}, call("reload_config")) - entry({"admin", "services", "AdGuardHome", "gettemplateconfig"}, call("get_template_config")) -end -function get_template_config() - local b - local d="" - local file = "/tmp/resolv.conf.d/resolv.conf.auto" - if not fs.access(file) then - file = "/tmp/resolv.conf.auto" - end - for cnt in io.lines(file) do - b = string.match(cnt, "^[^#]*nameserver%s+([^%s]+)$") - if (b ~= nil) then d = d .. " - " .. b .. "\n" end - end - local f=io.open("/usr/share/AdGuardHome/AdGuardHome_template.yaml", "r+") - local tbl = {} - local a="" - while (1) do - a=f:read("*l") - if (a=="#bootstrap_dns") then - a=d - elseif (a=="#upstream_dns") then - a=d - elseif (a==nil) then - break - end - table.insert(tbl, a) - end - f:close() - http.prepare_content("text/plain; charset=utf-8") - http.write(table.concat(tbl, "\n")) -end -function reload_config() - fs.remove("/tmp/AdGuardHometmpconfig.yaml") - http.prepare_content("application/json") - http.write('') -end -function act_status() - local e={} - local binpath=uci:get("AdGuardHome","AdGuardHome","binpath") - e.running=luci.sys.call("pgrep "..binpath.." >/dev/null")==0 - e.redirect=(fs.readfile("/var/run/AdGredir")=="1") - http.prepare_content("application/json") - http.write_json(e) -end -function do_update() - fs.writefile("/var/run/lucilogpos","0") - http.prepare_content("application/json") - http.write('') - local arg - if luci.http.formvalue("force") == "1" then - arg="force" - else - arg="" - end - if arg=="force" then - luci.sys.exec("kill $(pgrep /usr/share/AdGuardHome/update_core.sh) ; sh /usr/share/AdGuardHome/update_core.sh "..arg.." >/tmp/AdGuardHome_update.log 2>&1 &") - - - else - luci.sys.exec("sh /usr/share/AdGuardHome/update_core.sh "..arg.." >/tmp/AdGuardHome_update.log 2>&1 &") - end -end -function get_log() - local logfile=uci:get("AdGuardHome","AdGuardHome","logfile") - if (logfile==nil) then - http.write("no log available\n") - return - elseif (logfile=="syslog") then - if not fs.access("/var/run/AdGuardHomesyslog") then - luci.sys.exec("(/usr/share/AdGuardHome/getsyslog.sh &); sleep 1;") - end - logfile="/tmp/AdGuardHometmp.log" - fs.writefile("/var/run/AdGuardHomesyslog","1") - elseif not fs.access(logfile) then - http.write("") - return - end - http.prepare_content("text/plain; charset=utf-8") - local fdp = tonumber(fs.readfile("/var/run/lucilogpos")) or 0 - local f=io.open(logfile, "r+") - f:seek("set",fdp) - local a=f:read(2048000) or "" - fdp=f:seek() - fs.writefile("/var/run/lucilogpos",tostring(fdp)) - f:close() - http.write(a) -end -function do_dellog() - local logfile=uci:get("AdGuardHome","AdGuardHome","logfile") - fs.writefile(logfile,"") - http.prepare_content("application/json") - http.write('') -end -function check_update() - http.prepare_content("text/plain; charset=utf-8") - local fdp=tonumber(fs.readfile("/var/run/lucilogpos")) or 0 - local f=io.open("/tmp/AdGuardHome_update.log", "r+") - f:seek("set",fdp) - local a=f:read(2048000) or "" - fdp=f:seek() - fs.writefile("/var/run/lucilogpos",tostring(fdp)) - f:close() -if fs.access("/var/run/update_core") then - http.write(a) -else - http.write(a.."\0") -end -end diff --git a/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/base.lua b/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/base.lua deleted file mode 100644 index 0bd24446..00000000 --- a/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/base.lua +++ /dev/null @@ -1,302 +0,0 @@ -require("luci.sys") -require("luci.util") -require("io") -local m,s,o,o1 -local fs=require"nixio.fs" -local uci=require"luci.model.uci".cursor() -local configpath=uci:get("AdGuardHome","AdGuardHome","configpath") or "/etc/AdGuardHome.yaml" -local binpath = uci:get("AdGuardHome", "AdGuardHome", "binpath") or "/usr/bin/AdGuardHome/AdGuardHome" -httpport=uci:get("AdGuardHome","AdGuardHome","httpport") or "3000" -m = Map("AdGuardHome", "AdGuard Home") -m.description = translate("Free and open source, powerful network-wide ads & trackers blocking DNS server.") -m:section(SimpleSection).template = "AdGuardHome/AdGuardHome_status" - -s = m:section(TypedSection, "AdGuardHome") -s.anonymous=true -s.addremove=false ----- enable -o = s:option(Flag, "enabled", translate("Enable")) -o.default = 0 -o.optional = false ----- httpport -o =s:option(Value,"httpport",translate("Browser management port")) -o.placeholder=3000 -o.default=3000 -o.datatype="port" -o.optional = false -o.description = translate("") ----- update warning not safe -local binmtime=uci:get("AdGuardHome","AdGuardHome","binmtime") or "0" -local e="" -if not fs.access(configpath) then e = e .. " " .. translate("no config") end -if not fs.access(binpath) then - e=e.." "..translate("no core") -else - local version=uci:get("AdGuardHome","AdGuardHome","version") - local testtime=fs.stat(binpath,"mtime") - if testtime~=tonumber(binmtime) or version==nil then - -- local tmp=luci.sys.exec(binpath.." -c /dev/null --check-config 2>&1| grep -m 1 -E 'v[0-9.]+' -o") - -- version=string.sub(tmp, 1, -2) - version = luci.sys.exec(string.format("echo -n $(%s --version 2>&1 | awk -F 'version ' '{print $2}' | awk -F ',' '{print $1}')", binpath)) - if version == "" then version = "core error" end - uci:set("AdGuardHome", "AdGuardHome", "version", version) - uci:set("AdGuardHome", "AdGuardHome", "binmtime", testtime) - uci:commit("AdGuardHome") - end - e=version..e -end - -o = s:option(ListValue, "core_version", translate("Core Version")) -o:value("latest", translate("Latest Version")) -o:value("beta", translate("Beta Version")) -o.default = "latest" -o = s:option(Button, "restart", translate("Upgrade Core")) -o.inputtitle=translate("Update core version") -o.template = "AdGuardHome/AdGuardHome_check" -o.showfastconfig=(not fs.access(configpath)) -o.description = string.format(translate("Current core version:") .. "%s ", e) ----- port warning not safe -local port=luci.sys.exec("awk '/ port:/{printf($2);exit;}' "..configpath.." 2>nul") -if (port=="") then port="?" end ----- Redirect -o = s:option(ListValue, "redirect", port..translate("Redirect"), translate("AdGuardHome redirect mode")) -o.placeholder = "none" -o:value("none", translate("none")) -o:value("dnsmasq-upstream", translate("Run as dnsmasq upstream server")) -o:value("redirect", translate("Redirect 53 port to AdGuardHome")) -o:value("exchange", translate("Use port 53 replace dnsmasq")) -o.default = "none" -o.optional = true ----- bin path -o = s:option(Value, "binpath", translate("Bin Path"), translate("AdGuardHome Bin path if no bin will auto download")) -o.default = "/usr/bin/AdGuardHome/AdGuardHome" -o.datatype = "string" -o.optional = false -o.rmempty=false -o.validate=function(self, value) -if value=="" then return nil end -if fs.stat(value,"type")=="dir" then - fs.rmdir(value) -end -if fs.stat(value,"type")=="dir" then - if (m.message) then - m.message =m.message.."\nerror!bin path is a dir" - else - m.message ="error!bin path is a dir" - end - return nil -end -return value -end ---- upx -o = s:option(ListValue, "upxflag", translate("use upx to compress bin after download")) -o:value("", translate("none")) -o:value("-1", translate("compress faster")) -o:value("-9", translate("compress better")) -o:value("--best", translate("compress best(can be slow for big files)")) -o:value("--brute", translate("try all available compression methods & filters [slow]")) -o:value("--ultra-brute", translate("try even more compression variants [very slow]")) -o.default = "" -o.description=translate("bin use less space,but may have compatibility issues") -o.rmempty = true ----- config path -o = s:option(Value, "configpath", translate("Config Path"), translate("AdGuardHome config path")) -o.default = "/etc/AdGuardHome.yaml" -o.datatype = "string" -o.optional = false -o.rmempty=false -o.validate=function(self, value) -if value==nil then return nil end -if fs.stat(value,"type")=="dir" then - fs.rmdir(value) -end -if fs.stat(value,"type")=="dir" then - if m.message then - m.message =m.message.."\nerror!config path is a dir" - else - m.message ="error!config path is a dir" - end - return nil -end -return value -end ----- work dir -o = s:option(Value, "workdir", translate("Work dir"), translate("AdGuardHome work dir include rules,audit log and database")) -o.default = "/usr/bin/AdGuardHome" -o.datatype = "string" -o.optional = false -o.rmempty=false -o.validate=function(self, value) -if value=="" then return nil end -if fs.stat(value,"type")=="reg" then - if m.message then - m.message =m.message.."\nerror!work dir is a file" - else - m.message ="error!work dir is a file" - end - return nil -end -if string.sub(value, -1)=="/" then - return string.sub(value, 1, -2) -else - return value -end -end ----- log file -o = s:option(Value, "logfile", translate("Runtime log file"), translate("AdGuardHome runtime Log file if 'syslog': write to system log;if empty no log")) -o.datatype = "string" -o.rmempty = true -o.validate=function(self, value) -if fs.stat(value,"type")=="dir" then - fs.rmdir(value) -end -if fs.stat(value,"type")=="dir" then - if m.message then - m.message =m.message.."\nerror!log file is a dir" - else - m.message ="error!log file is a dir" - end - return nil -end -return value -end ----- debug -o = s:option(Flag, "verbose", translate("Verbose log")) -o.default = 0 -o.optional = true ----- gfwlist -local a=luci.sys.call("grep -m 1 -q programadd "..configpath) -if (a==0) then -a="Added" -else -a="Not added" -end -o=s:option(Button,"gfwdel",translate("Del gfwlist"),translate(a)) -o.optional = true -o.inputtitle=translate("Del") -o.write=function() - luci.sys.exec("sh /usr/share/AdGuardHome/gfw2adg.sh del 2>&1") - luci.http.redirect(luci.dispatcher.build_url("admin","services","AdGuardHome")) -end -o=s:option(Button,"gfwadd",translate("Add gfwlist"),translate(a)) -o.optional = true -o.inputtitle=translate("Add") -o.write=function() - luci.sys.exec("sh /usr/share/AdGuardHome/gfw2adg.sh 2>&1") - luci.http.redirect(luci.dispatcher.build_url("admin","services","AdGuardHome")) -end -o = s:option(Value, "gfwupstream", translate("Gfwlist upstream dns server"), translate("Gfwlist domain upstream dns service")..translate(a)) -o.default = "tcp://208.67.220.220:5353" -o.datatype = "string" -o.optional = true ----- chpass -o = s:option(Value, "hashpass", translate("Change browser management password"), translate("Press load culculate model and culculate finally save/apply")) -o.default = "" -o.datatype = "string" -o.template = "AdGuardHome/AdGuardHome_chpass" -o.optional = true ----- upgrade protect -o = s:option(MultiValue, "upprotect", translate("Keep files when system upgrade")) -o:value("$binpath",translate("core bin")) -o:value("$configpath",translate("config file")) -o:value("$logfile",translate("log file")) -o:value("$workdir/data/sessions.db",translate("sessions.db")) -o:value("$workdir/data/stats.db",translate("stats.db")) -o:value("$workdir/data/querylog.json",translate("querylog.json")) -o:value("$workdir/data/filters",translate("filters")) -o.widget = "checkbox" -o.default = nil -o.optional=true ----- wait net on boot -o = s:option(Flag, "waitonboot", translate("On boot when network ok restart")) -o.default = 1 -o.optional = true ----- backup workdir on shutdown -local workdir = uci:get("AdGuardHome", "AdGuardHome", "workdir") or "/usr/bin/AdGuardHome" -o = s:option(MultiValue, "backupfile", translate("Backup workdir files when shutdown")) -o1 = s:option(Value, "backupwdpath", translate("Backup workdir path")) -local name -o:value("filters","filters") -o:value("stats.db","stats.db") -o:value("querylog.json","querylog.json") -o:value("sessions.db","sessions.db") -o1:depends ("backupfile", "filters") -o1:depends ("backupfile", "stats.db") -o1:depends ("backupfile", "querylog.json") -o1:depends ("backupfile", "sessions.db") -for name in fs.glob(workdir.."/data/*") -do - name=fs.basename (name) - if name~="filters" and name~="stats.db" and name~="querylog.json" and name~="sessions.db" then - o:value(name,name) - o1:depends ("backupfile", name) - end -end -o.widget = "checkbox" -o.default = nil -o.optional=false -o.description=translate("Will be restore when workdir/data is empty") -----backup workdir path - -o1.default = "/usr/bin/AdGuardHome" -o1.datatype = "string" -o1.optional = false -o1.validate=function(self, value) -if fs.stat(value,"type")=="reg" then - if m.message then - m.message =m.message.."\nerror!backup dir is a file" - else - m.message ="error!backup dir is a file" - end - return nil -end -if string.sub(value,-1)=="/" then - return string.sub(value, 1, -2) -else - return value -end -end - -----Crontab -o = s:option(MultiValue, "crontab", translate("Crontab task"),translate("Please change time and args in crontab")) -o:value("autoupdate",translate("Auto update core")) -o:value("cutquerylog",translate("Auto tail querylog")) -o:value("cutruntimelog",translate("Auto tail runtime log")) -o:value("autohost",translate("Auto update ipv6 hosts and restart adh")) -o:value("autogfw",translate("Auto update gfwlist and restart adh")) -o.widget = "checkbox" -o.default = nil -o.optional=true - -o = s:option(Value, "update_url", translate("Core Update URL")) -o.default = "https://github.com/AdguardTeam/AdGuardHome/releases/download/${Cloud_Version}/AdGuardHome_linux_${Arch}.tar.gz" -o.placeholder = "https://github.com/AdguardTeam/AdGuardHome/releases/download/${Cloud_Version}/AdGuardHome_linux_${Arch}.tar.gz" -o.rmempty = false -o.optional = false - -function m.on_commit(map) - if (fs.access("/var/run/AdGserverdis")) then - io.popen("/etc/init.d/AdGuardHome reload &") - return - end - local ucitracktest=uci:get("AdGuardHome","AdGuardHome","ucitracktest") - if ucitracktest=="1" then - return - elseif ucitracktest=="0" then - io.popen("/etc/init.d/AdGuardHome reload &") - else - if (fs.access("/var/run/AdGlucitest")) then - uci:set("AdGuardHome","AdGuardHome","ucitracktest","0") - io.popen("/etc/init.d/AdGuardHome reload &") - else - fs.writefile("/var/run/AdGlucitest","") - if (ucitracktest=="2") then - uci:set("AdGuardHome","AdGuardHome","ucitracktest","1") - else - uci:set("AdGuardHome","AdGuardHome","ucitracktest","2") - end - end - uci:commit("AdGuardHome") - end -end -return m diff --git a/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/log.lua b/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/log.lua deleted file mode 100644 index 2581ade5..00000000 --- a/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/log.lua +++ /dev/null @@ -1,16 +0,0 @@ -local fs = require "nixio.fs" -local uci = require"luci.model.uci".cursor() -local f, t -f = SimpleForm("logview") -f.reset = false -f.submit = false -t=f:field(TextValue,"conf") -t.rmempty=true -t.rows=20 -t.template="AdGuardHome/log" -t.readonly="readonly" -local logfile=uci:get("AdGuardHome","AdGuardHome","logfile") or "" -t.timereplace=(logfile~="syslog" and logfile~="" ) -t.pollcheck=logfile~="" -fs.writefile("/var/run/lucilogpos", "0") -return f diff --git a/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/manual.lua b/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/manual.lua deleted file mode 100644 index 11d8a0c1..00000000 --- a/luci-app-adguardhome/luasrc/model/cbi/AdGuardHome/manual.lua +++ /dev/null @@ -1,96 +0,0 @@ -local m, s, o -local fs = require "nixio.fs" -local uci=require"luci.model.uci".cursor() -local sys=require"luci.sys" -require("string") -require("io") -require("table") -function gen_template_config() - local b - local d="" - local file = "/tmp/resolv.conf.d/resolv.conf.auto" - if not fs.access(file) then - file = "/tmp/resolv.conf.auto" - end - for cnt in io.lines(file) do - b = string.match(cnt, "^[^#]*nameserver%s+([^%s]+)$") - if (b ~= nil) then d = d .. " - " .. b .. "\n" end - end - local f=io.open("/usr/share/AdGuardHome/AdGuardHome_template.yaml", "r+") - local tbl = {} - local a="" - while (1) do - a=f:read("*l") - if (a=="#bootstrap_dns") then - a=d - elseif (a=="#upstream_dns") then - a=d - elseif (a==nil) then - break - end - table.insert(tbl, a) - end - f:close() - return table.concat(tbl, "\n") -end -m = Map("AdGuardHome") -local configpath = uci:get("AdGuardHome","AdGuardHome","configpath") -local binpath = uci:get("AdGuardHome","AdGuardHome","binpath") -s = m:section(TypedSection, "AdGuardHome") -s.anonymous=true -s.addremove=false ---- config -o = s:option(TextValue, "escconf") -o.rows = 66 -o.wrap = "off" -o.rmempty = true -o.cfgvalue = function(self, section) - return fs.readfile("/tmp/AdGuardHometmpconfig.yaml") or fs.readfile(configpath) or gen_template_config() or "" -end -o.validate=function(self, value) - fs.writefile("/tmp/AdGuardHometmpconfig.yaml", value:gsub("\r\n", "\n")) - if fs.access(binpath) then - if (sys.call(binpath .. " -c /tmp/AdGuardHometmpconfig.yaml --check-config 2> /tmp/AdGuardHometest.log") == 0) then return value end - else - return value - end - luci.http.redirect(luci.dispatcher.build_url("admin","services","AdGuardHome","manual")) - return nil -end -o.write = function(self, section, value) - fs.move("/tmp/AdGuardHometmpconfig.yaml",configpath) -end -o.remove = function(self, section, value) fs.writefile(configpath, "") end - ---- js and reload button -o = s:option(DummyValue, "") -o.anonymous=true -o.template = "AdGuardHome/yamleditor" -if not fs.access(binpath) then - o.description=translate("WARNING!!! no bin found apply config will not be test") -end ---- log -if (fs.access("/tmp/AdGuardHometmpconfig.yaml")) then -local c=fs.readfile("/tmp/AdGuardHometest.log") -if (c~="") then -o = s:option(TextValue, "") -o.readonly=true -o.rows = 5 -o.rmempty = true -o.name="" -o.cfgvalue = function(self, section) - return fs.readfile("/tmp/AdGuardHometest.log") -end -end -end -function m.on_commit(map) - local ucitracktest=uci:get("AdGuardHome","AdGuardHome","ucitracktest") - if ucitracktest=="1" then - return - elseif ucitracktest=="0" then - io.popen("/etc/init.d/AdGuardHome reload &") - else - fs.writefile("/var/run/AdGlucitest","") - end -end -return m \ No newline at end of file diff --git a/luci-app-adguardhome/luasrc/view/AdGuardHome/AdGuardHome_check.htm b/luci-app-adguardhome/luasrc/view/AdGuardHome/AdGuardHome_check.htm deleted file mode 100644 index 35887b40..00000000 --- a/luci-app-adguardhome/luasrc/view/AdGuardHome/AdGuardHome_check.htm +++ /dev/null @@ -1,78 +0,0 @@ -<%+cbi/valueheader%> -<%local fs=require"nixio.fs"%> - - -<% if self.showfastconfig then %> - -<%end%> - - -<%+cbi/valuefooter%> \ No newline at end of file diff --git a/luci-app-adguardhome/luasrc/view/AdGuardHome/AdGuardHome_chpass.htm b/luci-app-adguardhome/luasrc/view/AdGuardHome/AdGuardHome_chpass.htm deleted file mode 100644 index 905c3a8e..00000000 --- a/luci-app-adguardhome/luasrc/view/AdGuardHome/AdGuardHome_chpass.htm +++ /dev/null @@ -1,49 +0,0 @@ -<%+cbi/valueheader%> - - 0, "data-choices", { self.keylist, self.vallist }) - %> /> - <% if self.password then %><% end %> - -<%+cbi/valuefooter%> \ No newline at end of file diff --git a/luci-app-adguardhome/luasrc/view/AdGuardHome/AdGuardHome_status.htm b/luci-app-adguardhome/luasrc/view/AdGuardHome/AdGuardHome_status.htm deleted file mode 100644 index a1bf86b5..00000000 --- a/luci-app-adguardhome/luasrc/view/AdGuardHome/AdGuardHome_status.htm +++ /dev/null @@ -1,27 +0,0 @@ - - -
-

- <%:Collecting data...%> -

-
\ No newline at end of file diff --git a/luci-app-adguardhome/luasrc/view/AdGuardHome/log.htm b/luci-app-adguardhome/luasrc/view/AdGuardHome/log.htm deleted file mode 100644 index a6d6bc36..00000000 --- a/luci-app-adguardhome/luasrc/view/AdGuardHome/log.htm +++ /dev/null @@ -1,111 +0,0 @@ -<%+cbi/valueheader%> -<%:reverse%> -<%if self.timereplace then%> -<%:localtime%>
-<%end%> - - - - -<%+cbi/valuefooter%> \ No newline at end of file diff --git a/luci-app-adguardhome/luasrc/view/AdGuardHome/yamleditor.htm b/luci-app-adguardhome/luasrc/view/AdGuardHome/yamleditor.htm deleted file mode 100644 index 639cb998..00000000 --- a/luci-app-adguardhome/luasrc/view/AdGuardHome/yamleditor.htm +++ /dev/null @@ -1,39 +0,0 @@ -<%+cbi/valueheader%> - - - - - - - - - -<%fs=require"nixio.fs"%> -<%if fs.access("/tmp/AdGuardHometmpconfig.yaml") then%> - -<%end%> - -<%+cbi/valuefooter%> \ No newline at end of file diff --git a/luci-app-adguardhome/po/zh-cn b/luci-app-adguardhome/po/zh-cn new file mode 120000 index 00000000..8d69574d --- /dev/null +++ b/luci-app-adguardhome/po/zh-cn @@ -0,0 +1 @@ +zh_Hans \ No newline at end of file diff --git a/luci-app-adguardhome/po/zh-cn/AdGuardHome.po b/luci-app-adguardhome/po/zh-cn/AdGuardHome.po deleted file mode 100644 index f4e9da6a..00000000 --- a/luci-app-adguardhome/po/zh-cn/AdGuardHome.po +++ /dev/null @@ -1,303 +0,0 @@ -#/cgi-bin/luci/admin/services/AdGuardHome -msgid "Base Setting" -msgstr "基础设置" - -msgid "Log" -msgstr "日志" - -msgid "AdGuardHome's version" -msgstr "AdGuardHome 版本" - -msgid "Needed to click 'save&apply' to generate the configuration file" -msgstr "需要点击“保存并应用”才能生成配置文件" - -msgid "In case of the latest realease is a source code that can not download the binary file" -msgstr "防止最新release只有源码,导致下载不成功" - -msgid "Manual Config" -msgstr "手动设置" - -msgid "Free and open source, powerful network-wide ads & trackers blocking DNS server." -msgstr "全网络广告和跟踪程序拦截DNS服务器,默认账号和密码均为:admin" - -msgid "RUNNING" -msgstr "运行中" - -msgid "NOT RUNNING" -msgstr "未运行" - -msgid "Redirected" -msgstr "已重定向" - -msgid "Not redirect" -msgstr "未重定向" - -msgid "Collecting data..." -msgstr "获取数据中..." - -msgid "Enable" -msgstr "启用" - -msgid "Browser management port" -msgstr "网页管理账号和密码:admin ,端口:" - -msgid "Upgrade Core" -msgstr "更新核心" - -#button change -msgid "Update core version" -msgstr "更新核心版本" - -msgid "Check..." -msgstr "检查中..." - -msgid "Updated" -msgstr "已更新" - -#button hide -msgid "Force update" -msgstr "强制更新核心" - -msgid "Fast config" -msgstr "快速配置" - -msgid "Core Version" -msgstr "核心版本" - -msgid "Latest Version" -msgstr "最新版" - -msgid "Beta Version" -msgstr "测试版" - -msgid "Current core version:" -msgstr "当前核心版本:" - -msgid "core version:" -msgstr "核心版本:" - -msgid "no config" -msgstr "没有配置文件" - -msgid "no core" -msgstr "没有核心" - -# -msgid "Redirect" -msgstr "重定向" - -#inlist -msgid "none" -msgstr "无" - -msgid "Run as dnsmasq upstream server" -msgstr "作为dnsmasq的上游服务器" - -msgid "Redirect 53 port to AdGuardHome" -msgstr "重定向53端口到AdGuardHome" - -msgid "Use port 53 replace dnsmasq" -msgstr "使用53端口替换dnsmasq" - -# -msgid "AdGuardHome redirect mode" -msgstr "AdGuardHome重定向模式" - -msgid "Bin Path" -msgstr "执行文件路径" - -msgid "AdGuardHome Bin path if no bin will auto download" -msgstr "AdGuardHome 执行文件路径 如果没有执行文件将自动下载" - -msgid "use upx to compress bin after download" -msgstr "下载后使用upx压缩执行文件" - -#inlist -msgid "compress faster" -msgstr "快速压缩" - -msgid "compress better" -msgstr "更好的压缩" - -msgid "compress best(can be slow for big files)" -msgstr "最好的压缩(大文件可能慢)" - -msgid "try all available compression methods & filters [slow]" -msgstr "尝试所有可能的压缩方法和过滤器[慢]" - -msgid "try even more compression variants [very slow]" -msgstr "尝试更多变体压缩手段[很慢]" - -msgid "bin use less space,but may have compatibility issues" -msgstr "减小执行文件空间占用,但是可能压缩后有兼容性问题" -# -msgid "Config Path" -msgstr "配置文件路径" - -msgid "AdGuardHome config path" -msgstr "AdGuardHome 配置文件路径" - -msgid "Work dir" -msgstr "工作目录" - -msgid "AdGuardHome work dir include rules,audit log and database" -msgstr "AdGuardHome 工作目录包含规则,审计日志和数据库" - -msgid "Runtime log file" -msgstr "运行日志路径" - -msgid "AdGuardHome runtime Log file if 'syslog': write to system log;if empty no log" -msgstr "AdGuardHome 运行日志, 如果填 syslog 将写入系统日志; 如果该项为空则不记录运行日志" - -msgid "Verbose log" -msgstr "输出详细日志" - -#hide div -msgid "Add gfwlist" -msgstr "添加 GFW 列表" - -msgid "Add" -msgstr "添加" - -msgid "Added" -msgstr "已添加" - -msgid "Not added" -msgstr "未添加" - -#hide div -msgid "Del gfwlist" -msgstr "删除gfw列表" - -msgid "Del" -msgstr "删除" - -#hide div -msgid "Gfwlist upstream dns server" -msgstr "gfw列表上游服务器" - -msgid "Gfwlist domain upstream dns service" -msgstr "gfw列表域名上游服务器" - -#hide div -msgid "Change browser management password" -msgstr "更改网页登录密码" - -msgid "Culculate" -msgstr "计算" - -##button change -msgid "Load culculate model" -msgstr "载入计算模块" - -msgid "loading..." -msgstr "载入中" - -msgid "Please save/apply" -msgstr "请点击[保存/应用]" - -msgid "is empty" -msgstr "为空" - -msgid "Press load culculate model and culculate finally save/apply" -msgstr "先输入你想要的密码, 点击[载入计算模块], 然后点击[计算], 最后点击下方[保存&应用]" - -# -msgid "Keep files when system upgrade" -msgstr "系统升级时保留文件" - -#checkbox -msgid "core bin" -msgstr "核心执行文件" - -msgid "config file" -msgstr "配置文件" - -msgid "log file" -msgstr "日志文件" - -msgid "querylog.json" -msgstr "审计日志.json" - -# -msgid "On boot when network ok restart" -msgstr "开机后网络准备好时重启" - -msgid "Backup workdir files when shutdown" -msgstr "在关机时备份工作目录文件" - -msgid "Will be restore when workdir/data is empty" -msgstr "在工作目录/data为空的时候恢复" - -msgid "Backup workdir path" -msgstr "工作目录备份路径" - -msgid "Crontab task" -msgstr "计划任务" - -msgid "Auto update core" -msgstr "自动升级核心" - -msgid "Auto tail querylog" -msgstr "自动截短查询日志" - -msgid "Auto tail runtime log" -msgstr "自动截短运行日志" - -msgid "Auto update ipv6 hosts and restart adh" -msgstr "自动更新ipv6主机并重启adh" - -msgid "Auto update gfwlist and restart adh" -msgstr "自动更新gfw列表并重启adh" - -msgid "Please change time and args in crontab" -msgstr "请在计划任务中修改时间和参数" - -msgid "Core Update URL" -msgstr "核心更新地址" - -#/cgi-bin/luci/admin/services/AdGuardHome/log/ -msgid "reverse" -msgstr "逆序" - -msgid "localtime" -msgstr "本地时间" - -msgid "Please add log path in config to enable log" -msgstr "请在设置里填写日志路径以启用日志" - -msgid "dellog" -msgstr "删除日志" - -msgid "download log" -msgstr "下载日志" - -#/cgi-bin/luci//admin/services/AdGuardHome/manual/ -msgid "Use template" -msgstr "使用模板" - -#hide button -msgid "Reload Config" -msgstr "重新载入配置" - -msgid "WARNING!!! no bin found apply config will not be test" -msgstr "警告!!!未找到执行文件,提交配置将不会进行校验" - -#unused -msgid "Change browser management username" -msgstr "改变网页登录用户名" - -msgid "Username" -msgstr "用户名" - -msgid "Check Config" -msgstr "检查配置" - -msgid "unknown" -msgstr "未知" - -msgid "Keep database when system upgrade" -msgstr "系统升级时保留数据" - -msgid "Boot delay until network ok" -msgstr "开机时直到网络准备好再启动" \ No newline at end of file diff --git a/luci-app-adguardhome/po/zh_Hans/AdGuardHome.po b/luci-app-adguardhome/po/zh_Hans/AdGuardHome.po deleted file mode 100644 index f4e9da6a..00000000 --- a/luci-app-adguardhome/po/zh_Hans/AdGuardHome.po +++ /dev/null @@ -1,303 +0,0 @@ -#/cgi-bin/luci/admin/services/AdGuardHome -msgid "Base Setting" -msgstr "基础设置" - -msgid "Log" -msgstr "日志" - -msgid "AdGuardHome's version" -msgstr "AdGuardHome 版本" - -msgid "Needed to click 'save&apply' to generate the configuration file" -msgstr "需要点击“保存并应用”才能生成配置文件" - -msgid "In case of the latest realease is a source code that can not download the binary file" -msgstr "防止最新release只有源码,导致下载不成功" - -msgid "Manual Config" -msgstr "手动设置" - -msgid "Free and open source, powerful network-wide ads & trackers blocking DNS server." -msgstr "全网络广告和跟踪程序拦截DNS服务器,默认账号和密码均为:admin" - -msgid "RUNNING" -msgstr "运行中" - -msgid "NOT RUNNING" -msgstr "未运行" - -msgid "Redirected" -msgstr "已重定向" - -msgid "Not redirect" -msgstr "未重定向" - -msgid "Collecting data..." -msgstr "获取数据中..." - -msgid "Enable" -msgstr "启用" - -msgid "Browser management port" -msgstr "网页管理账号和密码:admin ,端口:" - -msgid "Upgrade Core" -msgstr "更新核心" - -#button change -msgid "Update core version" -msgstr "更新核心版本" - -msgid "Check..." -msgstr "检查中..." - -msgid "Updated" -msgstr "已更新" - -#button hide -msgid "Force update" -msgstr "强制更新核心" - -msgid "Fast config" -msgstr "快速配置" - -msgid "Core Version" -msgstr "核心版本" - -msgid "Latest Version" -msgstr "最新版" - -msgid "Beta Version" -msgstr "测试版" - -msgid "Current core version:" -msgstr "当前核心版本:" - -msgid "core version:" -msgstr "核心版本:" - -msgid "no config" -msgstr "没有配置文件" - -msgid "no core" -msgstr "没有核心" - -# -msgid "Redirect" -msgstr "重定向" - -#inlist -msgid "none" -msgstr "无" - -msgid "Run as dnsmasq upstream server" -msgstr "作为dnsmasq的上游服务器" - -msgid "Redirect 53 port to AdGuardHome" -msgstr "重定向53端口到AdGuardHome" - -msgid "Use port 53 replace dnsmasq" -msgstr "使用53端口替换dnsmasq" - -# -msgid "AdGuardHome redirect mode" -msgstr "AdGuardHome重定向模式" - -msgid "Bin Path" -msgstr "执行文件路径" - -msgid "AdGuardHome Bin path if no bin will auto download" -msgstr "AdGuardHome 执行文件路径 如果没有执行文件将自动下载" - -msgid "use upx to compress bin after download" -msgstr "下载后使用upx压缩执行文件" - -#inlist -msgid "compress faster" -msgstr "快速压缩" - -msgid "compress better" -msgstr "更好的压缩" - -msgid "compress best(can be slow for big files)" -msgstr "最好的压缩(大文件可能慢)" - -msgid "try all available compression methods & filters [slow]" -msgstr "尝试所有可能的压缩方法和过滤器[慢]" - -msgid "try even more compression variants [very slow]" -msgstr "尝试更多变体压缩手段[很慢]" - -msgid "bin use less space,but may have compatibility issues" -msgstr "减小执行文件空间占用,但是可能压缩后有兼容性问题" -# -msgid "Config Path" -msgstr "配置文件路径" - -msgid "AdGuardHome config path" -msgstr "AdGuardHome 配置文件路径" - -msgid "Work dir" -msgstr "工作目录" - -msgid "AdGuardHome work dir include rules,audit log and database" -msgstr "AdGuardHome 工作目录包含规则,审计日志和数据库" - -msgid "Runtime log file" -msgstr "运行日志路径" - -msgid "AdGuardHome runtime Log file if 'syslog': write to system log;if empty no log" -msgstr "AdGuardHome 运行日志, 如果填 syslog 将写入系统日志; 如果该项为空则不记录运行日志" - -msgid "Verbose log" -msgstr "输出详细日志" - -#hide div -msgid "Add gfwlist" -msgstr "添加 GFW 列表" - -msgid "Add" -msgstr "添加" - -msgid "Added" -msgstr "已添加" - -msgid "Not added" -msgstr "未添加" - -#hide div -msgid "Del gfwlist" -msgstr "删除gfw列表" - -msgid "Del" -msgstr "删除" - -#hide div -msgid "Gfwlist upstream dns server" -msgstr "gfw列表上游服务器" - -msgid "Gfwlist domain upstream dns service" -msgstr "gfw列表域名上游服务器" - -#hide div -msgid "Change browser management password" -msgstr "更改网页登录密码" - -msgid "Culculate" -msgstr "计算" - -##button change -msgid "Load culculate model" -msgstr "载入计算模块" - -msgid "loading..." -msgstr "载入中" - -msgid "Please save/apply" -msgstr "请点击[保存/应用]" - -msgid "is empty" -msgstr "为空" - -msgid "Press load culculate model and culculate finally save/apply" -msgstr "先输入你想要的密码, 点击[载入计算模块], 然后点击[计算], 最后点击下方[保存&应用]" - -# -msgid "Keep files when system upgrade" -msgstr "系统升级时保留文件" - -#checkbox -msgid "core bin" -msgstr "核心执行文件" - -msgid "config file" -msgstr "配置文件" - -msgid "log file" -msgstr "日志文件" - -msgid "querylog.json" -msgstr "审计日志.json" - -# -msgid "On boot when network ok restart" -msgstr "开机后网络准备好时重启" - -msgid "Backup workdir files when shutdown" -msgstr "在关机时备份工作目录文件" - -msgid "Will be restore when workdir/data is empty" -msgstr "在工作目录/data为空的时候恢复" - -msgid "Backup workdir path" -msgstr "工作目录备份路径" - -msgid "Crontab task" -msgstr "计划任务" - -msgid "Auto update core" -msgstr "自动升级核心" - -msgid "Auto tail querylog" -msgstr "自动截短查询日志" - -msgid "Auto tail runtime log" -msgstr "自动截短运行日志" - -msgid "Auto update ipv6 hosts and restart adh" -msgstr "自动更新ipv6主机并重启adh" - -msgid "Auto update gfwlist and restart adh" -msgstr "自动更新gfw列表并重启adh" - -msgid "Please change time and args in crontab" -msgstr "请在计划任务中修改时间和参数" - -msgid "Core Update URL" -msgstr "核心更新地址" - -#/cgi-bin/luci/admin/services/AdGuardHome/log/ -msgid "reverse" -msgstr "逆序" - -msgid "localtime" -msgstr "本地时间" - -msgid "Please add log path in config to enable log" -msgstr "请在设置里填写日志路径以启用日志" - -msgid "dellog" -msgstr "删除日志" - -msgid "download log" -msgstr "下载日志" - -#/cgi-bin/luci//admin/services/AdGuardHome/manual/ -msgid "Use template" -msgstr "使用模板" - -#hide button -msgid "Reload Config" -msgstr "重新载入配置" - -msgid "WARNING!!! no bin found apply config will not be test" -msgstr "警告!!!未找到执行文件,提交配置将不会进行校验" - -#unused -msgid "Change browser management username" -msgstr "改变网页登录用户名" - -msgid "Username" -msgstr "用户名" - -msgid "Check Config" -msgstr "检查配置" - -msgid "unknown" -msgstr "未知" - -msgid "Keep database when system upgrade" -msgstr "系统升级时保留数据" - -msgid "Boot delay until network ok" -msgstr "开机时直到网络准备好再启动" \ No newline at end of file diff --git a/luci-app-adguardhome/po/zh_Hans/adguardhome.po b/luci-app-adguardhome/po/zh_Hans/adguardhome.po new file mode 100644 index 00000000..deaa0907 --- /dev/null +++ b/luci-app-adguardhome/po/zh_Hans/adguardhome.po @@ -0,0 +1,179 @@ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Project-Id-Version: PACKAGE VERSION\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: zh\n" +"MIME-Version: 1.0\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "AdGuard Home" +msgstr "" + +msgid "AdGuard Home Configuration" +msgstr "配置" + +msgid "AdGuard Home Statistics" +msgstr "统计" + +msgid "AdGuard Home Status" +msgstr "状态" + +msgid "AdGuard Home Status - Error" +msgstr "状态 - 错误" + +msgid "Average processing time (seconds)" +msgstr "平均处理时间(秒)" + +msgid "Bootstrap DNS addresses" +msgstr "Bootstrap DNS 地址" + +msgid "Configuration" +msgstr "配置" + +msgid "DNS blocks" +msgstr "DNS 拦截" + +msgid "DNS listen addresses" +msgstr "DNS 监听地址" + +msgid "DNS listen port" +msgstr "DNS 监听端口" + +msgid "DNS queries" +msgstr "DNS 查询" + +msgid "DNS replacements (malware/phishing)" +msgstr "DNS 替换(恶意软件/钓鱼)" + +msgid "DNS replacements (safesearch)" +msgstr "DNS 替换(安全搜索)" + +msgid "General settings" +msgstr "常规设置" + +msgid "Grant permissions for the AdGuard Home LuCI app" +msgstr "授予 AdGuard Home LuCI 应用权限" + +msgid "Logs" +msgstr "日志" + +msgid "No" +msgstr "否" + +msgid "Not found" +msgstr "未找到" + +msgid "Password for AdGuard Home" +msgstr "密码" + +msgid "Please open the Configuration section, and provide the credentials." +msgstr "请打开配置部分,并提供凭证。" + +msgid "Protection enabled" +msgstr "保护已启用" + +msgid "RPC call failure:" +msgstr "RPC 调用失败:" + +msgid "Running" +msgstr "运行中" + +msgid "Showing last 50 lines" +msgstr "显示最近的50行" + +msgid "Statistics period (days)" +msgstr "统计周期(天)" + +msgid "Status" +msgstr "状态" + +msgid "System Log (AdGuard Home)" +msgstr "系统日志" + +msgid "The password you configured when you set up AdGuard Home" +msgstr "您在设置 AdGuard Home 时配置的密码" + +msgid "The username you configured when you set up AdGuard Home" +msgstr "您在设置 AdGuard Home 时配置的用户名" + +msgid "" +"This application requires the username and password that were configured " +"when you set up AdGuard Home, as the REST API for AdGuard Home is password " +"protected. The password cannot be read from the YAML configuration file for " +"AdGuard Home, as it is encrypted in that store. The credentials supplied " +"here will be stored unencrypted in /etc/config/adguardhome on your device." +msgstr "" +"此应用程序需要您在设置 AdGuard Home 时配置的用户名和密码,因为 AdGuard Home 的 REST API 受密码保护。" +"密码无法从 AdGuard Home 的 YAML 配置文件中读取,因为它在存储中是加密的。" +"此处提供的凭证将以未加密的形式存储在设备上的 /etc/config/adguardhome 中。" + +msgid "Top Blocked Domains" +msgstr "最常被拦截的域名" + +msgid "Top Queried Domains" +msgstr "最常查询的域名" + +msgid "Unable to load log data:" +msgstr "无法加载日志数据:" + +msgid "Upstream DNS addresses" +msgstr "上游 DNS 地址" + +msgid "Username for AdGuard Home" +msgstr "用户名" + +msgid "Version" +msgstr "版本" + +msgid "Web interface" +msgstr "AdGuardHome 管理界面" + +msgid "Yes" +msgstr "是" + +msgid "RUNNING" +msgstr "运行中" + +msgid "NOT RUNNING" +msgstr "未运行" + +msgid "Collecting data..." +msgstr "获取数据中..." + +msgid "Enable" +msgstr "启用" + +msgid "Redirect" +msgstr "重定向" + +msgid "none" +msgstr "无" + +msgid "Run as dnsmasq upstream server" +msgstr "作为dnsmasq的上游服务器" + +msgid "Redirect 53 port to AdGuardHome" +msgstr "重定向53端口到AdGuardHome" + +msgid "Use port 53 replace dnsmasq" +msgstr "使用53端口替换dnsmasq" + +msgid "AdGuardHome redirect mode" +msgstr "重定向模式" + +msgid "Change Password" +msgstr "修改密码" + +msgid "Work Dir" +msgstr "工作目录" + +msgid "Service user" +msgstr "以此用户权限运行" + +msgid "Service group" +msgstr "以此用户组权限运行" + +msgid "Configuration file" +msgstr "配置文件" diff --git a/luci-app-adguardhome/root/etc/AdGuardHome.yaml b/luci-app-adguardhome/root/etc/AdGuardHome.yaml deleted file mode 100644 index 95c665f3..00000000 --- a/luci-app-adguardhome/root/etc/AdGuardHome.yaml +++ /dev/null @@ -1,219 +0,0 @@ -http: - address: 0.0.0.0:3000 - session_ttl: 720h -users: - - name: admin - password: $2y$10$vHRcARdPCieYG3RXWomV5evDYN.Nj/edtwEkQgQJZcK6z7qTLaIc6 -auth_attempts: 5 -block_auth_min: 15 -http_proxy: "" -language: zh-cn -theme: auto -debug_pprof: false -dns: - bind_hosts: - - 0.0.0.0 - port: 1745 - anonymize_client_ip: false - protection_enabled: true - blocking_mode: default - blocking_ipv4: "" - blocking_ipv6: "" - blocked_response_ttl: 10 - protection_disabled_until: null - parental_block_host: family-block.dns.adguard.com - safebrowsing_block_host: standard-block.dns.adguard.com - ratelimit: 0 - ratelimit_whitelist: [] - refuse_any: false - upstream_dns: - - 223.5.5.5 - upstream_dns_file: "" - bootstrap_dns: - - 119.29.29.29 - - 223.5.5.5 - all_servers: false - fastest_addr: false - fastest_timeout: 1s - allowed_clients: [] - disallowed_clients: [] - blocked_hosts: - - version.bind - - id.server - - hostname.bind - trusted_proxies: - - 127.0.0.0/8 - - ::1/128 - cache_size: 4194304 - cache_ttl_min: 0 - cache_ttl_max: 0 - cache_optimistic: true - bogus_nxdomain: [] - aaaa_disabled: false - enable_dnssec: false - edns_client_subnet: false - max_goroutines: 300 - ipset: [] - filtering_enabled: true - filters_update_interval: 24 - parental_enabled: false - safesearch_enabled: false - safebrowsing_enabled: false - safebrowsing_cache_size: 1048576 - safesearch_cache_size: 1048576 - parental_cache_size: 1048576 - cache_time: 30 - rewrites: [] - blocked_services: [] - upstream_timeout: 10s - private_networks: [] - use_private_ptr_resolvers: true - local_ptr_upstreams: [] -tls: - enabled: false - server_name: "" - force_https: false - port_https: 443 - port_dns_over_tls: 853 - port_dns_over_quic: 784 - port_dnscrypt: 0 - dnscrypt_config_file: "" - allow_unencrypted_doh: false - certificate_chain: "" - private_key: "" - certificate_path: "" - private_key_path: "" -filters: - - enabled: true - url: https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt - name: AdGuard DNS filter - id: 1228750870 - - enabled: true - url: http://sub.adtchrome.com/adt-chinalist-easylist.txt - name: 广告终结者使用的拦截规则,基于ChinaList+EasyList修正维护 - id: 139789181 - - enabled: true - url: https://easylist-downloads.adblockplus.org/easylist.txt - name: EasyList-去除国际网页中大多数广告,包括不需要的框架、图像和对象 - id: 139789112 - - enabled: true - url: https://easylist-downloads.adblockplus.org/easylistchina.txt - name: EasyList China-EasyList针对国内的补充规则 - id: 139789121 - - enabled: true - url: https://anti-ad.net/adguard.txt - name: anti-AD命中率最高列表 - id: 139789122 - - enabled: false - url: https://raw.iqiq.io/banbendalao/ADgk/master/ADgk.txt - name: ADgk去广告easylistchina补充规则 - id: 139789131 - - enabled: false - url: https://raw.iqiq.io/banbendalao/ADgk/master/kill-baidu-ad.txt - name: ADgk百度广告过滤 - id: 139789133 - - enabled: false - url: https://pgl.yoyo.org/adservers/serverlist.php?hostformat=hosts&showintro=1&mimetype=plaintext - name: Peter Lowe’s Ad and tracking server list​ - id: 139789152 - - enabled: false - url: https://easylist.to/easylist/fanboy-social.txt - name: Fanboy's Social Blocking List - id: 139789153 - - enabled: false - url: https://easylist.to/easylist/fanboy-annoyance.txt - name: Fanboy's Annoyance List - id: 139789154 - - enabled: false - url: https://secure.fanboy.co.nz/fanboy-cookiemonster.txt - name: EasyList Cookie List - id: 139789155 - - enabled: false - url: https://fanboy.co.nz/fanboy-antifacebook.txt - name: Anti-Facebook List - id: 139789161 - - enabled: false - url: https://filters.adtidy.org/extension/ublock/filters/14.txt - name: AdGuard Annoyances filter - id: 139789162 - - enabled: false - url: https://www.fanboy.co.nz/enhancedstats.txt - name: Fanboy's Enhanced Tracking List - id: 139789164 - - enabled: false - url: https://filters.adtidy.org/extension/ublock/filters/3.txt - name: AdGuard Tracking Protection filter - id: 139789165 - - enabled: false - url: https://easylist.to/easylist/easylist.txt - name: EasyList - id: 139789171 - - enabled: false - url: https://filters.adtidy.org/extension/ublock/filters/11.txt - name: AdGuard Mobile Ads filter - id: 139789172 - - enabled: false - url: https://filters.adtidy.org/extension/ublock/filters/2_without_easylist.txt - name: AdGuard Base filter - id: 139789173 - - enabled: false - url: https://easylist-downloads.adblockplus.org/antiadblockfilters.txt - name: Adblock Warning Removal List - id: 139789174 - - enabled: false - url: https://fanboy.co.nz/fanboy-problematic-sites.txt - name: Fanboy's problematic-sites - id: 139789175 - - enabled: false - url: https://adaway.org/hosts.txt - name: Adaway HOST - id: 139789187 -whitelist_filters: [] -user_rules: - - '@@||taobao.com^$important' - - '@@||tmall.com^$important' - - '@@||jd.com^important' - - '@@||flyme.cn^$important' - - '@@||meizu.com^$important' - - '@@||wl.jd.com^$important' - - '@@||flydigi.com^' - - '@@||pv.sohu.com^$important' - - /googleads.$~script,domain=~googleads.github.io - - /pagead/lvz? - - '||google.com/pagead/' - - '||static.doubleclick.net^$domain=youtube.com' - - '||youtube.com/get_midroll_' - - '||5hz.org^' - - '@@||000714.xyz^' - - '@@||blueskyxn.com^' - - '||topnewsfeeds.net^' - - '||nbryb.com^' - - '||superbdolly.com^' - - '||salutationcheerlessdemote.com^' - - '||buildingdoodlesquare.com^' - - '||colonistnobilityheroic.com^' -dhcp: - enabled: false - interface_name: "" - dhcpv4: - gateway_ip: "" - subnet_mask: "" - range_start: "" - range_end: "" - lease_duration: 86400 - icmp_timeout_msec: 1000 - options: [] - dhcpv6: - range_start: "" - lease_duration: 86400 - ra_slaac_only: false - ra_allow_slaac: false -clients: [] -log_compress: false -log_localtime: false -log_max_backups: 0 -log_max_size: 100 -log_max_age: 3 -log_file: "" -verbose: false -schema_version: 10 diff --git a/luci-app-adguardhome/root/etc/adguardhome/adguardhome.yaml b/luci-app-adguardhome/root/etc/adguardhome/adguardhome.yaml new file mode 100644 index 00000000..e5c0a509 --- /dev/null +++ b/luci-app-adguardhome/root/etc/adguardhome/adguardhome.yaml @@ -0,0 +1,180 @@ +http: + pprof: + port: 6060 + enabled: false + address: 0.0.0.0:3000 + session_ttl: 720h +users: + - name: admin + password: $2y$10$.ujnc.Bphsaz4Z.SbOoMiux2z8DxpJUaIrD5gcITed.vKx.qrZSfC +auth_attempts: 5 +block_auth_min: 15 +http_proxy: "" +language: "" +theme: auto +dns: + bind_hosts: + - 0.0.0.0 + port: 5333 + anonymize_client_ip: false + ratelimit: 20 + ratelimit_subnet_len_ipv4: 24 + ratelimit_subnet_len_ipv6: 56 + ratelimit_whitelist: [] + refuse_any: true + upstream_dns: + - https://dns10.quad9.net/dns-query + upstream_dns_file: "" + bootstrap_dns: + - 9.9.9.10 + - 149.112.112.10 + - 2620:fe::10 + - 2620:fe::fe:10 + fallback_dns: [] + upstream_mode: parallel + fastest_timeout: 1s + allowed_clients: [] + disallowed_clients: [] + blocked_hosts: + - version.bind + - id.server + - hostname.bind + trusted_proxies: + - 127.0.0.0/8 + - ::1/128 + cache_size: 4194304 + cache_ttl_min: 0 + cache_ttl_max: 0 + cache_optimistic: false + bogus_nxdomain: [] + aaaa_disabled: false + enable_dnssec: false + edns_client_subnet: + custom_ip: "" + enabled: false + use_custom: false + max_goroutines: 300 + handle_ddr: true + ipset: [] + ipset_file: "" + bootstrap_prefer_ipv6: false + upstream_timeout: 10s + private_networks: [] + use_private_ptr_resolvers: true + local_ptr_upstreams: [] + use_dns64: false + dns64_prefixes: [] + serve_http3: false + use_http3_upstreams: false + serve_plain_dns: true + hostsfile_enabled: true +tls: + enabled: false + server_name: "" + force_https: false + port_https: 443 + port_dns_over_tls: 853 + port_dns_over_quic: 853 + port_dnscrypt: 0 + dnscrypt_config_file: "" + allow_unencrypted_doh: false + certificate_chain: "" + private_key: "" + certificate_path: "" + private_key_path: "" + strict_sni_check: false +querylog: + dir_path: "" + ignored: [] + interval: 2160h + size_memory: 1000 + enabled: true + file_enabled: true +statistics: + dir_path: "" + ignored: [] + interval: 24h + enabled: true +filters: + - enabled: true + url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_1.txt + name: AdGuard DNS filter + id: 1 + - enabled: false + url: https://adguardteam.github.io/HostlistsRegistry/assets/filter_2.txt + name: AdAway Default Blocklist + id: 2 +whitelist_filters: [] +user_rules: [] +dhcp: + enabled: false + interface_name: "" + local_domain_name: lan + dhcpv4: + gateway_ip: "" + subnet_mask: "" + range_start: "" + range_end: "" + lease_duration: 86400 + icmp_timeout_msec: 1000 + options: [] + dhcpv6: + range_start: "" + lease_duration: 86400 + ra_slaac_only: false + ra_allow_slaac: false +filtering: + blocking_ipv4: "" + blocking_ipv6: "" + blocked_services: + schedule: + time_zone: UTC + ids: [] + protection_disabled_until: null + safe_search: + enabled: false + bing: true + duckduckgo: true + ecosia: true + google: true + pixabay: true + yandex: true + youtube: true + blocking_mode: default + parental_block_host: family-block.dns.adguard.com + safebrowsing_block_host: standard-block.dns.adguard.com + rewrites: [] + safe_fs_patterns: + - /tmp/lib/adguardhome/userfilters/* + safebrowsing_cache_size: 1048576 + safesearch_cache_size: 1048576 + parental_cache_size: 1048576 + cache_time: 30 + filters_update_interval: 24 + blocked_response_ttl: 10 + filtering_enabled: true + parental_enabled: false + safebrowsing_enabled: false + protection_enabled: true +clients: + runtime_sources: + whois: true + arp: true + rdns: true + dhcp: true + hosts: true + persistent: [] +log: + enabled: true + file: "" + max_backups: 0 + max_size: 100 + max_age: 3 + compress: false + local_time: false + verbose: false +os: + group: "" + user: "" + rlimit_nofile: 0 +schema_version: 29 diff --git a/luci-app-adguardhome/root/etc/config/AdGuardHome b/luci-app-adguardhome/root/etc/config/AdGuardHome deleted file mode 100644 index de6d9f29..00000000 --- a/luci-app-adguardhome/root/etc/config/AdGuardHome +++ /dev/null @@ -1,19 +0,0 @@ - -config AdGuardHome 'AdGuardHome' - option enabled '0' - option httpport '3000' - option redirect 'dnsmasq-upstream' - option configpath '/etc/AdGuardHome.yaml' - option workdir '/tmp/AdGuardHome' - option logfile '/tmp/AdGuardHome.log' - option verbose '0' - option binpath '/usr/bin/AdGuardHome/AdGuardHome' - option upxflag '-1' - - option waitonboot '0' - option update_url 'https://github.com/AdguardTeam/AdGuardHome/releases/download/${Cloud_Version}/AdGuardHome_linux_${Arch}.tar.gz' - option ucitracktest '2' - list old_redirect 'dnsmasq-upstream' - list old_port '5553' - list old_enabled '0' - option version 'v0.107.26' \ No newline at end of file diff --git a/luci-app-adguardhome/root/etc/init.d/AdGuardHome b/luci-app-adguardhome/root/etc/init.d/AdGuardHome deleted file mode 100755 index 32ab310c..00000000 --- a/luci-app-adguardhome/root/etc/init.d/AdGuardHome +++ /dev/null @@ -1,647 +0,0 @@ -#!/bin/sh /etc/rc.common - -USE_PROCD=1 - -START=95 -STOP=01 - -ipt=$(command -v iptables-legacy || command -v iptables) -ip6t=$(command -v ip6tables-legacy || command -v ip6tables) -CONFIGURATION=AdGuardHome -CRON_FILE=/etc/crontabs/root -EXTRA_COMMANDS="do_redirect testbackup test_crontab force_reload isrunning" -EXTRA_HELP=" do_redirect 0 or 1\ - testbackup backup or restore\ - test_crontab - force_reload - isrunning" - -set_forward_dnsmasq() -{ - local PORT="$1" - addr="127.0.0.1#$PORT" - OLD_SERVER="`uci get dhcp.@dnsmasq[0].server 2>/dev/null`" - echo $OLD_SERVER | grep "^$addr" >/dev/null 2>&1 - if [ $? -eq 0 ]; then - return - fi - uci delete dhcp.@dnsmasq[0].server 2>/dev/null - uci add_list dhcp.@dnsmasq[0].server=$addr - for server in $OLD_SERVER; do - if [ "$server" = "$addr" ]; then - continue - fi - # uci add_list dhcp.@dnsmasq[0].server=$server - done - uci delete dhcp.@dnsmasq[0].resolvfile 2>/dev/null - uci set dhcp.@dnsmasq[0].noresolv=1 - uci commit dhcp - /etc/init.d/dnsmasq restart -} - -stop_forward_dnsmasq() -{ - local OLD_PORT="$1" - addr="127.0.0.1#$OLD_PORT" - OLD_SERVER="`uci get dhcp.@dnsmasq[0].server 2>/dev/null`" - echo $OLD_SERVER | grep "^$addr" >/dev/null 2>&1 - if [ $? -ne 0 ]; then - return - fi - - uci del_list dhcp.@dnsmasq[0].server=$addr 2>/dev/null - addrlist="`uci get dhcp.@dnsmasq[0].server 2>/dev/null`" - if [ -z "$addrlist" ] ; then - resolvfile="/tmp/resolv.conf.d/resolv.conf.auto" - [ ! -f "$resolvfile" ] && resolvfile="/tmp/resolv.conf.auto" - uci set dhcp.@dnsmasq[0].resolvfile="$resolvfile" 2>/dev/null - uci delete dhcp.@dnsmasq[0].noresolv 2>/dev/null - fi - uci commit dhcp - /etc/init.d/dnsmasq restart -} - -set_iptable() -{ - local ipv6_server=$1 - local tcp_server=$2 - uci -q batch <<-EOF >/dev/null 2>&1 - delete firewall.AdGuardHome - set firewall.AdGuardHome=include - set firewall.AdGuardHome.type=script - set firewall.AdGuardHome.path=/usr/share/AdGuardHome/firewall.start - set firewall.AdGuardHome.reload=1 - commit firewall -EOF - - IPS="`ifconfig | grep "inet addr" | grep -v ":127" | grep "Bcast" | awk '{print $2}' | awk -F : '{print $2}'`" - for IP in $IPS - do - if [ "$tcp_server" == "1" ]; then - $ipt -t nat -A PREROUTING -p tcp -d $IP --dport 53 -j REDIRECT --to-ports $AdGuardHome_PORT >/dev/null 2>&1 - fi - $ipt -t nat -A PREROUTING -p udp -d $IP --dport 53 -j REDIRECT --to-ports $AdGuardHome_PORT >/dev/null 2>&1 - done - - if [ "$ipv6_server" == 0 ]; then - return - fi - - IPS="`ifconfig | grep "inet6 addr" | grep -v " fe80::" | grep -v " ::1" | grep "Global" | awk '{print $3}'`" - for IP in $IPS - do - if [ "$tcp_server" == "1" ]; then - $ipt -t nat -A PREROUTING -p tcp -d $IP --dport 53 -j REDIRECT --to-ports $AdGuardHome_PORT >/dev/null 2>&1 - fi - $ipt -t nat -A PREROUTING -p udp -d $IP --dport 53 -j REDIRECT --to-ports $AdGuardHome_PORT >/dev/null 2>&1 - done -} - -clear_iptable() -{ - uci -q batch <<-EOF >/dev/null 2>&1 - delete firewall.AdGuardHome - commit firewall -EOF - local OLD_PORT="$1" - local ipv6_server=$2 - IPS="`ifconfig | grep "inet addr" | grep -v ":127" | grep "Bcast" | awk '{print $2}' | awk -F : '{print $2}'`" - for IP in $IPS - do - $ipt -t nat -D PREROUTING -p udp -d $IP --dport 53 -j REDIRECT --to-ports $OLD_PORT >/dev/null 2>&1 - $ipt -t nat -D PREROUTING -p tcp -d $IP --dport 53 -j REDIRECT --to-ports $OLD_PORT >/dev/null 2>&1 - done - - if [ "$ipv6_server" == 0 ]; then - return - fi - echo "warn ip6tables nat mod is needed" - IPS="`ifconfig | grep "inet6 addr" | grep -v " fe80::" | grep -v " ::1" | grep "Global" | awk '{print $3}'`" - for IP in $IPS - do - $ipt -t nat -D PREROUTING -p udp -d $IP --dport 53 -j REDIRECT --to-ports $OLD_PORT >/dev/null 2>&1 - $ipt -t nat -D PREROUTING -p tcp -d $IP --dport 53 -j REDIRECT --to-ports $OLD_PORT >/dev/null 2>&1 - done -} - -service_triggers() { - procd_add_reload_trigger "$CONFIGURATION" - [ "$(uci get AdGuardHome.AdGuardHome.redirect)" == "redirect" ] && procd_add_reload_trigger firewall -} - -isrunning(){ - config_load "${CONFIGURATION}" - _isrunning - local r=$? - ([ "$r" == "0" ] && echo "running") || ([ "$r" == "1" ] && echo "not run" ) || echo "no bin" - return $r -} - -_isrunning(){ - config_get binpath $CONFIGURATION binpath "/usr/bin/AdGuardHome/AdGuardHome" - [ ! -f "$binpath" ] && return 2 - pgrep $binpath 2>&1 >/dev/null && return 0 - return 1 -} - -force_reload(){ - config_load "${CONFIGURATION}" - _isrunning && procd_send_signal "$CONFIGURATION" || start -} - -get_tz() -{ - SET_TZ="" - - if [ -e "/etc/localtime" ]; then - return - fi - - for tzfile in /etc/TZ /var/etc/TZ - do - if [ ! -e "$tzfile" ]; then - continue - fi - - tz="`cat $tzfile 2>/dev/null`" - done - - if [ -z "$tz" ]; then - return - fi - - SET_TZ=$tz -} - -rm_port53() -{ - local AdGuardHome_PORT=$(config_editor "dns.port" "" "$configpath" "1") - dnsmasq_port=$(uci get dhcp.@dnsmasq[0].port 2>/dev/null) - if [ -z "$dnsmasq_port" ]; then - dnsmasq_port="53" - fi - if [ "$dnsmasq_port" == "$AdGuardHome_PORT" ]; then - if [ "$dnsmasq_port" == "53" ]; then - dnsmasq_port="1745" - fi - elif [ "$dnsmasq_port" == "53" ]; then - return - fi - config_editor "dns.port" "$dnsmasq_port" "$configpath" - uci set dhcp.@dnsmasq[0].port="53" - uci commit dhcp - config_get binpath $CONFIGURATION binpath "/usr/bin/AdGuardHome/AdGuardHome" - killall -9 $binpath - /etc/init.d/dnsmasq restart -} - -use_port53() -{ - local AdGuardHome_PORT=$(config_editor "dns.port" "" "$configpath" "1") - dnsmasq_port=$(uci get dhcp.@dnsmasq[0].port 2>/dev/null) - if [ -z "$dnsmasq_port" ]; then - dnsmasq_port="53" - fi - if [ "$dnsmasq_port" == "$AdGuardHome_PORT" ]; then - if [ "$dnsmasq_port" == "53" ]; then - AdGuardHome_PORT="1745" - fi - elif [ "$AdGuardHome_PORT" == "53" ]; then - return - fi - config_editor "dns.port" "53" "$configpath" - uci set dhcp.@dnsmasq[0].port="$AdGuardHome_PORT" - uci commit dhcp - /etc/init.d/dnsmasq restart -} - -do_redirect() -{ - config_load "${CONFIGURATION}" - _do_redirect $1 -} - -_do_redirect() -{ - local section="$CONFIGURATION" - args="" - ipv6_server=1 - tcp_server=0 - enabled=$1 - if [ "$enabled" == "1" ]; then - echo -n "1">/var/run/AdGredir - else - echo -n "0">/var/run/AdGredir - fi - config_get configpath $CONFIGURATION configpath "/etc/AdGuardHome.yaml" - AdGuardHome_PORT=$(config_editor "dns.port" "" "$configpath" "1") - if [ ! -s "$configpath" ]; then - cp -f /usr/share/AdGuardHome/AdGuardHome_template.yaml $configpath - fi - if [ -z "$AdGuardHome_PORT" ]; then - AdGuardHome_PORT="0" - fi - config_get "redirect" "$section" "redirect" "none" - config_get "old_redirect" "$section" "old_redirect" "none" - config_get "old_port" "$section" "old_port" "0" - config_get "old_enabled" "$section" "old_enabled" "0" - uci get dhcp.@dnsmasq[0].port >/dev/null 2>&1 || uci set dhcp.@dnsmasq[0].port="53" >/dev/null 2>&1 - uci commit dhcp - if [ "$old_enabled" = "1" -a "$old_redirect" == "exchange" ]; then - AdGuardHome_PORT=$(uci get dhcp.@dnsmasq[0].port 2>/dev/null) - fi - - if [ "$old_redirect" != "$redirect" ] || [ "$old_port" != "$AdGuardHome_PORT" ] || [ "$old_enabled" = "1" -a "$enabled" = "0" ]; then - if [ "$old_redirect" != "none" ]; then - if [ "$old_redirect" == "redirect" -a "$old_port" != "0" ]; then - clear_iptable "$old_port" "$ipv6_server" - elif [ "$old_redirect" == "dnsmasq-upstream" ]; then - stop_forward_dnsmasq "$old_port" - elif [ "$old_redirect" == "exchange" ]; then - rm_port53 - fi - fi - elif [ "$old_enabled" = "1" -a "$enabled" = "1" ]; then - if [ "$old_redirect" == "redirect" -a "$old_port" != "0" ]; then - clear_iptable "$old_port" "$ipv6_server" - fi - fi - uci delete AdGuardHome.@AdGuardHome[0].old_redirect 2>/dev/null - uci delete AdGuardHome.@AdGuardHome[0].old_port 2>/dev/null - uci delete AdGuardHome.@AdGuardHome[0].old_enabled 2>/dev/null - uci add_list AdGuardHome.@AdGuardHome[0].old_redirect="$redirect" 2>/dev/null - uci add_list AdGuardHome.@AdGuardHome[0].old_port="$AdGuardHome_PORT" 2>/dev/null - uci add_list AdGuardHome.@AdGuardHome[0].old_enabled="$enabled" 2>/dev/null - uci commit AdGuardHome - [ "$enabled" == "0" ] && return 1 - if [ "$AdGuardHome_PORT" == "0" ]; then - return 1 - fi - if [ "$redirect" = "redirect" ]; then - set_iptable $ipv6_server $tcp_server - elif [ "$redirect" = "dnsmasq-upstream" ]; then - set_forward_dnsmasq "$AdGuardHome_PORT" - elif [ "$redirect" == "exchange" -a "$(uci get dhcp.@dnsmasq[0].port 2>/dev/null)" == "53" ]; then - use_port53 - fi -} - -get_filesystem() -{ -# print out path filesystem - echo $1 | awk ' - BEGIN{ - while (("mount"| getline ret) > 0) - { - split(ret,d); - fs[d[3]]=d[5]; - m=index(d[1],":") - if (m==0) - { - pt[d[3]]=d[1] - }else{ - pt[d[3]]=substr(d[1],m+1) - }}}{ - split($0,d,"/"); - if ("/" in fs) - { - result1=fs["/"]; - } - if ("/" in pt) - { - result2=pt["/"]; - } - for (i=2;i<=length(d);i++) - { - p[i]=p[i-1]"/"d[i]; - if (p[i] in fs) - { - result1=fs[p[i]]; - result2=pt[p[i]]; - } - } - if (result2 in fs){ - result=fs[result2]} - else{ - result=result1} - print(result);}' -} - -config_editor() -{ - awk -v yaml="$1" -v value="$2" -v file="$3" -v ro="$4" ' - BEGIN{split(yaml,part,"\.");s="";i=1;l=length(part);} - { - if (match($0,s""part[i]":")) - { - if (i==l) - { - split($0,t,": "); - if (ro==""){ - system("sed -i '\''"FNR"c \\"t[1]": "value"'\'' "file); - }else{ - print(t[2]); - } - exit; - } - s=s"[- ]{2}"; - i++; - } - }' $3 -} - -boot_service() { - rm /var/run/AdGserverdis >/dev/null 2>&1 - config_load "${CONFIGURATION}" - config_get waitonboot $CONFIGURATION waitonboot "0" - config_get_bool enabled $CONFIGURATION enabled 0 - config_get binpath $CONFIGURATION binpath "/usr/bin/AdGuardHome/AdGuardHome" - [ -f "$binpath" ] && start_service - if [ "$enabled" == "1" ] && [ "$waitonboot" == "1" ]; then - procd_open_instance "waitnet" - procd_set_param command "/usr/share/AdGuardHome/waitnet.sh" - procd_close_instance - echo "no net start pinging" - fi -} - -testbackup(){ - config_load "${CONFIGURATION}" - if [ "$1" == "backup" ]; then - backup - elif [ "$1" == "restore" ]; then - restore - fi -} - -restore() -{ - config_get workdir $CONFIGURATION workdir "/usr/bin/AdGuardHome" - config_get backupwdpath $CONFIGURATION backupwdpath "/usr/bin/AdGuardHome" - cp -u -r -f $backupwdpath/data $workdir -} - -backup() { - config_get backupwdpath $CONFIGURATION backupwdpath "/usr/bin/AdGuardHome" - mkdir -p $backupwdpath/data - config_get workdir $CONFIGURATION workdir "/usr/bin/AdGuardHome" - config_get backupfile $CONFIGURATION backupfile "" - for one in $backupfile; - do - while : - do - if [ -d "$backupwdpath/data/$one" ]; then - cpret=$(cp -u -r -f $workdir/data/$one $backupwdpath/data 2>&1) - else - cpret=$(cp -u -r -f $workdir/data/$one $backupwdpath/data/$one 2>&1) - fi - echo "$cpret" - echo "$cpret" | grep "no space left on device" - if [ "$?" == "0" ]; then - echo "磁盘已满,删除log重试中" - del_querylog && continue - rm -f -r $backupwdpath/data/filters - rm -f -r $workdir/data/filters && continue - echo "backup failed" - fi - break - done - done -} - -start_service() { - # Reading config - rm /var/run/AdGserverdis >/dev/null 2>&1 - config_load "${CONFIGURATION}" - # update password - config_get hashpass $CONFIGURATION hashpass "" - config_get configpath $CONFIGURATION configpath "/etc/AdGuardHome.yaml" - if [ -n "$hashpass" ]; then - config_editor "users.password" "$hashpass" "$configpath" - uci set $CONFIGURATION.$CONFIGURATION.hashpass="" - fi - local enabled - config_get_bool enabled $CONFIGURATION enabled 0 - # update crontab - do_crontab - if [ "$enabled" == "0" ]; then - _do_redirect 0 - return - fi - #what need to do before reload - config_get workdir $CONFIGURATION workdir "/usr/bin/AdGuardHome" - - config_get backupfile $CONFIGURATION backupfile "" - mkdir -p $workdir/data - if [ -n "$backupfile" ] && [ ! -d "$workdir/data" ]; then - restore - fi - # for overlay data-stk-oo not suppport - local cwdfs=$(get_filesystem $workdir) - echo "workdir is a $cwdfs filesystem" - if [ "$cwdfs" == "jffs2" ]; then - echo "fs error ln db to tmp $workdir $cwdfs" - logger "AdGuardHome" "warning db redirect to tmp" - touch $workdir/data/stats.db - if [ ! -L $workdir/data/stats.db ]; then - mv -f $workdir/data/stats.db /tmp/stats.db 2>/dev/null - ln -s /tmp/stats.db $workdir/data/stats.db 2>/dev/null - fi - touch $workdir/data/sessions.db - if [ ! -L $workdir/data/sessions.db ]; then - mv -f $workdir/data/sessions.db /tmp/sessions.db 2>/dev/null - ln -s /tmp/sessions.db $workdir/data/sessions.db 2>/dev/null - fi - fi - local ADDITIONAL_ARGS="" - config_get binpath $CONFIGURATION binpath "/usr/bin/AdGuardHome/AdGuardHome" - - mkdir -p ${binpath%/*} - ADDITIONAL_ARGS="$ADDITIONAL_ARGS -c $configpath" - ADDITIONAL_ARGS="$ADDITIONAL_ARGS -w $workdir" - config_get httpport $CONFIGURATION httpport 3000 - ADDITIONAL_ARGS="$ADDITIONAL_ARGS -p $httpport" - - # hack to save config file when upgrade system - config_get upprotect $CONFIGURATION upprotect "" - eval upprotect=${upprotect// /\\\\n} - echo -e "$upprotect">/lib/upgrade/keep.d/luci-app-adguardhome - - config_get logfile $CONFIGURATION logfile "" - if [ -n "$logfile" ]; then - ADDITIONAL_ARGS="$ADDITIONAL_ARGS -l $logfile" - fi - - if [ ! -f "$binpath" ]; then - _do_redirect 0 - /usr/share/AdGuardHome/update_core.sh 2>&1 >/tmp/AdGuardHome_update.log & - exit 0 - fi - - config_get_bool verbose $CONFIGURATION verbose 0 - if [ "$verbose" -eq 1 ]; then - ADDITIONAL_ARGS="$ADDITIONAL_ARGS -v" - fi - - procd_open_instance - get_tz - if [ -n "$SET_TZ" ]; then - procd_set_param env TZ="$SET_TZ" - fi - procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5} - procd_set_param limits core="unlimited" nofile="65535 65535" - procd_set_param stderr 1 - procd_set_param command $binpath $ADDITIONAL_ARGS - procd_set_param file "$configpath" "/etc/hosts" "/etc/config/AdGuardHome" - procd_close_instance - if [ -f "$configpath" ]; then - _do_redirect 1 - else - _do_redirect 0 - config_get "redirect" "AdGuardHome" "redirect" "none" - if [ "$redirect" != "none" ]; then - procd_open_instance "waitconfig" - procd_set_param command "/usr/share/AdGuardHome/watchconfig.sh" - procd_close_instance - echo "no config start watching" - fi - fi - echo "AdGuardHome service enabled" - echo "luci enable switch=$enabled" - (sleep 10 && [ -z "$(pgrep $binpath)" ] && logger "AdGuardHome" "no process in 10s cancel redirect" && _do_redirect 0 )& - if [[ "`uci get bypass.@global[0].global_server 2>/dev/null`" && "`uci get bypass.@global[0].adguardhome 2>/dev/null`" == 1 && "$(uci get dhcp.@dnsmasq[0].port)" == "53" ]]; then - uci -q set AdGuardHome.AdGuardHome.redirect='exchange' - uci commit AdGuardHome - do_redirect 1 - fi -} - -reload_service() -{ - rm /var/run/AdGlucitest >/dev/null 2>&1 - echo "AdGuardHome reloading" - start -} - -del_querylog(){ - local btarget=$(ls $backupwdpath/data | grep -F "querylog.json" | sort -r | head -n 1) - local wtarget=$(ls $workdir/data | grep -F "querylog.json" | sort -r | head -n 1) - if [ "$btarget"x == "$wtarget"x ]; then - [ -z "$btarget" ] && return 1 - rm -f $workdir/data/$wtarget - rm -f $backupwdpath/data/$btarget - return 0 - fi - if [ "$btarget" \> "$wtarget" ]; then - rm -f $backupwdpath/data/$btarget - return 0 - else - rm -f $workdir/data/$wtarget - return 0 - fi -} - -stop_service() -{ - config_load "${CONFIGURATION}" - _do_redirect 0 - do_crontab - if [ "$1" != "nobackup" ]; then - config_get backupfile $CONFIGURATION backupfile "0" - if [ -n "$backupfile" ]; then - backup - fi - fi - echo "AdGuardHome service disabled" - touch /var/run/AdGserverdis -} - -boot() { - rc_procd boot_service "$@" - if eval "type service_started" 2>/dev/null >/dev/null; then - service_started - fi -} - -test_crontab(){ - config_load "${CONFIGURATION}" - do_crontab -} - -do_crontab(){ - config_get_bool enabled $CONFIGURATION enabled 0 - config_get crontab $CONFIGURATION crontab "" - local findstr default cronenable replace commit - local cronreload=0 - local commit=0 - findstr="/usr/share/AdGuardHome/update_core.sh" - default="30 3 * * * /usr/share/AdGuardHome/update_core.sh 2>&1" - [ "$enabled" == "0" ] || [ "${crontab//autoupdate/}" == "$crontab" ] && cronenable=0 || cronenable=1 - crontab_editor - - config_get workdir $CONFIGURATION workdir "/usr/bin/AdGuardHome" - config_get lastworkdir $CONFIGURATION lastworkdir "/usr/bin/AdGuardHome" - findstr="/usr/share/AdGuardHome/tailto.sh [0-9]* \$(uci get AdGuardHome.AdGuardHome.workdir)/data/querylog.json" - #[ -n "$lastworkdir" ] && findstr="/usr/share/AdGuardHome/tailto.sh [0-9]* $lastworkdir/data/querylog.json" && [ "$lastworkdir" != "$workdir" ] && replace="${lastworkdir//\//\\/}/${workdir//\//\\/}" - default="0 * * * * /usr/share/AdGuardHome/tailto.sh 2000 \$(uci get AdGuardHome.AdGuardHome.workdir)/data/querylog.json" - [ "$enabled" == "0" ] || [ "${crontab//cutquerylog/}" == "$crontab" ] && cronenable=0 || cronenable=1 - crontab_editor - #[ "$lastworkdir" != "$workdir" ] && uci set AdGuardHome.AdGuardHome.lastworkdir="$workdir" && commit=1 - - config_get logfile $CONFIGURATION logfile "" - config_get lastlogfile $CONFIGURATION lastlogfile "" - findstr="/usr/share/AdGuardHome/tailto.sh [0-9]* \$(uci get AdGuardHome.AdGuardHome.logfile)" - default="30 3 * * * /usr/share/AdGuardHome/tailto.sh 2000 \$(uci get AdGuardHome.AdGuardHome.logfile)" - #[ -n "$lastlogfile" ] && findstr="/usr/share/AdGuardHome/tailto.sh [0-9]* $lastlogfile" && [ -n "$logfile" ] && [ "$lastlogfile" != "$logfile" ] && replace="${lastlogfile//\//\\/}/${logfile//\//\\/}" - [ "$logfile" == "syslog" ] || [ "$logfile" == "" ] || [ "$enabled" == "0" ] || [ "${crontab//cutruntimelog/}" == "$crontab" ] && cronenable=0 || cronenable=1 - crontab_editor - #[ -n "$logfile" ] && [ "$lastlogfile" != "$logfile" ] && uci set AdGuardHome.AdGuardHome.lastlogfile="$logfile" && commit=1 - - findstr="/usr/share/AdGuardHome/addhost.sh" - default="0 * * * * /usr/share/AdGuardHome/addhost.sh" - [ "$enabled" == "0" ] || [ "${crontab//autohost/}" == "$crontab" ] && cronenable=0 || cronenable=1 - crontab_editor - [ "$cronenable" == "0" ] && /usr/share/AdGuardHome/addhost.sh "del" "noreload" || /usr/share/AdGuardHome/addhost.sh "" "noreload" - - findstr="/usr/share/AdGuardHome/gfw2adg.sh" - default="30 3 * * * /usr/share/AdGuardHome/gfw2adg.sh" - [ "$enabled" == "0" ] || [ "${crontab//autogfw/}" == "$crontab" ] && cronenable=0 || cronenable=1 - crontab_editor - [ "$cronreload" -gt 0 ] && /etc/init.d/cron restart - #[ "$commit" -gt 0 ] && uci commit AdGuardHome -} - -crontab_editor(){ - #usage input: - #findstr= - #default= - #cronenable= - #replace="${last//\//\\/}/${now//\//\\/}" - #output:cronreload:if >1 please /etc/init.d/cron restart manual - local testline reload - local line="$(grep "$findstr" $CRON_FILE)" - [ -n "$replace" ] && [ -n "$line" ] && eval testline="\${line//$replace}" && [ "$testline" != "$line" ] && line="$testline" && reload="1" && replace="" - if [ "${line:0:1}" != "#" ]; then - if [ $cronenable -eq 1 ]; then - [ -z "$line" ] && line="$default" && reload="1" - if [ -n "$reload" ]; then - sed -i "\,$findstr,d" $CRON_FILE - echo "$line" >> $CRON_FILE - cronreload=$((cronreload+1)) - fi - elif [ -n "$line" ]; then - sed -i "\,$findstr,d" $CRON_FILE - echo "#$line" >> $CRON_FILE - cronreload=$((cronreload+1)) - fi - else - if [ $cronenable -eq 1 ]; then - sed -i "\,$findstr,d" $CRON_FILE - echo "${line:1}" >> $CRON_FILE - cronreload=$((cronreload+1)) - elif [ -z "$reload" ]; then - sed -i "\,$findstr,d" $CRON_FILE - echo "$line" >> $CRON_FILE - fi - fi -} diff --git a/luci-app-adguardhome/root/etc/init.d/adguardhome b/luci-app-adguardhome/root/etc/init.d/adguardhome new file mode 100755 index 00000000..3ac88c37 --- /dev/null +++ b/luci-app-adguardhome/root/etc/init.d/adguardhome @@ -0,0 +1,258 @@ +#!/bin/sh /etc/rc.common + +# Start after network (19 matches dnsmasq) +START=19 +# Stop before network stops +STOP=89 + +PROG=/usr/bin/AdGuardHome +USE_PROCD=1 + +boot() { + ADGUARDHOME_BOOT=1 + start "$@" +} + +# Configure DNS to use port 53 +use_port53() { + local dns_port="$1" + local adguard_port="$2" + local config_file="$3" + + [ "$dns_port" != "53" ] && return + + # Update AdGuardHome config + sed -i '/dns:/,/^[^ ]/{ /[[:space:]]*port:/ s/port:[[:space:]]*[0-9]\+/port: 53/ }' "$config_file" + + # Update dnsmasq config + uci set "dhcp.@dnsmasq[0].port=$adguard_port" + uci commit dhcp + /etc/init.d/dnsmasq restart +} + +# Restore original port configuration +rm_port53() { + local current_port="$1" + local new_port="$2" + local config_file="$3" + + [ "$current_port" != "53" ] && return + + # Update AdGuardHome config + sed -i '/dns:/,/^[^ ]/{ /[[:space:]]*port:/ s/port:[[:space:]]*[0-9]\+/port: '"$new_port"'/ }' "$config_file" + + # Restore dnsmasq config + uci -q set "dhcp.@dnsmasq[0].port=53" + uci commit dhcp + /etc/init.d/dnsmasq restart +} + +# Set up firewall redirect rules +set_redirect() { + local dest_port="$1" + local section + + # Add new redirect section + section=$(uci add firewall redirect) + [ -z "$section" ] && return + [ "$(uci -q get "firewall.$section.dest_port")" = "$dest_port" ] && return + + # Configure redirect rules + uci -q set "firewall.$section.target=DNAT" + uci -q set "firewall.$section.name=AdGuard Home" + uci -q set "firewall.$section.src=lan" + uci -q set "firewall.$section.src_dport=53" + uci -q set "firewall.$section.dest_port=$dest_port" + + # Apply changes + uci commit firewall + /etc/init.d/firewall reload + echo "Firewall rules updated." +} + +# Clear all AdGuard Home redirect rules +clear_redirect() { + local redirects + redirects=$(uci show firewall | grep "AdGuard Home" | cut -d'.' -f1-2) + [ -z "$redirects" ] && return + + for redirect in $redirects; do + uci -q delete "$redirect" + echo "Deleted redirect rule: $redirect" + done + + uci commit firewall + /etc/init.d/firewall reload + echo "Firewall rules updated." +} + +# Configure dnsmasq to forward requests to AdGuard Home +set_forward_dnsmasq() { + local port="$1" + local current_server="$2" + local addr="127.0.0.1#$port" + + echo "$current_server" | grep -q "^$addr" && return + + uci -q add_list dhcp.@dnsmasq[0].server="$addr" + uci -q delete "dhcp.@dnsmasq[0].resolvfile" + uci set "dhcp.@dnsmasq[0].noresolv=1" + uci commit dhcp + /etc/init.d/dnsmasq restart +} + +# Stop forwarding requests to AdGuard Home +stop_forward_dnsmasq() { + local port="$1" + local current_server="$2" + local addr="127.0.0.1#$port" + + echo "$current_server" | grep -q "^$addr" || return + + uci -q delete "dhcp.@dnsmasq[0].server" + uci -q delete "dhcp.@dnsmasq[0].noresolv" + uci commit dhcp + /etc/init.d/dnsmasq restart +} + +# Start AdGuard Home service +start_service() { + if [ -n "$ADGUARDHOME_BOOT" ]; then + # Do not start yet, wait for triggers + return 0 + fi + + config_load 'adguardhome' + + local config_name='config' + local config_file config group user verbose work_dir workdir + local gc maxprocs memlimit redirect enabled + + uci_validate_section 'adguardhome' 'adguardhome' "$config_name" \ + 'enabled:bool:0' \ + 'redirect:string:none' \ + 'gc:uinteger:0' \ + 'group:string:adguardhome' \ + 'config:string' \ + 'config_file:string:/etc/adguardhome/adguardhome.yaml' \ + 'jail_mount:list(string)' \ + 'jail_mount_rw:list(string)' \ + 'maxprocs:uinteger:0' \ + 'memlimit:uinteger:0' \ + 'user:string:adguardhome' \ + 'verbose:bool:0' \ + 'workdir:string' \ + 'work_dir:string:/var/lib/adguardhome' + + # Compatibility with older configs + [ -n "$config" ] && config_file="$config" + [ -n "$workdir" ] && work_dir="$workdir" + + [ "$enabled" -eq 0 ] && return 1 + + local config_dir + config_dir=$(dirname "$config_file") + if [ "$config_dir" = '/etc' ]; then + echo 'AdGuard Home config must be stored in its own directory, and not in /etc' >&2 + return 1 + fi + mkdir -m 0700 -p "$config_dir" + chown -R "$user":"$group" "$config_dir" + + mkdir -m 0700 -p "$work_dir" + chown -R "$user":"$group" "$work_dir" + + # Get ports configuration + local AdGuardHome_PORT=$(awk '/dns:/{f=1} f&&/port:/{split($0,a,": *");print a[2];exit}' "$config_file") + local dnsmasq_port=$(uci -q get dhcp.@dnsmasq[0].port) + local DNSMASQ_SERVER=$(uci -q get dhcp.@dnsmasq[0].server) + + # Configure redirect mode + case "$redirect" in + "redirect") + set_redirect "$AdGuardHome_PORT" + ;; + "dnsmasq-upstream") + set_forward_dnsmasq "$AdGuardHome_PORT" "$DNSMASQ_SERVER" + ;; + "exchange") + use_port53 "$dnsmasq_port" "$AdGuardHome_PORT" "$config_file" + ;; + esac + + procd_open_instance adguardhome + + procd_set_param command "$PROG" + + [ "$gc" -le 0 ] || procd_append_param env GOGC="$gc" + [ "$maxprocs" -le 0 ] || procd_append_param env GOMAXPROCS="$maxprocs" + [ "$memlimit" -le 0 ] || procd_append_param env GOMEMLIMIT="$memlimit" + + procd_append_param command --config "$config_file" + procd_append_param command --logfile syslog + procd_append_param command --no-check-update + [ "$verbose" = 1 ] && procd_append_param command --verbose + procd_append_param command --work-dir "$work_dir" + + procd_set_param stdout 1 + procd_set_param stderr 1 + procd_set_param user "$user" + procd_set_param group "$group" + procd_set_param capabilities '/etc/capabilities/adguardhome.json' + procd_set_param no_new_privs 1 + procd_set_param respawn + + # log is needed for logging to syslog instead of stdout + # procfs is needed to readlink /proc/self/exe + procd_add_jail adguardhome log procfs + + # config directory must be writable to write new config files + procd_add_jail_mount_rw "$config_dir" + procd_add_jail_mount_rw "$work_dir" + + procd_add_jail_mount '/etc/hosts' + procd_add_jail_mount '/etc/ssl/certs' + config_list_foreach "$config_name" jail_mount procd_add_jail_mount + config_list_foreach "$config_name" jail_mount_rw procd_add_jail_mount_rw + + procd_close_instance +} + +# Stop AdGuard Home service +stop_service() { + if [ -n "$ADGUARDHOME_BOOT" ]; then + # Do not start yet, wait for triggers + return 0 + fi + + local config_file='/etc/adguardhome/adguardhome.yaml' + + config_load 'adguardhome' + + # Get ports configuration + local AdGuardHome_PORT=$(awk '/dns:/{f=1} f&&/port:/{split($0,a,": *");print a[2];exit}' "$config_file") + local dnsmasq_port=$(uci -q get dhcp.@dnsmasq[0].port) + local DNSMASQ_SERVER=$(uci -q get dhcp.@dnsmasq[0].server) + + # Clean up configurations + rm_port53 "$AdGuardHome_PORT" "$dnsmasq_port" "$config_file" + clear_redirect + stop_forward_dnsmasq "$AdGuardHome_PORT" "$DNSMASQ_SERVER" +} + +# Reload service +reload_service() { + restart +} + +# Service triggers +service_triggers() { + procd_add_reload_trigger adguardhome + + # Add interface trigger during boot + if [ -n "$ADGUARDHOME_BOOT" ]; then + # Wait for interfaces to be up before starting AdGuard Home + # Prevents issues like https://github.com/openwrt/packages/issues/21868 + procd_add_raw_trigger 'interface.*.up' 5000 /etc/init.d/adguardhome restart + fi +} diff --git a/luci-app-adguardhome/root/etc/uci-defaults/40_luci-AdGuardHome b/luci-app-adguardhome/root/etc/uci-defaults/40_luci-AdGuardHome deleted file mode 100644 index efabeede..00000000 --- a/luci-app-adguardhome/root/etc/uci-defaults/40_luci-AdGuardHome +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh -[ ! -f "/usr/share/ucitrack/luci-app-AdGuardHome.json" ] && { - cat > /usr/share/ucitrack/luci-app-AdGuardHome.json << EEOF -{ - "config": "AdGuardHome", - "init": "AdGuardHome" -} -EEOF -} -chmod +x /etc/init.d/AdGuardHome -uci -q batch <<-EOF >/dev/null 2>&1 - delete ucitrack.@AdGuardHome[-1] - add ucitrack AdGuardHome - set ucitrack.@AdGuardHome[-1].init=AdGuardHome - commit ucitrack - delete AdGuardHome.AdGuardHome.ucitracktest -EOF - -rm -f /tmp/luci-indexcache -exit 0 diff --git a/luci-app-adguardhome/root/usr/libexec/rpcd/luci.adguardhome b/luci-app-adguardhome/root/usr/libexec/rpcd/luci.adguardhome new file mode 100755 index 00000000..71f6004c --- /dev/null +++ b/luci-app-adguardhome/root/usr/libexec/rpcd/luci.adguardhome @@ -0,0 +1,153 @@ +#!/bin/sh +. /usr/share/libubox/jshn.sh + +############################################################################################ +# Functions to parse AdGuardHome YAML file: +############################################################################################ +parse_yaml() { + local prefix=$2 + local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @|tr @ '\034') + sed -ne "s|,$s\]$s\$|]|" \ + -e ":1;s|^\($s\)\($w\)$s:$s\[$s\(.*\)$s,$s\(.*\)$s\]|\1\2: [\3]\n\1 - \4|;t1" \ + -e "s|^\($s\)\($w\)$s:$s\[$s\(.*\)$s\]|\1\2:\n\1 - \3|;p" $1 | \ + sed -ne "s|,$s}$s\$|}|" \ + -e ":1;s|^\($s\)-$s{$s\(.*\)$s,$s\($w\)$s:$s\(.*\)$s}|\1- {\2}\n\1 \3: \4|;t1" \ + -e "s|^\($s\)-$s{$s\(.*\)$s}|\1-\n\1 \2|;p" | \ + sed -ne "s|^\($s\):|\1|" \ + -e "s|^\($s\)-$s[\"']\(.*\)[\"']$s\$|\1$fs$fs\2|p" \ + -e "s|^\($s\)-$s\(.*\)$s\$|\1$fs$fs\2|p" \ + -e "s|^\($s\)\($w\)$s:$s[\"']\(.*\)[\"']$s\$|\1$fs\2$fs\3|p" \ + -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" | \ + awk -F$fs '{ + indent = length($1)/2; + vname[indent] = $2; + for (i in vname) {if (i > indent) {delete vname[i]; idx[i]=0}} + if(length($2)== 0){ vname[indent]= ++idx[indent] }; + if (length($3) > 0) { + vn=""; for (i=0; i /dev/null) + check_if_empty "Username not found in uci adguardhome" ${AGH_USER} || exit 1 + AGH_PASS=$(uci get adguardhome.config.web_password 2> /dev/null) + check_if_empty "Password not found in uci adguardhome" ${AGH_PASS} || exit 1 + CODE=$(curl --silent -L -k -u ${AGH_USER}:${AGH_PASS} ${PROTO}://${HOST}:${PORT}/control/$1 -o $TFILE -w "%{http_code"}) + if [[ "${CODE}" == "200" ]]; then + cat $TFILE | tr -d '\n' + else + MSG="REST call failed with '$(cat ${TFILE})'. Are the credentials correct?" + log_error "$MSG" + echo "{\"error\":\"$MSG\"}" > ${TFILE} + fi +} + +############################################################################################ +# Function that groups variables starting with specified string into a single JSON object: +############################################################################################ +group_vars() { + local LOOK_FOR=${1/_1/} + echo -n "\"$LOOK_FOR\":[" + cat ${TFILE} | grep "${LOOK_FOR}" | while read FOUND; do + sed -i "/${FOUND%=*}/d" ${TFILE} + echo "${FOUND##*=}" + done | sed '$!s/$/,/' | tr -d '\n' + echo -n "]," +} + +############################################################################################ +# Parse AGH yaml file and determine necessary variables in order to function: +############################################################################################ +TFILE=/tmp/rpcd-adguardhome-$(date -Ins).tmp +trap 'rm ${TFILE}; exit' EXIT +read_config > ${TFILE} +source ${TFILE} +HOST=${http_address%:*} +[[ "${HOST}" == "0.0.0.0" ]] && HOST=$(uci get system.@system[0].hostname).$(uci get dhcp.@dnsmasq[0].domain) +HOST=$(echo ${HOST} | awk '{print tolower($0)}') +PORT=${http_address##*:} +PROTO="http" +if [[ "${tls_enabled}" == "true" ]]; then + PROTO="https" + HOST=${tls_server_name} + PORT=${tls_port_https} +fi +[[ -z "${http_address}" ]] && http_address=${bind_host}:${bind_port} + +############################################################################################ +# Decision-making cade: +############################################################################################ +case "$1" in + list) + echo '{ "get_config": {}, "get_statistics": {}, "get_status": {}, "set_passwd": {"username":"string", "hash":"string"} }' + ;; + call) + case "$2" in + get_config) + # Start the JSON array: + echo -n "{" + # Group any variables starting with "dns_" together: + grep "_1=\"" ${TFILE} | grep dns_ | while read LINE; do group_vars ${LINE%=*}; done + # Return the AGH configuration as a JSON table: + cat ${TFILE} | sed "s|^|\"|g" | sed "s|=\"|\":\"|g" | sed "s|\"$|\",|g" | tr -d '\n' + # Include web url, then close the JSON array: + echo "\"web_url\":\"${PROTO}://${HOST}:${PORT}\"}" + ;; + + get_statistics) + # Return the AGH statistics as a JSON table: + call_rest_api stats + ;; + + get_status) + # Return the AGH status as a JSON table: + call_rest_api status + ;; + + set_passwd) + # Check if bcrypt-tool is available for use: + # Read and load the argument into JSON array: + read input + json_load "$input" + # Get username and password from JSON array and verify they aren't empty: + json_get_var AGH_USER "username" + check_if_empty "username parameter missing." "${AGH_USER}" || exit 1 + json_get_var AGH_HASH "hash" + check_if_empty "hash parameter missing." "${AGH_HASH}" || exit 1 + # Change the username in the AGH configuration file: + sed -i "s|\- name: .*|\- name: ${AGH_USER} |" /etc/adguardhome/adguardhome.yaml + # Calculate and replace password hash in the AGH configuration file: + sed -i "s|\password: .*|\password: ${AGH_HASH}|" /etc/adguardhome/adguardhome.yaml + # Restart AdGaurdHome: + service adguardhome restart + # Return success to caller: + echo "{\"success\":true}" + ;; + esac + ;; +esac diff --git a/luci-app-adguardhome/root/usr/share/AdGuardHome/AdGuardHome_template.yaml b/luci-app-adguardhome/root/usr/share/AdGuardHome/AdGuardHome_template.yaml deleted file mode 100644 index 25f69f59..00000000 --- a/luci-app-adguardhome/root/usr/share/AdGuardHome/AdGuardHome_template.yaml +++ /dev/null @@ -1,128 +0,0 @@ -bind_host: 0.0.0.0 -bind_port: 3000 -beta_bind_port: 0 -users: - - name: admin - password: $2y$10$vHRcARdPCieYG3RXWomV5evDYN.Nj/edtwEkQgQJZcK6z7qTLaIc6 -auth_attempts: 5 -block_auth_min: 15 -http_proxy: "" -language: zh-cn -theme: auto -debug_pprof: false -dns: - bind_hosts: - - 0.0.0.0 - port: 1745 - anonymize_client_ip: false - protection_enabled: true - blocking_mode: default - blocking_ipv4: "" - blocking_ipv6: "" - blocked_response_ttl: 10 - protection_disabled_until: null - parental_block_host: family-block.dns.adguard.com - safebrowsing_block_host: standard-block.dns.adguard.com - ratelimit: 0 - ratelimit_whitelist: [] - refuse_any: false - upstream_dns: - - 223.5.5.5 - upstream_dns_file: "" - bootstrap_dns: - - 119.29.29.29 - - 223.5.5.5 - all_servers: false - fastest_addr: false - fastest_timeout: 1s - allowed_clients: [] - disallowed_clients: [] - blocked_hosts: - - version.bind - - id.server - - hostname.bind - trusted_proxies: - - 127.0.0.0/8 - - ::1/128 - cache_size: 4194304 - cache_ttl_min: 0 - cache_ttl_max: 0 - cache_optimistic: true - bogus_nxdomain: [] - aaaa_disabled: false - enable_dnssec: false - edns_client_subnet: false - max_goroutines: 300 - ipset: [] - filtering_enabled: true - filters_update_interval: 24 - parental_enabled: false - safesearch_enabled: false - safebrowsing_enabled: false - safebrowsing_cache_size: 1048576 - safesearch_cache_size: 1048576 - parental_cache_size: 1048576 - cache_time: 30 - rewrites: [] - blocked_services: [] - upstream_timeout: 10s - private_networks: [] - use_private_ptr_resolvers: true - local_ptr_upstreams: [] -tls: - enabled: false - server_name: "" - force_https: false - port_https: 443 - port_dns_over_tls: 853 - port_dns_over_quic: 784 - port_dnscrypt: 0 - dnscrypt_config_file: "" - allow_unencrypted_doh: false - certificate_chain: "" - private_key: "" - certificate_path: "" - private_key_path: "" -filters: -- enabled: true - url: https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt - name: AdGuard DNS filter - id: 1628750870 -- enabled: true - url: https://anti-ad.net/easylist.txt - name: 'CHN: anti-AD' - id: 1628750871 -whitelist_filters: [] -user_rules: -- '@@||taobao.com^$important' -- '@@||jd.com^important' -- '@@||flyme.cn^$important' -- '@@||meizu.com^$important' -- '@@||wl.jd.com^$important' -- '@@||flydigi.com^' -- '@@||pv.sohu.com^$important' -dhcp: - enabled: false - interface_name: "" - dhcpv4: - gateway_ip: "" - subnet_mask: "" - range_start: "" - range_end: "" - lease_duration: 86400 - icmp_timeout_msec: 1000 - options: [] - dhcpv6: - range_start: "" - lease_duration: 86400 - ra_slaac_only: false - ra_allow_slaac: false -clients: [] -log_compress: false -log_localtime: false -log_max_backups: 0 -log_max_size: 100 -log_max_age: 3 -log_file: "" -verbose: false -schema_version: 10 diff --git a/luci-app-adguardhome/root/usr/share/AdGuardHome/addhost.sh b/luci-app-adguardhome/root/usr/share/AdGuardHome/addhost.sh deleted file mode 100755 index 6c6b7b76..00000000 --- a/luci-app-adguardhome/root/usr/share/AdGuardHome/addhost.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh - -checkmd5(){ -local nowmd5=$(md5sum /etc/hosts) -nowmd5=${nowmd5%% *} -local lastmd5=$(uci get AdGuardHome.AdGuardHome.hostsmd5 2>/dev/null) -if [ "$nowmd5" != "$lastmd5" ]; then - uci set AdGuardHome.AdGuardHome.hostsmd5="$nowmd5" - uci commit AdGuardHome - [ "$1" == "noreload" ] || /etc/init.d/AdGuardHome reload -fi -} - -[ "$1" == "del" ] && sed -i '/programaddstart/,/programaddend/d' /etc/hosts && checkmd5 "$2" && exit 0 -/usr/bin/awk 'BEGIN{ -while ((getline < "/tmp/dhcp.leases") > 0) -{ - a[$2]=$4; -} -while (("ip -6 neighbor show | grep -v fe80" | getline) > 0) -{ - if (a[$5]) {print $1" "a[$5] >"/tmp/tmphost"; } -} -print "#programaddend" >"/tmp/tmphost"; -}' -grep programaddstart /etc/hosts >/dev/null 2>&1 -if [ "$?" == "0" ]; then - sed -i '/programaddstart/,/programaddend/c\#programaddstart' /etc/hosts - sed -i '/programaddstart/'r/tmp/tmphost /etc/hosts -else - echo "#programaddstart" >>/etc/hosts - cat /tmp/tmphost >> /etc/hosts -fi -rm /tmp/tmphost -checkmd5 "$2" diff --git a/luci-app-adguardhome/root/usr/share/AdGuardHome/firewall.start b/luci-app-adguardhome/root/usr/share/AdGuardHome/firewall.start deleted file mode 100644 index 562117e5..00000000 --- a/luci-app-adguardhome/root/usr/share/AdGuardHome/firewall.start +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -AdGuardHome_enable=$(uci get AdGuardHome.AdGuardHome.enabled) -redirect=$(uci get AdGuardHome.AdGuardHome.redirect) - -if [ $AdGuardHome_enable -eq 1 -a "$redirect" == "redirect" ]; then - /etc/init.d/AdGuardHome do_redirect 1 -fi diff --git a/luci-app-adguardhome/root/usr/share/AdGuardHome/getsyslog.sh b/luci-app-adguardhome/root/usr/share/AdGuardHome/getsyslog.sh deleted file mode 100755 index 908bdf63..00000000 --- a/luci-app-adguardhome/root/usr/share/AdGuardHome/getsyslog.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh - -PATH="/usr/sbin:/usr/bin:/sbin:/bin" -logread -e AdGuardHome > /tmp/AdGuardHometmp.log -logread -e AdGuardHome -f >> /tmp/AdGuardHometmp.log & -pid=$! -echo "1">/var/run/AdGuardHomesyslog -while true -do - sleep 12 - watchdog=$(cat /var/run/AdGuardHomesyslog) - if [ "$watchdog"x == "0"x ]; then - kill $pid - rm /tmp/AdGuardHometmp.log - rm /var/run/AdGuardHomesyslog - exit 0 - else - echo "0">/var/run/AdGuardHomesyslog - fi -done diff --git a/luci-app-adguardhome/root/usr/share/AdGuardHome/gfw2adg.sh b/luci-app-adguardhome/root/usr/share/AdGuardHome/gfw2adg.sh deleted file mode 100755 index a3add84e..00000000 --- a/luci-app-adguardhome/root/usr/share/AdGuardHome/gfw2adg.sh +++ /dev/null @@ -1,89 +0,0 @@ -#!/bin/sh - -PATH="/usr/sbin:/usr/bin:/sbin:/bin" - -checkmd5(){ -local nowmd5=$(md5sum /tmp/adguard.list 2>/dev/null) -nowmd5=${nowmd5%% *} -local lastmd5=$(uci get AdGuardHome.AdGuardHome.gfwlistmd5 2>/dev/null) -if [ "$nowmd5" != "$lastmd5" ]; then - uci set AdGuardHome.AdGuardHome.gfwlistmd5="$nowmd5" - uci commit AdGuardHome - [ "$1" == "noreload" ] || /etc/init.d/AdGuardHome reload -fi -} - -configpath=$(uci get AdGuardHome.AdGuardHome.configpath 2>/dev/null) -[ "$1" == "del" ] && sed -i '/programaddstart/,/programaddend/d' $configpath && checkmd5 "$2" && exit 0 -gfwupstream=$(uci get AdGuardHome.AdGuardHome.gfwupstream 2>/dev/null) -if [ -z $gfwupstream ]; then -gfwupstream="tcp://208.67.220.220:5353" -fi -if [ ! -f "$configpath" ]; then - echo "please make a config first" - exit 1 -fi -wget-ssl --no-check-certificate https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt -O- | base64 -d > /tmp/gfwlist.txt -cat /tmp/gfwlist.txt | awk -v upst="$gfwupstream" 'BEGIN{getline;}{ -s1=substr($0,1,1); -if (s1=="!") -{next;} -if (s1=="@"){ - $0=substr($0,3); - s1=substr($0,1,1); - white=1;} -else{ - white=0; -} - -if (s1=="|") - {s2=substr($0,2,1); - if (s2=="|") - { - $0=substr($0,3); - split($0,d,"/"); - $0=d[1]; - }else{ - split($0,d,"/"); - $0=d[3]; - }} -else{ - split($0,d,"/"); - $0=d[1]; -} -star=index($0,"*"); -if (star!=0) -{ - $0=substr($0,star+1); - dot=index($0,"."); - if (dot!=0) - $0=substr($0,dot+1); - else - next; - s1=substr($0,1,1); -} -if (s1==".") -{fin=substr($0,2);} -else{fin=$0;} -if (index(fin,".")==0) next; -if (index(fin,"%")!=0) next; -if (index(fin,":")!=0) next; -match(fin,"^[0-9\.]+") -if (RSTART==1 && RLENGTH==length(fin)) {print "ipset add gfwlist "fin>"/tmp/doipset.sh";next;} -if (fin=="" || finl==fin) next; -finl=fin; -if (white==0) - {print(" - '\''[/"fin"/]"upst"'\''");} -else{ - print(" - '\''[/"fin"/]#'\''");} -}END{print(" - '\''[/programaddend/]#'\''")}' > /tmp/adguard.list -grep programaddstart $configpath -if [ "$?" == "0" ]; then - sed -i '/programaddstart/,/programaddend/c\ - '\''\[\/programaddstart\/\]#'\''' $configpath - sed -i '/programaddstart/'r/tmp/adguard.list $configpath -else - sed -i '1i\ - '\''[/programaddstart/]#'\''' /tmp/adguard.list - sed -i '/upstream_dns:/'r/tmp/adguard.list $configpath -fi -checkmd5 "$2" -rm -f /tmp/gfwlist.txt /tmp/adguard.list diff --git a/luci-app-adguardhome/root/usr/share/AdGuardHome/links.txt b/luci-app-adguardhome/root/usr/share/AdGuardHome/links.txt deleted file mode 100644 index 75c3e2eb..00000000 --- a/luci-app-adguardhome/root/usr/share/AdGuardHome/links.txt +++ /dev/null @@ -1,3 +0,0 @@ -https://github.com/AdguardTeam/AdGuardHome/releases/download/${latest_ver}/AdGuardHome_linux_${Arch}.tar.gz -https://static.adguard.com/adguardhome/release/AdGuardHome_linux_${Arch}.tar.gz -https://static.adguard.com/adguardhome/beta/AdGuardHome_linux_${Arch}.tar.gz diff --git a/luci-app-adguardhome/root/usr/share/AdGuardHome/tailto.sh b/luci-app-adguardhome/root/usr/share/AdGuardHome/tailto.sh deleted file mode 100755 index 9ccc2190..00000000 --- a/luci-app-adguardhome/root/usr/share/AdGuardHome/tailto.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -tail -n $1 "$2" > /var/run/tailtmp -cat /var/run/tailtmp > "$2" -rm /var/run/tailtmp diff --git a/luci-app-adguardhome/root/usr/share/AdGuardHome/update_core.sh b/luci-app-adguardhome/root/usr/share/AdGuardHome/update_core.sh deleted file mode 100755 index d00bd521..00000000 --- a/luci-app-adguardhome/root/usr/share/AdGuardHome/update_core.sh +++ /dev/null @@ -1,218 +0,0 @@ -#!/bin/sh - -PATH="/usr/sbin:/usr/bin:/sbin:/bin" -update_mode=$1 -binpath=$(uci get AdGuardHome.AdGuardHome.binpath) -if [[ -z ${binpath} ]]; then - uci set AdGuardHome.AdGuardHome.binpath="/tmp/AdGuardHome/AdGuardHome" - binpath="/tmp/AdGuardHome/AdGuardHome" -fi -[[ ! -d ${binpath%/*} ]] && mkdir -p ${binpath%/*} -upxflag=$(uci get AdGuardHome.AdGuardHome.upxflag 2>/dev/null) - -[[ -z ${upxflag} ]] && upxflag=off -enabled=$(uci get AdGuardHome.AdGuardHome.enabled 2>/dev/null) -core_version=$(uci get AdGuardHome.AdGuardHome.core_version 2>/dev/null) -update_url=$(uci get AdGuardHome.AdGuardHome.update_url 2>/dev/null) - -case "${core_version}" in -beta) - core_api_url=https://api.github.com/repos/AdguardTeam/AdGuardHome/releases -;; -*) - core_api_url=https://api.github.com/repos/AdguardTeam/AdGuardHome/releases/latest -;; -esac - -Check_Task(){ - running_tasks="$(ps -efww | grep -v grep | grep "AdGuardHome" | grep "update_core" | awk '{print $1}' | wc -l)" - case $1 in - force) - echo -e "执行: 强制更新核心" - echo -e "清除 ${running_tasks} 个进程 ..." - ps -efww | grep -v grep | grep -v $$ | grep "AdGuardHome" | grep "update_core" | awk '{print $1}' | xargs kill -9 2> /dev/null - ;; - *) - [[ ${running_tasks} -gt 2 ]] && echo -e "已经有 ${running_tasks} 个任务正在运行, 请等待其执行结束或将其强行停止!" && EXIT 2 - ;; - esac -} - -Check_Downloader(){ - which curl > /dev/null 2>&1 && PKG="curl" && return - echo -e "\n未安装 curl" - which wget-ssl > /dev/null 2>&1 && PKG="wget-ssl" && return - echo "未安装 curl 和 wget, 无法检测更新!" && EXIT 1 -} - -Check_Updates(){ - Check_Downloader - case "${PKG}" in - curl) - Downloader="curl -L -k -o" - _Downloader="curl -s" - ;; - wget-ssl) - Downloader="wget-ssl --no-check-certificate -T 5 -O" - _Downloader="wget-ssl -q -O -" - ;; - esac - echo "[${PKG}] 开始检查更新, 请耐心等待 ..." - Cloud_Version="$(${_Downloader} ${core_api_url} 2>/dev/null | grep 'tag_name' | egrep -o "v[0-9].+[0-9.]" | awk 'NR==1')" - [[ -z ${Cloud_Version} ]] && echo -e "\n检查更新失败, 请检查网络或稍后重试!" && EXIT 1 - if [[ -f ${binpath} ]]; then - Current_Version="$(${binpath} --version 2>/dev/null | egrep -o "v[0-9].+[0-9]" | sed -r 's/(.*), c(.*)/\1/')" - else - Current_Version="未知" - fi - [[ -z ${Current_Version} ]] && Current_Version="未知" - echo -e "\n执行文件路径: ${binpath%/*}\n\n正在检查更新, 请耐心等待 ..." - echo -e "\n当前 AdGuardHome 版本: ${Current_Version}\n云端 AdGuardHome 版本: ${Cloud_Version}" - if [[ ! "${Cloud_Version}" == "${Current_Version}" || "$1" == force ]]; then - Update_Core - else - echo -e "\n已是最新版本, 无需更新!" - EXIT 0 - fi - EXIT 0 -} - -UPX_Compress(){ - GET_Arch - upx_name="upx-${upx_latest_ver}-${Arch_upx}_linux.tar.xz" - echo -e "开始下载 ${upx_name} ...\n" - $Downloader /tmp/upx-${upx_latest_ver}-${Arch_upx}_linux.tar.xz "https://github.com/upx/upx/releases/download/v${upx_latest_ver}/${upx_name}" - if [[ ! -e /tmp/upx-${upx_latest_ver}-${Arch_upx}_linux.tar.xz ]]; then - echo -e "\n${upx_name} 下载失败!\n" - EXIT 1 - else - echo -e "\n${upx_name} 下载成功!\n" - fi - which xz > /dev/null 2>&1 || (opkg list | grep ^xz || opkg update > /dev/null 2>&1 && opkg install xz --force-depends) || (echo "软件包 xz 安装失败!" && EXIT 1) - mkdir -p /tmp/upx-${upx_latest_ver}-${Arch_upx}_linux - echo -e "正在解压 ${upx_name} ...\n" - xz -d -c /tmp/upx-${upx_latest_ver}-${Arch_upx}_linux.tar.xz | tar -x -C "/tmp" - [[ ! -f /tmp/upx-${upx_latest_ver}-${Arch_upx}_linux/upx ]] && echo -e "\n${upx_name} 解压失败!" && EXIT 1 -} - -Update_Core(){ - rm -r /tmp/AdGuardHome_Update > /dev/null 2>&1 - mkdir -p "/tmp/AdGuardHome_Update" - GET_Arch - eval link="${update_url}" - echo -e "下载链接:${link}" - echo -e "文件名称:${link##*/}" - echo -e "\n开始下载 AdGuardHome 核心文件 ...\n" - $Downloader /tmp/AdGuardHome_Update/${link##*/} ${link} - if [[ $? != 0 ]];then - echo -e "\nAdGuardHome 核心下载失败 ..." - rm -r /tmp/AdGuardHome_Update - EXIT 1 - fi - if [[ ${link##*.} == gz ]]; then - echo -e "\n正在解压 AdGuardHome ..." - tar -zxf "/tmp/AdGuardHome_Update/${link##*/}" -C "/tmp/AdGuardHome_Update/" - if [[ ! -e /tmp/AdGuardHome_Update/AdGuardHome ]] - then - echo "AdGuardHome 核心解压失败!" - rm -rf "/tmp/AdGuardHome_Update" > /dev/null 2>&1 - EXIT 1 - fi - downloadbin="/tmp/AdGuardHome_Update/AdGuardHome/AdGuardHome" - else - downloadbin="/tmp/AdGuardHome_Update/${link##*/}" - fi - chmod +x ${downloadbin} - echo -e "\nAdGuardHome 核心体积: $(awk 'BEGIN{printf "%.2fMB\n",'$((`ls -l $downloadbin | awk '{print $5}'`))'/1000000}')" - if [[ ${upxflag} != off ]]; then - UPX_Compress - echo -e "使用 UPX 压缩可能会花很长时间, 期间请耐心等待!\n正在压缩 $downloadbin ..." - /tmp/upx-${upx_latest_ver}-${Arch_upx}_linux/upx $upxflag $downloadbin > /dev/null 2>&1 - echo -e "\n压缩后的核心体积: $(awk 'BEGIN{printf "%.2fMB\n",'$((`ls -l $downloadbin | awk '{print $5}'`))'/1000000}')" - else - echo "未启用 UPX 压缩, 跳过操作..." - fi - /etc/init.d/AdGuardHome stop > /dev/null 2>&1 - echo -e "\n移动 AdGuardHome 核心文件到 ${binpath%/*} ..." - mv -f ${downloadbin} ${binpath} > /dev/null 2>&1 - if [[ ! -s ${binpath} && $? != 0 ]]; then - echo -e "AdGuardHome 核心移动失败!\n可能是设备空间不足导致, 请尝试开启 UPX 压缩, 或更改 [执行文件路径] 为 /tmp/AdGuardHome" - EXIT 1 - fi - rm -f /tmp/upx*.tar.xz - rm -rf /tmp/upx* - rm -rf /tmp/AdGuardHome_Update - chmod +x ${binpath} - if [[ ${enabled} == 1 ]]; then - echo -e "\n正在重启 AdGuardHome 服务..." - /etc/init.d/AdGuardHome restart - fi - echo -e "\nAdGuardHome 核心更新成功!" -} - -GET_Arch() { - Archt="$(opkg info kernel | grep Architecture | awk -F "[ _]" '{print($2)}')" - case "${Archt}" in - i386) - Arch=i386 - ;; - i686) - Arch=i386 - ;; - x86) - Arch=amd64 - ;; - mipsel) - Arch=mipsle_softfloat - ;; - mips) - Arch=mips_softfloat - ;; - mips64el) - Arch=mips64le_softfloat - ;; - mips64) - Arch=mips64_softfloat - ;; - arm) - Arch=arm - ;; - armeb) - Arch=armeb - ;; - aarch64) - Arch=arm64 - ;; - *) - echo -e "\nAdGuardHome 暂不支持当前的设备架构: [${Archt}]!" - EXIT 1 - esac - case "${Archt}" in - mipsel) - Arch_upx="mipsel" - upx_latest_ver="3.95" - ;; - *) - Arch_upx="${Arch}" - upx_latest_ver="$(${_Downloader} https://api.github.com/repos/upx/upx/releases/latest 2>/dev/null | egrep 'tag_name' | egrep '[0-9.]+' -o 2>/dev/null)" - - esac - echo -e "\n当前设备架构: ${Arch}\n" -} - -EXIT(){ - rm -rf /var/run/update_core $LOCKU 2>/dev/null - [[ $1 != 0 ]] && touch /var/run/update_core_error - exit $1 -} - -main(){ - Check_Task ${update_mode} - Check_Updates ${update_mode} -} - -trap "EXIT 1" SIGTERM SIGINT -touch /var/run/update_core -rm - rf /var/run/update_core_error 2>/dev/null - -main diff --git a/luci-app-adguardhome/root/usr/share/AdGuardHome/waitnet.sh b/luci-app-adguardhome/root/usr/share/AdGuardHome/waitnet.sh deleted file mode 100755 index c7745e10..00000000 --- a/luci-app-adguardhome/root/usr/share/AdGuardHome/waitnet.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh - -PATH="/usr/sbin:/usr/bin:/sbin:/bin" -count=0 -while : -do - ping -c 1 -W 1 -q www.baidu.com 1>/dev/null 2>&1 - if [ "$?" == "0" ]; then - /etc/init.d/AdGuardHome force_reload - break - fi - ping -c 1 -W 1 -q 202.108.22.5 1>/dev/null 2>&1 - if [ "$?" == "0" ]; then - /etc/init.d/AdGuardHome force_reload - break - fi - sleep 5 - ping -c 1 -W 1 -q www.google.com 1>/dev/null 2>&1 - if [ "$?" == "0" ]; then - /etc/init.d/AdGuardHome force_reload - break - fi - ping -c 1 -W 1 -q 8.8.8.8 1>/dev/null 2>&1 - if [ "$?" == "0" ]; then - /etc/init.d/AdGuardHome force_reload - break - fi - sleep 5 - count=$((count+1)) - if [ $count -gt 18 ]; then - /etc/init.d/AdGuardHome force_reload - break - fi -done -return 0 diff --git a/luci-app-adguardhome/root/usr/share/AdGuardHome/watchconfig.sh b/luci-app-adguardhome/root/usr/share/AdGuardHome/watchconfig.sh deleted file mode 100755 index 61ba09de..00000000 --- a/luci-app-adguardhome/root/usr/share/AdGuardHome/watchconfig.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh - -PATH="/usr/sbin:/usr/bin:/sbin:/bin" -configpath=$(uci get AdGuardHome.AdGuardHome.configpath) -while : -do - sleep 10 - if [ -f "$configpath" ]; then - /etc/init.d/AdGuardHome do_redirect 1 - break - fi -done -return 0 diff --git a/luci-app-adguardhome/root/usr/share/luci/menu.d/luci-app-adguardhome.json b/luci-app-adguardhome/root/usr/share/luci/menu.d/luci-app-adguardhome.json new file mode 100644 index 00000000..547b638c --- /dev/null +++ b/luci-app-adguardhome/root/usr/share/luci/menu.d/luci-app-adguardhome.json @@ -0,0 +1,40 @@ +{ + "admin/services/adguardhome": { + "title": "AdGuard Home", + "action": { + "type": "firstchild" + }, + "depends": { + "acl": [ + "luci-app-adguardhome" + ], + "uci": { + "adguardhome": true + } + } + }, + "admin/services/adguardhome/config": { + "title": "Configuration", + "order": 1, + "action": { + "type": "view", + "path": "adguardhome/config" + } + }, + "admin/services/adguardhome/status": { + "title": "Status", + "order": 11, + "action": { + "type": "view", + "path": "adguardhome/status" + } + }, + "admin/services/adguardhome/logs": { + "title": "Logs", + "order": 21, + "action": { + "type": "view", + "path": "adguardhome/logs" + } + } +} \ No newline at end of file diff --git a/luci-app-adguardhome/root/usr/share/rpcd/acl.d/luci-app-adguardhome.json b/luci-app-adguardhome/root/usr/share/rpcd/acl.d/luci-app-adguardhome.json index 485aa620..689923c0 100644 --- a/luci-app-adguardhome/root/usr/share/rpcd/acl.d/luci-app-adguardhome.json +++ b/luci-app-adguardhome/root/usr/share/rpcd/acl.d/luci-app-adguardhome.json @@ -1,11 +1,30 @@ { "luci-app-adguardhome": { - "description": "Grant UCI access for luci-app-adguardhome", + "description": "Grant permissions for the AdGuard Home LuCI app", "read": { - "uci": [ "AdGuardHome" ] + "ubus": { + "luci.adguardhome": [ + "get_config", + "get_status", + "get_statistics", + "set_passwd" + ] + }, + "uci": [ "adguardhome" ], + "file": { + "/sbin/logread": [ + "stat", + "exec" + ], + "/sbin/logread -e AdGuardHome": [ + "exec" + ], + "/etc/init.d/dnsmasq": [ "exec" ], + "/etc/init.d/firewall": [ "exec" ] + } }, "write": { - "uci": [ "AdGuardHome" ] + "uci": [ "adguardhome" ] } } } diff --git a/luci-app-adguardhome/root/www/luci-static/resources/codemirror/addon/fold/foldcode.js b/luci-app-adguardhome/root/www/luci-static/resources/codemirror/addon/fold/foldcode.js deleted file mode 100644 index f93d42b7..00000000 --- a/luci-app-adguardhome/root/www/luci-static/resources/codemirror/addon/fold/foldcode.js +++ /dev/null @@ -1 +0,0 @@ -!function(n){"object"==typeof exports&&"object"==typeof module?n(require("../../lib/codemirror")):"function"==typeof define&&define.amd?define(["../../lib/codemirror"],n):n(CodeMirror)}(function(n){"use strict";function e(e,o,i,t){if(i&&i.call){var l=i;i=null}else l=r(e,i,"rangeFinder");"number"==typeof o&&(o=n.Pos(o,0));var f=r(e,i,"minFoldSize");function d(n){var r=l(e,o);if(!r||r.to.line-r.from.linee.firstLine();)o=n.Pos(o.line-1,0),u=d(!1);if(u&&!u.cleared&&"unfold"!==t){var a=function(n,e){var o=r(n,e,"widget");if("string"==typeof o){var i=document.createTextNode(o);(o=document.createElement("span")).appendChild(i),o.className="CodeMirror-foldmarker"}else o&&(o=o.cloneNode(!0));return o}(e,i);n.on(a,"mousedown",function(e){c.clear(),n.e_preventDefault(e)});var c=e.markText(u.from,u.to,{replacedWith:a,clearOnEnter:r(e,i,"clearOnEnter"),__isFold:!0});c.on("clear",function(o,r){n.signal(e,"unfold",e,o,r)}),n.signal(e,"fold",e,u.from,u.to)}}n.newFoldFunction=function(n,o){return function(r,i){e(r,i,{rangeFinder:n,widget:o})}},n.defineExtension("foldCode",function(n,o,r){e(this,n,o,r)}),n.defineExtension("isFolded",function(n){for(var e=this.findMarksAt(n),o=0;o=u){if(s&&f&&s.test(f.className))return;i=r(a.indicatorOpen)}}(i||f)&&t.setGutterMarker(n,a.gutter,i)})}function i(t){return new RegExp("(^|\\s)"+t+"(?:$|\\s)\\s*")}function f(t){var o=t.getViewport(),e=t.state.foldGutter;e&&(t.operation(function(){n(t,o.from,o.to)}),e.from=o.from,e.to=o.to)}function a(t,r,n){var i=t.state.foldGutter;if(i){var f=i.options;if(n==f.gutter){var a=e(t,r);a?a.clear():t.foldCode(o(r,0),f)}}}function d(t){var o=t.state.foldGutter;if(o){var e=o.options;o.from=o.to=0,clearTimeout(o.changeUpdate),o.changeUpdate=setTimeout(function(){f(t)},e.foldOnChangeTimeSpan||600)}}function u(t){var o=t.state.foldGutter;if(o){var e=o.options;clearTimeout(o.changeUpdate),o.changeUpdate=setTimeout(function(){var e=t.getViewport();o.from==o.to||e.from-o.to>20||o.from-e.to>20?f(t):t.operation(function(){e.fromo.to&&(n(t,o.to,e.to),o.to=e.to)})},e.updateViewportTimeSpan||400)}}function l(t,o){var e=t.state.foldGutter;if(e){var r=o.line;r>=e.from&&ro))break;r=l}}return r?{from:e.Pos(i.line,t.getLine(i.line).length),to:e.Pos(r,t.getLine(r).length)}:void 0}})}); \ No newline at end of file diff --git a/luci-app-adguardhome/root/www/luci-static/resources/codemirror/lib/codemirror.css b/luci-app-adguardhome/root/www/luci-static/resources/codemirror/lib/codemirror.css deleted file mode 100644 index 43ac1a9f..00000000 --- a/luci-app-adguardhome/root/www/luci-static/resources/codemirror/lib/codemirror.css +++ /dev/null @@ -1 +0,0 @@ -.CodeMirror{font-family:monospace;height:500px;color:black;direction:ltr}.CodeMirror-lines{padding:4px 0}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{padding:0 4px}.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{background-color:white}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.CodeMirror-guttermarker{color:black}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror-cursor{border-left:1px solid black;border-right:0;width:0}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.cm-fat-cursor .CodeMirror-cursor{width:auto;border:0 !important;background:#7e7}.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-fat-cursor-mark{background-color:rgba(20,255,20,0.5);-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite}.cm-animate-fat-cursor{width:auto;border:0;-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite;background-color:#7e7}@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-rulers{position:absolute;left:0;right:0;top:-50px;bottom:0;overflow:hidden}.CodeMirror-ruler{border-left:1px solid #ccc;top:0;bottom:0;position:absolute}.cm-s-default .cm-header{color:blue}.cm-s-default .cm-quote{color:#090}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:bold}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-variable-3,.cm-s-default .cm-type{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta{color:#555}.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-s-default .cm-error{color:red}.cm-invalidchar{color:red}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0b0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#a22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{position:relative;overflow:hidden;background:white}.CodeMirror-scroll{overflow:scroll !important;margin-bottom:-30px;margin-right:-30px;padding-bottom:30px;height:100%;outline:0;position:relative}.CodeMirror-sizer{position:relative;border-right:30px solid transparent}.CodeMirror-vscrollbar,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-gutter-filler{position:absolute;z-index:6;display:none}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;min-height:100%;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;vertical-align:top;margin-bottom:-30px}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:none !important;border:none !important}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-gutter-wrapper ::selection{background-color:transparent}.CodeMirror-gutter-wrapper ::-moz-selection{background-color:transparent}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:transparent;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent;-webkit-font-variant-ligatures:contextual;font-variant-ligatures:contextual}.CodeMirror-wrap pre.CodeMirror-line,.CodeMirror-wrap pre.CodeMirror-line-like{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;padding:.1px}.CodeMirror-rtl pre{direction:rtl}.CodeMirror-code{outline:0}.CodeMirror-scroll,.CodeMirror-sizer,.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber{-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-cursor{position:absolute;pointer-events:none}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}div.CodeMirror-dragcursors{visibility:visible}.CodeMirror-focused div.CodeMirror-cursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background-color:#ffa;background-color:rgba(255,255,0,.4)}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:''}span.CodeMirror-selectedtext{background:0} diff --git a/luci-app-adguardhome/root/www/luci-static/resources/codemirror/lib/codemirror.js b/luci-app-adguardhome/root/www/luci-static/resources/codemirror/lib/codemirror.js deleted file mode 100644 index d01f072e..00000000 --- a/luci-app-adguardhome/root/www/luci-static/resources/codemirror/lib/codemirror.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.CodeMirror=t()}(this,function(){"use strict";var e=navigator.userAgent,t=navigator.platform,r=/gecko\/\d/i.test(e),n=/MSIE \d/.test(e),i=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(e),o=/Edge\/(\d+)/.exec(e),l=n||i||o,s=l&&(n?document.documentMode||6:+(o||i)[1]),a=!o&&/WebKit\//.test(e),u=a&&/Qt\/\d+\.\d+/.test(e),c=!o&&/Chrome\//.test(e),h=/Opera\//.test(e),f=/Apple Computer/.test(navigator.vendor),d=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(e),p=/PhantomJS/.test(e),g=!o&&/AppleWebKit/.test(e)&&/Mobile\/\w+/.test(e),v=/Android/.test(e),m=g||v||/webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(e),y=g||/Mac/.test(t),b=/\bCrOS\b/.test(e),w=/win/i.test(t),x=h&&e.match(/Version\/(\d*\.\d*)/);x&&(x=Number(x[1])),x&&x>=15&&(h=!1,a=!0);var C=y&&(u||h&&(null==x||x<12.11)),S=r||l&&s>=9;function L(e){return new RegExp("(^|\\s)"+e+"(?:$|\\s)\\s*")}var k,T=function(e,t){var r=e.className,n=L(t).exec(r);if(n){var i=r.slice(n.index+n[0].length);e.className=r.slice(0,n.index)+(i?n[1]+i:"")}};function M(e){for(var t=e.childNodes.length;t>0;--t)e.removeChild(e.firstChild);return e}function N(e,t){return M(e).appendChild(t)}function O(e,t,r,n){var i=document.createElement(e);if(r&&(i.className=r),n&&(i.style.cssText=n),"string"==typeof t)i.appendChild(document.createTextNode(t));else if(t)for(var o=0;o=t)return l+(t-o);l+=s-o,l+=r-l%r,o=s+1}}g?P=function(e){e.selectionStart=0,e.selectionEnd=e.value.length}:l&&(P=function(e){try{e.select()}catch(e){}});var R=function(){this.id=null,this.f=null,this.time=0,this.handler=E(this.onTimeout,this)};function B(e,t){for(var r=0;r=t)return n+Math.min(l,t-i);if(i+=o-n,n=o+1,(i+=r-i%r)>=t)return n}}var Y=[""];function _(e){for(;Y.length<=e;)Y.push($(Y)+" ");return Y[e]}function $(e){return e[e.length-1]}function q(e,t){for(var r=[],n=0;n"€"&&(e.toUpperCase()!=e.toLowerCase()||J.test(e))}function te(e,t){return t?!!(t.source.indexOf("\\w")>-1&&ee(e))||t.test(e):ee(e)}function re(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t])return!1;return!0}var ne=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;function ie(e){return e.charCodeAt(0)>=768&&ne.test(e)}function oe(e,t,r){for(;(r<0?t>0:tr?-1:1;;){if(t==r)return t;var i=(t+r)/2,o=n<0?Math.ceil(i):Math.floor(i);if(o==t)return e(o)?t:r;e(o)?r=o:t=o+n}}var se=null;function ae(e,t,r){var n;se=null;for(var i=0;it)return i;o.to==t&&(o.from!=o.to&&"before"==r?n=i:se=i),o.from==t&&(o.from!=o.to&&"before"!=r?n=i:se=i)}return null!=n?n:se}var ue=function(){var e="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN",t="nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111";var r=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,n=/[stwN]/,i=/[LRr]/,o=/[Lb1n]/,l=/[1n]/;function s(e,t,r){this.level=e,this.from=t,this.to=r}return function(a,u){var c="ltr"==u?"L":"R";if(0==a.length||"ltr"==u&&!r.test(a))return!1;for(var h,f=a.length,d=[],p=0;p-1&&(n[t]=i.slice(0,o).concat(i.slice(o+1)))}}}function ge(e,t){var r=de(e,t);if(r.length)for(var n=Array.prototype.slice.call(arguments,2),i=0;i0}function be(e){e.prototype.on=function(e,t){fe(this,e,t)},e.prototype.off=function(e,t){pe(this,e,t)}}function we(e){e.preventDefault?e.preventDefault():e.returnValue=!1}function xe(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0}function Ce(e){return null!=e.defaultPrevented?e.defaultPrevented:0==e.returnValue}function Se(e){we(e),xe(e)}function Le(e){return e.target||e.srcElement}function ke(e){var t=e.which;return null==t&&(1&e.button?t=1:2&e.button?t=3:4&e.button&&(t=2)),y&&e.ctrlKey&&1==t&&(t=3),t}var Te,Me,Ne=function(){if(l&&s<9)return!1;var e=O("div");return"draggable"in e||"dragDrop"in e}();function Oe(e){if(null==Te){var t=O("span","​");N(e,O("span",[t,document.createTextNode("x")])),0!=e.firstChild.offsetHeight&&(Te=t.offsetWidth<=1&&t.offsetHeight>2&&!(l&&s<8))}var r=Te?O("span","​"):O("span"," ",null,"display: inline-block; width: 1px; margin-right: -1px");return r.setAttribute("cm-text",""),r}function Ae(e){if(null!=Me)return Me;var t=N(e,document.createTextNode("AخA")),r=k(t,0,1).getBoundingClientRect(),n=k(t,1,2).getBoundingClientRect();return M(e),!(!r||r.left==r.right)&&(Me=n.right-r.right<3)}var De,We=3!="\n\nb".split(/\n/).length?function(e){for(var t=0,r=[],n=e.length;t<=n;){var i=e.indexOf("\n",t);-1==i&&(i=e.length);var o=e.slice(t,"\r"==e.charAt(i-1)?i-1:i),l=o.indexOf("\r");-1!=l?(r.push(o.slice(0,l)),t+=l+1):(r.push(o),t=i+1)}return r}:function(e){return e.split(/\r\n?|\n/)},He=window.getSelection?function(e){try{return e.selectionStart!=e.selectionEnd}catch(e){return!1}}:function(e){var t;try{t=e.ownerDocument.selection.createRange()}catch(e){}return!(!t||t.parentElement()!=e)&&0!=t.compareEndPoints("StartToEnd",t)},Fe="oncopy"in(De=O("div"))||(De.setAttribute("oncopy","return;"),"function"==typeof De.oncopy),Pe=null;var Ee={},Ie={};function ze(e){if("string"==typeof e&&Ie.hasOwnProperty(e))e=Ie[e];else if(e&&"string"==typeof e.name&&Ie.hasOwnProperty(e.name)){var t=Ie[e.name];"string"==typeof t&&(t={name:t}),(e=Q(t,e)).name=t.name}else{if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+xml$/.test(e))return ze("application/xml");if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+json$/.test(e))return ze("application/json")}return"string"==typeof e?{name:e}:e||{name:"null"}}function Re(e,t){t=ze(t);var r=Ee[t.name];if(!r)return Re(e,"text/plain");var n=r(e,t);if(Be.hasOwnProperty(t.name)){var i=Be[t.name];for(var o in i)i.hasOwnProperty(o)&&(n.hasOwnProperty(o)&&(n["_"+o]=n[o]),n[o]=i[o])}if(n.name=t.name,t.helperType&&(n.helperType=t.helperType),t.modeProps)for(var l in t.modeProps)n[l]=t.modeProps[l];return n}var Be={};function Ge(e,t){I(t,Be.hasOwnProperty(e)?Be[e]:Be[e]={})}function Ue(e,t){if(!0===t)return t;if(e.copyState)return e.copyState(t);var r={};for(var n in t){var i=t[n];i instanceof Array&&(i=i.concat([])),r[n]=i}return r}function Ve(e,t){for(var r;e.innerMode&&(r=e.innerMode(t))&&r.mode!=e;)t=r.state,e=r.mode;return r||{mode:e,state:t}}function Ke(e,t,r){return!e.startState||e.startState(t,r)}var je=function(e,t,r){this.pos=this.start=0,this.string=e,this.tabSize=t||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0,this.lineOracle=r};function Xe(e,t){if((t-=e.first)<0||t>=e.size)throw new Error("There is no line "+(t+e.first)+" in the document.");for(var r=e;!r.lines;)for(var n=0;;++n){var i=r.children[n],o=i.chunkSize();if(t=e.first&&tr?et(r,Xe(e,r).text.length):function(e,t){var r=e.ch;return null==r||r>t?et(e.line,t):r<0?et(e.line,0):e}(t,Xe(e,t.line).text.length)}function at(e,t){for(var r=[],n=0;n=this.string.length},je.prototype.sol=function(){return this.pos==this.lineStart},je.prototype.peek=function(){return this.string.charAt(this.pos)||void 0},je.prototype.next=function(){if(this.post},je.prototype.eatSpace=function(){for(var e=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>e},je.prototype.skipToEnd=function(){this.pos=this.string.length},je.prototype.skipTo=function(e){var t=this.string.indexOf(e,this.pos);if(t>-1)return this.pos=t,!0},je.prototype.backUp=function(e){this.pos-=e},je.prototype.column=function(){return this.lastColumnPos0?null:(n&&!1!==t&&(this.pos+=n[0].length),n)}var i=function(e){return r?e.toLowerCase():e};if(i(this.string.substr(this.pos,e.length))==i(e))return!1!==t&&(this.pos+=e.length),!0},je.prototype.current=function(){return this.string.slice(this.start,this.pos)},je.prototype.hideFirstChars=function(e,t){this.lineStart+=e;try{return t()}finally{this.lineStart-=e}},je.prototype.lookAhead=function(e){var t=this.lineOracle;return t&&t.lookAhead(e)},je.prototype.baseToken=function(){var e=this.lineOracle;return e&&e.baseToken(this.pos)};var ut=function(e,t){this.state=e,this.lookAhead=t},ct=function(e,t,r,n){this.state=t,this.doc=e,this.line=r,this.maxLookAhead=n||0,this.baseTokens=null,this.baseTokenPos=1};function ht(e,t,r,n){var i=[e.state.modeGen],o={};wt(e,t.text,e.doc.mode,r,function(e,t){return i.push(e,t)},o,n);for(var l=r.state,s=function(n){r.baseTokens=i;var s=e.state.overlays[n],a=1,u=0;r.state=!0,wt(e,t.text,s.mode,r,function(e,t){for(var r=a;ue&&i.splice(a,1,e,i[a+1],n),a+=2,u=Math.min(e,n)}if(t)if(s.opaque)i.splice(r,a-r,e,"overlay "+t),a=r+2;else for(;re.options.maxHighlightLength&&Ue(e.doc.mode,n.state),o=ht(e,t,n);i&&(n.state=i),t.stateAfter=n.save(!i),t.styles=o.styles,o.classes?t.styleClasses=o.classes:t.styleClasses&&(t.styleClasses=null),r===e.doc.highlightFrontier&&(e.doc.modeFrontier=Math.max(e.doc.modeFrontier,++e.doc.highlightFrontier))}return t.styles}function dt(e,t,r){var n=e.doc,i=e.display;if(!n.mode.startState)return new ct(n,!0,t);var o=function(e,t,r){for(var n,i,o=e.doc,l=r?-1:t-(e.doc.mode.innerMode?1e3:100),s=t;s>l;--s){if(s<=o.first)return o.first;var a=Xe(o,s-1),u=a.stateAfter;if(u&&(!r||s+(u instanceof ut?u.lookAhead:0)<=o.modeFrontier))return s;var c=z(a.text,null,e.options.tabSize);(null==i||n>c)&&(i=s-1,n=c)}return i}(e,t,r),l=o>n.first&&Xe(n,o-1).stateAfter,s=l?ct.fromSaved(n,l,o):new ct(n,Ke(n.mode),o);return n.iter(o,t,function(r){pt(e,r.text,s);var n=s.line;r.stateAfter=n==t-1||n%5==0||n>=i.viewFrom&&nt.start)return o}throw new Error("Mode "+e.name+" failed to advance stream.")}ct.prototype.lookAhead=function(e){var t=this.doc.getLine(this.line+e);return null!=t&&e>this.maxLookAhead&&(this.maxLookAhead=e),t},ct.prototype.baseToken=function(e){if(!this.baseTokens)return null;for(;this.baseTokens[this.baseTokenPos]<=e;)this.baseTokenPos+=2;var t=this.baseTokens[this.baseTokenPos+1];return{type:t&&t.replace(/( |^)overlay .*/,""),size:this.baseTokens[this.baseTokenPos]-e}},ct.prototype.nextLine=function(){this.line++,this.maxLookAhead>0&&this.maxLookAhead--},ct.fromSaved=function(e,t,r){return t instanceof ut?new ct(e,Ue(e.mode,t.state),r,t.lookAhead):new ct(e,Ue(e.mode,t),r)},ct.prototype.save=function(e){var t=!1!==e?Ue(this.doc.mode,this.state):this.state;return this.maxLookAhead>0?new ut(t,this.maxLookAhead):t};var mt=function(e,t,r){this.start=e.start,this.end=e.pos,this.string=e.current(),this.type=t||null,this.state=r};function yt(e,t,r,n){var i,o,l=e.doc,s=l.mode,a=Xe(l,(t=st(l,t)).line),u=dt(e,t.line,r),c=new je(a.text,e.options.tabSize,u);for(n&&(o=[]);(n||c.pose.options.maxHighlightLength?(s=!1,l&&pt(e,t,n,h.pos),h.pos=t.length,a=null):a=bt(vt(r,h,n.state,f),o),f){var d=f[0].name;d&&(a="m-"+(a?d+" "+a:d))}if(!s||c!=a){for(;u=t:o.to>t);(n||(n=[])).push(new St(l,o.from,s?null:o.to))}}return n}(r,i,l),a=function(e,t,r){var n;if(e)for(var i=0;i=t:o.to>t)||o.from==t&&"bookmark"==l.type&&(!r||o.marker.insertLeft)){var s=null==o.from||(l.inclusiveLeft?o.from<=t:o.from0&&s)for(var b=0;bt)&&(!r||Wt(r,o.marker)<0)&&(r=o.marker)}return r}function It(e,t,r,n,i){var o=Xe(e,t),l=Ct&&o.markedSpans;if(l)for(var s=0;s=0&&h<=0||c<=0&&h>=0)&&(c<=0&&(a.marker.inclusiveRight&&i.inclusiveLeft?tt(u.to,r)>=0:tt(u.to,r)>0)||c>=0&&(a.marker.inclusiveRight&&i.inclusiveLeft?tt(u.from,n)<=0:tt(u.from,n)<0)))return!0}}}function zt(e){for(var t;t=Ft(e);)e=t.find(-1,!0).line;return e}function Rt(e,t){var r=Xe(e,t),n=zt(r);return r==n?t:qe(n)}function Bt(e,t){if(t>e.lastLine())return t;var r,n=Xe(e,t);if(!Gt(e,n))return t;for(;r=Pt(n);)n=r.find(1,!0).line;return qe(n)+1}function Gt(e,t){var r=Ct&&t.markedSpans;if(r)for(var n=void 0,i=0;it.maxLineLength&&(t.maxLineLength=r,t.maxLine=e)})}var Xt=function(e,t,r){this.text=e,Ot(this,t),this.height=r?r(this):1};function Yt(e){e.parent=null,Nt(e)}Xt.prototype.lineNo=function(){return qe(this)},be(Xt);var _t={},$t={};function qt(e,t){if(!e||/^\s*$/.test(e))return null;var r=t.addModeClass?$t:_t;return r[e]||(r[e]=e.replace(/\S+/g,"cm-$&"))}function Zt(e,t){var r=A("span",null,null,a?"padding-right: .1px":null),n={pre:A("pre",[r],"CodeMirror-line"),content:r,col:0,pos:0,cm:e,trailingSpace:!1,splitSpaces:e.getOption("lineWrapping")};t.measure={};for(var i=0;i<=(t.rest?t.rest.length:0);i++){var o=i?t.rest[i-1]:t.line,l=void 0;n.pos=0,n.addToken=Jt,Ae(e.display.measure)&&(l=ce(o,e.doc.direction))&&(n.addToken=er(n.addToken,l)),n.map=[],rr(o,n,ft(e,o,t!=e.display.externalMeasured&&qe(o))),o.styleClasses&&(o.styleClasses.bgClass&&(n.bgClass=F(o.styleClasses.bgClass,n.bgClass||"")),o.styleClasses.textClass&&(n.textClass=F(o.styleClasses.textClass,n.textClass||""))),0==n.map.length&&n.map.push(0,0,n.content.appendChild(Oe(e.display.measure))),0==i?(t.measure.map=n.map,t.measure.cache={}):((t.measure.maps||(t.measure.maps=[])).push(n.map),(t.measure.caches||(t.measure.caches=[])).push({}))}if(a){var s=n.content.lastChild;(/\bcm-tab\b/.test(s.className)||s.querySelector&&s.querySelector(".cm-tab"))&&(n.content.className="cm-tab-wrap-hack")}return ge(e,"renderLine",e,t.line,n.pre),n.pre.className&&(n.textClass=F(n.pre.className,n.textClass||"")),n}function Qt(e){var t=O("span","•","cm-invalidchar");return t.title="\\u"+e.charCodeAt(0).toString(16),t.setAttribute("aria-label",t.title),t}function Jt(e,t,r,n,i,o,a){if(t){var u,c=e.splitSpaces?function(e,t){if(e.length>1&&!/ /.test(e))return e;for(var r=t,n="",i=0;iu&&h.from<=u);f++);if(h.to>=c)return e(r,n,i,o,l,s,a);e(r,n.slice(0,h.to-u),i,o,null,s,a),o=null,n=n.slice(h.to-u),u=h.to}}}function tr(e,t,r,n){var i=!n&&r.widgetNode;i&&e.map.push(e.pos,e.pos+t,i),!n&&e.cm.display.input.needsContentAttribute&&(i||(i=e.content.appendChild(document.createElement("span"))),i.setAttribute("cm-marker",r.id)),i&&(e.cm.display.input.setUneditable(i),e.content.appendChild(i)),e.pos+=t,e.trailingSpace=!1}function rr(e,t,r){var n=e.markedSpans,i=e.text,o=0;if(n)for(var l,s,a,u,c,h,f,d=i.length,p=0,g=1,v="",m=0;;){if(m==p){a=u=c=s="",f=null,h=null,m=1/0;for(var y=[],b=void 0,w=0;wp||C.collapsed&&x.to==p&&x.from==p)){if(null!=x.to&&x.to!=p&&m>x.to&&(m=x.to,u=""),C.className&&(a+=" "+C.className),C.css&&(s=(s?s+";":"")+C.css),C.startStyle&&x.from==p&&(c+=" "+C.startStyle),C.endStyle&&x.to==m&&(b||(b=[])).push(C.endStyle,x.to),C.title&&((f||(f={})).title=C.title),C.attributes)for(var S in C.attributes)(f||(f={}))[S]=C.attributes[S];C.collapsed&&(!h||Wt(h.marker,C)<0)&&(h=x)}else x.from>p&&m>x.from&&(m=x.from)}if(b)for(var L=0;L=d)break;for(var T=Math.min(d,m);;){if(v){var M=p+v.length;if(!h){var N=M>T?v.slice(0,T-p):v;t.addToken(t,N,l?l+a:a,c,p+N.length==m?u:"",s,f)}if(M>=T){v=v.slice(T-p),p=T;break}p=M,c=""}v=i.slice(o,o=r[g++]),l=qt(r[g++],t.cm.options)}}else for(var O=1;Or)return{map:e.measure.maps[i],cache:e.measure.caches[i],before:!0}}function Or(e,t,r,n){return Wr(e,Dr(e,t),r,n)}function Ar(e,t){if(t>=e.display.viewFrom&&t=r.lineN&&t2&&o.push((a.bottom+u.top)/2-r.top)}}o.push(r.bottom-r.top)}}(e,t.view,t.rect),t.hasHeights=!0),(o=function(e,t,r,n){var i,o=Pr(t.map,r,n),a=o.node,u=o.start,c=o.end,h=o.collapse;if(3==a.nodeType){for(var f=0;f<4;f++){for(;u&&ie(t.line.text.charAt(o.coverStart+u));)--u;for(;o.coverStart+c1}(e))return t;var r=screen.logicalXDPI/screen.deviceXDPI,n=screen.logicalYDPI/screen.deviceYDPI;return{left:t.left*r,right:t.right*r,top:t.top*n,bottom:t.bottom*n}}(e.display.measure,i))}else{var d;u>0&&(h=n="right"),i=e.options.lineWrapping&&(d=a.getClientRects()).length>1?d["right"==n?d.length-1:0]:a.getBoundingClientRect()}if(l&&s<9&&!u&&(!i||!i.left&&!i.right)){var p=a.parentNode.getClientRects()[0];i=p?{left:p.left,right:p.left+tn(e.display),top:p.top,bottom:p.bottom}:Fr}for(var g=i.top-t.rect.top,v=i.bottom-t.rect.top,m=(g+v)/2,y=t.view.measure.heights,b=0;bt)&&(i=(o=a-s)-1,t>=a&&(l="right")),null!=i){if(n=e[u+2],s==a&&r==(n.insertLeft?"left":"right")&&(l=r),"left"==r&&0==i)for(;u&&e[u-2]==e[u-3]&&e[u-1].insertLeft;)n=e[2+(u-=3)],l="left";if("right"==r&&i==a-s)for(;u=0&&(r=e[i]).left==r.right;i--);return r}function Ir(e){if(e.measure&&(e.measure.cache={},e.measure.heights=null,e.rest))for(var t=0;t=n.text.length?(a=n.text.length,u="before"):a<=0&&(a=0,u="after"),!s)return l("before"==u?a-1:a,"before"==u);function c(e,t,r){return l(r?e-1:e,1==s[t].level!=r)}var h=ae(s,a,u),f=se,d=c(a,h,"before"==u);return null!=f&&(d.other=c(a,f,"before"!=u)),d}function Yr(e,t){var r=0;t=st(e.doc,t),e.options.lineWrapping||(r=tn(e.display)*t.ch);var n=Xe(e.doc,t.line),i=Vt(n)+Cr(e.display);return{left:r,right:r,top:i,bottom:i+n.height}}function _r(e,t,r,n,i){var o=et(e,t,r);return o.xRel=i,n&&(o.outside=n),o}function $r(e,t,r){var n=e.doc;if((r+=e.display.viewOffset)<0)return _r(n.first,0,null,-1,-1);var i=Ze(n,r),o=n.first+n.size-1;if(i>o)return _r(n.first+n.size-1,Xe(n,o).text.length,null,1,1);t<0&&(t=0);for(var l=Xe(n,i);;){var s=Jr(e,l,i,t,r),a=Et(l,s.ch+(s.xRel>0||s.outside>0?1:0));if(!a)return s;var u=a.find(1);if(u.line==i)return u;l=Xe(n,i=u.line)}}function qr(e,t,r,n){n-=Ur(t);var i=t.text.length,o=le(function(t){return Wr(e,r,t-1).bottom<=n},i,0);return{begin:o,end:i=le(function(t){return Wr(e,r,t).top>n},o,i)}}function Zr(e,t,r,n){return r||(r=Dr(e,t)),qr(e,t,r,Vr(e,t,Wr(e,r,n),"line").top)}function Qr(e,t,r,n){return!(e.bottom<=r)&&(e.top>r||(n?e.left:e.right)>t)}function Jr(e,t,r,n,i){i-=Vt(t);var o=Dr(e,t),l=Ur(t),s=0,a=t.text.length,u=!0,c=ce(t,e.doc.direction);if(c){var h=(e.options.lineWrapping?function(e,t,r,n,i,o,l){var s=qr(e,t,n,l),a=s.begin,u=s.end;/\s/.test(t.text.charAt(u-1))&&u--;for(var c=null,h=null,f=0;f=u||d.to<=a)){var p=1!=d.level,g=Wr(e,n,p?Math.min(u,d.to)-1:Math.max(a,d.from)).right,v=gv)&&(c=d,h=v)}}c||(c=i[i.length-1]);c.fromu&&(c={from:c.from,to:u,level:c.level});return c}:function(e,t,r,n,i,o,l){var s=le(function(s){var a=i[s],u=1!=a.level;return Qr(Xr(e,et(r,u?a.to:a.from,u?"before":"after"),"line",t,n),o,l,!0)},0,i.length-1),a=i[s];if(s>0){var u=1!=a.level,c=Xr(e,et(r,u?a.from:a.to,u?"after":"before"),"line",t,n);Qr(c,o,l,!0)&&c.top>l&&(a=i[s-1])}return a})(e,t,r,o,c,n,i);s=(u=1!=h.level)?h.from:h.to-1,a=u?h.to:h.from-1}var f,d,p=null,g=null,v=le(function(t){var r=Wr(e,o,t);return r.top+=l,r.bottom+=l,!!Qr(r,n,i,!1)&&(r.top<=i&&r.left<=n&&(p=t,g=r),!0)},s,a),m=!1;if(g){var y=n-g.left=w.bottom?1:0}return _r(r,v=oe(t.text,v,1),d,m,n-f)}function en(e){if(null!=e.cachedTextHeight)return e.cachedTextHeight;if(null==Hr){Hr=O("pre",null,"CodeMirror-line-like");for(var t=0;t<49;++t)Hr.appendChild(document.createTextNode("x")),Hr.appendChild(O("br"));Hr.appendChild(document.createTextNode("x"))}N(e.measure,Hr);var r=Hr.offsetHeight/50;return r>3&&(e.cachedTextHeight=r),M(e.measure),r||1}function tn(e){if(null!=e.cachedCharWidth)return e.cachedCharWidth;var t=O("span","xxxxxxxxxx"),r=O("pre",[t],"CodeMirror-line-like");N(e.measure,r);var n=t.getBoundingClientRect(),i=(n.right-n.left)/10;return i>2&&(e.cachedCharWidth=i),i||10}function rn(e){for(var t=e.display,r={},n={},i=t.gutters.clientLeft,o=t.gutters.firstChild,l=0;o;o=o.nextSibling,++l){var s=e.display.gutterSpecs[l].className;r[s]=o.offsetLeft+o.clientLeft+i,n[s]=o.clientWidth}return{fixedPos:nn(t),gutterTotalWidth:t.gutters.offsetWidth,gutterLeft:r,gutterWidth:n,wrapperWidth:t.wrapper.clientWidth}}function nn(e){return e.scroller.getBoundingClientRect().left-e.sizer.getBoundingClientRect().left}function on(e){var t=en(e.display),r=e.options.lineWrapping,n=r&&Math.max(5,e.display.scroller.clientWidth/tn(e.display)-3);return function(i){if(Gt(e.doc,i))return 0;var o=0;if(i.widgets)for(var l=0;l=e.display.viewTo)return null;if((t-=e.display.viewFrom)<0)return null;for(var r=e.display.view,n=0;nt)&&(i.updateLineNumbers=t),e.curOp.viewChanged=!0,t>=i.viewTo)Ct&&Rt(e.doc,t)i.viewFrom?hn(e):(i.viewFrom+=n,i.viewTo+=n);else if(t<=i.viewFrom&&r>=i.viewTo)hn(e);else if(t<=i.viewFrom){var o=fn(e,r,r+n,1);o?(i.view=i.view.slice(o.index),i.viewFrom=o.lineN,i.viewTo+=n):hn(e)}else if(r>=i.viewTo){var l=fn(e,t,t,-1);l?(i.view=i.view.slice(0,l.index),i.viewTo=l.lineN):hn(e)}else{var s=fn(e,t,t,-1),a=fn(e,r,r+n,1);s&&a?(i.view=i.view.slice(0,s.index).concat(ir(e,s.lineN,a.lineN)).concat(i.view.slice(a.index)),i.viewTo+=n):hn(e)}var u=i.externalMeasured;u&&(r=i.lineN&&t=n.viewTo)){var o=n.view[an(e,t)];if(null!=o.node){var l=o.changes||(o.changes=[]);-1==B(l,r)&&l.push(r)}}}function hn(e){e.display.viewFrom=e.display.viewTo=e.doc.first,e.display.view=[],e.display.viewOffset=0}function fn(e,t,r,n){var i,o=an(e,t),l=e.display.view;if(!Ct||r==e.doc.first+e.doc.size)return{index:o,lineN:r};for(var s=e.display.viewFrom,a=0;a0){if(o==l.length-1)return null;i=s+l[o].size-t,o++}else i=s-t;t+=i,r+=i}for(;Rt(e.doc,r)!=r;){if(o==(n<0?0:l.length-1))return null;r+=n*l[o-(n<0?1:0)].size,o+=n}return{index:o,lineN:r}}function dn(e){for(var t=e.display.view,r=0,n=0;n=e.display.viewTo||s.to().linet||t==r&&l.to==t)&&(n(Math.max(l.from,t),Math.min(l.to,r),1==l.level?"rtl":"ltr",o),i=!0)}i||n(t,r,"ltr")}(g,r||0,null==n?f:n,function(e,t,i,h){var v="ltr"==i,m=d(e,v?"left":"right"),y=d(t-1,v?"right":"left"),b=null==r&&0==e,w=null==n&&t==f,x=0==h,C=!g||h==g.length-1;if(y.top-m.top<=3){var S=(u?w:b)&&C,L=(u?b:w)&&x?s:(v?m:y).left,k=S?a:(v?y:m).right;c(L,m.top,k-L,m.bottom)}else{var T,M,N,O;v?(T=u&&b&&x?s:m.left,M=u?a:p(e,i,"before"),N=u?s:p(t,i,"after"),O=u&&w&&C?a:y.right):(T=u?p(e,i,"before"):s,M=!u&&b&&x?a:m.right,N=!u&&w&&C?s:y.left,O=u?p(t,i,"after"):a),c(T,m.top,M-T,m.bottom),m.bottom0?t.blinker=setInterval(function(){return t.cursorDiv.style.visibility=(r=!r)?"":"hidden"},e.options.cursorBlinkRate):e.options.cursorBlinkRate<0&&(t.cursorDiv.style.visibility="hidden")}}function wn(e){e.state.focused||(e.display.input.focus(),Cn(e))}function xn(e){e.state.delayingBlurEvent=!0,setTimeout(function(){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1,Sn(e))},100)}function Cn(e,t){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1),"nocursor"!=e.options.readOnly&&(e.state.focused||(ge(e,"focus",e,t),e.state.focused=!0,H(e.display.wrapper,"CodeMirror-focused"),e.curOp||e.display.selForContextMenu==e.doc.sel||(e.display.input.reset(),a&&setTimeout(function(){return e.display.input.reset(!0)},20)),e.display.input.receivedFocus()),bn(e))}function Sn(e,t){e.state.delayingBlurEvent||(e.state.focused&&(ge(e,"blur",e,t),e.state.focused=!1,T(e.display.wrapper,"CodeMirror-focused")),clearInterval(e.display.blinker),setTimeout(function(){e.state.focused||(e.display.shift=!1)},150))}function Ln(e){for(var t=e.display,r=t.lineDiv.offsetTop,n=0;n.005||f<-.005)&&($e(i.line,a),kn(i.line),i.rest))for(var d=0;de.display.sizerWidth){var p=Math.ceil(u/tn(e.display));p>e.display.maxLineLength&&(e.display.maxLineLength=p,e.display.maxLine=i.line,e.display.maxLineChanged=!0)}}}}function kn(e){if(e.widgets)for(var t=0;t=l&&(o=Ze(t,Vt(Xe(t,a))-e.wrapper.clientHeight),l=a)}return{from:o,to:Math.max(l,o+1)}}function Mn(e,t){var r=e.display,n=en(e.display);t.top<0&&(t.top=0);var i=e.curOp&&null!=e.curOp.scrollTop?e.curOp.scrollTop:r.scroller.scrollTop,o=Mr(e),l={};t.bottom-t.top>o&&(t.bottom=t.top+o);var s=e.doc.height+Sr(r),a=t.tops-n;if(t.topi+o){var c=Math.min(t.top,(u?s:t.bottom)-o);c!=i&&(l.scrollTop=c)}var h=e.curOp&&null!=e.curOp.scrollLeft?e.curOp.scrollLeft:r.scroller.scrollLeft,f=Tr(e)-(e.options.fixedGutter?r.gutters.offsetWidth:0),d=t.right-t.left>f;return d&&(t.right=t.left+f),t.left<10?l.scrollLeft=0:t.leftf+h-3&&(l.scrollLeft=t.right+(d?0:10)-f),l}function Nn(e,t){null!=t&&(Dn(e),e.curOp.scrollTop=(null==e.curOp.scrollTop?e.doc.scrollTop:e.curOp.scrollTop)+t)}function On(e){Dn(e);var t=e.getCursor();e.curOp.scrollToPos={from:t,to:t,margin:e.options.cursorScrollMargin}}function An(e,t,r){null==t&&null==r||Dn(e),null!=t&&(e.curOp.scrollLeft=t),null!=r&&(e.curOp.scrollTop=r)}function Dn(e){var t=e.curOp.scrollToPos;t&&(e.curOp.scrollToPos=null,Wn(e,Yr(e,t.from),Yr(e,t.to),t.margin))}function Wn(e,t,r,n){var i=Mn(e,{left:Math.min(t.left,r.left),top:Math.min(t.top,r.top)-n,right:Math.max(t.right,r.right),bottom:Math.max(t.bottom,r.bottom)+n});An(e,i.scrollLeft,i.scrollTop)}function Hn(e,t){Math.abs(e.doc.scrollTop-t)<2||(r||oi(e,{top:t}),Fn(e,t,!0),r&&oi(e),ei(e,100))}function Fn(e,t,r){t=Math.min(e.display.scroller.scrollHeight-e.display.scroller.clientHeight,t),(e.display.scroller.scrollTop!=t||r)&&(e.doc.scrollTop=t,e.display.scrollbars.setScrollTop(t),e.display.scroller.scrollTop!=t&&(e.display.scroller.scrollTop=t))}function Pn(e,t,r,n){t=Math.min(t,e.display.scroller.scrollWidth-e.display.scroller.clientWidth),(r?t==e.doc.scrollLeft:Math.abs(e.doc.scrollLeft-t)<2)&&!n||(e.doc.scrollLeft=t,ai(e),e.display.scroller.scrollLeft!=t&&(e.display.scroller.scrollLeft=t),e.display.scrollbars.setScrollLeft(t))}function En(e){var t=e.display,r=t.gutters.offsetWidth,n=Math.round(e.doc.height+Sr(e.display));return{clientHeight:t.scroller.clientHeight,viewHeight:t.wrapper.clientHeight,scrollWidth:t.scroller.scrollWidth,clientWidth:t.scroller.clientWidth,viewWidth:t.wrapper.clientWidth,barLeft:e.options.fixedGutter?r:0,docHeight:n,scrollHeight:n+kr(e)+t.barHeight,nativeBarWidth:t.nativeBarWidth,gutterWidth:r}}var In=function(e,t,r){this.cm=r;var n=this.vert=O("div",[O("div",null,null,"min-width: 1px")],"CodeMirror-vscrollbar"),i=this.horiz=O("div",[O("div",null,null,"height: 100%; min-height: 1px")],"CodeMirror-hscrollbar");n.tabIndex=i.tabIndex=-1,e(n),e(i),fe(n,"scroll",function(){n.clientHeight&&t(n.scrollTop,"vertical")}),fe(i,"scroll",function(){i.clientWidth&&t(i.scrollLeft,"horizontal")}),this.checkedZeroWidth=!1,l&&s<8&&(this.horiz.style.minHeight=this.vert.style.minWidth="18px")};In.prototype.update=function(e){var t=e.scrollWidth>e.clientWidth+1,r=e.scrollHeight>e.clientHeight+1,n=e.nativeBarWidth;if(r){this.vert.style.display="block",this.vert.style.bottom=t?n+"px":"0";var i=e.viewHeight-(t?n:0);this.vert.firstChild.style.height=Math.max(0,e.scrollHeight-e.clientHeight+i)+"px"}else this.vert.style.display="",this.vert.firstChild.style.height="0";if(t){this.horiz.style.display="block",this.horiz.style.right=r?n+"px":"0",this.horiz.style.left=e.barLeft+"px";var o=e.viewWidth-e.barLeft-(r?n:0);this.horiz.firstChild.style.width=Math.max(0,e.scrollWidth-e.clientWidth+o)+"px"}else this.horiz.style.display="",this.horiz.firstChild.style.width="0";return!this.checkedZeroWidth&&e.clientHeight>0&&(0==n&&this.zeroWidthHack(),this.checkedZeroWidth=!0),{right:r?n:0,bottom:t?n:0}},In.prototype.setScrollLeft=function(e){this.horiz.scrollLeft!=e&&(this.horiz.scrollLeft=e),this.disableHoriz&&this.enableZeroWidthBar(this.horiz,this.disableHoriz,"horiz")},In.prototype.setScrollTop=function(e){this.vert.scrollTop!=e&&(this.vert.scrollTop=e),this.disableVert&&this.enableZeroWidthBar(this.vert,this.disableVert,"vert")},In.prototype.zeroWidthHack=function(){var e=y&&!d?"12px":"18px";this.horiz.style.height=this.vert.style.width=e,this.horiz.style.pointerEvents=this.vert.style.pointerEvents="none",this.disableHoriz=new R,this.disableVert=new R},In.prototype.enableZeroWidthBar=function(e,t,r){e.style.pointerEvents="auto",t.set(1e3,function n(){var i=e.getBoundingClientRect();("vert"==r?document.elementFromPoint(i.right-1,(i.top+i.bottom)/2):document.elementFromPoint((i.right+i.left)/2,i.bottom-1))!=e?e.style.pointerEvents="none":t.set(1e3,n)})},In.prototype.clear=function(){var e=this.horiz.parentNode;e.removeChild(this.horiz),e.removeChild(this.vert)};var zn=function(){};function Rn(e,t){t||(t=En(e));var r=e.display.barWidth,n=e.display.barHeight;Bn(e,t);for(var i=0;i<4&&r!=e.display.barWidth||n!=e.display.barHeight;i++)r!=e.display.barWidth&&e.options.lineWrapping&&Ln(e),Bn(e,En(e)),r=e.display.barWidth,n=e.display.barHeight}function Bn(e,t){var r=e.display,n=r.scrollbars.update(t);r.sizer.style.paddingRight=(r.barWidth=n.right)+"px",r.sizer.style.paddingBottom=(r.barHeight=n.bottom)+"px",r.heightForcer.style.borderBottom=n.bottom+"px solid transparent",n.right&&n.bottom?(r.scrollbarFiller.style.display="block",r.scrollbarFiller.style.height=n.bottom+"px",r.scrollbarFiller.style.width=n.right+"px"):r.scrollbarFiller.style.display="",n.bottom&&e.options.coverGutterNextToScrollbar&&e.options.fixedGutter?(r.gutterFiller.style.display="block",r.gutterFiller.style.height=n.bottom+"px",r.gutterFiller.style.width=t.gutterWidth+"px"):r.gutterFiller.style.display=""}zn.prototype.update=function(){return{bottom:0,right:0}},zn.prototype.setScrollLeft=function(){},zn.prototype.setScrollTop=function(){},zn.prototype.clear=function(){};var Gn={native:In,null:zn};function Un(e){e.display.scrollbars&&(e.display.scrollbars.clear(),e.display.scrollbars.addClass&&T(e.display.wrapper,e.display.scrollbars.addClass)),e.display.scrollbars=new Gn[e.options.scrollbarStyle](function(t){e.display.wrapper.insertBefore(t,e.display.scrollbarFiller),fe(t,"mousedown",function(){e.state.focused&&setTimeout(function(){return e.display.input.focus()},0)}),t.setAttribute("cm-not-content","true")},function(t,r){"horizontal"==r?Pn(e,t):Hn(e,t)},e),e.display.scrollbars.addClass&&H(e.display.wrapper,e.display.scrollbars.addClass)}var Vn=0;function Kn(e){var t;e.curOp={cm:e,viewChanged:!1,startHeight:e.doc.height,forceUpdate:!1,updateInput:0,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:!1,id:++Vn},t=e.curOp,or?or.ops.push(t):t.ownsGroup=or={ops:[t],delayedCallbacks:[]}}function jn(e){var t=e.curOp;t&&function(e,t){var r=e.ownsGroup;if(r)try{!function(e){var t=e.delayedCallbacks,r=0;do{for(;r=r.viewTo)||r.maxLineChanged&&t.options.lineWrapping,e.update=e.mustUpdate&&new ri(t,e.mustUpdate&&{top:e.scrollTop,ensure:e.scrollToPos},e.forceUpdate)}function Yn(e){var t=e.cm,r=t.display;e.updatedDisplay&&Ln(t),e.barMeasure=En(t),r.maxLineChanged&&!t.options.lineWrapping&&(e.adjustWidthTo=Or(t,r.maxLine,r.maxLine.text.length).left+3,t.display.sizerWidth=e.adjustWidthTo,e.barMeasure.scrollWidth=Math.max(r.scroller.clientWidth,r.sizer.offsetLeft+e.adjustWidthTo+kr(t)+t.display.barWidth),e.maxScrollLeft=Math.max(0,r.sizer.offsetLeft+e.adjustWidthTo-Tr(t))),(e.updatedDisplay||e.selectionChanged)&&(e.preparedSelection=r.input.prepareSelection())}function _n(e){var t=e.cm;null!=e.adjustWidthTo&&(t.display.sizer.style.minWidth=e.adjustWidthTo+"px",e.maxScrollLeft(window.innerHeight||document.documentElement.clientHeight)&&(i=!1),null!=i&&!p){var o=O("div","​",null,"position: absolute;\n top: "+(t.top-r.viewOffset-Cr(e.display))+"px;\n height: "+(t.bottom-t.top+kr(e)+r.barHeight)+"px;\n left: "+t.left+"px; width: "+Math.max(2,t.right-t.left)+"px;");e.display.lineSpace.appendChild(o),o.scrollIntoView(i),e.display.lineSpace.removeChild(o)}}}(t,function(e,t,r,n){var i;null==n&&(n=0),e.options.lineWrapping||t!=r||(r="before"==(t=t.ch?et(t.line,"before"==t.sticky?t.ch-1:t.ch,"after"):t).sticky?et(t.line,t.ch+1,"before"):t);for(var o=0;o<5;o++){var l=!1,s=Xr(e,t),a=r&&r!=t?Xr(e,r):s,u=Mn(e,i={left:Math.min(s.left,a.left),top:Math.min(s.top,a.top)-n,right:Math.max(s.left,a.left),bottom:Math.max(s.bottom,a.bottom)+n}),c=e.doc.scrollTop,h=e.doc.scrollLeft;if(null!=u.scrollTop&&(Hn(e,u.scrollTop),Math.abs(e.doc.scrollTop-c)>1&&(l=!0)),null!=u.scrollLeft&&(Pn(e,u.scrollLeft),Math.abs(e.doc.scrollLeft-h)>1&&(l=!0)),!l)break}return i}(t,st(n,e.scrollToPos.from),st(n,e.scrollToPos.to),e.scrollToPos.margin));var i=e.maybeHiddenMarkers,o=e.maybeUnhiddenMarkers;if(i)for(var l=0;l=e.display.viewTo)){var r=+new Date+e.options.workTime,n=dt(e,t.highlightFrontier),i=[];t.iter(n.line,Math.min(t.first+t.size,e.display.viewTo+500),function(o){if(n.line>=e.display.viewFrom){var l=o.styles,s=o.text.length>e.options.maxHighlightLength?Ue(t.mode,n.state):null,a=ht(e,o,n,!0);s&&(n.state=s),o.styles=a.styles;var u=o.styleClasses,c=a.classes;c?o.styleClasses=c:u&&(o.styleClasses=null);for(var h=!l||l.length!=o.styles.length||u!=c&&(!u||!c||u.bgClass!=c.bgClass||u.textClass!=c.textClass),f=0;!h&&fr)return ei(e,e.options.workDelay),!0}),t.highlightFrontier=n.line,t.modeFrontier=Math.max(t.modeFrontier,n.line),i.length&&qn(e,function(){for(var t=0;t=r.viewFrom&&t.visible.to<=r.viewTo&&(null==r.updateLineNumbers||r.updateLineNumbers>=r.viewTo)&&r.renderedView==r.view&&0==dn(e))return!1;ui(e)&&(hn(e),t.dims=rn(e));var i=n.first+n.size,o=Math.max(t.visible.from-e.options.viewportMargin,n.first),l=Math.min(i,t.visible.to+e.options.viewportMargin);r.viewFroml&&r.viewTo-l<20&&(l=Math.min(i,r.viewTo)),Ct&&(o=Rt(e.doc,o),l=Bt(e.doc,l));var s=o!=r.viewFrom||l!=r.viewTo||r.lastWrapHeight!=t.wrapperHeight||r.lastWrapWidth!=t.wrapperWidth;!function(e,t,r){var n=e.display;0==n.view.length||t>=n.viewTo||r<=n.viewFrom?(n.view=ir(e,t,r),n.viewFrom=t):(n.viewFrom>t?n.view=ir(e,t,n.viewFrom).concat(n.view):n.viewFromr&&(n.view=n.view.slice(0,an(e,r)))),n.viewTo=r}(e,o,l),r.viewOffset=Vt(Xe(e.doc,r.viewFrom)),e.display.mover.style.top=r.viewOffset+"px";var u=dn(e);if(!s&&0==u&&!t.force&&r.renderedView==r.view&&(null==r.updateLineNumbers||r.updateLineNumbers>=r.viewTo))return!1;var c=function(e){if(e.hasFocus())return null;var t=W();if(!t||!D(e.display.lineDiv,t))return null;var r={activeElt:t};if(window.getSelection){var n=window.getSelection();n.anchorNode&&n.extend&&D(e.display.lineDiv,n.anchorNode)&&(r.anchorNode=n.anchorNode,r.anchorOffset=n.anchorOffset,r.focusNode=n.focusNode,r.focusOffset=n.focusOffset)}return r}(e);return u>4&&(r.lineDiv.style.display="none"),function(e,t,r){var n=e.display,i=e.options.lineNumbers,o=n.lineDiv,l=o.firstChild;function s(t){var r=t.nextSibling;return a&&y&&e.display.currentWheelTarget==t?t.style.display="none":t.parentNode.removeChild(t),r}for(var u=n.view,c=n.viewFrom,h=0;h-1&&(d=!1),ur(e,f,c,r)),d&&(M(f.lineNumber),f.lineNumber.appendChild(document.createTextNode(Je(e.options,c)))),l=f.node.nextSibling}else{var p=vr(e,f,c,r);o.insertBefore(p,l)}c+=f.size}for(;l;)l=s(l)}(e,r.updateLineNumbers,t.dims),u>4&&(r.lineDiv.style.display=""),r.renderedView=r.view,function(e){if(e&&e.activeElt&&e.activeElt!=W()&&(e.activeElt.focus(),e.anchorNode&&D(document.body,e.anchorNode)&&D(document.body,e.focusNode))){var t=window.getSelection(),r=document.createRange();r.setEnd(e.anchorNode,e.anchorOffset),r.collapse(!1),t.removeAllRanges(),t.addRange(r),t.extend(e.focusNode,e.focusOffset)}}(c),M(r.cursorDiv),M(r.selectionDiv),r.gutters.style.height=r.sizer.style.minHeight=0,s&&(r.lastWrapHeight=t.wrapperHeight,r.lastWrapWidth=t.wrapperWidth,ei(e,400)),r.updateLineNumbers=null,!0}function ii(e,t){for(var r=t.viewport,n=!0;(n&&e.options.lineWrapping&&t.oldDisplayWidth!=Tr(e)||(r&&null!=r.top&&(r={top:Math.min(e.doc.height+Sr(e.display)-Mr(e),r.top)}),t.visible=Tn(e.display,e.doc,r),!(t.visible.from>=e.display.viewFrom&&t.visible.to<=e.display.viewTo)))&&ni(e,t);n=!1){Ln(e);var i=En(e);pn(e),Rn(e,i),si(e,i),t.force=!1}t.signal(e,"update",e),e.display.viewFrom==e.display.reportedViewFrom&&e.display.viewTo==e.display.reportedViewTo||(t.signal(e,"viewportChange",e,e.display.viewFrom,e.display.viewTo),e.display.reportedViewFrom=e.display.viewFrom,e.display.reportedViewTo=e.display.viewTo)}function oi(e,t){var r=new ri(e,t);if(ni(e,r)){Ln(e),ii(e,r);var n=En(e);pn(e),Rn(e,n),si(e,n),r.finish()}}function li(e){var t=e.gutters.offsetWidth;e.sizer.style.marginLeft=t+"px"}function si(e,t){e.display.sizer.style.minHeight=t.docHeight+"px",e.display.heightForcer.style.top=t.docHeight+"px",e.display.gutters.style.height=t.docHeight+e.display.barHeight+kr(e)+"px"}function ai(e){var t=e.display,r=t.view;if(t.alignWidgets||t.gutters.firstChild&&e.options.fixedGutter){for(var n=nn(t)-t.scroller.scrollLeft+e.doc.scrollLeft,i=t.gutters.offsetWidth,o=n+"px",l=0;ls.clientWidth,c=s.scrollHeight>s.clientHeight;if(i&&u||o&&c){if(o&&y&&a)e:for(var f=t.target,d=l.view;f!=s;f=f.parentNode)for(var p=0;p=0&&tt(e,n.to())<=0)return r}return-1};var bi=function(e,t){this.anchor=e,this.head=t};function wi(e,t,r){var n=e&&e.options.selectionsMayTouch,i=t[r];t.sort(function(e,t){return tt(e.from(),t.from())}),r=B(t,i);for(var o=1;o0:a>=0){var u=ot(s.from(),l.from()),c=it(s.to(),l.to()),h=s.empty()?l.from()==l.head:s.from()==s.head;o<=r&&--r,t.splice(--o,2,new bi(h?c:u,h?u:c))}}return new yi(t,r)}function xi(e,t){return new yi([new bi(e,t||e)],0)}function Ci(e){return e.text?et(e.from.line+e.text.length-1,$(e.text).length+(1==e.text.length?e.from.ch:0)):e.to}function Si(e,t){if(tt(e,t.from)<0)return e;if(tt(e,t.to)<=0)return Ci(t);var r=e.line+t.text.length-(t.to.line-t.from.line)-1,n=e.ch;return e.line==t.to.line&&(n+=Ci(t).ch-t.to.ch),et(r,n)}function Li(e,t){for(var r=[],n=0;n1&&e.remove(s.line+1,p-1),e.insert(s.line+1,m)}sr(e,"change",e,t)}function Ai(e,t,r){!function e(n,i,o){if(n.linked)for(var l=0;ls-(e.cm?e.cm.options.historyEventDelay:500)||"*"==t.origin.charAt(0)))&&(o=function(e,t){return t?(Pi(e.done),$(e.done)):e.done.length&&!$(e.done).ranges?$(e.done):e.done.length>1&&!e.done[e.done.length-2].ranges?(e.done.pop(),$(e.done)):void 0}(i,i.lastOp==n)))l=$(o.changes),0==tt(t.from,t.to)&&0==tt(t.from,l.to)?l.to=Ci(t):o.changes.push(Fi(e,t));else{var a=$(i.done);for(a&&a.ranges||zi(e.sel,i.done),o={changes:[Fi(e,t)],generation:i.generation},i.done.push(o);i.done.length>i.undoDepth;)i.done.shift(),i.done[0].ranges||i.done.shift()}i.done.push(r),i.generation=++i.maxGeneration,i.lastModTime=i.lastSelTime=s,i.lastOp=i.lastSelOp=n,i.lastOrigin=i.lastSelOrigin=t.origin,l||ge(e,"historyAdded")}function Ii(e,t,r,n){var i=e.history,o=n&&n.origin;r==i.lastSelOp||o&&i.lastSelOrigin==o&&(i.lastModTime==i.lastSelTime&&i.lastOrigin==o||function(e,t,r,n){var i=t.charAt(0);return"*"==i||"+"==i&&r.ranges.length==n.ranges.length&&r.somethingSelected()==n.somethingSelected()&&new Date-e.history.lastSelTime<=(e.cm?e.cm.options.historyEventDelay:500)}(e,o,$(i.done),t))?i.done[i.done.length-1]=t:zi(t,i.done),i.lastSelTime=+new Date,i.lastSelOrigin=o,i.lastSelOp=r,n&&!1!==n.clearRedo&&Pi(i.undone)}function zi(e,t){var r=$(t);r&&r.ranges&&r.equals(e)||t.push(e)}function Ri(e,t,r,n){var i=t["spans_"+e.id],o=0;e.iter(Math.max(e.first,r),Math.min(e.first+e.size,n),function(r){r.markedSpans&&((i||(i=t["spans_"+e.id]={}))[o]=r.markedSpans),++o})}function Bi(e){if(!e)return null;for(var t,r=0;r-1&&($(s)[h]=u[h],delete u[h])}}}return n}function Vi(e,t,r,n){if(n){var i=e.anchor;if(r){var o=tt(t,i)<0;o!=tt(r,i)<0?(i=t,t=r):o!=tt(t,r)<0&&(t=r)}return new bi(i,t)}return new bi(r||t,t)}function Ki(e,t,r,n,i){null==i&&(i=e.cm&&(e.cm.display.shift||e.extend)),$i(e,new yi([Vi(e.sel.primary(),t,r,i)],0),n)}function ji(e,t,r){for(var n=[],i=e.cm&&(e.cm.display.shift||e.extend),o=0;o=t.ch:s.to>t.ch))){if(i&&(ge(a,"beforeCursorEnter"),a.explicitlyCleared)){if(o.markedSpans){--l;continue}break}if(!a.atomic)continue;if(r){var h=a.find(n<0?1:-1),f=void 0;if((n<0?c:u)&&(h=ro(e,h,-n,h&&h.line==t.line?o:null)),h&&h.line==t.line&&(f=tt(h,r))&&(n<0?f<0:f>0))return eo(e,h,t,n,i)}var d=a.find(n<0?-1:1);return(n<0?u:c)&&(d=ro(e,d,n,d.line==t.line?o:null)),d?eo(e,d,t,n,i):null}}return t}function to(e,t,r,n,i){var o=n||1,l=eo(e,t,r,o,i)||!i&&eo(e,t,r,o,!0)||eo(e,t,r,-o,i)||!i&&eo(e,t,r,-o,!0);return l||(e.cantEdit=!0,et(e.first,0))}function ro(e,t,r,n){return r<0&&0==t.ch?t.line>e.first?st(e,et(t.line-1)):null:r>0&&t.ch==(n||Xe(e,t.line)).text.length?t.line0)){var c=[a,1],h=tt(u.from,s.from),f=tt(u.to,s.to);(h<0||!l.inclusiveLeft&&!h)&&c.push({from:u.from,to:s.from}),(f>0||!l.inclusiveRight&&!f)&&c.push({from:s.to,to:u.to}),i.splice.apply(i,c),a+=c.length-3}}return i}(e,t.from,t.to);if(n)for(var i=n.length-1;i>=0;--i)lo(e,{from:n[i].from,to:n[i].to,text:i?[""]:t.text,origin:t.origin});else lo(e,t)}}function lo(e,t){if(1!=t.text.length||""!=t.text[0]||0!=tt(t.from,t.to)){var r=Li(e,t);Ei(e,t,r,e.cm?e.cm.curOp.id:NaN),uo(e,t,r,Tt(e,t));var n=[];Ai(e,function(e,r){r||-1!=B(n,e.history)||(po(e.history,t),n.push(e.history)),uo(e,t,null,Tt(e,t))})}}function so(e,t,r){var n=e.cm&&e.cm.state.suppressEdits;if(!n||r){for(var i,o=e.history,l=e.sel,s="undo"==t?o.done:o.undone,a="undo"==t?o.undone:o.done,u=0;u=0;--d){var p=f(d);if(p)return p.v}}}}function ao(e,t){if(0!=t&&(e.first+=t,e.sel=new yi(q(e.sel.ranges,function(e){return new bi(et(e.anchor.line+t,e.anchor.ch),et(e.head.line+t,e.head.ch))}),e.sel.primIndex),e.cm)){un(e.cm,e.first,e.first-t,t);for(var r=e.cm.display,n=r.viewFrom;ne.lastLine())){if(t.from.lineo&&(t={from:t.from,to:et(o,Xe(e,o).text.length),text:[t.text[0]],origin:t.origin}),t.removed=Ye(e,t.from,t.to),r||(r=Li(e,t)),e.cm?function(e,t,r){var n=e.doc,i=e.display,o=t.from,l=t.to,s=!1,a=o.line;e.options.lineWrapping||(a=qe(zt(Xe(n,o.line))),n.iter(a,l.line+1,function(e){if(e==i.maxLine)return s=!0,!0}));n.sel.contains(t.from,t.to)>-1&&me(e);Oi(n,t,r,on(e)),e.options.lineWrapping||(n.iter(a,o.line+t.text.length,function(e){var t=Kt(e);t>i.maxLineLength&&(i.maxLine=e,i.maxLineLength=t,i.maxLineChanged=!0,s=!1)}),s&&(e.curOp.updateMaxLine=!0));(function(e,t){if(e.modeFrontier=Math.min(e.modeFrontier,t),!(e.highlightFrontierr;n--){var i=Xe(e,n).stateAfter;if(i&&(!(i instanceof ut)||n+i.lookAhead1||!(this.children[0]instanceof vo))){var s=[];this.collapse(s),this.children=[new vo(s)],this.children[0].parent=this}},collapse:function(e){for(var t=0;t50){for(var l=i.lines.length%25+25,s=l;s10);e.parent.maybeSpill()}},iterN:function(e,t,r){for(var n=0;n0||0==l&&!1!==o.clearWhenEmpty)return o;if(o.replacedWith&&(o.collapsed=!0,o.widgetNode=A("span",[o.replacedWith],"CodeMirror-widget"),n.handleMouseEvents||o.widgetNode.setAttribute("cm-ignore-events","true"),n.insertLeft&&(o.widgetNode.insertLeft=!0)),o.collapsed){if(It(e,t.line,t,r,o)||t.line!=r.line&&It(e,r.line,t,r,o))throw new Error("Inserting collapsed marker partially overlapping an existing one");Ct=!0}o.addToHistory&&Ei(e,{from:t,to:r,origin:"markText"},e.sel,NaN);var s,a=t.line,u=e.cm;if(e.iter(a,r.line+1,function(e){u&&o.collapsed&&!u.options.lineWrapping&&zt(e)==u.display.maxLine&&(s=!0),o.collapsed&&a!=t.line&&$e(e,0),function(e,t){e.markedSpans=e.markedSpans?e.markedSpans.concat([t]):[t],t.marker.attachLine(e)}(e,new St(o,a==t.line?t.ch:null,a==r.line?r.ch:null)),++a}),o.collapsed&&e.iter(t.line,r.line+1,function(t){Gt(e,t)&&$e(t,0)}),o.clearOnEnter&&fe(o,"beforeCursorEnter",function(){return o.clear()}),o.readOnly&&(xt=!0,(e.history.done.length||e.history.undone.length)&&e.clearHistory()),o.collapsed&&(o.id=++wo,o.atomic=!0),u){if(s&&(u.curOp.updateMaxLine=!0),o.collapsed)un(u,t.line,r.line+1);else if(o.className||o.startStyle||o.endStyle||o.css||o.attributes||o.title)for(var c=t.line;c<=r.line;c++)cn(u,c,"text");o.atomic&&Qi(u.doc),sr(u,"markerAdded",u,o)}return o}xo.prototype.clear=function(){if(!this.explicitlyCleared){var e=this.doc.cm,t=e&&!e.curOp;if(t&&Kn(e),ye(this,"clear")){var r=this.find();r&&sr(this,"clear",r.from,r.to)}for(var n=null,i=null,o=0;oe.display.maxLineLength&&(e.display.maxLine=u,e.display.maxLineLength=c,e.display.maxLineChanged=!0)}null!=n&&e&&this.collapsed&&un(e,n,i+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,e&&Qi(e.doc)),e&&sr(e,"markerCleared",e,this,n,i),t&&jn(e),this.parent&&this.parent.clear()}},xo.prototype.find=function(e,t){var r,n;null==e&&"bookmark"==this.type&&(e=1);for(var i=0;i=0;a--)oo(this,n[a]);s?_i(this,s):this.cm&&On(this.cm)}),undo:Jn(function(){so(this,"undo")}),redo:Jn(function(){so(this,"redo")}),undoSelection:Jn(function(){so(this,"undo",!0)}),redoSelection:Jn(function(){so(this,"redo",!0)}),setExtending:function(e){this.extend=e},getExtending:function(){return this.extend},historySize:function(){for(var e=this.history,t=0,r=0,n=0;n=e.ch)&&t.push(i.marker.parent||i.marker)}return t},findMarks:function(e,t,r){e=st(this,e),t=st(this,t);var n=[],i=e.line;return this.iter(e.line,t.line+1,function(o){var l=o.markedSpans;if(l)for(var s=0;s=a.to||null==a.from&&i!=e.line||null!=a.from&&i==t.line&&a.from>=t.ch||r&&!r(a.marker)||n.push(a.marker.parent||a.marker)}++i}),n},getAllMarks:function(){var e=[];return this.iter(function(t){var r=t.markedSpans;if(r)for(var n=0;ne)return t=e,!0;e-=o,++r}),st(this,et(r,t))},indexFromPos:function(e){var t=(e=st(this,e)).ch;if(e.linet&&(t=e.from),null!=e.to&&e.to-1)return t.state.draggingText(e),void setTimeout(function(){return t.display.input.focus()},20);try{var c=e.dataTransfer.getData("Text");if(c){var h;if(t.state.draggingText&&!t.state.draggingText.copy&&(h=t.listSelections()),qi(t.doc,xi(r,r)),h)for(var f=0;f=0;t--)co(e.doc,"",n[t].from,n[t].to,"+delete");On(e)})}function _o(e,t,r){var n=oe(e.text,t+r,r);return n<0||n>e.text.length?null:n}function $o(e,t,r){var n=_o(e,t.ch,r);return null==n?null:new et(t.line,n,r<0?"after":"before")}function qo(e,t,r,n,i){if(e){var o=ce(r,t.doc.direction);if(o){var l,s=i<0?$(o):o[0],a=i<0==(1==s.level)?"after":"before";if(s.level>0||"rtl"==t.doc.direction){var u=Dr(t,r);l=i<0?r.text.length-1:0;var c=Wr(t,u,l).top;l=le(function(e){return Wr(t,u,e).top==c},i<0==(1==s.level)?s.from:s.to-1,l),"before"==a&&(l=_o(r,l,1))}else l=i<0?s.to:s.from;return new et(n,l,a)}}return new et(n,i<0?r.text.length:0,i<0?"before":"after")}Ro.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharAfter",Backspace:"delCharBefore","Shift-Backspace":"delCharBefore",Tab:"defaultTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite",Esc:"singleSelection"},Ro.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Up":"goLineUp","Ctrl-Down":"goLineDown","Ctrl-Left":"goGroupLeft","Ctrl-Right":"goGroupRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delGroupBefore","Ctrl-Delete":"delGroupAfter","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore","Ctrl-U":"undoSelection","Shift-Ctrl-U":"redoSelection","Alt-U":"redoSelection",fallthrough:"basic"},Ro.emacsy={"Ctrl-F":"goCharRight","Ctrl-B":"goCharLeft","Ctrl-P":"goLineUp","Ctrl-N":"goLineDown","Alt-F":"goWordRight","Alt-B":"goWordLeft","Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd","Ctrl-V":"goPageDown","Shift-Ctrl-V":"goPageUp","Ctrl-D":"delCharAfter","Ctrl-H":"delCharBefore","Alt-D":"delWordAfter","Alt-Backspace":"delWordBefore","Ctrl-K":"killLine","Ctrl-T":"transposeChars","Ctrl-O":"openLine"},Ro.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Home":"goDocStart","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineLeft","Cmd-Right":"goLineRight","Alt-Backspace":"delGroupBefore","Ctrl-Alt-Backspace":"delGroupAfter","Alt-Delete":"delGroupAfter","Cmd-S":"save","Cmd-F":"find","Cmd-G":"findNext","Shift-Cmd-G":"findPrev","Cmd-Alt-F":"replace","Shift-Cmd-Alt-F":"replaceAll","Cmd-[":"indentLess","Cmd-]":"indentMore","Cmd-Backspace":"delWrappedLineLeft","Cmd-Delete":"delWrappedLineRight","Cmd-U":"undoSelection","Shift-Cmd-U":"redoSelection","Ctrl-Up":"goDocStart","Ctrl-Down":"goDocEnd",fallthrough:["basic","emacsy"]},Ro.default=y?Ro.macDefault:Ro.pcDefault;var Zo={selectAll:no,singleSelection:function(e){return e.setSelection(e.getCursor("anchor"),e.getCursor("head"),V)},killLine:function(e){return Yo(e,function(t){if(t.empty()){var r=Xe(e.doc,t.head.line).text.length;return t.head.ch==r&&t.head.line0)i=new et(i.line,i.ch+1),e.replaceRange(o.charAt(i.ch-1)+o.charAt(i.ch-2),et(i.line,i.ch-2),i,"+transpose");else if(i.line>e.doc.first){var l=Xe(e.doc,i.line-1).text;l&&(i=new et(i.line,1),e.replaceRange(o.charAt(0)+e.doc.lineSeparator()+l.charAt(l.length-1),et(i.line-1,l.length-1),i,"+transpose"))}r.push(new bi(i,i))}e.setSelections(r)})},newlineAndIndent:function(e){return qn(e,function(){for(var t=e.listSelections(),r=t.length-1;r>=0;r--)e.replaceRange(e.doc.lineSeparator(),t[r].anchor,t[r].head,"+input");t=e.listSelections();for(var n=0;n-1&&(tt((i=u.ranges[i]).from(),t)<0||t.xRel>0)&&(tt(i.to(),t)>0||t.xRel<0)?function(e,t,r,n){var i=e.display,o=!1,u=Zn(e,function(t){a&&(i.scroller.draggable=!1),e.state.draggingText=!1,pe(i.wrapper.ownerDocument,"mouseup",u),pe(i.wrapper.ownerDocument,"mousemove",c),pe(i.scroller,"dragstart",h),pe(i.scroller,"drop",u),o||(we(t),n.addNew||Ki(e.doc,r,null,null,n.extend),a||l&&9==s?setTimeout(function(){i.wrapper.ownerDocument.body.focus(),i.input.focus()},20):i.input.focus())}),c=function(e){o=o||Math.abs(t.clientX-e.clientX)+Math.abs(t.clientY-e.clientY)>=10},h=function(){return o=!0};a&&(i.scroller.draggable=!0);e.state.draggingText=u,u.copy=!n.moveOnDrag,i.scroller.dragDrop&&i.scroller.dragDrop();fe(i.wrapper.ownerDocument,"mouseup",u),fe(i.wrapper.ownerDocument,"mousemove",c),fe(i.scroller,"dragstart",h),fe(i.scroller,"drop",u),xn(e),setTimeout(function(){return i.input.focus()},20)}(e,n,t,o):function(e,t,r,n){var i=e.display,o=e.doc;we(t);var l,s,a=o.sel,u=a.ranges;n.addNew&&!n.extend?(s=o.sel.contains(r),l=s>-1?u[s]:new bi(r,r)):(l=o.sel.primary(),s=o.sel.primIndex);if("rectangle"==n.unit)n.addNew||(l=new bi(r,r)),r=sn(e,t,!0,!0),s=-1;else{var c=dl(e,r,n.unit);l=n.extend?Vi(l,c.anchor,c.head,n.extend):c}n.addNew?-1==s?(s=u.length,$i(o,wi(e,u.concat([l]),s),{scroll:!1,origin:"*mouse"})):u.length>1&&u[s].empty()&&"char"==n.unit&&!n.extend?($i(o,wi(e,u.slice(0,s).concat(u.slice(s+1)),0),{scroll:!1,origin:"*mouse"}),a=o.sel):Xi(o,s,l,K):(s=0,$i(o,new yi([l],0),K),a=o.sel);var h=r;function f(t){if(0!=tt(h,t))if(h=t,"rectangle"==n.unit){for(var i=[],u=e.options.tabSize,c=z(Xe(o,r.line).text,r.ch,u),f=z(Xe(o,t.line).text,t.ch,u),d=Math.min(c,f),p=Math.max(c,f),g=Math.min(r.line,t.line),v=Math.min(e.lastLine(),Math.max(r.line,t.line));g<=v;g++){var m=Xe(o,g).text,y=X(m,d,u);d==p?i.push(new bi(et(g,y),et(g,y))):m.length>y&&i.push(new bi(et(g,y),et(g,X(m,p,u))))}i.length||i.push(new bi(r,r)),$i(o,wi(e,a.ranges.slice(0,s).concat(i),s),{origin:"*mouse",scroll:!1}),e.scrollIntoView(t)}else{var b,w=l,x=dl(e,t,n.unit),C=w.anchor;tt(x.anchor,C)>0?(b=x.head,C=ot(w.from(),x.anchor)):(b=x.anchor,C=it(w.to(),x.head));var S=a.ranges.slice(0);S[s]=function(e,t){var r=t.anchor,n=t.head,i=Xe(e.doc,r.line);if(0==tt(r,n)&&r.sticky==n.sticky)return t;var o=ce(i);if(!o)return t;var l=ae(o,r.ch,r.sticky),s=o[l];if(s.from!=r.ch&&s.to!=r.ch)return t;var a,u=l+(s.from==r.ch==(1!=s.level)?0:1);if(0==u||u==o.length)return t;if(n.line!=r.line)a=(n.line-r.line)*("ltr"==e.doc.direction?1:-1)>0;else{var c=ae(o,n.ch,n.sticky),h=c-l||(n.ch-r.ch)*(1==s.level?-1:1);a=c==u-1||c==u?h<0:h>0}var f=o[u+(a?-1:0)],d=a==(1==f.level),p=d?f.from:f.to,g=d?"after":"before";return r.ch==p&&r.sticky==g?t:new bi(new et(r.line,p,g),n)}(e,new bi(st(o,C),b)),$i(o,wi(e,S,s),K)}}var d=i.wrapper.getBoundingClientRect(),p=0;function g(t){e.state.selectingText=!1,p=1/0,t&&(we(t),i.input.focus()),pe(i.wrapper.ownerDocument,"mousemove",v),pe(i.wrapper.ownerDocument,"mouseup",m),o.history.lastSelOrigin=null}var v=Zn(e,function(t){0!==t.buttons&&ke(t)?function t(r){var l=++p;var s=sn(e,r,!0,"rectangle"==n.unit);if(!s)return;if(0!=tt(s,h)){e.curOp.focus=W(),f(s);var a=Tn(i,o);(s.line>=a.to||s.lined.bottom?20:0;u&&setTimeout(Zn(e,function(){p==l&&(i.scroller.scrollTop+=u,t(r))}),50)}}(t):g(t)}),m=Zn(e,g);e.state.selectingText=m,fe(i.wrapper.ownerDocument,"mousemove",v),fe(i.wrapper.ownerDocument,"mouseup",m)}(e,n,t,o)}(t,n,o,e):Le(e)==r.scroller&&we(e):2==i?(n&&Ki(t.doc,n),setTimeout(function(){return r.input.focus()},20)):3==i&&(S?t.display.input.onContextMenu(e):xn(t)))}}function dl(e,t,r){if("char"==r)return new bi(t,t);if("word"==r)return e.findWordAt(t);if("line"==r)return new bi(et(t.line,0),st(e.doc,et(t.line+1,0)));var n=r(e,t);return new bi(n.from,n.to)}function pl(e,t,r,n){var i,o;if(t.touches)i=t.touches[0].clientX,o=t.touches[0].clientY;else try{i=t.clientX,o=t.clientY}catch(t){return!1}if(i>=Math.floor(e.display.gutters.getBoundingClientRect().right))return!1;n&&we(t);var l=e.display,s=l.lineDiv.getBoundingClientRect();if(o>s.bottom||!ye(e,r))return Ce(t);o-=s.top-l.viewOffset;for(var a=0;a=i)return ge(e,r,e,Ze(e.doc,o),e.display.gutterSpecs[a].className,t),Ce(t)}}function gl(e,t){return pl(e,t,"gutterClick",!0)}function vl(e,t){xr(e.display,t)||function(e,t){if(!ye(e,"gutterContextMenu"))return!1;return pl(e,t,"gutterContextMenu",!1)}(e,t)||ve(e,t,"contextmenu")||S||e.display.input.onContextMenu(t)}function ml(e){e.display.wrapper.className=e.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+e.options.theme.replace(/(^|\s)\s*/g," cm-s-"),Rr(e)}hl.prototype.compare=function(e,t,r){return this.time+400>e&&0==tt(t,this.pos)&&r==this.button};var yl={toString:function(){return"CodeMirror.Init"}},bl={},wl={};function xl(e,t,r){if(!t!=!(r&&r!=yl)){var n=e.display.dragFunctions,i=t?fe:pe;i(e.display.scroller,"dragstart",n.start),i(e.display.scroller,"dragenter",n.enter),i(e.display.scroller,"dragover",n.over),i(e.display.scroller,"dragleave",n.leave),i(e.display.scroller,"drop",n.drop)}}function Cl(e){e.options.lineWrapping?(H(e.display.wrapper,"CodeMirror-wrap"),e.display.sizer.style.minWidth="",e.display.sizerWidth=null):(T(e.display.wrapper,"CodeMirror-wrap"),jt(e)),ln(e),un(e),Rr(e),setTimeout(function(){return Rn(e)},100)}function Sl(e,t){var n=this;if(!(this instanceof Sl))return new Sl(e,t);this.options=t=t?I(t):{},I(bl,t,!1);var i=t.value;"string"==typeof i?i=new Mo(i,t.mode,null,t.lineSeparator,t.direction):t.mode&&(i.modeOption=t.mode),this.doc=i;var o=new Sl.inputStyles[t.inputStyle](this),u=this.display=new function(e,t,n,i){var o=this;this.input=n,o.scrollbarFiller=O("div",null,"CodeMirror-scrollbar-filler"),o.scrollbarFiller.setAttribute("cm-not-content","true"),o.gutterFiller=O("div",null,"CodeMirror-gutter-filler"),o.gutterFiller.setAttribute("cm-not-content","true"),o.lineDiv=A("div",null,"CodeMirror-code"),o.selectionDiv=O("div",null,null,"position: relative; z-index: 1"),o.cursorDiv=O("div",null,"CodeMirror-cursors"),o.measure=O("div",null,"CodeMirror-measure"),o.lineMeasure=O("div",null,"CodeMirror-measure"),o.lineSpace=A("div",[o.measure,o.lineMeasure,o.selectionDiv,o.cursorDiv,o.lineDiv],null,"position: relative; outline: none");var u=A("div",[o.lineSpace],"CodeMirror-lines");o.mover=O("div",[u],null,"position: relative"),o.sizer=O("div",[o.mover],"CodeMirror-sizer"),o.sizerWidth=null,o.heightForcer=O("div",null,null,"position: absolute; height: "+G+"px; width: 1px;"),o.gutters=O("div",null,"CodeMirror-gutters"),o.lineGutter=null,o.scroller=O("div",[o.sizer,o.heightForcer,o.gutters],"CodeMirror-scroll"),o.scroller.setAttribute("tabIndex","-1"),o.wrapper=O("div",[o.scrollbarFiller,o.gutterFiller,o.scroller],"CodeMirror"),l&&s<8&&(o.gutters.style.zIndex=-1,o.scroller.style.paddingRight=0),a||r&&m||(o.scroller.draggable=!0),e&&(e.appendChild?e.appendChild(o.wrapper):e(o.wrapper)),o.viewFrom=o.viewTo=t.first,o.reportedViewFrom=o.reportedViewTo=t.first,o.view=[],o.renderedView=null,o.externalMeasured=null,o.viewOffset=0,o.lastWrapHeight=o.lastWrapWidth=0,o.updateLineNumbers=null,o.nativeBarWidth=o.barHeight=o.barWidth=0,o.scrollbarsClipped=!1,o.lineNumWidth=o.lineNumInnerWidth=o.lineNumChars=null,o.alignWidgets=!1,o.cachedCharWidth=o.cachedTextHeight=o.cachedPaddingH=null,o.maxLine=null,o.maxLineLength=0,o.maxLineChanged=!1,o.wheelDX=o.wheelDY=o.wheelStartX=o.wheelStartY=null,o.shift=!1,o.selForContextMenu=null,o.activeTouch=null,o.gutterSpecs=ci(i.gutters,i.lineNumbers),hi(o),n.init(o)}(e,i,o,t);for(var c in u.wrapper.CodeMirror=this,ml(this),t.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap"),Un(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,delayingBlurEvent:!1,focused:!1,suppressEdits:!1,pasteIncoming:-1,cutIncoming:-1,selectingText:!1,draggingText:!1,highlight:new R,keySeq:null,specialChars:null},t.autofocus&&!m&&u.input.focus(),l&&s<11&&setTimeout(function(){return n.display.input.reset(!0)},20),function(e){var t=e.display;fe(t.scroller,"mousedown",Zn(e,fl)),fe(t.scroller,"dblclick",l&&s<11?Zn(e,function(t){if(!ve(e,t)){var r=sn(e,t);if(r&&!gl(e,t)&&!xr(e.display,t)){we(t);var n=e.findWordAt(r);Ki(e.doc,n.anchor,n.head)}}}):function(t){return ve(e,t)||we(t)});fe(t.scroller,"contextmenu",function(t){return vl(e,t)});var r,n={end:0};function i(){t.activeTouch&&(r=setTimeout(function(){return t.activeTouch=null},1e3),(n=t.activeTouch).end=+new Date)}function o(e,t){if(null==t.left)return!0;var r=t.left-e.left,n=t.top-e.top;return r*r+n*n>400}fe(t.scroller,"touchstart",function(i){if(!ve(e,i)&&!function(e){if(1!=e.touches.length)return!1;var t=e.touches[0];return t.radiusX<=1&&t.radiusY<=1}(i)&&!gl(e,i)){t.input.ensurePolled(),clearTimeout(r);var o=+new Date;t.activeTouch={start:o,moved:!1,prev:o-n.end<=300?n:null},1==i.touches.length&&(t.activeTouch.left=i.touches[0].pageX,t.activeTouch.top=i.touches[0].pageY)}}),fe(t.scroller,"touchmove",function(){t.activeTouch&&(t.activeTouch.moved=!0)}),fe(t.scroller,"touchend",function(r){var n=t.activeTouch;if(n&&!xr(t,r)&&null!=n.left&&!n.moved&&new Date-n.start<300){var l,s=e.coordsChar(t.activeTouch,"page");l=!n.prev||o(n,n.prev)?new bi(s,s):!n.prev.prev||o(n,n.prev.prev)?e.findWordAt(s):new bi(et(s.line,0),st(e.doc,et(s.line+1,0))),e.setSelection(l.anchor,l.head),e.focus(),we(r)}i()}),fe(t.scroller,"touchcancel",i),fe(t.scroller,"scroll",function(){t.scroller.clientHeight&&(Hn(e,t.scroller.scrollTop),Pn(e,t.scroller.scrollLeft,!0),ge(e,"scroll",e))}),fe(t.scroller,"mousewheel",function(t){return mi(e,t)}),fe(t.scroller,"DOMMouseScroll",function(t){return mi(e,t)}),fe(t.wrapper,"scroll",function(){return t.wrapper.scrollTop=t.wrapper.scrollLeft=0}),t.dragFunctions={enter:function(t){ve(e,t)||Se(t)},over:function(t){ve(e,t)||(!function(e,t){var r=sn(e,t);if(r){var n=document.createDocumentFragment();vn(e,r,n),e.display.dragCursor||(e.display.dragCursor=O("div",null,"CodeMirror-cursors CodeMirror-dragcursors"),e.display.lineSpace.insertBefore(e.display.dragCursor,e.display.cursorDiv)),N(e.display.dragCursor,n)}}(e,t),Se(t))},start:function(t){return function(e,t){if(l&&(!e.state.draggingText||+new Date-No<100))Se(t);else if(!ve(e,t)&&!xr(e.display,t)&&(t.dataTransfer.setData("Text",e.getSelection()),t.dataTransfer.effectAllowed="copyMove",t.dataTransfer.setDragImage&&!f)){var r=O("img",null,null,"position: fixed; left: 0; top: 0;");r.src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",h&&(r.width=r.height=1,e.display.wrapper.appendChild(r),r._top=r.offsetTop),t.dataTransfer.setDragImage(r,0,0),h&&r.parentNode.removeChild(r)}}(e,t)},drop:Zn(e,Oo),leave:function(t){ve(e,t)||Ao(e)}};var a=t.input.getField();fe(a,"keyup",function(t){return sl.call(e,t)}),fe(a,"keydown",Zn(e,ll)),fe(a,"keypress",Zn(e,al)),fe(a,"focus",function(t){return Cn(e,t)}),fe(a,"blur",function(t){return Sn(e,t)})}(this),Ho(),Kn(this),this.curOp.forceUpdate=!0,Di(this,i),t.autofocus&&!m||this.hasFocus()?setTimeout(E(Cn,this),20):Sn(this),wl)wl.hasOwnProperty(c)&&wl[c](n,t[c],yl);ui(this),t.finishInit&&t.finishInit(this);for(var d=0;d150)){if(!n)return;r="prev"}}else u=0,r="not";"prev"==r?u=t>o.first?z(Xe(o,t-1).text,null,l):0:"add"==r?u=a+e.options.indentUnit:"subtract"==r?u=a-e.options.indentUnit:"number"==typeof r&&(u=a+r),u=Math.max(0,u);var h="",f=0;if(e.options.indentWithTabs)for(var d=Math.floor(u/l);d;--d)f+=l,h+="\t";if(fl,a=We(t),u=null;if(s&&n.ranges.length>1)if(Tl&&Tl.text.join("\n")==t){if(n.ranges.length%Tl.text.length==0){u=[];for(var c=0;c=0;f--){var d=n.ranges[f],p=d.from(),g=d.to();d.empty()&&(r&&r>0?p=et(p.line,p.ch-r):e.state.overwrite&&!s?g=et(g.line,Math.min(Xe(o,g.line).text.length,g.ch+$(a).length)):s&&Tl&&Tl.lineWise&&Tl.text.join("\n")==t&&(p=g=et(p.line,0)));var v={from:p,to:g,text:u?u[f%u.length]:a,origin:i||(s?"paste":e.state.cutIncoming>l?"cut":"+input")};oo(e.doc,v),sr(e,"inputRead",e,v)}t&&!s&&Al(e,t),On(e),e.curOp.updateInput<2&&(e.curOp.updateInput=h),e.curOp.typing=!0,e.state.pasteIncoming=e.state.cutIncoming=-1}function Ol(e,t){var r=e.clipboardData&&e.clipboardData.getData("Text");if(r)return e.preventDefault(),t.isReadOnly()||t.options.disableInput||qn(t,function(){return Nl(t,r,0,null,"paste")}),!0}function Al(e,t){if(e.options.electricChars&&e.options.smartIndent)for(var r=e.doc.sel,n=r.ranges.length-1;n>=0;n--){var i=r.ranges[n];if(!(i.head.ch>100||n&&r.ranges[n-1].head.line==i.head.line)){var o=e.getModeAt(i.head),l=!1;if(o.electricChars){for(var s=0;s-1){l=kl(e,i.head.line,"smart");break}}else o.electricInput&&o.electricInput.test(Xe(e.doc,i.head.line).text.slice(0,i.head.ch))&&(l=kl(e,i.head.line,"smart"));l&&sr(e,"electricInput",e,i.head.line)}}}function Dl(e){for(var t=[],r=[],n=0;n=t.text.length?(r.ch=t.text.length,r.sticky="before"):r.ch<=0&&(r.ch=0,r.sticky="after");var o=ae(i,r.ch,r.sticky),l=i[o];if("ltr"==e.doc.direction&&l.level%2==0&&(n>0?l.to>r.ch:l.from=l.from&&f>=c.begin)){var d=h?"before":"after";return new et(r.line,f,d)}}var p=function(e,t,n){for(var o=function(e,t){return t?new et(r.line,a(e,1),"before"):new et(r.line,e,"after")};e>=0&&e0==(1!=l.level),u=s?n.begin:a(n.end,-1);if(l.from<=u&&u0?c.end:a(c.begin,-1);return null==v||n>0&&v==t.text.length||!(g=p(n>0?0:i.length-1,n,u(v)))?null:g}(e.cm,s,t,r):$o(s,t,r))){if(n||(l=t.line+r)=e.first+e.size||(t=new et(l,t.ch,t.sticky),!(s=Xe(e,l))))return!1;t=qo(i,e.cm,s,t.line,r)}else t=o;return!0}if("char"==n)a();else if("column"==n)a(!0);else if("word"==n||"group"==n)for(var u=null,c="group"==n,h=e.cm&&e.cm.getHelper(t,"wordChars"),f=!0;!(r<0)||a(!f);f=!1){var d=s.text.charAt(t.ch)||"\n",p=te(d,h)?"w":c&&"\n"==d?"n":!c||/\s/.test(d)?null:"p";if(!c||f||p||(p="s"),u&&u!=p){r<0&&(r=1,a(),t.sticky="after");break}if(p&&(u=p),r>0&&!a(!f))break}var g=to(e,t,o,l,!0);return rt(o,g)&&(g.hitSide=!0),g}function Pl(e,t,r,n){var i,o,l=e.doc,s=t.left;if("page"==n){var a=Math.min(e.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight),u=Math.max(a-.5*en(e.display),3);i=(r>0?t.bottom:t.top)+r*u}else"line"==n&&(i=r>0?t.bottom+3:t.top-3);for(;(o=$r(e,s,i)).outside;){if(r<0?i<=0:i>=l.height){o.hitSide=!0;break}i+=5*r}return o}var El=function(e){this.cm=e,this.lastAnchorNode=this.lastAnchorOffset=this.lastFocusNode=this.lastFocusOffset=null,this.polling=new R,this.composing=null,this.gracePeriod=!1,this.readDOMTimeout=null};function Il(e,t){var r=Ar(e,t.line);if(!r||r.hidden)return null;var n=Xe(e.doc,t.line),i=Nr(r,n,t.line),o=ce(n,e.doc.direction),l="left";o&&(l=ae(o,t.ch)%2?"right":"left");var s=Pr(i.map,t.ch,l);return s.offset="right"==s.collapse?s.end:s.start,s}function zl(e,t){return t&&(e.bad=!0),e}function Rl(e,t,r){var n;if(t==e.display.lineDiv){if(!(n=e.display.lineDiv.childNodes[r]))return zl(e.clipPos(et(e.display.viewTo-1)),!0);t=null,r=0}else for(n=t;;n=n.parentNode){if(!n||n==e.display.lineDiv)return null;if(n.parentNode&&n.parentNode==e.display.lineDiv)break}for(var i=0;i=t.display.viewTo||o.line=t.display.viewFrom&&Il(t,i)||{node:a[0].measure.map[2],offset:0},c=o.linen.firstLine()&&(l=et(l.line-1,Xe(n.doc,l.line-1).length)),s.ch==Xe(n.doc,s.line).text.length&&s.linei.viewTo-1)return!1;l.line==i.viewFrom||0==(e=an(n,l.line))?(t=qe(i.view[0].line),r=i.view[0].node):(t=qe(i.view[e].line),r=i.view[e-1].node.nextSibling);var a,u,c=an(n,s.line);if(c==i.view.length-1?(a=i.viewTo-1,u=i.lineDiv.lastChild):(a=qe(i.view[c+1].line)-1,u=i.view[c+1].node.previousSibling),!r)return!1;for(var h=n.doc.splitLines(function(e,t,r,n,i){var o="",l=!1,s=e.doc.lineSeparator(),a=!1;function u(){l&&(o+=s,a&&(o+=s),l=a=!1)}function c(e){e&&(u(),o+=e)}function h(t){if(1==t.nodeType){var r=t.getAttribute("cm-text");if(r)return void c(r);var o,f=t.getAttribute("cm-marker");if(f){var d=e.findMarks(et(n,0),et(i+1,0),(v=+f,function(e){return e.id==v}));return void(d.length&&(o=d[0].find(0))&&c(Ye(e.doc,o.from,o.to).join(s)))}if("false"==t.getAttribute("contenteditable"))return;var p=/^(pre|div|p|li|table|br)$/i.test(t.nodeName);if(!/^br$/i.test(t.nodeName)&&0==t.textContent.length)return;p&&u();for(var g=0;g1&&f.length>1;)if($(h)==$(f))h.pop(),f.pop(),a--;else{if(h[0]!=f[0])break;h.shift(),f.shift(),t++}for(var d=0,p=0,g=h[0],v=f[0],m=Math.min(g.length,v.length);dl.ch&&y.charCodeAt(y.length-p-1)==b.charCodeAt(b.length-p-1);)d--,p++;h[h.length-1]=y.slice(0,y.length-p).replace(/^\u200b+/,""),h[0]=h[0].slice(d).replace(/\u200b+$/,"");var x=et(t,d),C=et(a,f.length?$(f).length-p:0);return h.length>1||h[0]||tt(x,C)?(co(n.doc,h,x,C,"+input"),!0):void 0},El.prototype.ensurePolled=function(){this.forceCompositionEnd()},El.prototype.reset=function(){this.forceCompositionEnd()},El.prototype.forceCompositionEnd=function(){this.composing&&(clearTimeout(this.readDOMTimeout),this.composing=null,this.updateFromDOM(),this.div.blur(),this.div.focus())},El.prototype.readFromDOMSoon=function(){var e=this;null==this.readDOMTimeout&&(this.readDOMTimeout=setTimeout(function(){if(e.readDOMTimeout=null,e.composing){if(!e.composing.done)return;e.composing=null}e.updateFromDOM()},80))},El.prototype.updateFromDOM=function(){var e=this;!this.cm.isReadOnly()&&this.pollContent()||qn(this.cm,function(){return un(e.cm)})},El.prototype.setUneditable=function(e){e.contentEditable="false"},El.prototype.onKeyPress=function(e){0==e.charCode||this.composing||(e.preventDefault(),this.cm.isReadOnly()||Zn(this.cm,Nl)(this.cm,String.fromCharCode(null==e.charCode?e.keyCode:e.charCode),0))},El.prototype.readOnlyChanged=function(e){this.div.contentEditable=String("nocursor"!=e)},El.prototype.onContextMenu=function(){},El.prototype.resetPosition=function(){},El.prototype.needsContentAttribute=!0;var Gl=function(e){this.cm=e,this.prevInput="",this.pollingFast=!1,this.polling=new R,this.hasSelection=!1,this.composing=null};Gl.prototype.init=function(e){var t=this,r=this,n=this.cm;this.createField(e);var i=this.textarea;function o(e){if(!ve(n,e)){if(n.somethingSelected())Ml({lineWise:!1,text:n.getSelections()});else{if(!n.options.lineWiseCopyCut)return;var t=Dl(n);Ml({lineWise:!0,text:t.text}),"cut"==e.type?n.setSelections(t.ranges,null,V):(r.prevInput="",i.value=t.text.join("\n"),P(i))}"cut"==e.type&&(n.state.cutIncoming=+new Date)}}e.wrapper.insertBefore(this.wrapper,e.wrapper.firstChild),g&&(i.style.width="0px"),fe(i,"input",function(){l&&s>=9&&t.hasSelection&&(t.hasSelection=null),r.poll()}),fe(i,"paste",function(e){ve(n,e)||Ol(e,n)||(n.state.pasteIncoming=+new Date,r.fastPoll())}),fe(i,"cut",o),fe(i,"copy",o),fe(e.scroller,"paste",function(t){if(!xr(e,t)&&!ve(n,t)){if(!i.dispatchEvent)return n.state.pasteIncoming=+new Date,void r.focus();var o=new Event("paste");o.clipboardData=t.clipboardData,i.dispatchEvent(o)}}),fe(e.lineSpace,"selectstart",function(t){xr(e,t)||we(t)}),fe(i,"compositionstart",function(){var e=n.getCursor("from");r.composing&&r.composing.range.clear(),r.composing={start:e,range:n.markText(e,n.getCursor("to"),{className:"CodeMirror-composing"})}}),fe(i,"compositionend",function(){r.composing&&(r.poll(),r.composing.range.clear(),r.composing=null)})},Gl.prototype.createField=function(e){this.wrapper=Hl(),this.textarea=this.wrapper.firstChild},Gl.prototype.prepareSelection=function(){var e=this.cm,t=e.display,r=e.doc,n=gn(e);if(e.options.moveInputWithCursor){var i=Xr(e,r.sel.primary().head,"div"),o=t.wrapper.getBoundingClientRect(),l=t.lineDiv.getBoundingClientRect();n.teTop=Math.max(0,Math.min(t.wrapper.clientHeight-10,i.top+l.top-o.top)),n.teLeft=Math.max(0,Math.min(t.wrapper.clientWidth-10,i.left+l.left-o.left))}return n},Gl.prototype.showSelection=function(e){var t=this.cm.display;N(t.cursorDiv,e.cursors),N(t.selectionDiv,e.selection),null!=e.teTop&&(this.wrapper.style.top=e.teTop+"px",this.wrapper.style.left=e.teLeft+"px")},Gl.prototype.reset=function(e){if(!this.contextMenuPending&&!this.composing){var t=this.cm;if(t.somethingSelected()){this.prevInput="";var r=t.getSelection();this.textarea.value=r,t.state.focused&&P(this.textarea),l&&s>=9&&(this.hasSelection=r)}else e||(this.prevInput=this.textarea.value="",l&&s>=9&&(this.hasSelection=null))}},Gl.prototype.getField=function(){return this.textarea},Gl.prototype.supportsTouch=function(){return!1},Gl.prototype.focus=function(){if("nocursor"!=this.cm.options.readOnly&&(!m||W()!=this.textarea))try{this.textarea.focus()}catch(e){}},Gl.prototype.blur=function(){this.textarea.blur()},Gl.prototype.resetPosition=function(){this.wrapper.style.top=this.wrapper.style.left=0},Gl.prototype.receivedFocus=function(){this.slowPoll()},Gl.prototype.slowPoll=function(){var e=this;this.pollingFast||this.polling.set(this.cm.options.pollInterval,function(){e.poll(),e.cm.state.focused&&e.slowPoll()})},Gl.prototype.fastPoll=function(){var e=!1,t=this;t.pollingFast=!0,t.polling.set(20,function r(){t.poll()||e?(t.pollingFast=!1,t.slowPoll()):(e=!0,t.polling.set(60,r))})},Gl.prototype.poll=function(){var e=this,t=this.cm,r=this.textarea,n=this.prevInput;if(this.contextMenuPending||!t.state.focused||He(r)&&!n&&!this.composing||t.isReadOnly()||t.options.disableInput||t.state.keySeq)return!1;var i=r.value;if(i==n&&!t.somethingSelected())return!1;if(l&&s>=9&&this.hasSelection===i||y&&/[\uf700-\uf7ff]/.test(i))return t.display.input.reset(),!1;if(t.doc.sel==t.display.selForContextMenu){var o=i.charCodeAt(0);if(8203!=o||n||(n="​"),8666==o)return this.reset(),this.cm.execCommand("undo")}for(var a=0,u=Math.min(n.length,i.length);a1e3||i.indexOf("\n")>-1?r.value=e.prevInput="":e.prevInput=i,e.composing&&(e.composing.range.clear(),e.composing.range=t.markText(e.composing.start,t.getCursor("to"),{className:"CodeMirror-composing"}))}),!0},Gl.prototype.ensurePolled=function(){this.pollingFast&&this.poll()&&(this.pollingFast=!1)},Gl.prototype.onKeyPress=function(){l&&s>=9&&(this.hasSelection=null),this.fastPoll()},Gl.prototype.onContextMenu=function(e){var t=this,r=t.cm,n=r.display,i=t.textarea;t.contextMenuPending&&t.contextMenuPending();var o=sn(r,e),u=n.scroller.scrollTop;if(o&&!h){r.options.resetSelectionOnContextMenu&&-1==r.doc.sel.contains(o)&&Zn(r,$i)(r.doc,xi(o),V);var c,f=i.style.cssText,d=t.wrapper.style.cssText,p=t.wrapper.offsetParent.getBoundingClientRect();if(t.wrapper.style.cssText="position: static",i.style.cssText="position: absolute; width: 30px; height: 30px;\n top: "+(e.clientY-p.top-5)+"px; left: "+(e.clientX-p.left-5)+"px;\n z-index: 1000; background: "+(l?"rgba(255, 255, 255, .05)":"transparent")+";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);",a&&(c=window.scrollY),n.input.focus(),a&&window.scrollTo(null,c),n.input.reset(),r.somethingSelected()||(i.value=t.prevInput=" "),t.contextMenuPending=m,n.selForContextMenu=r.doc.sel,clearTimeout(n.detectingSelectAll),l&&s>=9&&v(),S){Se(e);var g=function(){pe(window,"mouseup",g),setTimeout(m,20)};fe(window,"mouseup",g)}else setTimeout(m,50)}function v(){if(null!=i.selectionStart){var e=r.somethingSelected(),o="​"+(e?i.value:"");i.value="⇚",i.value=o,t.prevInput=e?"":"​",i.selectionStart=1,i.selectionEnd=o.length,n.selForContextMenu=r.doc.sel}}function m(){if(t.contextMenuPending==m&&(t.contextMenuPending=!1,t.wrapper.style.cssText=d,i.style.cssText=f,l&&s<9&&n.scrollbars.setScrollTop(n.scroller.scrollTop=u),null!=i.selectionStart)){(!l||l&&s<9)&&v();var e=0,o=function(){n.selForContextMenu==r.doc.sel&&0==i.selectionStart&&i.selectionEnd>0&&"​"==t.prevInput?Zn(r,no)(r):e++<10?n.detectingSelectAll=setTimeout(o,500):(n.selForContextMenu=null,n.input.reset())};n.detectingSelectAll=setTimeout(o,200)}}},Gl.prototype.readOnlyChanged=function(e){e||this.reset(),this.textarea.disabled="nocursor"==e},Gl.prototype.setUneditable=function(){},Gl.prototype.needsContentAttribute=!1,function(e){var t=e.optionHandlers;function r(r,n,i,o){e.defaults[r]=n,i&&(t[r]=o?function(e,t,r){r!=yl&&i(e,t,r)}:i)}e.defineOption=r,e.Init=yl,r("value","",function(e,t){return e.setValue(t)},!0),r("mode",null,function(e,t){e.doc.modeOption=t,Ti(e)},!0),r("indentUnit",2,Ti,!0),r("indentWithTabs",!1),r("smartIndent",!0),r("tabSize",4,function(e){Mi(e),Rr(e),un(e)},!0),r("lineSeparator",null,function(e,t){if(e.doc.lineSep=t,t){var r=[],n=e.doc.first;e.doc.iter(function(e){for(var i=0;;){var o=e.text.indexOf(t,i);if(-1==o)break;i=o+t.length,r.push(et(n,o))}n++});for(var i=r.length-1;i>=0;i--)co(e.doc,t,r[i],et(r[i].line,r[i].ch+t.length))}}),r("specialChars",/[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g,function(e,t,r){e.state.specialChars=new RegExp(t.source+(t.test("\t")?"":"|\t"),"g"),r!=yl&&e.refresh()}),r("specialCharPlaceholder",Qt,function(e){return e.refresh()},!0),r("electricChars",!0),r("inputStyle",m?"contenteditable":"textarea",function(){throw new Error("inputStyle can not (yet) be changed in a running editor")},!0),r("spellcheck",!1,function(e,t){return e.getInputField().spellcheck=t},!0),r("autocorrect",!1,function(e,t){return e.getInputField().autocorrect=t},!0),r("autocapitalize",!1,function(e,t){return e.getInputField().autocapitalize=t},!0),r("rtlMoveVisually",!w),r("wholeLineUpdateBefore",!0),r("theme","default",function(e){ml(e),fi(e)},!0),r("keyMap","default",function(e,t,r){var n=Xo(t),i=r!=yl&&Xo(r);i&&i.detach&&i.detach(e,n),n.attach&&n.attach(e,i||null)}),r("extraKeys",null),r("configureMouse",null),r("lineWrapping",!1,Cl,!0),r("gutters",[],function(e,t){e.display.gutterSpecs=ci(t,e.options.lineNumbers),fi(e)},!0),r("fixedGutter",!0,function(e,t){e.display.gutters.style.left=t?nn(e.display)+"px":"0",e.refresh()},!0),r("coverGutterNextToScrollbar",!1,function(e){return Rn(e)},!0),r("scrollbarStyle","native",function(e){Un(e),Rn(e),e.display.scrollbars.setScrollTop(e.doc.scrollTop),e.display.scrollbars.setScrollLeft(e.doc.scrollLeft)},!0),r("lineNumbers",!1,function(e,t){e.display.gutterSpecs=ci(e.options.gutters,t),fi(e)},!0),r("firstLineNumber",1,fi,!0),r("lineNumberFormatter",function(e){return e},fi,!0),r("showCursorWhenSelecting",!1,pn,!0),r("resetSelectionOnContextMenu",!0),r("lineWiseCopyCut",!0),r("pasteLinesPerSelection",!0),r("selectionsMayTouch",!1),r("readOnly",!1,function(e,t){"nocursor"==t&&(Sn(e),e.display.input.blur()),e.display.input.readOnlyChanged(t)}),r("disableInput",!1,function(e,t){t||e.display.input.reset()},!0),r("dragDrop",!0,xl),r("allowDropFileTypes",null),r("cursorBlinkRate",530),r("cursorScrollMargin",0),r("cursorHeight",1,pn,!0),r("singleCursorHeightPerLine",!0,pn,!0),r("workTime",100),r("workDelay",100),r("flattenSpans",!0,Mi,!0),r("addModeClass",!1,Mi,!0),r("pollInterval",100),r("undoDepth",200,function(e,t){return e.doc.history.undoDepth=t}),r("historyEventDelay",1250),r("viewportMargin",10,function(e){return e.refresh()},!0),r("maxHighlightLength",1e4,Mi,!0),r("moveInputWithCursor",!0,function(e,t){t||e.display.input.resetPosition()}),r("tabindex",null,function(e,t){return e.display.input.getField().tabIndex=t||""}),r("autofocus",null),r("direction","ltr",function(e,t){return e.doc.setDirection(t)},!0),r("phrases",null)}(Sl),function(e){var t=e.optionHandlers,r=e.helpers={};e.prototype={constructor:e,focus:function(){window.focus(),this.display.input.focus()},setOption:function(e,r){var n=this.options,i=n[e];n[e]==r&&"mode"!=e||(n[e]=r,t.hasOwnProperty(e)&&Zn(this,t[e])(this,r,i),ge(this,"optionChange",this,e))},getOption:function(e){return this.options[e]},getDoc:function(){return this.doc},addKeyMap:function(e,t){this.state.keyMaps[t?"push":"unshift"](Xo(e))},removeKeyMap:function(e){for(var t=this.state.keyMaps,r=0;rr&&(kl(this,i.head.line,e,!0),r=i.head.line,n==this.doc.sel.primIndex&&On(this));else{var o=i.from(),l=i.to(),s=Math.max(r,o.line);r=Math.min(this.lastLine(),l.line-(l.ch?0:1))+1;for(var a=s;a0&&Xi(this.doc,n,new bi(o,u[n].to()),V)}}}),getTokenAt:function(e,t){return yt(this,e,t)},getLineTokens:function(e,t){return yt(this,et(e),t,!0)},getTokenTypeAt:function(e){e=st(this.doc,e);var t,r=ft(this,Xe(this.doc,e.line)),n=0,i=(r.length-1)/2,o=e.ch;if(0==o)t=r[2];else for(;;){var l=n+i>>1;if((l?r[2*l-1]:0)>=o)i=l;else{if(!(r[2*l+1]o&&(e=o,i=!0),n=Xe(this.doc,e)}else n=e;return Vr(this,n,{top:0,left:0},t||"page",r||i).top+(i?this.doc.height-Vt(n):0)},defaultTextHeight:function(){return en(this.display)},defaultCharWidth:function(){return tn(this.display)},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(e,t,r,n,i){var o,l,s,a=this.display,u=(e=Xr(this,st(this.doc,e))).bottom,c=e.left;if(t.style.position="absolute",t.setAttribute("cm-ignore-events","true"),this.display.input.setUneditable(t),a.sizer.appendChild(t),"over"==n)u=e.top;else if("above"==n||"near"==n){var h=Math.max(a.wrapper.clientHeight,this.doc.height),f=Math.max(a.sizer.clientWidth,a.lineSpace.clientWidth);("above"==n||e.bottom+t.offsetHeight>h)&&e.top>t.offsetHeight?u=e.top-t.offsetHeight:e.bottom+t.offsetHeight<=h&&(u=e.bottom),c+t.offsetWidth>f&&(c=f-t.offsetWidth)}t.style.top=u+"px",t.style.left=t.style.right="","right"==i?(c=a.sizer.clientWidth-t.offsetWidth,t.style.right="0px"):("left"==i?c=0:"middle"==i&&(c=(a.sizer.clientWidth-t.offsetWidth)/2),t.style.left=c+"px"),r&&(o=this,l={left:c,top:u,right:c+t.offsetWidth,bottom:u+t.offsetHeight},null!=(s=Mn(o,l)).scrollTop&&Hn(o,s.scrollTop),null!=s.scrollLeft&&Pn(o,s.scrollLeft))},triggerOnKeyDown:Qn(ll),triggerOnKeyPress:Qn(al),triggerOnKeyUp:sl,triggerOnMouseDown:Qn(fl),execCommand:function(e){if(Zo.hasOwnProperty(e))return Zo[e].call(null,this)},triggerElectric:Qn(function(e){Al(this,e)}),findPosH:function(e,t,r,n){var i=1;t<0&&(i=-1,t=-t);for(var o=st(this.doc,e),l=0;l0&&l(t.charAt(r-1));)--r;for(;n.5)&&ln(this),ge(this,"refresh",this)}),swapDoc:Qn(function(e){var t=this.doc;return t.cm=null,this.state.selectingText&&this.state.selectingText(),Di(this,e),Rr(this),this.display.input.reset(),An(this,e.scrollLeft,e.scrollTop),this.curOp.forceScroll=!0,sr(this,"swapDoc",this,t),t}),phrase:function(e){var t=this.options.phrases;return t&&Object.prototype.hasOwnProperty.call(t,e)?t[e]:e},getInputField:function(){return this.display.input.getField()},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},be(e),e.registerHelper=function(t,n,i){r.hasOwnProperty(t)||(r[t]=e[t]={_global:[]}),r[t][n]=i},e.registerGlobalHelper=function(t,n,i,o){e.registerHelper(t,n,o),r[t]._global.push({pred:i,val:o})}}(Sl);var Ul="iter insert remove copy getEditor constructor".split(" ");for(var Vl in Mo.prototype)Mo.prototype.hasOwnProperty(Vl)&&B(Ul,Vl)<0&&(Sl.prototype[Vl]=function(e){return function(){return e.apply(this.doc,arguments)}}(Mo.prototype[Vl]));return be(Mo),Sl.inputStyles={textarea:Gl,contenteditable:El},Sl.defineMode=function(e){Sl.defaults.mode||"null"==e||(Sl.defaults.mode=e),function(e,t){arguments.length>2&&(t.dependencies=Array.prototype.slice.call(arguments,2)),Ee[e]=t}.apply(this,arguments)},Sl.defineMIME=function(e,t){Ie[e]=t},Sl.defineMode("null",function(){return{token:function(e){return e.skipToEnd()}}}),Sl.defineMIME("text/plain","null"),Sl.defineExtension=function(e,t){Sl.prototype[e]=t},Sl.defineDocExtension=function(e,t){Mo.prototype[e]=t},Sl.fromTextArea=function(e,t){if((t=t?I(t):{}).value=e.value,!t.tabindex&&e.tabIndex&&(t.tabindex=e.tabIndex),!t.placeholder&&e.placeholder&&(t.placeholder=e.placeholder),null==t.autofocus){var r=W();t.autofocus=r==e||null!=e.getAttribute("autofocus")&&r==document.body}function n(){e.value=s.getValue()}var i;if(e.form&&(fe(e.form,"submit",n),!t.leaveSubmitMethodAlone)){var o=e.form;i=o.submit;try{var l=o.submit=function(){n(),o.submit=i,o.submit(),o.submit=l}}catch(e){}}t.finishInit=function(r){r.save=n,r.getTextArea=function(){return e},r.toTextArea=function(){r.toTextArea=isNaN,n(),e.parentNode.removeChild(r.getWrapperElement()),e.style.display="",e.form&&(pe(e.form,"submit",n),t.leaveSubmitMethodAlone||"function"!=typeof e.form.submit||(e.form.submit=i))}},e.style.display="none";var s=Sl(function(t){return e.parentNode.insertBefore(t,e.nextSibling)},t);return s},function(e){e.off=pe,e.on=fe,e.wheelEventPixels=vi,e.Doc=Mo,e.splitLines=We,e.countColumn=z,e.findColumn=X,e.isWordChar=ee,e.Pass=U,e.signal=ge,e.Line=Xt,e.changeEnd=Ci,e.scrollbarModel=Gn,e.Pos=et,e.cmpPos=tt,e.modes=Ee,e.mimeModes=Ie,e.resolveMode=ze,e.getMode=Re,e.modeExtensions=Be,e.extendMode=Ge,e.copyState=Ue,e.startState=Ke,e.innerMode=Ve,e.commands=Zo,e.keyMap=Ro,e.keyName=jo,e.isModifierKey=Vo,e.lookupKey=Uo,e.normalizeKeyMap=Go,e.StringStream=je,e.SharedTextMarker=So,e.TextMarker=xo,e.LineWidget=yo,e.e_preventDefault=we,e.e_stopPropagation=xe,e.e_stop=Se,e.addClass=H,e.contains=D,e.rmClass=T,e.keyNames=Po}(Sl),Sl.version="5.49.2",Sl}); \ No newline at end of file diff --git a/luci-app-adguardhome/root/www/luci-static/resources/codemirror/mode/yaml/yaml.js b/luci-app-adguardhome/root/www/luci-static/resources/codemirror/mode/yaml/yaml.js deleted file mode 100644 index 4a5e499b..00000000 --- a/luci-app-adguardhome/root/www/luci-static/resources/codemirror/mode/yaml/yaml.js +++ /dev/null @@ -1 +0,0 @@ -!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 e=new RegExp("\\b(("+["true","false","on","off","yes","no"].join(")|(")+"))$","i");return{token:function(i,t){var r=i.peek(),n=t.escaped;if(t.escaped=!1,"#"==r&&(0==i.pos||/\s/.test(i.string.charAt(i.pos-1))))return i.skipToEnd(),"comment";if(i.match(/^('([^']|\\.)*'?|"([^"]|\\.)*"?)/))return"string";if(t.literal&&i.indentation()>t.keyCol)return i.skipToEnd(),"string";if(t.literal&&(t.literal=!1),i.sol()){if(t.keyCol=0,t.pair=!1,t.pairStart=!1,i.match(/---/))return"def";if(i.match(/\.\.\./))return"def";if(i.match(/\s*-\s+/))return"meta"}if(i.match(/^(\{|\}|\[|\])/))return"{"==r?t.inlinePairs++:"}"==r?t.inlinePairs--:"["==r?t.inlineList++:t.inlineList--,"meta";if(t.inlineList>0&&!n&&","==r)return i.next(),"meta";if(t.inlinePairs>0&&!n&&","==r)return t.keyCol=0,t.pair=!1,t.pairStart=!1,i.next(),"meta";if(t.pairStart){if(i.match(/^\s*(\||\>)\s*/))return t.literal=!0,"meta";if(i.match(/^\s*(\&|\*)[a-z0-9\._-]+\b/i))return"variable-2";if(0==t.inlinePairs&&i.match(/^\s*-?[0-9\.\,]+\s?$/))return"number";if(t.inlinePairs>0&&i.match(/^\s*-?[0-9\.\,]+\s?(?=(,|}))/))return"number";if(i.match(e))return"keyword"}return!t.pair&&i.match(/^\s*(?:[,\[\]{}&*!|>'"%@`][^\s'":]|[^,\[\]{}#&*!|>'"%@`])[^#]*?(?=\s*:($|\s))/)?(t.pair=!0,t.keyCol=i.indentation(),"atom"):t.pair&&i.match(/^:\s*/)?(t.pairStart=!0,"meta"):(t.pairStart=!1,t.escaped="\\"==r,i.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")}); \ No newline at end of file diff --git a/luci-app-adguardhome/root/www/luci-static/resources/codemirror/theme/dracula.css b/luci-app-adguardhome/root/www/luci-static/resources/codemirror/theme/dracula.css deleted file mode 100644 index 6c708c01..00000000 --- a/luci-app-adguardhome/root/www/luci-static/resources/codemirror/theme/dracula.css +++ /dev/null @@ -1 +0,0 @@ -.cm-s-dracula.CodeMirror,.cm-s-dracula .CodeMirror-gutters{background-color:#282a36 !important;color:#f8f8f2 !important;border:0}.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,0.10)}.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,0.10)}.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,0.10)}.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:white}.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-variable-3,.cm-s-dracula span.cm-type{color:#ffb86c}.cm-s-dracula .CodeMirror-activeline-background{background:rgba(255,255,255,0.1)}.cm-s-dracula .CodeMirror-matchingbracket{text-decoration:underline;color:white !important} diff --git a/luci-app-cloudreve b/luci-app-cloudreve deleted file mode 160000 index fe34dd93..00000000 --- a/luci-app-cloudreve +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fe34dd9377e85d328e680a17f53003f5f29ef8b6 diff --git a/luci-app-cloudreve/Makefile b/luci-app-cloudreve/Makefile new file mode 100644 index 00000000..92df55de --- /dev/null +++ b/luci-app-cloudreve/Makefile @@ -0,0 +1,21 @@ +# Copyright (C) 2019 Openwrt.org +# +# This is a free software, use it under Apache Licene 2.0 & GNU General Public License v3.0. +# + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=Cloudreve for LuCI +LUCI_DEPENDS:=+cloudreve +LUCI_PKGARCH:=all + +PKG_NAME:=luci-app-cloudreve + +define Package/luci-app-cloudreve/conffiles +/etc/config/cloudreve +/etc/cloudreve/ +endef + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-cloudreve/luasrc/controller/cloudreve.lua b/luci-app-cloudreve/luasrc/controller/cloudreve.lua new file mode 100644 index 00000000..d85deba1 --- /dev/null +++ b/luci-app-cloudreve/luasrc/controller/cloudreve.lua @@ -0,0 +1,17 @@ +module("luci.controller.cloudreve",package.seeall) + +function index() + entry({"admin", "nas"}, firstchild(), _("NAS") , 45).dependent = false + if not nixio.fs.access("/etc/config/cloudreve")then + return + end + entry({"admin","nas","cloudreve"},cbi("cloudreve"),_("Cloudreve")).acl_depends = { "luci-app-cloudreve" } + entry({"admin","nas","cloudreve","status"},call("act_status")).leaf=true +end + +function act_status() + local e={} + e.running=luci.sys.call("pgrep cloudreve >/dev/null")==0 + luci.http.prepare_content("application/json") + luci.http.write_json(e) +end diff --git a/luci-app-cloudreve/luasrc/model/cbi/cloudreve.lua b/luci-app-cloudreve/luasrc/model/cbi/cloudreve.lua new file mode 100644 index 00000000..e18c4bf9 --- /dev/null +++ b/luci-app-cloudreve/luasrc/model/cbi/cloudreve.lua @@ -0,0 +1,16 @@ +m = Map("cloudreve", translate("Cloudreve"), translate("Self-hosted file management and sharing system, supports multiple storage providers.")) + +m:section(SimpleSection).template="cloudreve/cloudreve_status" + +s = m:section(TypedSection, "cloudreve") +s.anonymous=true + +enabled = s:option(Flag, "enabled", translate("Enable")) +enabled.rmempty = false + +port = s:option(Value,"port",translate("Port")) +port.default = "8052" +port.placeholder = "8052" +port.rmempty = false + +return m diff --git a/luci-app-cloudreve/luasrc/view/cloudreve/cloudreve_status.htm b/luci-app-cloudreve/luasrc/view/cloudreve/cloudreve_status.htm new file mode 100644 index 00000000..33fd69f8 --- /dev/null +++ b/luci-app-cloudreve/luasrc/view/cloudreve/cloudreve_status.htm @@ -0,0 +1,27 @@ + + +
+

+ <%:Collecting data...%> +

+
diff --git a/luci-app-cloudreve/po/zh-cn b/luci-app-cloudreve/po/zh-cn new file mode 120000 index 00000000..8d69574d --- /dev/null +++ b/luci-app-cloudreve/po/zh-cn @@ -0,0 +1 @@ +zh_Hans \ No newline at end of file diff --git a/luci-app-cloudreve/po/zh_Hans/cloudreve.po b/luci-app-cloudreve/po/zh_Hans/cloudreve.po new file mode 100644 index 00000000..ac9375a5 --- /dev/null +++ b/luci-app-cloudreve/po/zh_Hans/cloudreve.po @@ -0,0 +1,27 @@ +msgid "Cloudreve" +msgstr "Cloudreve" + +msgid "Self-hosted file management and sharing system, supports multiple storage providers." +msgstr "Cloudreve 可助你即刻构建出兼备自用或公用的网盘服务,通过多种存储策略的支持、虚拟文件系统等特性实现灵活的文件管理体验。" + +msgid "Default login username: admin@cloudreve.org, password: password." +msgstr "默认登录用户名:admin@cloudreve.org,密码:password。" + +msgid "Open Web Interface" +msgstr "打开Web界面" + +msgid "Cloudreve Run Status" +msgstr "Cloudreve 运行状态" + +msgid "Running" +msgstr "运行中" + +msgid "Not running" +msgstr "未运行" + +msgid "Enable" +msgstr "启用" + +msgid "Port" +msgstr "端口" + diff --git a/luci-app-cloudreve/root/etc/config/cloudreve b/luci-app-cloudreve/root/etc/config/cloudreve new file mode 100644 index 00000000..196d921b --- /dev/null +++ b/luci-app-cloudreve/root/etc/config/cloudreve @@ -0,0 +1,4 @@ + +config cloudreve + option enabled '0' + option port '8052' diff --git a/luci-app-cloudreve/root/etc/init.d/cloudreve b/luci-app-cloudreve/root/etc/init.d/cloudreve new file mode 100755 index 00000000..cb016ac1 --- /dev/null +++ b/luci-app-cloudreve/root/etc/init.d/cloudreve @@ -0,0 +1,37 @@ +#!/bin/sh /etc/rc.common + +START=99 +USE_PROCD=1 + +homedir="/etc/cloudreve" + +get_config() { + config_get_bool enabled $1 enabled 0 + config_get port $1 port 8052 +} + +start_service() { + config_load cloudreve + config_foreach get_config cloudreve + [ $enabled != 1 ] && return 1 + mkdir -p "$homedir" + if [ -f "$homedir/cloudreve.ini" ]; then + sed -i "s/Listen = :[0-9]*/Listen = :$port/g" "$homedir/cloudreve.ini" + else + cat >"$homedir/cloudreve.ini"< /usr/share/ucitrack/luci-app-cloudreve.json << EEOF +{ + "config": "cloudreve", + "init": "cloudreve" +} +EEOF +} + +uci -q batch <<-EOF >/dev/null + delete ucitrack.@cloudreve[-1] + add ucitrack cloudreve + set ucitrack.@cloudreve[-1].init=cloudreve + commit ucitrack +EOF + +chmod +x /etc/init.d/cloudreve >/dev/null 2>&1 + +rm -f /tmp/luci-indexcache +exit 0 diff --git a/luci-app-cloudreve/root/usr/share/rpcd/acl.d/luci-app-cloudreve.json b/luci-app-cloudreve/root/usr/share/rpcd/acl.d/luci-app-cloudreve.json new file mode 100644 index 00000000..75a1cd03 --- /dev/null +++ b/luci-app-cloudreve/root/usr/share/rpcd/acl.d/luci-app-cloudreve.json @@ -0,0 +1,11 @@ +{ + "luci-app-cloudreve": { + "description": "Grant UCI access for luci-app-cloudreve", + "read": { + "uci": [ "cloudreve" ] + }, + "write": { + "uci": [ "cloudreve" ] + } + } +} diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua index 29970985..a913865c 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua @@ -133,9 +133,11 @@ o.validate = function(self, value) return value:gsub("%s+", ""):gsub("%z", "") end -o = s:option(Flag, "allowInsecure", translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped.")) +o = s:option(Flag, "allowInsecure", translate("allowInsecure")) o.default = "0" o.rmempty = false +o.description = translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped.") .. "
" .. + translate("Used when the node link does not include this parameter.") o = s:option(ListValue, "filter_keyword_mode", translate("Filter keyword Mode")) o.default = "5" diff --git a/luci-app-passwall/luasrc/view/passwall/node_config/link_share_man.htm b/luci-app-passwall/luasrc/view/passwall/node_config/link_share_man.htm index 83165135..b5e9a99d 100644 --- a/luci-app-passwall/luasrc/view/passwall/node_config/link_share_man.htm +++ b/luci-app-passwall/luasrc/view/passwall/node_config/link_share_man.htm @@ -1063,10 +1063,7 @@ local current_node = map:get(section) opt.set(dom_prefix + 'reality', false); opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); - opt.set(dom_prefix + 'tls_allowInsecure', true); - if ((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0') { - opt.set(dom_prefix + 'tls_allowInsecure', false); - } + opt.set(dom_prefix + 'tls_allowInsecure', !((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0')); if (queryParam.fp && queryParam.fp.trim() != "") { opt.set(dom_prefix + 'utls', true); opt.set(dom_prefix + 'fingerprint', queryParam.fp); @@ -1317,11 +1314,7 @@ local current_node = map:get(section) opt.set(dom_prefix + 'tls_CertSha', queryParam.pcs || ''); opt.set(dom_prefix + 'tls_CertByName', queryParam.vcn || ''); } - opt.set(dom_prefix + 'tls_allowInsecure', true); - if ((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0') { - opt.set(dom_prefix + 'tls_allowInsecure', false); - } - + opt.set(dom_prefix + 'tls_allowInsecure', !((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0')); opt.set(dom_prefix + 'tcp_fast_open', queryParam.tfo); opt.set(dom_prefix + 'use_finalmask', !!queryParam.fm); opt.set(dom_prefix + 'finalmask', queryParam.fm || ""); @@ -1353,11 +1346,8 @@ local current_node = map:get(section) opt.set(dom_prefix + 'uuid', ssm.id); opt.set(dom_prefix + 'tls', ssm.tls === "tls"); if (ssm.tls === "tls") { - var tls_serverName = ssm.host; - if (ssm.sni) { - tls_serverName = ssm.sni - } - opt.set(dom_prefix + 'tls_serverName', tls_serverName); + opt.set(dom_prefix + 'tls_serverName', ssm.sni || ssm.host); + opt.set(dom_prefix + 'tls_allowInsecure', !((ssm.allowinsecure ?? '0') === '0' && (ssm.insecure ?? '0') === '0')); } ssm.net = ssm.net.toLowerCase(); if (ssm.net === "kcp" || ssm.net === "mkcp") @@ -1469,10 +1459,7 @@ local current_node = map:get(section) opt.set(dom_prefix + 'reality', false); opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); - opt.set(dom_prefix + 'tls_allowInsecure', true); - if ((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0') { - opt.set(dom_prefix + 'tls_allowInsecure', false); - } + opt.set(dom_prefix + 'tls_allowInsecure', !((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0')); if (queryParam.fp && queryParam.fp.trim() != "") { opt.set(dom_prefix + 'utls', true); opt.set(dom_prefix + 'fingerprint', queryParam.fp); @@ -1630,9 +1617,7 @@ local current_node = map:get(section) opt.set(dom_prefix + 'port', m.port || "443"); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ""); - if (queryParam.insecure && queryParam.insecure == "1") { - opt.set(dom_prefix + 'tls_allowInsecure', true); - } + opt.set(dom_prefix + 'tls_allowInsecure', !((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0')); opt.set(dom_prefix + 'tls_CertSha', queryParam.pcs || ''); opt.set(dom_prefix + 'tls_CertByName', queryParam.vcn || ''); if (m.hash) { @@ -1680,10 +1665,7 @@ local current_node = map:get(section) opt.set(dom_prefix + 'tuic_alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); opt.set(dom_prefix + 'tls_disable_sni', queryParam.disable_sni === "1"); - opt.set(dom_prefix + 'tls_allowInsecure', true); - if ((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0') { - opt.set(dom_prefix + 'tls_allowInsecure', false); - } + opt.set(dom_prefix + 'tls_allowInsecure', !((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0' && (queryParam.allow_insecure ?? '0') === '0')); if (hash) { opt.set('remarks', decodeURIComponent(hash.substr(1))); } @@ -1723,10 +1705,7 @@ local current_node = map:get(section) opt.set(dom_prefix + 'reality', false); opt.set(dom_prefix + 'alpn', queryParam.alpn || 'default'); opt.set(dom_prefix + 'tls_serverName', queryParam.sni || ''); - opt.set(dom_prefix + 'tls_allowInsecure', true); - if ((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0') { - opt.set(dom_prefix + 'tls_allowInsecure', false); - } + opt.set(dom_prefix + 'tls_allowInsecure', !((queryParam.allowinsecure ?? '0') === '0' && (queryParam.insecure ?? '0') === '0')); if (queryParam.fp && queryParam.fp.trim() != "") { opt.set(dom_prefix + 'utls', true); opt.set(dom_prefix + 'fingerprint', queryParam.fp); diff --git a/luci-app-passwall/po/zh-cn/passwall.po b/luci-app-passwall/po/zh-cn/passwall.po index fd697d9c..43027dd8 100644 --- a/luci-app-passwall/po/zh-cn/passwall.po +++ b/luci-app-passwall/po/zh-cn/passwall.po @@ -1228,6 +1228,9 @@ msgstr "使用全局配置" msgid "User-Agent" msgstr "用户代理(User-Agent)" +msgid "Used when the node link does not include this parameter." +msgstr "当节点链接未包含该参数时,将使用此设置。" + msgid "Add" msgstr "添加" diff --git a/luci-app-passwall/root/usr/share/passwall/subscribe.lua b/luci-app-passwall/root/usr/share/passwall/subscribe.lua index 636a9740..baa75bcb 100755 --- a/luci-app-passwall/root/usr/share/passwall/subscribe.lua +++ b/luci-app-passwall/root/usr/share/passwall/subscribe.lua @@ -602,14 +602,10 @@ local function processData(szType, content, add_mode, group) if info.tls == "tls" or info.tls == "1" then result.tls = "1" result.tls_serverName = (info.sni and info.sni ~= "") and info.sni or info.host - info.allowinsecure = info.allowinsecure or info.insecure - if info.allowinsecure and (info.allowinsecure == "1" or info.allowinsecure == "0") then - result.tls_allowInsecure = info.allowinsecure - else - result.tls_allowInsecure = allowInsecure_default and "1" or "0" - end result.tls_CertSha = info.pcs result.tls_CertByName = info.vcn + local insecure = info.allowinsecure or info.insecure + result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (allowInsecure_default and "1" or "0") else result.tls = "0" end @@ -894,12 +890,8 @@ local function processData(szType, content, add_mode, group) result.reality_mldsa65Verify = params.pqv or nil end end - params.allowinsecure = params.allowinsecure or params.insecure - if params.allowinsecure and (params.allowinsecure == "1" or params.allowinsecure == "0") then - result.tls_allowInsecure = params.allowinsecure - else - result.tls_allowInsecure = allowInsecure_default and "1" or "0" - end + local insecure = params.allowinsecure or params.insecure + result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (allowInsecure_default and "1" or "0") result.uot = params.udp elseif (params.type ~= "tcp" and params.type ~= "raw") and (params.headerType and params.headerType ~= "none") then result.error_msg = "请更换 Xray 或 Sing-Box 来支持 SS 更多的传输方式。" @@ -1003,18 +995,8 @@ local function processData(szType, content, add_mode, group) result.tls_serverName = params.peer or params.sni or "" result.tls_CertSha = params.pcs result.tls_CertByName = params.vcn - - params.allowinsecure = params.allowinsecure or params.insecure - if params.allowinsecure then - if params.allowinsecure == "1" or params.allowinsecure == "0" then - result.tls_allowInsecure = params.allowinsecure - else - result.tls_allowInsecure = string.lower(params.allowinsecure) == "true" and "1" or "0" - end - --log(result.remarks .. ' 使用节点AllowInsecure设定: '.. result.tls_allowInsecure) - else - result.tls_allowInsecure = allowInsecure_default and "1" or "0" - end + local insecure = params.allowinsecure or params.insecure + result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (allowInsecure_default and "1" or "0") if not params.type then params.type = "tcp" end params.type = string.lower(params.type) @@ -1280,17 +1262,11 @@ local function processData(szType, content, add_mode, group) result.use_mldsa65Verify = (params.pqv and params.pqv ~= "") and "1" or nil result.reality_mldsa65Verify = params.pqv or nil end + local insecure = params.allowinsecure or params.insecure + result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (allowInsecure_default and "1" or "0") end result.port = port - - params.allowinsecure = params.allowinsecure or params.insecure - if params.allowinsecure and (params.allowinsecure == "1" or params.allowinsecure == "0") then - result.tls_allowInsecure = params.allowinsecure - else - result.tls_allowInsecure = allowInsecure_default and "1" or "0" - end - result.tcp_fast_open = params.tfo result.use_finalmask = (params.fm and params.fm ~= "") and "1" or nil result.finalmask = (params.fm and params.fm ~= "") and api.base64Encode(params.fm) or nil @@ -1343,13 +1319,8 @@ local function processData(szType, content, add_mode, group) result.hysteria_auth_type = "string" result.hysteria_auth_password = params.auth result.tls_serverName = params.peer or params.sni or "" - params.allowinsecure = params.allowinsecure or params.insecure - if params.allowinsecure and (params.allowinsecure == "1" or params.allowinsecure == "0") then - result.tls_allowInsecure = params.allowinsecure - --log(result.remarks ..' 使用节点AllowInsecure设定: '.. result.tls_allowInsecure) - else - result.tls_allowInsecure = allowInsecure_default and "1" or "0" - end + local insecure = params.allowinsecure or params.insecure + result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (allowInsecure_default and "1" or "0") result.alpn = params.alpn result.hysteria_up_mbps = params.upmbps result.hysteria_down_mbps = params.downmbps @@ -1394,13 +1365,8 @@ local function processData(szType, content, add_mode, group) result.tls_serverName = params.sni result.tls_CertSha = params.pcs result.tls_CertByName = params.vcn - params.allowinsecure = params.allowinsecure or params.insecure - if params.allowinsecure and (params.allowinsecure == "1" or params.allowinsecure == "0") then - result.tls_allowInsecure = params.allowinsecure - --log(result.remarks ..' 使用节点AllowInsecure设定: '.. result.tls_allowInsecure) - else - result.tls_allowInsecure = allowInsecure_default and "1" or "0" - end + local insecure = params.allowinsecure or params.insecure + result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (allowInsecure_default and "1" or "0") result.hysteria2_tls_pinSHA256 = params.pinSHA256 result.hysteria2_hop = params.mport @@ -1479,17 +1445,8 @@ local function processData(szType, content, add_mode, group) result.tuic_alpn = params.alpn or "default" result.tuic_congestion_control = params.congestion_control or "cubic" result.tuic_udp_relay_mode = params.udp_relay_mode or "native" - params.allowinsecure = params.allowinsecure or params.insecure - if params.allowinsecure then - if params.allowinsecure == "1" or params.allowinsecure == "0" then - result.tls_allowInsecure = params.allowinsecure - else - result.tls_allowInsecure = string.lower(params.allowinsecure) == "true" and "1" or "0" - end - --log(result.remarks .. ' 使用节点AllowInsecure设定: '.. result.tls_allowInsecure) - else - result.tls_allowInsecure = allowInsecure_default and "1" or "0" - end + local insecure = params.allowinsecure or params.insecure or params.allow_insecure + result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (allowInsecure_default and "1" or "0") elseif szType == "anytls" then if has_singbox then result.type = 'sing-box' @@ -1552,18 +1509,8 @@ local function processData(szType, content, add_mode, group) end end result.port = port - params.allowinsecure = params.allowinsecure or params.insecure - if params.allowinsecure and (params.allowinsecure == "1" or params.allowinsecure == "0") then - result.tls_allowInsecure = params.allowinsecure - else - result.tls_allowInsecure = allowInsecure_default and "1" or "0" - end - local singbox_version = api.get_app_version("sing-box") - local version_ge_1_12 = api.compare_versions(singbox_version:match("[^v]+"), ">=", "1.12.0") - if not has_singbox or not version_ge_1_12 then - log("跳过节点:" .. result.remarks ..",因 " .. szType .. " 类型的节点需要 Sing-Box 1.12 以上版本支持。") - return nil - end + local insecure = params.allowinsecure or params.insecure + result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (allowInsecure_default and "1" or "0") end elseif szType == 'naive+https' or szType == 'naive+quic' then if has_singbox then diff --git a/luci-app-ssr-plus/Makefile b/luci-app-ssr-plus/Makefile index 9cbb8305..98ed6721 100644 --- a/luci-app-ssr-plus/Makefile +++ b/luci-app-ssr-plus/Makefile @@ -4,7 +4,7 @@ LUCI_TITLE:=luci-app-ssr-plus LUCI_PKGARCH:=all PKG_NAME:=luci-app-ssr-plus PKG_VERSION:=190 -PKG_RELEASE:=4 +PKG_RELEASE:=5 PKG_CONFIG_DEPENDS:= \ CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \ diff --git a/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua b/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua index 4c3c716d..f8fc8ad4 100644 --- a/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua +++ b/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua @@ -372,17 +372,23 @@ if is_finded("xray") then o.default = "100-200" o:depends("fragment", true) - o = s:option(Value, "fragment_interval", translate("Fragment Interval"), translate("Fragmentation interval (ms)")) + o = s:option(Value, "fragment_delay", translate("Fragment Delay"), translate("Fragmentation interval (ms)")) o.datatype = "or(uinteger,portrange)" o.default = "10-20" o:depends("fragment", true) + o = s:option(Value, "fragment_maxSplit", translate("Max Split"), translate("Limit the maximum number of splits.")) + o.datatype = "or(uinteger,portrange)" + o.default = "100-200" + o:depends("fragment", true) + o = s:option(Flag, "noise", translate("Noise"), translate("UDP noise, Under some circumstances it can bypass some UDP based protocol restrictions.")) o.default = 0 s = m:section(TypedSection, "xray_noise_packets", translate("Xray Noise Packets")) s.description = translate( "" .. translate("To send noise packets, select \"Noise\" in Xray Settings.") .. "" .. + "
" .. translate("Packet or Rand length as a string, e.g., 10-20.") .. "" .. "
" .. translate("For specific usage, see:") .. "" .. "" .. "" .. translate("Click to the page") .. "") @@ -406,12 +412,13 @@ if is_finded("xray") then o = s:option(ListValue, "type", translate("Type")) o.default = "base64" o:value("rand", "rand") + o:value("array", "array") o:value("str", "str") o:value("hex", "hex") o:value("base64", "base64") o = s:option(Value, "domainStrategy", translate("Domain Strategy")) - o.default = "UseIP" + o.default = "AsIs" o:value("AsIs", "AsIs") o:value("UseIP", "UseIP") o:value("UseIPv4", "UseIPv4") @@ -419,7 +426,7 @@ if is_finded("xray") then o:value("ForceIPv4", "ForceIPv4") o.rmempty = false - o = s:option(Value, "packet", translate("Packet")) + o = s:option(Value, "packet", translate("Packet | Rand Length")) o.datatype = "minlength(1)" o.rmempty = false diff --git a/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua b/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua index b2950b93..2a885cc4 100644 --- a/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua +++ b/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua @@ -38,15 +38,18 @@ local function trim(text) return (text:gsub("^%s*(.-)%s*$", "%1")) end --- base64 +-- base64 解码 local function base64Decode(text) local raw = text if not text or text == "" then return '' end text = text:gsub("%z", "") + text = text:gsub("%c", "") + text = text:gsub("%s", "") text = text:gsub("_", "/") text = text:gsub("-", "+") + text = text:gsub("=", "") local mod4 = #text % 4 text = text .. string.sub('====', mod4 + 1) local result = b64decode(text) @@ -57,6 +60,7 @@ local function base64Decode(text) end end +-- base64 编码 local function base64Encode(text) if not text or text == "" then return '' @@ -64,9 +68,6 @@ local function base64Encode(text) local result = b64encode(text) if result then result = result:gsub("%z", "") - result = result:gsub("/", "_") - result = result:gsub("+", "-") - result = result:gsub("=", "") return result else return text @@ -1212,7 +1213,8 @@ o:depends({type = "v2ray", v2ray_protocol = "wireguard"}) o:depends({type = "v2ray", v2ray_protocol = "hysteria2"}) o = s:option(TextValue, "finalmask", " ") -o.description = translate("An FinalMaskObject in JSON format, used for sharing.") +o.description = translate("An FinalMaskObject in JSON format, used for sharing.") .. "
" .. + translate("Custom finalmask overrides mkcp, hysteria2, fragment, noise, and related settings.") o:depends("enable_finalmask", true) o.rows = 10 o.wrap = "off" @@ -1510,6 +1512,7 @@ o.rmempty = true o.default = "" o:value("", translate("comment_tcpcongestion_disable")) o:value("bbr", translate("BBR")) +o:value("brutal", translate("BRUTAL")) o:value("cubic", translate("CUBIC")) o:value("reno", translate("Reno")) o:depends({type = "v2ray", v2ray_protocol = "vless"}) diff --git a/luci-app-ssr-plus/po/templates/ssr-plus.pot b/luci-app-ssr-plus/po/templates/ssr-plus.pot index 6092038f..5078a4d3 100644 --- a/luci-app-ssr-plus/po/templates/ssr-plus.pot +++ b/luci-app-ssr-plus/po/templates/ssr-plus.pot @@ -8,12 +8,12 @@ msgid "" "fragmentation." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:277 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:278 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:165 msgid "%s Node Use Type" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:346 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:347 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:175 msgid "%s Node Use Version" msgstr "" @@ -30,7 +30,7 @@ msgstr "" msgid "128 Threads" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1466 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1468 msgid "16" msgstr "" @@ -46,7 +46,7 @@ msgstr "" msgid "32 Threads" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1297 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1299 msgid "360" msgstr "" @@ -66,7 +66,7 @@ msgstr "" msgid "64 Threads" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1453 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1455 msgid "8" msgstr "" @@ -74,13 +74,13 @@ msgstr "" msgid "8 Threads" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:385 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:390 msgid "" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:959 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1312 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1339 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:960 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1314 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1341 msgid "" msgstr "" @@ -93,10 +93,10 @@ msgstr "" #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:160 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:186 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:220 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1155 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1446 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1459 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1472 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1156 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1448 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1461 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1474 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client.lua:188 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client.lua:214 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client.lua:249 @@ -112,7 +112,7 @@ msgstr "" msgid "AdGuard DNSCrypt SDNS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:728 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:749 msgid "Add" msgstr "" @@ -132,7 +132,7 @@ msgstr "" msgid "Alias" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:334 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:335 msgid "Alias(optional)" msgstr "" @@ -152,11 +152,11 @@ msgstr "" msgid "Allow subscribe Insecure nodes By default" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:805 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:806 msgid "AlterId" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1215 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1216 msgid "An FinalMaskObject in JSON format, used for sharing." msgstr "" @@ -195,7 +195,7 @@ msgstr "" msgid "Apply" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:379 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:391 msgid "Are you sure to delete this node?" msgstr "" @@ -219,13 +219,14 @@ msgstr "" msgid "Auto Update Server subscription, GFW list and CHN route" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:739 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1512 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1527 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:740 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1514 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1530 msgid "BBR" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1528 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1515 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1531 msgid "BRUTAL" msgstr "" @@ -249,8 +250,8 @@ msgstr "" msgid "Base64 sstr failed." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1082 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1092 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1083 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1093 msgid "BitTorrent (uTP)" msgstr "" @@ -258,7 +259,7 @@ msgstr "" msgid "Black Domain List" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:465 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:466 msgid "Bloom Filter" msgstr "" @@ -274,22 +275,22 @@ msgstr "" msgid "CNNIC SDNS (1.2.4.8)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:740 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1513 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1531 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:741 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1516 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1534 msgid "CUBIC" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1099 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1100 msgid "Camouflage Domain" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:867 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1088 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:868 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1089 msgid "Camouflage Type" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1422 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1424 msgid "Certificate fingerprint" msgstr "" @@ -353,10 +354,10 @@ msgstr "" msgid "Click here to view or manage the DNS list file" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:388 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:961 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1314 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1341 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:394 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:962 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1316 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1343 msgid "Click to the page" msgstr "" @@ -381,15 +382,15 @@ msgstr "" msgid "Collecting data..." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:959 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:960 msgid "Configure XHTTP Extra Settings (JSON format), see:" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1148 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1149 msgid "Congestion" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:737 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:738 msgid "Congestion control algorithm" msgstr "" @@ -405,7 +406,7 @@ msgstr "" msgid "Connection Timeout" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1325 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1327 msgid "" "Controls the policy used when performing DNS queries for ECH configuration." msgstr "" @@ -418,15 +419,15 @@ msgstr "" msgid "Create Backup File" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1559 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1562 msgid "Create upload file error." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1579 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1582 msgid "Current Certificate Path" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:491 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:492 msgid "Custom" msgstr "" @@ -455,7 +456,7 @@ msgid "" "(tcp://8.8.8.8 or tls://dns.google:853)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:495 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:496 msgid "Custom Plugin Path" msgstr "" @@ -463,6 +464,12 @@ msgstr "" msgid "Custom Ports" msgstr "" +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1217 +msgid "" +"Custom finalmask overrides mkcp, hysteria2, fragment, noise, and related " +"settings." +msgstr "" + #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:103 msgid "Customize Netflix IP Url" msgstr "" @@ -471,7 +478,7 @@ msgstr "" msgid "DL Backup" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1096 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1097 msgid "DNS" msgstr "" @@ -487,36 +494,36 @@ msgstr "" msgid "DNSPod Public DNS (119.29.29.29)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1084 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1094 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1085 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1095 msgid "DTLS 1.2" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1170 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1171 msgid "Decimal numbers separated by \",\" or Base64-encoded strings." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1362 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1374 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1388 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1364 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1376 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1390 msgid "Default" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1473 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1475 msgid "Default reject rejects traffic." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:635 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:636 msgid "Default value 0 indicatesno heartbeat." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1447 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1449 msgid "" "Default: disable. When entering a negative number, such as -1, The Mux " "module will not be used to carry TCP traffic." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1460 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1462 msgid "" "Default:16. When entering a negative number, such as -1, The Mux module will " "not be used to carry UDP traffic, Use original UDP transmission method of " @@ -535,11 +542,11 @@ msgid "" "fastest_addr (default: load_balance)." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:426 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:433 msgid "Delay (ms)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:717 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:738 msgid "Delete" msgstr "" @@ -575,15 +582,15 @@ msgstr "" msgid "Disable IPv6 query mode" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:592 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:593 msgid "Disable QUIC path MTU discovery" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:781 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:782 msgid "Disable SNI" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:662 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:663 msgid "Disable TCP No_delay" msgstr "" @@ -604,7 +611,7 @@ msgstr "" msgid "DoT upstream (Need use wolfssl version)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:413 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:420 msgid "Domain Strategy" msgstr "" @@ -612,78 +619,78 @@ msgstr "" msgid "Domestic DNS Server" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1124 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1125 msgid "Downlink Capacity(Default:Mbps)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:718 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:739 msgid "Drag to reorder" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:792 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:793 msgid "Dual-stack Listening Socket" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1310 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1312 msgid "ECH Config" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1324 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1326 msgid "ECH Query Policy" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:909 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:910 msgid "Early Data Header Name" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:716 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:737 msgid "Edit" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:257 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:258 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:69 msgid "Edit ShadowSocksR Server" msgstr "" #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:271 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:402 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:408 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:82 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server.lua:101 msgid "Enable" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:786 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:787 msgid "Enable 0-RTT QUIC handshake" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:411 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:412 msgid "Enable Authentication" msgstr "" #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:63 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1595 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1598 msgid "Enable Auto Switch" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1305 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1307 msgid "Enable ECH(optional)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:568 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:569 msgid "Enable Lazy Mode" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1332 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1334 msgid "Enable ML-DSA-65(optional)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1491 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1493 msgid "" "Enable Multipath TCP, need to be enabled in both server and client " "configuration." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1427 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1429 msgid "Enable Mux.Cool" msgstr "" @@ -691,15 +698,15 @@ msgstr "" msgid "Enable Netflix Mode" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:562 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:563 msgid "Enable Obfuscation" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:471 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:472 msgid "Enable Plugin" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:531 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:532 msgid "Enable Port Hopping" msgstr "" @@ -707,15 +714,15 @@ msgstr "" msgid "Enable Server" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:544 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:545 msgid "Enable Transport Protocol Settings" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:648 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:649 msgid "Enable V2 protocol." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:647 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:648 msgid "Enable V3 protocol." msgstr "" @@ -723,15 +730,15 @@ msgstr "" msgid "Enable adblock" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:460 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:461 msgid "Enable the SUoT protocol, requires server support." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:952 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:953 msgid "Enable this option to configure XHTTP Extra (JSON format)." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1153 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1154 msgid "Enabled Kernel virtual NIC TUN(optional)" msgstr "" @@ -739,16 +746,16 @@ msgstr "" msgid "Enabled Mixed" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:657 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1585 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:658 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1588 msgid "Enabling TCP Fast Open Requires Server Support." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:439 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:446 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:689 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:700 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:831 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:440 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:447 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:690 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:701 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:832 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:118 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:125 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server.lua:122 @@ -799,7 +806,7 @@ msgstr "" msgid "External Proxy Mode" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1529 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1532 msgid "FORCE BRUTAL" msgstr "" @@ -807,15 +814,15 @@ msgstr "" msgid "Filter Words splited by /" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1204 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1205 msgid "FinalMask" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1289 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1291 msgid "Finger Print" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1276 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1278 msgid "Flow" msgstr "" @@ -825,11 +832,11 @@ msgid "" "Chinese CDN IP addresses" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:386 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:392 msgid "For specific usage, see:" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:538 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:539 msgid "" "Format as 10000:20000 or 10000-20000 Multiple groups are separated by commas " "(,)." @@ -844,7 +851,7 @@ msgid "Fragment" msgstr "" #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:375 -msgid "Fragment Interval" +msgid "Fragment Delay" msgstr "" #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:370 @@ -883,11 +890,11 @@ msgstr "" msgid "Game Mode UDP Server" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:757 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:758 msgid "Garbage collection interval(second)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:763 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:764 msgid "Garbage collection lifetime(second)" msgstr "" @@ -940,71 +947,71 @@ msgstr "" msgid "Grant UCI access for luci-app-ssr-plus" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1023 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1024 msgid "Gun" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1042 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1043 msgid "H2 Read Idle Timeout" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1037 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1038 msgid "H2/gRPC Health Check" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:382 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:870 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:383 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:871 msgid "HTTP" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:874 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:875 msgid "HTTP Host" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:879 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:880 msgid "HTTP Path" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1005 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1006 msgid "HTTP/2 Host" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1010 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1011 msgid "HTTP/2 Path" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1077 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1078 msgid "Header" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1054 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1055 msgid "Health Check Timeout" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:745 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:746 msgid "Heartbeat interval(second)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:896 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:897 msgid "HeartbeatPeriod(second)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:918 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:919 msgid "Httpupgrade Host" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:923 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:924 msgid "Httpupgrade Path" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:285 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:317 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:379 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:286 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:318 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:380 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:79 msgid "Hysteria2" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:586 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:587 msgid "Hysterir QUIC parameters" msgstr "" @@ -1012,7 +1019,7 @@ msgstr "" msgid "IP Route Mode" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1386 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1388 msgid "IP Stack Preference" msgstr "" @@ -1020,23 +1027,23 @@ msgstr "" msgid "If empty, Not change Apple domains parsing DNS (Default is empty)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1312 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1314 msgid "" "If it is not empty, it indicates that the Client has enabled Encrypted " "Client, see:" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:793 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:794 msgid "If this option is not set, the socket behavior is platform dependent." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1399 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1401 msgid "" "If true, allowss insecure connection at TLS client, e.g., TLS server uses " "unverifiable certificates." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1543 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1546 msgid "If you have a self-signed certificate,please check the box" msgstr "" @@ -1056,7 +1063,7 @@ msgstr "" msgid "Import configuration information successfully." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1030 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1031 msgid "Initial Windows Size" msgstr "" @@ -1076,19 +1083,19 @@ msgstr "" msgid "KcpTun" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1605 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1608 msgid "KcpTun Enable" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1622 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1625 msgid "KcpTun Param" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1617 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1620 msgid "KcpTun Password" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1611 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1614 msgid "KcpTun Port" msgstr "" @@ -1173,7 +1180,11 @@ msgstr "" msgid "Level 3 Public DNS-3 (4.2.2.3-4)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1156 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:380 +msgid "Limit the maximum number of splits." +msgstr "" + +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1157 msgid "" "Linux kernel TUN virtual NIC requires system support and root privileges." msgstr "" @@ -1183,7 +1194,7 @@ msgid "Listen only on the given interface or, if unspecified, on all" msgstr "" #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:348 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1599 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1602 msgid "Local Port" msgstr "" @@ -1191,7 +1202,7 @@ msgstr "" msgid "Local Servers" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1164 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1165 msgid "Local addresses" msgstr "" @@ -1207,15 +1218,15 @@ msgstr "" msgid "Loyalsoldier/v2ray-rules-dat" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1337 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1339 msgid "ML-DSA-65 Public key" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1491 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1493 msgid "MPTCP" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1103 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1104 msgid "MTU" msgstr "" @@ -1223,21 +1234,25 @@ msgstr "" msgid "Main Server" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:902 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:903 msgid "Max Early Data" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:798 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:380 +msgid "Max Split" +msgstr "" + +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:799 msgid "Maximum packet size the socks5 server can receive from external" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1461 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1463 msgid "" "Min value is 1, Max value is 1024. When omitted or set to 0, Will same path " "as TCP traffic." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1448 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1450 msgid "" "Min value is 1, Max value is 128. When omitted or set to 0, it equals 8." msgstr "" @@ -1247,12 +1262,12 @@ msgid "Mixed as an alias of socks, default:Enabled." msgstr "" #: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/optimize_cbi_ui.htm:10 -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:714 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:735 msgid "Move down" msgstr "" #: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/optimize_cbi_ui.htm:7 -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:713 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:734 msgid "Move up" msgstr "" @@ -1261,7 +1276,7 @@ msgstr "" msgid "Muitiple DNS server can saperate with ','" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1024 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1025 msgid "Multi" msgstr "" @@ -1269,12 +1284,12 @@ msgstr "" msgid "Multi Threads Option" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:994 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1233 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:995 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1235 msgid "Must be JSON text!" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1427 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1429 msgid "Mux" msgstr "" @@ -1286,7 +1301,7 @@ msgstr "" msgid "NOT RUNNING" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:314 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:315 msgid "NaiveProxy" msgstr "" @@ -1314,15 +1329,15 @@ msgstr "" msgid "Netflix and AWS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:329 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:330 msgid "Network Tunnel" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:336 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:337 msgid "Network interface to use" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:741 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:742 msgid "New Reno" msgstr "" @@ -1336,19 +1351,19 @@ msgstr "" msgid "No new data!" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1575 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1578 msgid "No specify upload file." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:380 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:385 msgid "Noise" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:478 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:869 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1068 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1080 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1090 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:479 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:870 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1069 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1081 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1091 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:270 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:275 msgid "None" @@ -1373,35 +1388,35 @@ msgid "" "compatibility issues." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1502 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1504 msgid "Number of early established connections to reduce latency." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:477 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:513 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:478 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:514 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:139 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server.lua:133 msgid "Obfs" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:520 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:521 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:146 msgid "Obfs param (optional)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1144 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1145 msgid "Obfuscate password (optional)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:579 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:580 msgid "Obfuscation Password" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:573 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:574 msgid "Obfuscation Type" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1411 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1413 msgid "Once set, connects only when the server’s chain fingerprint matches." msgstr "" @@ -1448,11 +1463,15 @@ msgstr "" msgid "Oversea Mode DNS-2 (114.114.115.115)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:422 -msgid "Packet" +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:391 +msgid "Packet or Rand length as a string, e.g., 10-20." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:425 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:429 +msgid "Packet | Rand Length" +msgstr "" + +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:426 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:114 msgid "Password" msgstr "" @@ -1461,7 +1480,7 @@ msgstr "" msgid "Paste sharing link here" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1179 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1180 msgid "Peer public key" msgstr "" @@ -1470,7 +1489,7 @@ msgstr "" msgid "Perform reset" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1060 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1061 msgid "Permit Without Stream" msgstr "" @@ -1478,7 +1497,7 @@ msgstr "" msgid "Ping Latency" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1582 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1585 msgid "Please confirm the current certificate path" msgstr "" @@ -1486,23 +1505,23 @@ msgstr "" msgid "Please fill in reset" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:499 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:500 msgid "Plugin Opts" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:555 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:556 msgid "Port Hopping Interval(Unit:Second)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:537 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:538 msgid "Port hopping range" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1502 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1504 msgid "Pre-connections" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1183 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1184 msgid "Pre-shared key" msgstr "" @@ -1510,17 +1529,17 @@ msgstr "" msgid "Prefer firewall tools" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1174 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1175 msgid "Private key" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:503 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:504 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:132 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server.lua:128 msgid "Protocol" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:510 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:511 msgid "Protocol param (optional)" msgstr "" @@ -1528,35 +1547,35 @@ msgstr "" msgid "Proxy Ports" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1263 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1265 msgid "Public key" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1073 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1074 msgid "QUIC Key" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1066 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1067 msgid "QUIC Security" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:613 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:614 msgid "QUIC initConnReceiveWindow" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:599 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:600 msgid "QUIC initStreamReceiveWindow" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:620 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:621 msgid "QUIC maxConnReceiveWindow" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:627 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:628 msgid "QUIC maxIdleTimeout(Unit:second)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:606 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:607 msgid "QUIC maxStreamReceiveWindow" msgstr "" @@ -1565,7 +1584,7 @@ msgstr "" msgid "Quad9 DNSCrypt SDNS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1258 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1260 msgid "REALITY" msgstr "" @@ -1577,7 +1596,7 @@ msgstr "" msgid "RUNNING" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1132 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1133 msgid "Read Buffer Size" msgstr "" @@ -1597,7 +1616,7 @@ msgstr "" msgid "Records" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:343 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:344 msgid "Redirect traffic to this network interface" msgstr "" @@ -1628,12 +1647,12 @@ msgstr "" msgid "Regular update (Min)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1514 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1530 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1517 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1533 msgid "Reno" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1169 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1170 msgid "Reserved bytes(optional)" msgstr "" @@ -1698,7 +1717,7 @@ msgstr "" msgid "Same as Global Server" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:729 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:750 msgid "Save Order" msgstr "" @@ -1706,15 +1725,15 @@ msgstr "" msgid "Save Words splited by /" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:472 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:484 msgid "Save failed!" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:470 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:482 msgid "Saved current page order successfully." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:726 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:747 msgid "Saving the new order..." msgstr "" @@ -1723,12 +1742,12 @@ msgstr "" msgid "Select DNS parse Mode" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:347 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:348 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:176 msgid "Selection ShadowSocks Node Use Version." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1535 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1538 msgid "Self-signed Certificate" msgstr "" @@ -1736,7 +1755,7 @@ msgstr "" msgid "Server" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:385 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:386 msgid "Server Address" msgstr "" @@ -1744,11 +1763,11 @@ msgstr "" msgid "Server Count" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:300 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:301 msgid "Server Node Type" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:398 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:399 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:96 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server.lua:112 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:278 @@ -1776,7 +1795,7 @@ msgstr "" msgid "Servers subscription and manage" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1252 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1254 msgid "Session Ticket" msgstr "" @@ -1785,27 +1804,27 @@ msgstr "" msgid "Set Single DNS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:323 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:324 msgid "Shadow-TLS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:674 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:675 msgid "Shadow-TLS ChainPoxy type" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:308 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:374 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:309 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:375 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:89 msgid "ShadowSocks" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:354 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:355 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:103 msgid "ShadowSocks-libev Version" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:351 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:677 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:352 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:678 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:100 msgid "ShadowSocks-rust Version" msgstr "" @@ -1818,16 +1837,16 @@ msgstr "" msgid "ShadowSocksR Plus+ Settings" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:685 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:686 msgid "Shadowsocks password" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:305 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:306 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:92 msgid "ShadowsocksR" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1267 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1269 msgid "Short ID" msgstr "" @@ -1835,11 +1854,11 @@ msgstr "" msgid "Socket Connected" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:381 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:382 msgid "Socks" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:839 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:840 msgid "Socks Version" msgstr "" @@ -1847,7 +1866,7 @@ msgstr "" msgid "Socks protocol auth methods, default:noauth." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:326 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:327 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:87 msgid "Socks5" msgstr "" @@ -1904,8 +1923,8 @@ msgstr "" msgid "Switch check cycly(second)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:657 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1585 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:658 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1588 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:149 msgid "TCP Fast Open" msgstr "" @@ -1921,67 +1940,67 @@ msgstr "" msgid "TCP upstream" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1238 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1240 msgid "TLS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:652 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:653 msgid "TLS 1.3 Strict mode" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1360 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1362 msgid "TLS ALPN" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1416 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1418 msgid "TLS Certificate Name (CertName)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1411 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1413 msgid "TLS Chain Fingerprint (SHA256)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1352 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1354 msgid "TLS Host" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:527 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:539 msgid "TLS handshake test, latency for reference only" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1416 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1418 msgid "TLS is used to verify the leaf certificate name." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1110 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1111 msgid "TTI" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:320 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:321 msgid "TUIC" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1372 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1374 msgid "TUIC ALPN" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:717 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:718 msgid "TUIC Server IP Address" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:724 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:725 msgid "TUIC User Password" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:710 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:711 msgid "TUIC User UUID" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:775 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:776 msgid "TUIC receive window" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:769 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:770 msgid "TUIC send window" msgstr "" @@ -1990,23 +2009,23 @@ msgstr "" msgid "TWNIC-101 DNSCrypt SDNS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:527 -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:592 -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:616 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:539 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:604 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:628 msgid "Test" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:569 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:581 msgid "Testing..." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1339 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1341 msgid "" "The client has not configured mldsa65Verify, but it will not perform the " "\"additional verification\" step and can still connect normally, see:" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:278 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:279 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:166 msgid "" "The configured type also applies to the core specified when manually " @@ -2017,7 +2036,7 @@ msgstr "" msgid "The content entered is incorrect!" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:634 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:635 msgid "The keep-alive period.(Unit:second)" msgstr "" @@ -2029,7 +2048,7 @@ msgstr "" msgid "Through proxy update list, Not Recommended" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:751 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:752 msgid "Timeout for establishing a connection to server(second)" msgstr "" @@ -2038,15 +2057,15 @@ msgstr "" msgid "Tips: Dnsproxy DNS Parse List Path:" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:715 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:736 msgid "To Bottom" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:712 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:733 msgid "To Top" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:385 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:390 msgid "To send noise packets, select \"Noise\" in Xray Settings." msgstr "" @@ -2054,39 +2073,39 @@ msgstr "" msgid "Total Records:" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:848 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:849 msgid "Transport" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:549 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:550 msgid "Transport Protocol" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:311 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:373 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:312 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:374 msgid "Trojan" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:406 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:412 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:268 msgid "Type" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:551 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:552 msgid "UDP" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:380 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:385 msgid "" "UDP noise, Under some circumstances it can bypass some UDP based protocol " "restrictions." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:459 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:460 msgid "UDP over TCP" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:730 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:731 msgid "UDP relay mode" msgstr "" @@ -2134,11 +2153,11 @@ msgstr "" msgid "Update subscribe url list first" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1116 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1117 msgid "Uplink Capacity(Default:Mbps)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1545 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1548 #: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/certupload.htm:3 msgid "Upload" msgstr "" @@ -2192,7 +2211,7 @@ msgstr "" msgid "Use MosDNS query" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1100 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1101 msgid "" "Use it together with the DNS disguised type. You can fill in any domain." msgstr "" @@ -2201,7 +2220,7 @@ msgstr "" msgid "User cancelled." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1196 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1197 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:238 msgid "User-Agent" msgstr "" @@ -2211,54 +2230,54 @@ msgstr "" msgid "Userinfo format error." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:418 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:419 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:110 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server.lua:117 msgid "Username" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:525 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:526 msgid "Users Authentication" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:332 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:333 msgid "Using incorrect encryption mothod may causes service fail to start" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:302 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:303 msgid "V2Ray/XRay" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:370 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:371 msgid "V2Ray/XRay protocol" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:371 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:372 msgid "VLESS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:820 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:821 msgid "VLESS Encryption" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:372 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:373 msgid "VMess" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1081 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1091 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1082 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1092 msgid "VideoCall (SRTP)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:680 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:681 msgid "Vmess Protocol" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:695 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:696 msgid "Vmess UUID" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:812 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:813 msgid "Vmess/VLESS ID (UUID)" msgstr "" @@ -2274,16 +2293,16 @@ msgstr "" msgid "WAN White List IP" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:885 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:886 msgid "WebSocket Host" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:891 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:892 msgid "WebSocket Path" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1083 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1093 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1084 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1094 msgid "WechatVideo" msgstr "" @@ -2296,7 +2315,7 @@ msgstr "" msgid "When disabled, all AAAA requests are not resolved." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1157 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1158 msgid "When enabled, it occupies IPv6 routing table 1023." msgstr "" @@ -2312,37 +2331,37 @@ msgid "" "correctly." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:376 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1085 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1095 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:377 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1086 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1096 msgid "WireGuard" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1189 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1190 msgid "Wireguard allows only traffic from specific source IP." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1138 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1139 msgid "Write Buffer Size" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:951 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:952 msgid "XHTTP Extra" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:939 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:940 msgid "XHTTP Host" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:930 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:931 msgid "XHTTP Mode" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:945 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:946 msgid "XHTTP Path" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:282 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:283 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:82 msgid "Xray (Hysteria2)" msgstr "" @@ -2355,7 +2374,7 @@ msgstr "" msgid "Xray Fragment Settings" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:383 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:388 msgid "Xray Noise Packets" msgstr "" @@ -2363,27 +2382,27 @@ msgstr "" msgid "adblock_url" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1069 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1070 msgid "aes-128-gcm" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1480 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1482 msgid "allow" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1474 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1476 msgid "allow: Allows use Mux connection." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1394 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1396 msgid "allowInsecure" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1188 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1189 msgid "allowedIPs(optional)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1295 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1297 msgid "android" msgstr "" @@ -2391,7 +2410,7 @@ msgstr "" msgid "anti-AD" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1070 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1071 msgid "chacha20-poly1305" msgstr "" @@ -2399,7 +2418,7 @@ msgstr "" msgid "china-operator-ip" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1291 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1293 msgid "chrome" msgstr "" @@ -2408,27 +2427,27 @@ msgstr "" msgid "cloudflare-dns.com DNSCrypt SDNS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1511 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1526 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1513 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1529 msgid "comment_tcpcongestion_disable" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1444 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1446 msgid "concurrency" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:666 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:678 msgid "connect" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1508 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1523 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1510 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1526 msgid "custom_tcpcongestion" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1301 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1452 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1465 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1303 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1454 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1467 msgid "disable" msgstr "" @@ -2437,7 +2456,7 @@ msgstr "" msgid "dns.sb DNSCrypt SDNS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1296 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1298 msgid "edge" msgstr "" @@ -2450,19 +2469,19 @@ msgstr "" msgid "felixonmars/dnsmasq-china-list" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1292 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1294 msgid "firefox" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1048 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1049 msgid "gRPC Idle Timeout" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1021 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1022 msgid "gRPC Mode" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1015 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1016 msgid "gRPC Service Name" msgstr "" @@ -2474,7 +2493,7 @@ msgstr "" msgid "gfwlist/gfwlist" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1294 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1296 msgid "ios" msgstr "" @@ -2483,11 +2502,11 @@ msgstr "" msgid "load_balance" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:733 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:734 msgid "lossless UDP relay using QUIC streams" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:732 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:733 msgid "native UDP characteristics" msgstr "" @@ -2495,12 +2514,12 @@ msgstr "" msgid "nfip_url" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:450 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1280 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:451 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1282 msgid "none" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:480 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:481 msgid "obfs-local" msgstr "" @@ -2509,49 +2528,49 @@ msgstr "" msgid "parallel" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1298 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1300 msgid "qq" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1299 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1301 msgid "random" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1300 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1302 msgid "randomized" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1479 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1481 msgid "reject" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1293 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1295 msgid "safari" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:667 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:668 msgid "shadow-TLS SNI" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:489 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:490 msgid "shadow-tls" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:645 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:646 msgid "shadowTLS protocol Version" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1481 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1483 msgid "skip" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1475 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1477 msgid "" "skip: Not use Mux module to carry UDP 443 traffic, Use original UDP " "transmission method of proxy protocol." msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1271 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1273 msgid "spiderX" msgstr "" @@ -2559,7 +2578,7 @@ msgstr "" msgid "v2fly/domain-list-community" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:483 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:484 msgid "v2ray-plugin" msgstr "" @@ -2571,14 +2590,14 @@ msgstr "" msgid "warning! Please do not reuse the port!" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:486 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:487 msgid "xray-plugin" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1457 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1459 msgid "xudpConcurrency" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1470 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1472 msgid "xudpProxyUDP443" msgstr "" diff --git a/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po b/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po index 081c4030..ee257c9a 100644 --- a/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po +++ b/luci-app-ssr-plus/po/zh_Hans/ssr-plus.po @@ -10,12 +10,12 @@ msgstr "" "\"1-3\" 是 TCP 的流切片,应用于客户端第 1 至第 3 次写数据。\"tlshello\" 是 " "TLS 握手包切片。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:277 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:278 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:165 msgid "%s Node Use Type" msgstr "%s 节点使用类型" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:346 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:347 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:175 msgid "%s Node Use Version" msgstr "%s 节点使用版本" @@ -32,7 +32,7 @@ msgstr "单线程" msgid "128 Threads" msgstr "128 线程" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1466 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1468 msgid "16" msgstr "" @@ -48,7 +48,7 @@ msgstr "2 线程" msgid "32 Threads" msgstr "32 线程" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1297 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1299 msgid "360" msgstr "" @@ -68,7 +68,7 @@ msgstr "4 线程" msgid "64 Threads" msgstr "64 线程" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1453 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1455 msgid "8" msgstr "" @@ -76,13 +76,13 @@ msgstr "" msgid "8 Threads" msgstr "8 线程" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:385 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:390 msgid "" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:959 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1312 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1339 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:960 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1314 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1341 msgid "" msgstr "" @@ -97,10 +97,10 @@ msgstr "" #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:160 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:186 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:220 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1155 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1446 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1459 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1472 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1156 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1448 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1461 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1474 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client.lua:188 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client.lua:214 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client.lua:249 @@ -116,7 +116,7 @@ msgstr "访问控制" msgid "AdGuard DNSCrypt SDNS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:728 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:749 msgid "Add" msgstr "添加" @@ -136,7 +136,7 @@ msgstr "" msgid "Alias" msgstr "别名" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:334 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:335 msgid "Alias(optional)" msgstr "别名(可选)" @@ -156,11 +156,11 @@ msgstr "仅允许列表内主机" msgid "Allow subscribe Insecure nodes By default" msgstr "订阅节点允许不验证 TLS 证书" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:805 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:806 msgid "AlterId" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1215 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1216 msgid "An FinalMaskObject in JSON format, used for sharing." msgstr "JSON 格式的 FinalMaskObject,用来实现分享。" @@ -199,7 +199,7 @@ msgstr "Apple 域名解析优化" msgid "Apply" msgstr "应用" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:379 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:391 msgid "Are you sure to delete this node?" msgstr "是否真的要删除该节点?" @@ -223,13 +223,14 @@ msgstr "自动更新" msgid "Auto Update Server subscription, GFW list and CHN route" msgstr "自动更新服务器订阅、GFW 列表和中国大陆 IP 段" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:739 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1512 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1527 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:740 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1514 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1530 msgid "BBR" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1528 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1515 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1531 msgid "BRUTAL" msgstr "" @@ -253,8 +254,8 @@ msgstr "" msgid "Base64 sstr failed." msgstr "Base64 解码失败。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1082 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1092 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1083 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1093 msgid "BitTorrent (uTP)" msgstr "BT 下载(uTP)" @@ -262,7 +263,7 @@ msgstr "BT 下载(uTP)" msgid "Black Domain List" msgstr "强制走代理的域名" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:465 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:466 msgid "Bloom Filter" msgstr "布隆过滤器" @@ -278,22 +279,22 @@ msgstr "关闭窗口" msgid "CNNIC SDNS (1.2.4.8)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:740 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1513 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1531 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:741 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1516 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1534 msgid "CUBIC" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1099 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1100 msgid "Camouflage Domain" msgstr "伪装域名" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:867 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1088 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:868 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1089 msgid "Camouflage Type" msgstr "伪装类型" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1422 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1424 msgid "Certificate fingerprint" msgstr "证书指纹" @@ -357,10 +358,10 @@ msgstr "清空日志" msgid "Click here to view or manage the DNS list file" msgstr "点击此处查看或管理 DNS 列表文件" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:388 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:961 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1314 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1341 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:394 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:962 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1316 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1343 msgid "Click to the page" msgstr "点击前往" @@ -385,15 +386,15 @@ msgstr "" msgid "Collecting data..." msgstr "正在收集数据中..." -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:959 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:960 msgid "Configure XHTTP Extra Settings (JSON format), see:" msgstr "配置 XHTTP 额外设置(JSON 格式),具体请参见:" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1148 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1149 msgid "Congestion" msgstr "拥塞控制" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:737 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:738 msgid "Congestion control algorithm" msgstr "拥塞控制算法" @@ -409,7 +410,7 @@ msgstr "连接正常" msgid "Connection Timeout" msgstr "连接超时" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1325 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1327 msgid "" "Controls the policy used when performing DNS queries for ECH configuration." msgstr "控制使用 DNS 查询 ECH 配置时的策略。" @@ -422,15 +423,15 @@ msgstr "成功复制 SSR 网址到剪贴板。" msgid "Create Backup File" msgstr "创建备份文件" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1559 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1562 msgid "Create upload file error." msgstr "创建上传文件错误。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1579 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1582 msgid "Current Certificate Path" msgstr "当前证书路径" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:491 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:492 msgid "Custom" msgstr "自定义" @@ -462,7 +463,7 @@ msgid "" msgstr "" "格式为tcp://IP:Port或tls://域名:Port (tcp://8.8.8.8或tls://dns.google:853)" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:495 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:496 msgid "Custom Plugin Path" msgstr "自定义插件路径" @@ -470,6 +471,12 @@ msgstr "自定义插件路径" msgid "Custom Ports" msgstr "自定义端口" +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1217 +msgid "" +"Custom finalmask overrides mkcp, hysteria2, fragment, noise, and related " +"settings." +msgstr "自定义 finalmask 将覆盖 mkcp、hysteria2、fragment、noise 等相关配置。" + #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:103 msgid "Customize Netflix IP Url" msgstr "" @@ -480,7 +487,7 @@ msgstr "" msgid "DL Backup" msgstr "下载备份" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1096 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1097 msgid "DNS" msgstr "" @@ -496,36 +503,36 @@ msgstr "分流模式下的 DNS 查询模式" msgid "DNSPod Public DNS (119.29.29.29)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1084 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1094 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1085 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1095 msgid "DTLS 1.2" msgstr "DTLS 1.2 数据包" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1170 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1171 msgid "Decimal numbers separated by \",\" or Base64-encoded strings." msgstr "用“,”隔开的十进制数字或 Base64 编码字符串。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1362 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1374 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1388 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1364 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1376 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1390 msgid "Default" msgstr "默认" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1473 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1475 msgid "Default reject rejects traffic." msgstr "默认 reject 拒绝流量。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:635 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:636 msgid "Default value 0 indicatesno heartbeat." msgstr "默认为 0 表示无心跳。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1447 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1449 msgid "" "Default: disable. When entering a negative number, such as -1, The Mux " "module will not be used to carry TCP traffic." msgstr "默认:禁用。填负数时,如 -1,不使用 Mux 模块承载 TCP 流量。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1460 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1462 msgid "" "Default:16. When entering a negative number, such as -1, The Mux module will " "not be used to carry UDP traffic, Use original UDP transmission method of " @@ -548,11 +555,11 @@ msgstr "" "定义上游逻辑模式,可选择值:负载均衡、并行查询、最快响应(默认值:负载均" "衡)。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:426 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:433 msgid "Delay (ms)" msgstr "延迟(ms)" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:717 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:738 msgid "Delete" msgstr "删除" @@ -588,15 +595,15 @@ msgstr "禁止 MOSDNS 返回 IPv6 记录" msgid "Disable IPv6 query mode" msgstr "禁止返回 IPv6 记录" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:592 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:593 msgid "Disable QUIC path MTU discovery" msgstr "禁用 QUIC 启用 MTU 探测" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:781 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:782 msgid "Disable SNI" msgstr "关闭 SNI 服务器名称指示" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:662 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:663 msgid "Disable TCP No_delay" msgstr "禁用 TCP 无延迟" @@ -617,7 +624,7 @@ msgstr "是否要恢复客户端默认配置?" msgid "DoT upstream (Need use wolfssl version)" msgstr "DoT 上游(需使用 wolfssl 版本)" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:413 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:420 msgid "Domain Strategy" msgstr "域名解析策略" @@ -625,78 +632,78 @@ msgstr "域名解析策略" msgid "Domestic DNS Server" msgstr "国内 DNS 服务器" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1124 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1125 msgid "Downlink Capacity(Default:Mbps)" msgstr "下行链路容量(默认:Mbps)" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:718 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:739 msgid "Drag to reorder" msgstr "拖动以重排" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:792 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:793 msgid "Dual-stack Listening Socket" msgstr "双栈 Socket 监听" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1310 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1312 msgid "ECH Config" msgstr "ECH 配置" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1324 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1326 msgid "ECH Query Policy" msgstr "ECH 查询策略" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:909 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:910 msgid "Early Data Header Name" msgstr "前置数据标头" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:716 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:737 msgid "Edit" msgstr "编辑" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:257 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:258 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:69 msgid "Edit ShadowSocksR Server" msgstr "编辑服务器配置" #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:271 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:402 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:408 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:82 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server.lua:101 msgid "Enable" msgstr "启用" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:786 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:787 msgid "Enable 0-RTT QUIC handshake" msgstr "客户端启用 0-RTT QUIC 连接握手" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:411 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:412 msgid "Enable Authentication" msgstr "启用用户名/密码认证" #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:63 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1595 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1598 msgid "Enable Auto Switch" msgstr "启用自动切换" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1305 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1307 msgid "Enable ECH(optional)" msgstr "启用 ECH (可选)" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:568 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:569 msgid "Enable Lazy Mode" msgstr "启用懒狗模式" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1332 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1334 msgid "Enable ML-DSA-65(optional)" msgstr "启用 ML-DSA-65 (可选)" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1491 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1493 msgid "" "Enable Multipath TCP, need to be enabled in both server and client " "configuration." msgstr "启用 Multipath TCP,需在服务端和客户端配置中同时启用。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1427 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1429 msgid "Enable Mux.Cool" msgstr "启用 Mux.Cool" @@ -704,15 +711,15 @@ msgstr "启用 Mux.Cool" msgid "Enable Netflix Mode" msgstr "启用 Netflix 分流模式" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:562 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:563 msgid "Enable Obfuscation" msgstr "启用混淆功能" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:471 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:472 msgid "Enable Plugin" msgstr "启用插件" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:531 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:532 msgid "Enable Port Hopping" msgstr "启用端口跳跃" @@ -720,15 +727,15 @@ msgstr "启用端口跳跃" msgid "Enable Server" msgstr "启动服务端" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:544 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:545 msgid "Enable Transport Protocol Settings" msgstr "启用传输协议设置" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:648 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:649 msgid "Enable V2 protocol." msgstr "开启 V2 协议。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:647 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:648 msgid "Enable V3 protocol." msgstr "开启 V3 协议。" @@ -736,15 +743,15 @@ msgstr "开启 V3 协议。" msgid "Enable adblock" msgstr "启用广告屏蔽" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:460 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:461 msgid "Enable the SUoT protocol, requires server support." msgstr "启用 SUoT 协议,需要服务端支持。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:952 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:953 msgid "Enable this option to configure XHTTP Extra (JSON format)." msgstr "启用此选项配置 XHTTP 附加项(JSON 格式)。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1153 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1154 msgid "Enabled Kernel virtual NIC TUN(optional)" msgstr "启用内核的虚拟网卡 TUN(可选)" @@ -752,16 +759,16 @@ msgstr "启用内核的虚拟网卡 TUN(可选)" msgid "Enabled Mixed" msgstr "启用 Mixed" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:657 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1585 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:658 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1588 msgid "Enabling TCP Fast Open Requires Server Support." msgstr "启用 TCP 快速打开需要服务端支持。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:439 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:446 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:689 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:700 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:831 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:440 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:447 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:690 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:701 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:832 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:118 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:125 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server.lua:122 @@ -812,7 +819,7 @@ msgstr "应为:%s" msgid "External Proxy Mode" msgstr "分流服务器(前置)代理" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1529 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1532 msgid "FORCE BRUTAL" msgstr "" @@ -820,15 +827,15 @@ msgstr "" msgid "Filter Words splited by /" msgstr "命中关键字的节点将被丢弃。多个关键字用 / 分隔" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1204 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1205 msgid "FinalMask" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1289 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1291 msgid "Finger Print" msgstr "指纹伪造" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1276 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1278 msgid "Flow" msgstr "流控(Flow)" @@ -838,11 +845,11 @@ msgid "" "Chinese CDN IP addresses" msgstr "配备中国大陆 CDN 的 Apple 域名,始终应答中国大陆 CDN 地址" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:386 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:392 msgid "For specific usage, see:" msgstr "具体使用方法,具体请参见:" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:538 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:539 msgid "" "Format as 10000:20000 or 10000-20000 Multiple groups are separated by commas " "(,)." @@ -857,8 +864,8 @@ msgid "Fragment" msgstr "分片" #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:375 -msgid "Fragment Interval" -msgstr "分片间隔" +msgid "Fragment Delay" +msgstr "分片延迟" #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:370 msgid "Fragment Length" @@ -896,11 +903,11 @@ msgstr "游戏模式 UDP 中继" msgid "Game Mode UDP Server" msgstr "游戏模式 UDP 中继服务器" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:757 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:758 msgid "Garbage collection interval(second)" msgstr "UDP 数据包片残片清理间隔(单位:秒)" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:763 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:764 msgid "Garbage collection lifetime(second)" msgstr "UDP 数据包残片在服务器的保留时间(单位:秒)" @@ -953,71 +960,71 @@ msgstr "" msgid "Grant UCI access for luci-app-ssr-plus" msgstr "授予访问 luci-app-ssr-plus 配置的权限" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1023 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1024 msgid "Gun" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1042 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1043 msgid "H2 Read Idle Timeout" msgstr "H2 读取空闲超时" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1037 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1038 msgid "H2/gRPC Health Check" msgstr "H2/gRPC 健康检查" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:382 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:870 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:383 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:871 msgid "HTTP" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:874 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:875 msgid "HTTP Host" msgstr "HTTP 主机名" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:879 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:880 msgid "HTTP Path" msgstr "HTTP 路径" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1005 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1006 msgid "HTTP/2 Host" msgstr "HTTP/2 主机名" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1010 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1011 msgid "HTTP/2 Path" msgstr "HTTP/2 路径" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1077 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1078 msgid "Header" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1054 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1055 msgid "Health Check Timeout" msgstr "健康检查超时" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:745 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:746 msgid "Heartbeat interval(second)" msgstr "保活心跳包发送间隔(单位:秒)" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:896 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:897 msgid "HeartbeatPeriod(second)" msgstr "心跳周期(单位:秒)" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:918 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:919 msgid "Httpupgrade Host" msgstr "HTTPUpgrade 主机名" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:923 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:924 msgid "Httpupgrade Path" msgstr "HTTPUpgrade 路径" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:285 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:317 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:379 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:286 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:318 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:380 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:79 msgid "Hysteria2" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:586 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:587 msgid "Hysterir QUIC parameters" msgstr "QUIC 参数" @@ -1025,7 +1032,7 @@ msgstr "QUIC 参数" msgid "IP Route Mode" msgstr "绕过中国大陆 IP 模式" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1386 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1388 msgid "IP Stack Preference" msgstr "IP 栈优先级" @@ -1033,24 +1040,24 @@ msgstr "IP 栈优先级" msgid "If empty, Not change Apple domains parsing DNS (Default is empty)" msgstr "如果为空,则不更改 Apple 域名解析 DNS(默认为空)" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1312 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1314 msgid "" "If it is not empty, it indicates that the Client has enabled Encrypted " "Client, see:" msgstr "如果不为空,表示客户端已启用加密客户端,具体请参见:" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:793 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:794 msgid "If this option is not set, the socket behavior is platform dependent." msgstr "如果未设置此选项,则 Socket 行为依赖于平台。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1399 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1401 msgid "" "If true, allowss insecure connection at TLS client, e.g., TLS server uses " "unverifiable certificates." msgstr "" "是否允许不安全连接。当选择时,将不会检查远端主机所提供的 TLS 证书的有效性。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1543 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1546 msgid "If you have a self-signed certificate,please check the box" msgstr "如果你使用自签证书,请选择" @@ -1070,7 +1077,7 @@ msgstr "导入配置信息" msgid "Import configuration information successfully." msgstr "导入配置信息成功。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1030 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1031 msgid "Initial Windows Size" msgstr "初始窗口大小" @@ -1090,19 +1097,19 @@ msgstr "无效的格式。" msgid "KcpTun" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1605 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1608 msgid "KcpTun Enable" msgstr "KcpTun 启用" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1622 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1625 msgid "KcpTun Param" msgstr "KcpTun 参数" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1617 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1620 msgid "KcpTun Password" msgstr "KcpTun 密码" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1611 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1614 msgid "KcpTun Port" msgstr "KcpTun 端口" @@ -1187,7 +1194,11 @@ msgstr "" msgid "Level 3 Public DNS-3 (4.2.2.3-4)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1156 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:380 +msgid "Limit the maximum number of splits." +msgstr "限制分片的最大数量。" + +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1157 msgid "" "Linux kernel TUN virtual NIC requires system support and root privileges." msgstr "Linux 内核 TUN 虚拟网卡需要系统支持和 root 权限。" @@ -1197,7 +1208,7 @@ msgid "Listen only on the given interface or, if unspecified, on all" msgstr "" #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:348 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1599 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1602 msgid "Local Port" msgstr "本地端口" @@ -1205,7 +1216,7 @@ msgstr "本地端口" msgid "Local Servers" msgstr "本机服务端" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1164 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1165 msgid "Local addresses" msgstr "本地地址" @@ -1221,15 +1232,15 @@ msgstr "" msgid "Loyalsoldier/v2ray-rules-dat" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1337 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1339 msgid "ML-DSA-65 Public key" msgstr "ML-DSA-65 公钥" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1491 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1493 msgid "MPTCP" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1103 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1104 msgid "MTU" msgstr "最大传输单元" @@ -1237,15 +1248,19 @@ msgstr "最大传输单元" msgid "Main Server" msgstr "主服务器" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:902 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:903 msgid "Max Early Data" msgstr "最大前置数据" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:798 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:380 +msgid "Max Split" +msgstr "最大分片数" + +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:799 msgid "Maximum packet size the socks5 server can receive from external" msgstr "socks5 服务器可以从外部接收的最大数据包大小(单位:字节)" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1461 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1463 msgid "" "Min value is 1, Max value is 1024. When omitted or set to 0, Will same path " "as TCP traffic." @@ -1253,7 +1268,7 @@ msgstr "" "最小值 1,最大值 1024。 省略或者填 0 时,将与 TCP 流量走同一条路,也就是传统" "的行为。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1448 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1450 msgid "" "Min value is 1, Max value is 128. When omitted or set to 0, it equals 8." msgstr "最小值 1,最大值 128。省略或者填 0 时都等于 8。" @@ -1263,12 +1278,12 @@ msgid "Mixed as an alias of socks, default:Enabled." msgstr "Mixed 作为 SOCKS 的别名,默认:启用。" #: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/optimize_cbi_ui.htm:10 -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:714 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:735 msgid "Move down" msgstr "下移" #: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/optimize_cbi_ui.htm:7 -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:713 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:734 msgid "Move up" msgstr "上移" @@ -1277,7 +1292,7 @@ msgstr "上移" msgid "Muitiple DNS server can saperate with ','" msgstr "多个上游 DNS 服务器请用 ',' 分隔(注意用英文逗号)" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1024 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1025 msgid "Multi" msgstr "" @@ -1285,12 +1300,12 @@ msgstr "" msgid "Multi Threads Option" msgstr "多线程并发转发" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:994 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1233 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:995 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1235 msgid "Must be JSON text!" msgstr "必须是 JSON 文本内容!" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1427 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1429 msgid "Mux" msgstr "" @@ -1302,7 +1317,7 @@ msgstr "" msgid "NOT RUNNING" msgstr "未运行" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:314 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:315 msgid "NaiveProxy" msgstr "" @@ -1330,15 +1345,15 @@ msgstr "Netflix 分流服务器" msgid "Netflix and AWS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:329 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:330 msgid "Network Tunnel" msgstr "网络隧道" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:336 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:337 msgid "Network interface to use" msgstr "使用的网络接口" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:741 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:742 msgid "New Reno" msgstr "" @@ -1352,19 +1367,19 @@ msgstr "未检查" msgid "No new data!" msgstr "你已经是最新数据,无需更新!" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1575 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1578 msgid "No specify upload file." msgstr "没有上传证书。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:380 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:385 msgid "Noise" msgstr "噪声" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:478 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:869 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1068 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1080 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1090 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:479 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:870 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1069 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1081 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1091 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:270 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:275 msgid "None" @@ -1389,35 +1404,35 @@ msgid "" "compatibility issues." msgstr "注意:不同版本间的配置恢复可能会导致兼容性问题。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1502 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1504 msgid "Number of early established connections to reduce latency." msgstr "预连接的数量,用于降低延迟。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:477 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:513 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:478 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:514 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:139 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server.lua:133 msgid "Obfs" msgstr "混淆插件" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:520 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:521 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:146 msgid "Obfs param (optional)" msgstr "混淆参数(可选)" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1144 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1145 msgid "Obfuscate password (optional)" msgstr "混淆密码(可选)" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:579 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:580 msgid "Obfuscation Password" msgstr "混淆密码" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:573 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:574 msgid "Obfuscation Type" msgstr "混淆类型" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1411 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1413 msgid "Once set, connects only when the server’s chain fingerprint matches." msgstr "设置后,仅在服务器证书链指纹匹配时连接。" @@ -1464,11 +1479,15 @@ msgstr "" msgid "Oversea Mode DNS-2 (114.114.115.115)" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:422 -msgid "Packet" -msgstr "数据包" +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:391 +msgid "Packet or Rand length as a string, e.g., 10-20." +msgstr "数据包或 Rand 长度以字符串形式输入,例如:10-20。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:425 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:429 +msgid "Packet | Rand Length" +msgstr "数据包 | Rand 长度" + +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:426 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:114 msgid "Password" msgstr "密码" @@ -1477,7 +1496,7 @@ msgstr "密码" msgid "Paste sharing link here" msgstr "在此处粘贴分享链接" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1179 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1180 msgid "Peer public key" msgstr "节点公钥" @@ -1486,7 +1505,7 @@ msgstr "节点公钥" msgid "Perform reset" msgstr "执行重置" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1060 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1061 msgid "Permit Without Stream" msgstr "允许无数据流" @@ -1494,7 +1513,7 @@ msgstr "允许无数据流" msgid "Ping Latency" msgstr "Ping 延迟" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1582 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1585 msgid "Please confirm the current certificate path" msgstr "请选择确认所传证书,证书不正确将无法运行" @@ -1502,23 +1521,23 @@ msgstr "请选择确认所传证书,证书不正确将无法运行" msgid "Please fill in reset" msgstr "请填写 reset" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:499 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:500 msgid "Plugin Opts" msgstr "插件参数" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:555 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:556 msgid "Port Hopping Interval(Unit:Second)" msgstr "端口跳跃间隔(单位:秒)" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:537 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:538 msgid "Port hopping range" msgstr "端口跳跃范围" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1502 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1504 msgid "Pre-connections" msgstr "预连接" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1183 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1184 msgid "Pre-shared key" msgstr "预共享密钥" @@ -1526,17 +1545,17 @@ msgstr "预共享密钥" msgid "Prefer firewall tools" msgstr "首选防火墙工具" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1174 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1175 msgid "Private key" msgstr "私钥" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:503 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:504 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:132 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server.lua:128 msgid "Protocol" msgstr "传输协议" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:510 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:511 msgid "Protocol param (optional)" msgstr "传输协议参数(可选)" @@ -1544,35 +1563,35 @@ msgstr "传输协议参数(可选)" msgid "Proxy Ports" msgstr "需要代理的端口" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1263 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1265 msgid "Public key" msgstr "公钥" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1073 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1074 msgid "QUIC Key" msgstr "QUIC 密钥" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1066 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1067 msgid "QUIC Security" msgstr "QUIC 加密方式" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:613 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:614 msgid "QUIC initConnReceiveWindow" msgstr "QUIC 初始的连接接收窗口大小" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:599 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:600 msgid "QUIC initStreamReceiveWindow" msgstr "QUIC 初始流接收窗口大小。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:620 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:621 msgid "QUIC maxConnReceiveWindow" msgstr "QUIC 最大的连接接收窗口大小" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:627 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:628 msgid "QUIC maxIdleTimeout(Unit:second)" msgstr "QUIC 最长空闲超时时间(单位:秒)" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:606 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:607 msgid "QUIC maxStreamReceiveWindow" msgstr "QUIC 最大的流接收窗口大小" @@ -1581,7 +1600,7 @@ msgstr "QUIC 最大的流接收窗口大小" msgid "Quad9 DNSCrypt SDNS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1258 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1260 msgid "REALITY" msgstr "" @@ -1593,7 +1612,7 @@ msgstr "恢复备份" msgid "RUNNING" msgstr "运行中" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1132 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1133 msgid "Read Buffer Size" msgstr "读取缓冲区大小" @@ -1613,7 +1632,7 @@ msgstr "重新应用" msgid "Records" msgstr "条记录" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:343 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:344 msgid "Redirect traffic to this network interface" msgstr "分流到这个网络接口" @@ -1644,12 +1663,12 @@ msgstr "定时更新(小时)" msgid "Regular update (Min)" msgstr "定时更新(分钟)" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1514 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1530 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1517 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1533 msgid "Reno" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1169 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1170 msgid "Reserved bytes(optional)" msgstr "保留字节(可选)" @@ -1714,7 +1733,7 @@ msgstr "服务端" msgid "Same as Global Server" msgstr "与全局服务器相同" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:729 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:750 msgid "Save Order" msgstr "保存当前顺序" @@ -1723,15 +1742,15 @@ msgid "Save Words splited by /" msgstr "" "命中关键字的节点将被保留。多个关键字用 / 分隔。此项为空则不启用保留匹配" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:472 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:484 msgid "Save failed!" msgstr "保存失败!" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:470 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:482 msgid "Saved current page order successfully." msgstr "保存当前页面顺序成功。" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:726 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:747 msgid "Saving the new order..." msgstr "正在保存新的顺序…" @@ -1740,12 +1759,12 @@ msgstr "正在保存新的顺序…" msgid "Select DNS parse Mode" msgstr "选择 DNS 解析方式" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:347 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:348 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:176 msgid "Selection ShadowSocks Node Use Version." msgstr "选择 ShadowSocks 节点使用版本。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1535 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1538 msgid "Self-signed Certificate" msgstr "自签证书" @@ -1753,7 +1772,7 @@ msgstr "自签证书" msgid "Server" msgstr "服务器" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:385 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:386 msgid "Server Address" msgstr "服务器地址" @@ -1761,11 +1780,11 @@ msgstr "服务器地址" msgid "Server Count" msgstr "服务器节点数量" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:300 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:301 msgid "Server Node Type" msgstr "服务器节点类型" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:398 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:399 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:96 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server.lua:112 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:278 @@ -1793,7 +1812,7 @@ msgstr "服务器节点" msgid "Servers subscription and manage" msgstr "服务器节点订阅与管理" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1252 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1254 msgid "Session Ticket" msgstr "会话凭据" @@ -1802,27 +1821,27 @@ msgstr "会话凭据" msgid "Set Single DNS" msgstr "设置单个 DNS" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:323 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:324 msgid "Shadow-TLS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:674 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:675 msgid "Shadow-TLS ChainPoxy type" msgstr "代理链类型" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:308 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:374 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:309 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:375 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:89 msgid "ShadowSocks" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:354 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:355 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:103 msgid "ShadowSocks-libev Version" msgstr "ShadowSocks-libev 版本" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:351 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:677 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:352 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:678 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:100 msgid "ShadowSocks-rust Version" msgstr "ShadowSocks-rust 版本" @@ -1835,16 +1854,16 @@ msgstr "" msgid "ShadowSocksR Plus+ Settings" msgstr "ShadowSocksR Plus+ 设置" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:685 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:686 msgid "Shadowsocks password" msgstr "shadowsocks密码" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:305 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:306 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:92 msgid "ShadowsocksR" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1267 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1269 msgid "Short ID" msgstr "" @@ -1852,11 +1871,11 @@ msgstr "" msgid "Socket Connected" msgstr "连接测试" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:381 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:382 msgid "Socks" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:839 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:840 msgid "Socks Version" msgstr "Socks 版本" @@ -1864,7 +1883,7 @@ msgstr "Socks 版本" msgid "Socks protocol auth methods, default:noauth." msgstr "Socks 协议的认证方式,默认值:noauth。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:326 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:327 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:87 msgid "Socks5" msgstr "" @@ -1921,8 +1940,8 @@ msgstr "同时支持 AdGuard Home 和 DNSMASQ 格式的过滤列表" msgid "Switch check cycly(second)" msgstr "自动切换检查周期(秒)" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:657 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1585 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:658 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1588 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:149 msgid "TCP Fast Open" msgstr "TCP 快速打开" @@ -1938,67 +1957,67 @@ msgstr "TCP 分片,在某些情况下可以欺骗审查系统,比如绕过 S msgid "TCP upstream" msgstr "TCP 上游" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1238 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1240 msgid "TLS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:652 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:653 msgid "TLS 1.3 Strict mode" msgstr "TLS 1.3 限定模式" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1360 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1362 msgid "TLS ALPN" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1416 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1418 msgid "TLS Certificate Name (CertName)" msgstr "TLS 证书名称(CertName)" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1411 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1413 msgid "TLS Chain Fingerprint (SHA256)" msgstr "TLS 证书链指纹(SHA256)" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1352 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1354 msgid "TLS Host" msgstr "TLS 主机名" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:527 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:539 msgid "TLS handshake test, latency for reference only" msgstr "TLS握手测试,延时仅供参考" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1416 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1418 msgid "TLS is used to verify the leaf certificate name." msgstr "TLS 用于验证 leaf 证书的 name。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1110 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1111 msgid "TTI" msgstr "传输时间间隔" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:320 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:321 msgid "TUIC" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1372 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1374 msgid "TUIC ALPN" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:717 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:718 msgid "TUIC Server IP Address" msgstr "TUIC 服务器 IP 地址" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:724 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:725 msgid "TUIC User Password" msgstr "TUIC 用户密钥" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:710 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:711 msgid "TUIC User UUID" msgstr "TUIC 用户 uuid" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:775 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:776 msgid "TUIC receive window" msgstr "接收窗口(无需确认即可接收的最大字节数:默认8Mb)" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:769 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:770 msgid "TUIC send window" msgstr "发送窗口(无需确认即可发送的最大字节数:默认8Mb*2)" @@ -2007,17 +2026,17 @@ msgstr "发送窗口(无需确认即可发送的最大字节数:默认8Mb*2 msgid "TWNIC-101 DNSCrypt SDNS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:527 -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:592 -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:616 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:539 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:604 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:628 msgid "Test" msgstr "测试" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:569 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:581 msgid "Testing..." msgstr "检测中…" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1339 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1341 msgid "" "The client has not configured mldsa65Verify, but it will not perform the " "\"additional verification\" step and can still connect normally, see:" @@ -2025,7 +2044,7 @@ msgstr "" "客户端若未配置 mldsa65Verify,但它不会执行 \"附加验证\" 步骤,仍可以正常连" "接,具体请参见:" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:278 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:279 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:166 msgid "" "The configured type also applies to the core specified when manually " @@ -2036,7 +2055,7 @@ msgstr "配置的类型同样适用于手动导入节点时所指定的核心程 msgid "The content entered is incorrect!" msgstr "输入的内容不正确!" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:634 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:635 msgid "The keep-alive period.(Unit:second)" msgstr "心跳包发送间隔(单位:秒)" @@ -2048,7 +2067,7 @@ msgstr "通过代理更新" msgid "Through proxy update list, Not Recommended" msgstr "通过路由器自身代理更新订阅" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:751 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:752 msgid "Timeout for establishing a connection to server(second)" msgstr "连接超时时间(单位:秒)" @@ -2057,15 +2076,15 @@ msgstr "连接超时时间(单位:秒)" msgid "Tips: Dnsproxy DNS Parse List Path:" msgstr "提示:Dnsproxy 的 DNS 解析列表路径:" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:715 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:736 msgid "To Bottom" msgstr "置底" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:712 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:733 msgid "To Top" msgstr "置顶" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:385 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:390 msgid "To send noise packets, select \"Noise\" in Xray Settings." msgstr "在 Xray 设置中勾选 “噪声” 以发送噪声包。" @@ -2073,39 +2092,39 @@ msgstr "在 Xray 设置中勾选 “噪声” 以发送噪声包。" msgid "Total Records:" msgstr "新的总记录数:" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:848 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:849 msgid "Transport" msgstr "传输协议" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:549 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:550 msgid "Transport Protocol" msgstr "传输协议" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:311 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:373 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:312 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:374 msgid "Trojan" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:406 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:412 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:268 msgid "Type" msgstr "类型" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:551 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:552 msgid "UDP" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:380 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:385 msgid "" "UDP noise, Under some circumstances it can bypass some UDP based protocol " "restrictions." msgstr "UDP 噪声,在某些情况下可以绕过一些针对 UDP 协议的限制。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:459 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:460 msgid "UDP over TCP" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:730 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:731 msgid "UDP relay mode" msgstr "UDP 中继模式" @@ -2153,11 +2172,11 @@ msgstr "更新周期(天/周)" msgid "Update subscribe url list first" msgstr "修改订阅 URL 和节点关键字后,请先点击更新" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1116 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1117 msgid "Uplink Capacity(Default:Mbps)" msgstr "上行链路容量(默认:Mbps)" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1545 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1548 #: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/certupload.htm:3 msgid "Upload" msgstr "上传" @@ -2211,7 +2230,7 @@ msgstr "使用 MOSDNS 查询 (不支持海外用户回国模式)" msgid "Use MosDNS query" msgstr "使用 MosDNS 查询" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1100 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1101 msgid "" "Use it together with the DNS disguised type. You can fill in any domain." msgstr "配合伪装类型 DNS 使用,可随便填一个域名。" @@ -2220,7 +2239,7 @@ msgstr "配合伪装类型 DNS 使用,可随便填一个域名。" msgid "User cancelled." msgstr "用户已取消。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1196 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1197 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:238 msgid "User-Agent" msgstr "用户代理(User-Agent)" @@ -2230,54 +2249,54 @@ msgstr "用户代理(User-Agent)" msgid "Userinfo format error." msgstr "用户信息格式错误。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:418 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:419 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua:110 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server.lua:117 msgid "Username" msgstr "用户名" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:525 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:526 msgid "Users Authentication" msgstr "用户验证" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:332 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:333 msgid "Using incorrect encryption mothod may causes service fail to start" msgstr "输入不正确的参数组合可能会导致服务无法启动" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:302 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:303 msgid "V2Ray/XRay" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:370 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:371 msgid "V2Ray/XRay protocol" msgstr "V2Ray/XRay 协议" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:371 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:372 msgid "VLESS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:820 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:821 msgid "VLESS Encryption" msgstr "VLESS 加密" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:372 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:373 msgid "VMess" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1081 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1091 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1082 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1092 msgid "VideoCall (SRTP)" msgstr "视频通话(SRTP)" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:680 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:681 msgid "Vmess Protocol" msgstr "VMESS 协议" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:695 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:696 msgid "Vmess UUID" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:812 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:813 msgid "Vmess/VLESS ID (UUID)" msgstr "" @@ -2293,16 +2312,16 @@ msgstr "WAN IP 访问控制" msgid "WAN White List IP" msgstr "不走代理的 WAN IP" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:885 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:886 msgid "WebSocket Host" msgstr "WebSocket 主机名" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:891 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:892 msgid "WebSocket Path" msgstr "WebSocket 路径" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1083 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1093 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1084 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1094 msgid "WechatVideo" msgstr "微信视频通话" @@ -2315,7 +2334,7 @@ msgstr "当停用分流模式时,将同时停止分流服务。" msgid "When disabled, all AAAA requests are not resolved." msgstr "当禁用时,不解析所有 AAAA 请求。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1157 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1158 msgid "When enabled, it occupies IPv6 routing table 1023." msgstr "启用后,将占用 IPv6 路由表 1023。" @@ -2331,37 +2350,37 @@ msgid "" "correctly." msgstr "当使用 DNS 列表文件时,请确保列表文件存在并且格式正确。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:376 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1085 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1095 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:377 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1086 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1096 msgid "WireGuard" msgstr "WireGuard 数据包" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1189 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1190 msgid "Wireguard allows only traffic from specific source IP." msgstr "Wireguard 仅允许特定源 IP 的流量。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1138 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1139 msgid "Write Buffer Size" msgstr "写入缓冲区大小" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:951 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:952 msgid "XHTTP Extra" msgstr "XHTTP 附加项" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:939 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:940 msgid "XHTTP Host" msgstr "XHTTP 主机名" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:930 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:931 msgid "XHTTP Mode" msgstr "XHTTP 模式" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:945 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:946 msgid "XHTTP Path" msgstr "XHTTP 路径" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:282 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:283 #: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/servers.lua:82 msgid "Xray (Hysteria2)" msgstr "" @@ -2374,7 +2393,7 @@ msgstr "" msgid "Xray Fragment Settings" msgstr "Xray 分片设置" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:383 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua:388 msgid "Xray Noise Packets" msgstr "Xray 噪声数据包" @@ -2382,27 +2401,27 @@ msgstr "Xray 噪声数据包" msgid "adblock_url" msgstr "广告屏蔽更新 URL" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1069 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1070 msgid "aes-128-gcm" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1480 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1482 msgid "allow" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1474 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1476 msgid "allow: Allows use Mux connection." msgstr "allow:允许走 Mux 连接。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1394 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1396 msgid "allowInsecure" msgstr "允许不安全连接" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1188 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1189 msgid "allowedIPs(optional)" msgstr "allowedIPs(可选)" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1295 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1297 msgid "android" msgstr "" @@ -2410,7 +2429,7 @@ msgstr "" msgid "anti-AD" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1070 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1071 msgid "chacha20-poly1305" msgstr "" @@ -2418,7 +2437,7 @@ msgstr "" msgid "china-operator-ip" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1291 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1293 msgid "chrome" msgstr "" @@ -2427,27 +2446,27 @@ msgstr "" msgid "cloudflare-dns.com DNSCrypt SDNS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1511 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1526 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1513 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1529 msgid "comment_tcpcongestion_disable" msgstr "系统默认值" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1444 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1446 msgid "concurrency" msgstr "TCP 最大并发连接数" -#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:666 +#: applications/luci-app-ssr-plus/luasrc/view/shadowsocksr/server_list.htm:678 msgid "connect" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1508 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1523 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1510 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1526 msgid "custom_tcpcongestion" msgstr "连接服务器节点的 TCP 拥塞控制算法" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1301 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1452 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1465 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1303 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1454 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1467 msgid "disable" msgstr "禁用" @@ -2456,7 +2475,7 @@ msgstr "禁用" msgid "dns.sb DNSCrypt SDNS" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1296 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1298 msgid "edge" msgstr "" @@ -2469,19 +2488,19 @@ msgstr "最快响应" msgid "felixonmars/dnsmasq-china-list" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1292 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1294 msgid "firefox" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1048 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1049 msgid "gRPC Idle Timeout" msgstr "gPRC 空闲超时" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1021 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1022 msgid "gRPC Mode" msgstr "gRPC 模式" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1015 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1016 msgid "gRPC Service Name" msgstr "gRPC 服务名称" @@ -2493,7 +2512,7 @@ msgstr "GFW 列表更新 URL" msgid "gfwlist/gfwlist" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1294 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1296 msgid "ios" msgstr "" @@ -2502,11 +2521,11 @@ msgstr "" msgid "load_balance" msgstr "负载均衡" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:733 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:734 msgid "lossless UDP relay using QUIC streams" msgstr "使用 QUIC 流的无损 UDP 中继" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:732 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:733 msgid "native UDP characteristics" msgstr "原生 UDP 特性" @@ -2514,12 +2533,12 @@ msgstr "原生 UDP 特性" msgid "nfip_url" msgstr "Netflix IP 段更新 URL" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:450 -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1280 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:451 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1282 msgid "none" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:480 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:481 msgid "obfs-local" msgstr "" @@ -2528,50 +2547,50 @@ msgstr "" msgid "parallel" msgstr "并行查询" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1298 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1300 msgid "qq" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1299 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1301 msgid "random" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1300 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1302 msgid "randomized" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1479 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1481 msgid "reject" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1293 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1295 msgid "safari" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:667 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:668 msgid "shadow-TLS SNI" msgstr "服务器名称指示" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:489 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:490 msgid "shadow-tls" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:645 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:646 msgid "shadowTLS protocol Version" msgstr "ShadowTLS 协议版本" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1481 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1483 msgid "skip" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1475 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1477 msgid "" "skip: Not use Mux module to carry UDP 443 traffic, Use original UDP " "transmission method of proxy protocol." msgstr "" "skip:不使用 Mux 模块承载 UDP 443 流量,将使用代理协议原本的 UDP 传输方式。" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1271 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1273 msgid "spiderX" msgstr "" @@ -2579,7 +2598,7 @@ msgstr "" msgid "v2fly/domain-list-community" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:483 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:484 msgid "v2ray-plugin" msgstr "" @@ -2591,15 +2610,15 @@ msgstr "有效的地址:端口" msgid "warning! Please do not reuse the port!" msgstr "警告!请不要重复使用端口!" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:486 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:487 msgid "xray-plugin" msgstr "" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1457 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1459 msgid "xudpConcurrency" msgstr "UDP 最大并发连接数" -#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1470 +#: applications/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua:1472 msgid "xudpProxyUDP443" msgstr "对被代理的 UDP/443 流量处理方式" @@ -2609,12 +2628,6 @@ msgstr "对被代理的 UDP/443 流量处理方式" #~ msgid "Invalid JSON format" #~ msgstr "无效的 JSON 格式" -#~ msgid "Limit the maximum number of splits." -#~ msgstr "限制分片的最大数量。" - -#~ msgid "Max Split" -#~ msgstr "最大分片数" - #~ msgid "" #~ "Virtual NIC TUN of Linux kernel can be used only when system supports and " #~ "have root permission. If used, IPv6 routing table 1023 is occupied." diff --git a/luci-app-ssr-plus/root/usr/share/shadowsocksr/gen_config.lua b/luci-app-ssr-plus/root/usr/share/shadowsocksr/gen_config.lua index 87700815..9596ca39 100755 --- a/luci-app-ssr-plus/root/usr/share/shadowsocksr/gen_config.lua +++ b/luci-app-ssr-plus/root/usr/share/shadowsocksr/gen_config.lua @@ -23,15 +23,20 @@ local xray_version_val = 0 local node_id = server_section local remarks = server.alias or "" local b64decode = nixio.bin.b64decode +local b64encode = nixio.bin.b64encode +-- base64 解码 local function base64Decode(text) local raw = text if not text or text == "" then return '' end text = text:gsub("%z", "") + text = text:gsub("%c", "") + text = text:gsub("%s", "") text = text:gsub("_", "/") text = text:gsub("-", "+") + text = text:gsub("=", "") local mod4 = #text % 4 text = text .. string.sub('====', mod4 + 1) local result = b64decode(text) @@ -42,6 +47,20 @@ local function base64Decode(text) end end +-- base64 编码 +local function base64Encode(text) + if not text or text == "" then + return '' + end + local result = b64encode(text) + if result then + result = result:gsub("%z", "") + return result + else + return text + end +end + local function cleanEmptyTables(t) if type(t) ~= "table" then return nil end for k, v in pairs(t) do @@ -456,6 +475,8 @@ end } or nil, finalmask = (function() local finalmask = {} + local PT = server.v2ray_protocol + local TP = server.transport if server.transport == "kcp" then local map = {none = "none", srtp = "header-srtp", utp = "header-utp", ["wechat-video"] = "header-wechat", dtls = "header-dtls", wireguard = "header-wireguard", dns = "header-dns"} @@ -473,7 +494,7 @@ end end udp[#udp+1] = c finalmask.udp = udp - elseif server.v2ray_protocol == "hysteria2" then + elseif PT == "hysteria2" then if (server.flag_obfs == "1" and (server.obfs_type and server.obfs_type ~= "")) then finalmask.udp = {{ type = server.obfs_type, @@ -507,6 +528,46 @@ end disablePathMTUDiscovery = (server.flag_quicparam == "1" and tostring(server.disablepathmtudiscovery) == "1") and true or nil } end + if xray_fragment.fragment == "1" and ({raw=1, ws=1, httpupgrade=1, grpc=1, xhttp=1})[TP] then + local n_packets = xray_fragment.fragment_packets + local n_length = xray_fragment.fragment_length + local n_delay = xray_fragment.fragment_delay + local n_maxsplit = xray_fragment.fragment_maxSplit + --local domainstr = xray_noise.domainStrategy + finalmask.tcp = finalmask.tcp or {} + finalmask.tcp[#finalmask.tcp + 1] = { + type = "fragment", + settings = { + --domainStrategy = (xray_fragment.noise == "1" and xray_noise.enabled == "1") and domainstr or nil, + packets = (n_packets and n_packets ~= "") and n_packets or nil, + length = (n_length and n_length ~= "") and n_length or nil, + delay = (type(n_delay) == "string" and string.find(n_delay, "-")) and n_delay or (n_delay and tonumber(n_delay)), + maxSplit = (n_maxsplit and n_maxsplit ~= "") and n_maxsplit or nil + } + } + end + if xray_fragment.noise == "1" and (TP == "kcp" or (TP == "xhttp" and (server.tls_alpn == "h3" or server.tls_alpn == "h3,h2"))) then + if xray_noise.enabled == "1" then + local n_type = xray_noise.type + local n_delay = xray_noise.delay + local n_packet = xray_noise.packet + finalmask.udp = finalmask.udp or {} + finalmask.udp[#finalmask.udp + 1] = { + type = "noise", + settings = { + reset = 0, + noise = { + { + rand = (n_type == "rand") and (n_packet and (type(n_packet) == "string" and (n_packet:find("-")) and n_packet or tonumber(n_packet))) or nil, + type = (type(n_type) == "string" and n_type ~= "rand") and n_type or nil, + packet = (n_type ~= "rand") and (n_type ~= "str" and (n_packet and type(n_packet) == "string" and base64Encode(n_packet)) or n_packet) or nil, + delay = (type(n_delay) == "string" and string.find(n_delay, "-")) and n_delay or (n_delay and tonumber(n_delay)) + } + } + } + } + end + end if server.finalmask and server.finalmask ~= "" then local ok, fm = pcall(json.parse, base64Decode(server.finalmask)) if ok and type(fm) == "table" then @@ -516,7 +577,7 @@ end return cleanEmptyTables(finalmask) end)(), sockopt = { - mark = 250, + mark = 255, tcpFastOpen = (function() if server.transport == "xhttp" then return (server.fast_open == "1") and true or false @@ -545,27 +606,16 @@ end -- 添加带有 fragment 设置的 dialerproxy 配置 if xray_fragment.fragment ~= "0" or (xray_fragment.noise ~= "0" and xray_noise.enabled ~= "0") then + local n_domainstrategy = xray_noise.domainStrategy table.insert(Xray.outbounds, { protocol = "freedom", tag = (remarks ~= nil and remarks ~= "") and (node_id .. "." .. remarks) or node_id, settings = { - domainStrategy = (xray_fragment.noise == "1" and xray_noise.enabled == "1") and xray_noise.domainStrategy, - fragment = (xray_fragment.fragment == "1") and { - packets = (xray_fragment.fragment_packets and xray_fragment.fragment_packets ~= "") and xray_fragment.fragment_packets or nil, - length = (xray_fragment.fragment_length and xray_fragment.fragment_length ~= "") and xray_fragment.fragment_length or nil, - interval = (xray_fragment.fragment_interval and xray_fragment.fragment_interval ~= "") and xray_fragment.fragment_interval or nil - } or nil, - noises = (xray_fragment.noise == "1" and xray_noise.enabled == "1") and { - { - type = xray_noise.type, - packet = xray_noise.packet, - delay = xray_noise.delay:find("-") and xray_noise.delay or tonumber(xray_noise.delay) - } - } or nil + domainStrategy = (xray_fragment.noise == "1" and xray_noise.enabled == "1") and n_domainstrategy or nil }, streamSettings = { sockopt = { - mark = 250, + mark = 255, tcpFastOpen = (function() if server.transport == "xhttp" then return (server.fast_open == "1") and true or false diff --git a/luci-app-ssr-plus/root/usr/share/shadowsocksr/subscribe.lua b/luci-app-ssr-plus/root/usr/share/shadowsocksr/subscribe.lua index ce196877..806f0c82 100755 --- a/luci-app-ssr-plus/root/usr/share/shadowsocksr/subscribe.lua +++ b/luci-app-ssr-plus/root/usr/share/shadowsocksr/subscribe.lua @@ -173,15 +173,18 @@ local function md5(content) -- assert(nixio.errno() == 0) return trim(stdout) end --- base64 +-- base64 解码 local function base64Decode(text) local raw = text - if not text then + if not text or text == "" then return '' end text = text:gsub("%z", "") + text = text:gsub("%c", "") + text = text:gsub("%s", "") text = text:gsub("_", "/") text = text:gsub("-", "+") + text = text:gsub("=", "") local mod4 = #text % 4 text = text .. string.sub('====', mod4 + 1) local result = b64decode(text) @@ -191,20 +194,18 @@ local function base64Decode(text) return raw end end +-- base64 编码 local function base64Encode(text) if not text or text == "" then return '' end - local result = b64encode(text) - if result then - result = result:gsub("%z", "") - result = result:gsub("/", "_") - result = result:gsub("+", "-") - result = result:gsub("=", "") - return result - else - return text - end + local result = b64encode(text) + if result then + result = result:gsub("%z", "") + return result + else + return text + end end -- 检查数组(table)中是否存在某个字符值 -- https://www.04007.cn/article/135.html diff --git a/luci-app-wizard/Makefile b/luci-app-wizard/Makefile new file mode 100644 index 00000000..231e4543 --- /dev/null +++ b/luci-app-wizard/Makefile @@ -0,0 +1,24 @@ +# +# Copyright (C) 2017-2019 Chen Minqiang +# +# This is free software, licensed under the GNU General Public License v3. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=LuCI Support for wizard +LUCI_DEPENDS:= +LUCI_PKGARCH:=all +PKG_NAME:=luci-app-wizard + +PKG_MAINTAINER:=Chen Minqiang +PKG_LICENSE:=GPLv3 + +define Package/luci-app-wizard/conffiles +/etc/config/wizard +endef + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature \ No newline at end of file diff --git a/luci-app-wizard/README.md b/luci-app-wizard/README.md new file mode 100644 index 00000000..940da954 --- /dev/null +++ b/luci-app-wizard/README.md @@ -0,0 +1,3 @@ +# luci-app-wizard + +修改自 https://github.com/x-wrt/com.x-wrt/tree/master/luci-app-wizard diff --git a/luci-app-wizard/htdocs/luci-static/resources/view/wizard/initsetup.js b/luci-app-wizard/htdocs/luci-static/resources/view/wizard/initsetup.js new file mode 100644 index 00000000..1e4bb723 --- /dev/null +++ b/luci-app-wizard/htdocs/luci-static/resources/view/wizard/initsetup.js @@ -0,0 +1,160 @@ +'use strict'; +'require view'; +'require dom'; +'require poll'; +'require uci'; +'require rpc'; +'require form'; +'require fs'; + +return view.extend({ + load: async function () { + const promises = await Promise.all([ + fs.exec('/etc/init.d/wizard', ['reconfig']), + uci.changes(), + L.resolveDefault(uci.load('wireless')), + uci.load('wizard'), + L.resolveDefault(fs.stat('/www/luci-static/istorex/style.css'), null), + L.resolveDefault(fs.stat('/www/luci-static/routerdog/style.css'), null), + L.resolveDefault(fs.stat('/usr/sbin/nginx'), null) + ]); + const data = { + istorex: promises[4], + routerdog: promises[5], + nginx: promises[6] + }; + return data; + }, + + render: function(data) { + var m, s, o; + var has_wifi = false; + + if (uci.sections('wireless', 'wifi-device').length > 0) { + has_wifi = true; + } + + m = new form.Map('wizard', [_('Initial Router Setup')], + _('If you are using this router for the first time, please configure it here.')); + + s = m.section(form.NamedSection, 'default', 'wizard'); + s.addremove = false; + s.tab('netsetup', _('Net Settings'), _('Three different ways to access the Internet, please choose according to your own situation.')); + + o = s.taboption('netsetup', form.ListValue, 'wan_proto', _('Protocol')); + o.rmempty = false; + o.value('dhcp', _('DHCP client')); + o.value('pppoe', _('PPPoE')); + + o = s.taboption('netsetup', form.Value, 'wan_pppoe_user', _('PAP/CHAP username')); + o.depends('wan_proto', 'pppoe'); + + o = s.taboption('netsetup', form.Value, 'wan_pppoe_pass', _('PAP/CHAP password')); + o.depends('wan_proto', 'pppoe'); + o.password = true; + + o = s.taboption('netsetup', form.Value, 'lan_ipaddr', _('IPv4 address')); + o.datatype = 'ip4addr'; + + o = s.taboption('netsetup', form.Value, 'lan_netmask', _('IPv4 netmask')); + o.datatype = 'ip4addr'; + o.value('255.255.255.0'); + o.value('255.255.0.0'); + o.value('255.0.0.0'); + o.default = '255.255.255.0'; + + o = s.taboption('netsetup', form.DynamicList, 'lan_dns', _('Use custom DNS servers'), _('Leave empty to use ISP DNS')); + o.datatype = 'ip4addr'; + o.cast = 'string'; + + o = s.taboption('netsetup', form.Flag, 'siderouter', _('Siderouter'), + _('Use as downstream router i.e. it will work like a switch')); + o.rmempty = false; + + o = s.taboption('netsetup', form.Value, 'lan_gateway', _('IPv4 gateway')); + o.depends('siderouter', '1'); + o.datatype = 'ip4addr'; + o.placeholder = _('Enter the main router IP'); + o.rmempty = false; + + o = s.taboption('netsetup', form.Flag, 'dhcp', _('DHCP Server'), + _('To turn on this DHCP, you need to turn off the DHCP of the main router, and to turn off this DHCP, you need to manually change the gateway and DNS of all Internet devices to the IP of this bypass router')); + o.depends('siderouter', '1'); + o.default = o.enabled; + + o = s.taboption('netsetup', form.Flag, 'ipv6', _('Enable IPv6'), _('Enable/Disable IPv6')); + o.default = o.enabled; + + s.tab('firmware', _('Firmware Settings')); + + // o = s.taboption('firmware', form.Flag, 'autoupgrade_pkg', _('Packages Auto Upgrade'),_('谨慎开启')); + // o.rmempty = false; + + o = s.taboption('firmware', form.Flag, 'autoupgrade_fm', _('Firmware Upgrade Notice')); + o.rmempty = false; + + o = s.taboption('firmware', form.Flag, 'coremark', _('CoreMark'), _('第一次开机后是否运行CPU跑分测试')); + o.rmempty = false; + + o = s.taboption('firmware', form.Flag, 'cookie_p', _('Persistent cookies'), + _('Keep the background login state to avoid the need to log in again every time the browser is closed')); + o.default = o.enabled; + + o = s.taboption('firmware', form.Flag, 'https', _('Force the use of HTTPS in the backend.')); + + if (data.istorex || data.routerdog){ + o = s.taboption('firmware', form.ListValue, 'landing_page', _('主题模式')); + o.value('default', _('默认')); + if (data.routerdog){ + o.value('routerdog', _('路由狗(专业NAS模式)')); + } + if (data.istorex){ + o.value('nas', _('NAS模式')); + o.value('next-nas', _('NEXT-NAS模式')); + o.value('router', _('路由模式')); + } + o.default = 'default'; + } + + if (has_wifi) { + s.tab('wifisetup', _('Wireless Settings'), _('Set the router\'s wireless name and password. For more advanced settings, please go to the Network-Wireless page.')); + o = s.taboption('wifisetup', form.Value, 'wifi_ssid', _('ESSID')); + o.datatype = 'maxlength(32)'; + + o = s.taboption("wifisetup", form.Value, "wifi_key", _("Key")); + o.datatype = 'wpakey'; + o.password = true; + } + + if (data.nginx) { + s.tab('shortcuts', _('Shortcuts'), _('比如设置google.com的快捷方式为字母g,则在此路由器网络的任何浏览器中输入g/即可访问google.com')); + + o = s.taboption('shortcuts', form.SectionValue, 'shortcuts', form.GridSection, 'shortcuts', null, + _('Shortcuts')); + + s = o.subsection; + s.addremove = true; + s.anonymous = true; + + o = s.option(form.Value, 'shortcut', _('Shortcut')); + o.rmempty = false; + + o = s.option(form.Value, 'to_url', _('Target URL')); + o.rmempty = false; + o.placeholder = 'https://example.com'; + o.validate = function(section_id, value) { + if (value.match(/^https?:\/\/.+/i)) { + return true; + } + return _('Please enter a valid URL starting with http:// or https://'); +}; + + o = s.option(form.Value, 'comments', _('Comments')); + o.optional = true; + } + + setTimeout("document.getElementsByClassName('cbi-button-apply')[0].children[3].children[0].value='1'", 1000) + + return m.render(); + } +}); diff --git a/luci-app-wizard/luasrc/controller/wizard.lua b/luci-app-wizard/luasrc/controller/wizard.lua new file mode 100644 index 00000000..0f247c6c --- /dev/null +++ b/luci-app-wizard/luasrc/controller/wizard.lua @@ -0,0 +1,28 @@ +module("luci.controller.wizard", package.seeall) + +local uci = luci.model.uci.cursor() +local http = require "luci.http" + +function index() + entry({"admin", "index"}, call("landing_page"), _("Home") , 1).dependent = false +end + +function landing_page() + local landing_page = uci:get("wizard", "default", "landing_page") + if (luci.sys.call("pgrep routergo >/dev/null") == 0 and landing_page == "routerdog") then + http.redirect(luci.dispatcher.build_url("admin","routerdog")); + elseif luci.sys.call("pgrep quickstart >/dev/null") == 0 then + if landing_page == "nas" then + http.redirect(luci.dispatcher.build_url("admin","istorex","nas")); + elseif landing_page == "next-nas" then + http.redirect(luci.dispatcher.build_url("admin","istorex","next-nas")); + elseif landing_page == "router" then + http.redirect(luci.dispatcher.build_url("admin","istorex","router")); + else + http.redirect(luci.dispatcher.build_url("admin","quickstart")); + end + else + http.redirect(luci.dispatcher.build_url("admin","status")) + end + +end diff --git a/luci-app-wizard/po/ru/wizard.po b/luci-app-wizard/po/ru/wizard.po new file mode 100644 index 00000000..e22e5793 --- /dev/null +++ b/luci-app-wizard/po/ru/wizard.po @@ -0,0 +1,44 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8\n" + +msgid "Wizard" +msgstr "Мастер настройки" + +msgid "Initial Router Setup" +msgstr "Мастер настройки маршрутизатора" + +msgid "Net Settings" +msgstr "Сетевые настройки" + +msgid "Wireless Settings" +msgstr "Настройки беспроводной связи" + +msgid "If you are using this router for the first time, please configure it here." +msgstr "Если вы используете этот маршрутизатор в первый раз, пожалуйста, просто настройте его здесь." + +msgid "Three different ways to access the Internet, please choose according to your own situation." +msgstr "Существует два различных способа серфинга в Интернете, пожалуйста, выбирайте в соответствии с вашей собственной ситуацией." + +msgid "Set the router's wireless name and password. For more advanced settings, please go to the Network-Wireless page." +msgstr "Задайте имя беспроводной сети и пароль маршрутизатора. для получения более подробных настроек, пожалуйста, перейдите на страницу Cеть-Беспроводная связь." + +msgid "Siderouter" +msgstr "Вторичный роутер" + +msgid "Enable IPv6" +msgstr "Включить IPv6" + +msgid "Enable/Disable IPv6" +msgstr "Включение/Отключение IPv6" + +msgid "Firmware Settings" +msgstr "Настройки встроенного ПО" + +msgid "Packages Auto Upgrade" +msgstr "Автоматическое обновление пакета" + +msgid "Firmware Upgrade Notice" +msgstr "Напоминание об обновлении прошивки" + +msgid "Persistent cookies" +msgstr "Постоянный вход в систему" diff --git a/luci-app-wizard/po/zh-cn b/luci-app-wizard/po/zh-cn new file mode 120000 index 00000000..8d69574d --- /dev/null +++ b/luci-app-wizard/po/zh-cn @@ -0,0 +1 @@ +zh_Hans \ No newline at end of file diff --git a/luci-app-wizard/po/zh_Hans/wizard.po b/luci-app-wizard/po/zh_Hans/wizard.po new file mode 100644 index 00000000..470760bf --- /dev/null +++ b/luci-app-wizard/po/zh_Hans/wizard.po @@ -0,0 +1,75 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8\n" + +msgid "Wizard" +msgstr "设置向导" + +msgid "Initial Router Setup" +msgstr "路由器设置向导" + +msgid "Net Settings" +msgstr "网络设置" + +msgid "Wireless Settings" +msgstr "无线设置" + +msgid "If you are using this router for the first time, please configure it here." +msgstr "如果你首次使用这个路由器,请在这里简单设置。" + +msgid "Three different ways to access the Internet, please choose according to your own situation." +msgstr "二种不同的上网方式,请您根据自身情况进行选择。" + +msgid "Set the router's wireless name and password. For more advanced settings, please go to the Network-Wireless page." +msgstr "设置路由器的无线名字和密码,更多高级设置请进入 网络-无线 页面。" + +msgid "Leave empty to use ISP DNS" +msgstr "留空则使用阿里DNS" + +msgid "Enter the main router IP" +msgstr "请输入主路由IP" + +msgid "Siderouter" +msgstr "旁路由模式" + +msgid "To turn on this DHCP, you need to turn off the DHCP of the main router, and to turn off this DHCP, you need to manually change the gateway and DNS of all Internet devices to the IP of this bypass router" +msgstr "开启此DHCP则需要关闭主路由的DHCP, 关闭此DHCP则需要手动将所有上网设备的网关和DNS改为此旁路由的IP" + +msgid "Enable IPv6" +msgstr "启用IPv6" + +msgid "Enable/Disable IPv6" +msgstr "一键开启/关闭 IPv6" + +msgid "Firmware Settings" +msgstr "固件设置" + +msgid "Packages Auto Upgrade" +msgstr "软件包自动更新" + +msgid "Firmware Upgrade Notice" +msgstr "固件更新提醒" + +msgid "Persistent cookies" +msgstr "持久化登录" + +msgid "Keep the background login state to avoid the need to log in again every time the browser is closed" +msgstr "保持后台登录状态,避免每次关闭浏览器后都需要重新登录" + +msgid "Home" +msgstr "首页" + +msgid "Shortcuts" +msgstr "快捷访问" + +msgid "Shortcut" +msgstr "快捷方式" + +msgid "Target URL" +msgstr "目标URL" + +msgid "Please enter a valid URL starting with http:// or https://" +msgstr "URL需以http:// 或 https://开头" + +msgid "Force the use of HTTPS in the backend." +msgstr "后台强制使用https" + diff --git a/luci-app-wizard/root/etc/config/wizard b/luci-app-wizard/root/etc/config/wizard new file mode 100644 index 00000000..160d0da4 --- /dev/null +++ b/luci-app-wizard/root/etc/config/wizard @@ -0,0 +1 @@ +config wizard 'default' diff --git a/luci-app-wizard/root/etc/init.d/wizard b/luci-app-wizard/root/etc/init.d/wizard new file mode 100755 index 00000000..d559f241 --- /dev/null +++ b/luci-app-wizard/root/etc/init.d/wizard @@ -0,0 +1,263 @@ +#!/bin/sh /etc/rc.common + +START=19 + +extra_command "reconfig" "" + +boot() { + exit 0; +} + +add_wizard() { + local cfg="$1" + local wan_proto wan_pppoe_user wan_pppoe_pass + local lan_ipaddr lan_netmask lan_dns lan_gateway dhcp + local device ipv6 old_ipv6 wifi_ssid wifi_key old_wifi_ssid old_wifi_key + + config_get wan_proto "$cfg" wan_proto + + device=$(uci get network.wan.device 2>/dev/null) + case "${wan_proto}" in + dhcp) + uci delete network.wan + uci set network.wan=interface + uci set network.wan.device="$device" + uci set network.wan.proto='dhcp' + ;; + pppoe) + config_get wan_pppoe_user "$cfg" wan_pppoe_user + config_get wan_pppoe_pass "$cfg" wan_pppoe_pass + [[ "${wan_pppoe_user} != $(uci -q get network.wan.username)" || "${wan_pppoe_pass} != $(uci -q get network.wan.password)" ]] && { + uci delete network.wan + uci set network.wan=interface + uci set network.wan.proto='pppoe' + uci set network.wan.device="$device" + uci set network.wan.username="${wan_pppoe_user}" + uci set network.wan.password="${wan_pppoe_pass}" + [ -n "${ipv6}" ] && { + uci -q set network.wan.ipv6='0' + uci -q set network.wan.delegate='0' + } + } + ;; + esac + + config_get lan_ipaddr "$cfg" lan_ipaddr + config_get lan_netmask "$cfg" lan_netmask + test -n "${lan_ipaddr}" && test -n "${lan_netmask}" && { + uci set network.lan.ipaddr="${lan_ipaddr}" + uci set network.lan.netmask="${lan_netmask}" + } + + config_get siderouter "$cfg" siderouter + config_get old_siderouter "$cfg" old_siderouter + config_get lan_gateway "$cfg" lan_gateway + config_get dhcp "$cfg" dhcp + config_get lan_dns "$cfg" lan_dns + config_get ipv6 "$cfg" ipv6 + config_get old_ipv6 "$cfg" old_ipv6 + config_get autoupgrade_pkg "$cfg" autoupgrade_pkg + + [ "$dhcp" == "0" ] && dhcp="1" + if [[ "${lan_gateway}" != "$(uci -q get network.lan.gateway)" || "${dhcp}" != "$(uci -q get dhcp.lan.ignore)" ]]; then + if [ "${siderouter}" == "1" ]; then + uci -q set network.lan.gateway="${lan_gateway}" + [ -n "$lan_dns" ] || lan_dns='223.5.5.5' + [ -n "$dhcp" ] && uci -q set dhcp.lan.ignore="1" || uci -q del dhcp.lan.ignore + uci -q set firewall.@zone[0].masq='1' + uci -q set network.wan.proto='none' + elif [ "${siderouter}" == "0" ]; then + uci -q del network.lan.gateway + uci -q del dhcp.lan.ignore + uci -q del network.lan.dns + uci -q del firewall.@zone[0].masq + uci -q set network.wan.proto='dhcp' + + fi + fi + + [ -n "$lan_dns" ] && { + [ "$(uci -q get dhcp.@dnsmasq[0].noresolv)" == 1 ] && { + uci -q del dhcp.@dnsmasq[0].noresolv + } + uci -q set network.wan.peerdns='0' + uci -q set network.lan.dns="${lan_dns}" + } || { + uci -q del network.wan.peerdns + uci -q del network.lan.dns + } + + if [ "${ipv6}" != "${old_ipv6}" ]; then + if [ -n "${ipv6}" ]; then + uci -q delete dhcp.lan.ra + uci -q delete dhcp.lan.dhcpv6 + uci -q set network.lan.delegate='0' + uci -q set network.wan.ipv6='0' + uci -q set network.wan.delegate='0' + uci -q delete network.globals.ula_prefix + else + uci -q set dhcp.lan.ra='hybrid' + uci -q set dhcp.lan.dhcpv6='hybrid' + uci -q del network.lan.delegate + uci -q set network.wan.ipv6='auto' + uci -q del network.wan.delegate + fi + uci -q set wizard.default.old_ipv6="${ipv6}" + fi + + wifi_setup_radio(){ + local radio=$1 + uci -q get wireless.${radio} >/dev/null 2>&1 && { + if [ "$(uci -q get wireless.${radio}.band)" = "5g" ]; then + uci -q set wireless.default_${radio}.ssid="${wifi_ssid}_5G" + elif [ "$(uci -q get wireless.${radio}.band)" = "2g" ]; then + uci -q set wireless.default_${radio}.ssid="${wifi_ssid}_2.4G" + fi + uci -q set wireless.default_${radio}.device="${radio}" + if [ "${wifi_key}" ]; then + uci -q set wireless.default_${radio}.encryption='psk2' + uci -q set wireless.default_${radio}.key="${wifi_key}" + else + uci -q set wireless.default_${radio}.encryption='none' + fi + } + } + + config_get wifi_ssid "$cfg" wifi_ssid + config_get wifi_key "$cfg" wifi_key + config_get old_wifi_ssid "$cfg" old_wifi_ssid + config_get old_wifi_key "$cfg" old_wifi_key + + if [[ "${wifi_ssid}" != "${old_wifi_ssid}" || "${wifi_key}" != "${old_wifi_key}" ]]; then + test -n "${wifi_ssid}" && { + for radio in radio0 radio1 radio2 radio3; do + wifi_setup_radio ${radio} + done + uci commit wireless + uci -q set wizard.default.old_wifi_ssid="${wifi_ssid}" + uci -q set wizard.default.old_wifi_key="${wifi_key}" + } + fi + + sethttps + + uci commit wizard + uci commit dhcp + uci commit firewall + uci commit network + + if [ "${autoupgrade_pkg}" != "1" ]; then + sed -i '/opkg-upgrade/d' /etc/crontabs/root + else + grep -q "opkg-upgrade" /etc/crontabs/root || { + hour="$(grep -m1 -ao '[4-6]' /dev/urandom | head -n1)" + min="$(grep -m1 -ao '[0-5][0-9]' /dev/urandom | head -n1)" + echo "$min $hour * * * . /etc/hotplug.d/online/51-opkg-upgrade >/dev/null 2>&1" >> /etc/crontabs/root + } + fi +} + +reconfig() { +uci -q set wizard.default.wan_proto="$(uci -q get network.wan.proto)" +uci -q set wizard.default.wan_pppoe_user="$(uci -q get network.wan.username)" +uci -q set wizard.default.wan_pppoe_pass="$(uci -q get network.wan.password)" +uci -q set wizard.default.lan_ipaddr="$(uci -q get network.lan.ipaddr)" +uci -q set wizard.default.lan_netmask="$(uci -q get network.lan.netmask)" +uci -q set wizard.default.lan_gateway="$(uci -q get network.lan.gateway)" +uci -q set wizard.default.lan_dns="$(uci -q get network.lan.dns)" +[ "$(uci -q get dhcp.lan.ignore)" ] && uci -q set wizard.default.dhcp="0" || uci -q del wizard.default.dhcp +uci commit wizard +} + +sethttps() { + config_get https "$cfg" https + if [ -n "$(command -v nginx)" ]; then + if [ -z "`uci -q get nginx._redirect2ssl`" ]; then + uci -q set nginx._redirect2ssl=server + uci -q set nginx._redirect2ssl.server_name='_redirect2ssl' + uci -q set nginx._redirect2ssl.return='302 https://$host$request_uri' + uci -q set nginx._redirect2ssl.access_log='off; # logd openwrt' + fi + if [ "x${https}" = "x1" ] ; then + uci -q del nginx.default_server.listen + uci -q add_list nginx.default_server.listen='80' + uci -q add_list nginx.default_server.listen='[::]:80' + uci -q del nginx._redirect2ssl.listen + uci -q add_list nginx._redirect2ssl.listen='80 default_server' + uci -q add_list nginx._redirect2ssl.listen='[::]:80 default_server' + else + uci -q del nginx._redirect2ssl.listen + uci -q add_list nginx._redirect2ssl.listen='80' + uci -q add_list nginx._redirect2ssl.listen='[::]:80' + uci -q del nginx.default_server.listen + uci -q add_list nginx.default_server.listen='80 default_server' + uci -q add_list nginx.default_server.listen='[::]:80 default_server' + fi + uci commit nginx + /etc/init.d/nginx reload + elif [ -n "$(command -v lighttpd)" ]; then + if [ "x${https}" = "x1" ] ; then + sed -i "s/ # url.redirect =/ url.redirect =/" /etc/lighttpd/conf.d/82-https.conf + else + sed -i "s/ url.redirect =/ # url.redirect =/" /etc/lighttpd/conf.d/82-https.conf + fi + /etc/init.d/lighttpd reload + else + if [ "x${https}" = "x1" ] ; then + uci -q set uhttpd.main.redirect_https='1' + else + uci -q set uhttpd.main.redirect_https='0' + fi + uci commit uhttpd + /etc/init.d/uhttpd reload + fi +} + +process_shortcut() { + local shortcut to_url comments lanaddr + local cfg="$1" + lanaddr="$(uci get network.lan.ipaddr)" + [ -n $lanaddr ] && lanaddr="$(echo "$lanaddr" | sed -e "s/\/2\+//")" + + config_get shortcut "$cfg" shortcut + config_get to_url "$cfg" to_url + config_get comments "$cfg" comments + + uci -q set nginx._sc_$shortcut=server + uci -q set nginx._sc_$shortcut.server_name="$shortcut" + uci -q add_list nginx._sc_$shortcut.listen="80" + uci -q add_list nginx._sc_$shortcut.listen="443" + uci -q set nginx._sc_$shortcut.return="302 $to_url" + + uci -q set dhcp._sc_$shortcut=domain + uci -q set dhcp._sc_$shortcut.name="$shortcut" + uci -q set dhcp._sc_$shortcut.ip="$lanaddr" + uci -q set dhcp._sc_$shortcut.comments="$comments" +} + +start() { + config_load wizard + config_foreach add_wizard wizard + if [ -n "$(command -v nginx)" ]; then + for server in $(uci show nginx | grep '_sc_' | grep '=server' | cut -d. -f2 | cut -d= -f1); do + uci delete nginx.$server + done + for server in $(uci show dhcp | grep '_sc_' | grep '=domain' | cut -d. -f2 | cut -d= -f1); do + uci delete dhcp.$server + done + config_foreach process_shortcut shortcuts + uci commit nginx + uci commit dhcp + /etc/init.d/nginx reload + fi + ( + /etc/init.d/network restart + /etc/init.d/firewall reload + /etc/init.d/dnsmasq reload + + )& +} + +restart() { + start +} diff --git a/luci-app-wizard/root/etc/uci-defaults/40-luci-wizard b/luci-app-wizard/root/etc/uci-defaults/40-luci-wizard new file mode 100644 index 00000000..6fbc5380 --- /dev/null +++ b/luci-app-wizard/root/etc/uci-defaults/40-luci-wizard @@ -0,0 +1,23 @@ +#!/bin/sh +[ ! -f "/usr/share/ucitrack/luci-app-wizard.json" ] && { + cat > /usr/share/ucitrack/luci-app-wizard.json << EEOF +{ + "config": "wizard", + "init": "wizard" +} +EEOF +} + +touch /etc/config/wizard + +uci -q batch <<-EOF >/dev/null + delete ucitrack.@wizard[-1] + add ucitrack wizard + set ucitrack.@wizard[-1].init=wizard + commit ucitrack +EOF + +chmod +x /etc/init.d/wizard 2>/dev/null +rm -f /tmp/luci-indexcache + +exit 0 diff --git a/luci-app-wizard/root/usr/share/luci/menu.d/luci-app-wizard.json b/luci-app-wizard/root/usr/share/luci/menu.d/luci-app-wizard.json new file mode 100644 index 00000000..cc6810db --- /dev/null +++ b/luci-app-wizard/root/usr/share/luci/menu.d/luci-app-wizard.json @@ -0,0 +1,14 @@ +{ + "admin/system/initsetup": { + "title": "Wizard", + "order": 1, + "action": { + "type": "view", + "path": "wizard/initsetup" + }, + "depends": { + "acl": [ "luci-app-wizard" ], + "uci": { "wizard": true } + } + } +} diff --git a/luci-app-wizard/root/usr/share/rpcd/acl.d/luci-app-wizard.json b/luci-app-wizard/root/usr/share/rpcd/acl.d/luci-app-wizard.json new file mode 100644 index 00000000..2641777e --- /dev/null +++ b/luci-app-wizard/root/usr/share/rpcd/acl.d/luci-app-wizard.json @@ -0,0 +1,14 @@ +{ + "luci-app-wizard": { + "description": "Grant UCI access for luci-app-wizard", + "read": { + "file": { + "/etc/init.d/wizard reconfig": [ "exec" ] + }, + "uci": [ "wizard", "wireless" ] + }, + "write": { + "uci": [ "wizard" ] + } + } +} diff --git a/luci-app-wizard/root/usr/share/ucitrack/luci-app-wizard.json b/luci-app-wizard/root/usr/share/ucitrack/luci-app-wizard.json new file mode 100644 index 00000000..87e0a684 --- /dev/null +++ b/luci-app-wizard/root/usr/share/ucitrack/luci-app-wizard.json @@ -0,0 +1,4 @@ +{ + "config": "wizard", + "init": "wizard" +}