openwrt-18.06: merge master

Due to a huge number of fixes and diverging development histories, I decided
to completely merge the current LuCI master into the 18.06 release branch to
have a common code base for upcoming maintenance releases.

Some LuCI apps have minor style glitches yet but I do not deem them to be
release critical as non-default components need to be opkg-installed anyway
and the package repositories are continuously refreshed, so we do not need
to fix everything for OpenWrt 18.06.0-rc2.

The most important changes introduced by this merge are:

1) New HTTP handling library in C

  The new library should vastly reduce the required RAM for processing
  large POST bodies while implementing some slightly more strict parsing
  logic.

2) Apply/Rollback workflow

  The ubus rpcd based apply/rollback handling will automatically revert
  config changes if access to the device is lost for a certain period
  of time, this is mainly intended for preventing issues with bad
  config settings and the like.

  The feature is not 100% error-proof yet but it successfully prevents a
  large number of issues already. For final, the handling of the firewall
  conntrack cache needs to be fixed yet as adding "lockout" firewall rules
  is not yet catched due to the open HTTP session allowed by netfilter
  conntrack

3) Template markup and theme style modifications

  A large number of changes have been made to the markup in the various
  templates, mainly to allow for responsive styling of tables.

  The only theme currently making full use of that is the non-default
  OpenWrt theme which will break table rows into disjunct boxes on
  very narrow screens.

  The changes have been tested on IE 11, MS Edge, Firefox, Chrome, an
  iPhone 5s, iPhone 6 and iPad Air.

4) Initial LuCI support for displaying virtual dynamic network interfaces

  Some protocol handlers will spawn purely dynamic sub-interfaces which
  are not present in UCI. Such interfaces have been invisible in LuCI so
  far which caused confusion especialy wrt. missing IP addresses etc.

  LuCI will now display such dynamic interfaces on the interface overview.

5) Initial LuCI support for display interface runtime error information

  LuCI will now expose interface error information stored in the ubus
  runtime information by protocol handlers.

  This is mainly useful to get notified of low level problems like
  bad SIM codes are missing APN information.

6) Various XSS and CSRF bypass fixes

  A number of code places performing inadequate markup escaping have been
  fixed and the dispatcher CSRF token enforcement rules have been reworked
  to actually catch all POST security cases.

7) Initial support for running under nginx

  Various bugs have been fixed to allow LuCI to function under nginx using
  a FastCGI wrapper.

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
Jo-Philipp Wich 2018-07-13 17:02:22 +02:00
commit fb817df836
249 changed files with 17761 additions and 9390 deletions

View file

@ -1,22 +1,21 @@
-- Copyright 2017 Dirk Brenken (dev@brenken.org) -- Copyright 2017-2018 Dirk Brenken (dev@brenken.org)
-- This is free software, licensed under the Apache License, Version 2.0 -- This is free software, licensed under the Apache License, Version 2.0
local fs = require("nixio.fs") local fs = require("nixio.fs")
local util = require("luci.util") local util = require("luci.util")
local uci = require("luci.model.uci").cursor() local uci = require("luci.model.uci").cursor()
local adbinput = uci:get("adblock", "blacklist", "adb_src") or "/etc/adblock/adblock.blacklist" local adbinput = uci:get("adblock", "blacklist", "adb_src") or "/etc/adblock/adblock.blacklist"
if not nixio.fs.access(adbinput) then if not fs.access(adbinput) then
m = SimpleForm("error", nil, m = SimpleForm("error", nil, translate("Input file not found, please check your configuration."))
translate("Input file not found, please check your configuration."))
m.reset = false m.reset = false
m.submit = false m.submit = false
return m return m
end end
if nixio.fs.stat(adbinput).size > 524288 then if fs.stat(adbinput).size >= 102400 then
m = SimpleForm("error", nil, m = SimpleForm("error", nil,
translate("The file size is too large for online editing in LuCI (&gt; 512 KB). ") translate("The file size is too large for online editing in LuCI (&ge; 100 KB). ")
.. translate("Please edit this file directly in a terminal session.")) .. translate("Please edit this file directly in a terminal session."))
m.reset = false m.reset = false
m.submit = false m.submit = false
@ -38,11 +37,11 @@ f.rows = 20
f.rmempty = true f.rmempty = true
function f.cfgvalue() function f.cfgvalue()
return nixio.fs.readfile(adbinput) or "" return fs.readfile(adbinput) or ""
end end
function f.write(self, section, data) function f.write(self, section, data)
return nixio.fs.writefile(adbinput, "\n" .. util.trim(data:gsub("\r\n", "\n")) .. "\n") return fs.writefile(adbinput, "\n" .. util.trim(data:gsub("\r\n", "\n")) .. "\n")
end end
function s.handle(self, state, data) function s.handle(self, state, data)

View file

@ -1,17 +1,26 @@
-- Copyright 2017 Dirk Brenken (dev@brenken.org) -- Copyright 2017-2018 Dirk Brenken (dev@brenken.org)
-- This is free software, licensed under the Apache License, Version 2.0 -- This is free software, licensed under the Apache License, Version 2.0
local fs = require("nixio.fs") local fs = require("nixio.fs")
local util = require("luci.util") local util = require("luci.util")
local adbinput = "/etc/config/adblock" local adbinput = "/etc/config/adblock"
if not nixio.fs.access(adbinput) then if not fs.access(adbinput) then
m = SimpleForm("error", nil, translate("Input file not found, please check your configuration.")) m = SimpleForm("error", nil, translate("Input file not found, please check your configuration."))
m.reset = false m.reset = false
m.submit = false m.submit = false
return m return m
end end
if fs.stat(adbinput).size >= 102400 then
m = SimpleForm("error", nil,
translate("The file size is too large for online editing in LuCI (&ge; 100 KB). ")
.. translate("Please edit this file directly in a terminal session."))
m.reset = false
m.submit = false
return m
end
m = SimpleForm("input", nil) m = SimpleForm("input", nil)
m:append(Template("adblock/config_css")) m:append(Template("adblock/config_css"))
m.submit = translate("Save") m.submit = translate("Save")
@ -25,11 +34,11 @@ f.rows = 20
f.rmempty = true f.rmempty = true
function f.cfgvalue() function f.cfgvalue()
return nixio.fs.readfile(adbinput) or "" return fs.readfile(adbinput) or ""
end end
function f.write(self, section, data) function f.write(self, section, data)
return nixio.fs.writefile(adbinput, "\n" .. util.trim(data:gsub("\r\n", "\n")) .. "\n") return fs.writefile(adbinput, "\n" .. util.trim(data:gsub("\r\n", "\n")) .. "\n")
end end
function s.handle(self, state, data) function s.handle(self, state, data)

View file

@ -183,7 +183,7 @@ end
des = bl:option(DummyValue, "adb_src_desc", translate("Description")) des = bl:option(DummyValue, "adb_src_desc", translate("Description"))
cat = bl:option(DynamicList, "adb_src_cat", translate("Categories")) cat = bl:option(DynamicList, "adb_src_cat", translate("Archive Categories"))
cat.datatype = "uciname" cat.datatype = "uciname"
cat.optional = true cat.optional = true

View file

@ -1,22 +1,22 @@
-- Copyright 2017 Dirk Brenken (dev@brenken.org) -- Copyright 2017-2018 Dirk Brenken (dev@brenken.org)
-- This is free software, licensed under the Apache License, Version 2.0 -- This is free software, licensed under the Apache License, Version 2.0
local fs = require("nixio.fs") local fs = require("nixio.fs")
local util = require("luci.util") local util = require("luci.util")
local uci = require("luci.model.uci").cursor() local uci = require("luci.model.uci").cursor()
local adbinput = uci:get("adblock", "global", "adb_whitelist") or "/etc/adblock/adblock.whitelist" local adbinput = uci:get("adblock", "global", "adb_whitelist") or "/etc/adblock/adblock.whitelist"
if not nixio.fs.access(adbinput) then if not fs.access(adbinput) then
m = SimpleForm("error", nil, translate("Input file not found, please check your configuration.")) m = SimpleForm("error", nil, translate("Input file not found, please check your configuration."))
m.reset = false m.reset = false
m.submit = false m.submit = false
return m return m
end end
if nixio.fs.stat(adbinput).size > 524288 then if fs.stat(adbinput).size >= 102400 then
m = SimpleForm("error", nil, m = SimpleForm("error", nil,
translate("The file size is too large for online editing in LuCI (&gt; 512 KB). ") translate("The file size is too large for online editing in LuCI (&ge; 100 KB). ")
.. translate("Please edit this file directly in a terminal session.")) .. translate("Please edit this file directly in a terminal session."))
m.reset = false m.reset = false
m.submit = false m.submit = false
return m return m
@ -37,11 +37,11 @@ f.rows = 20
f.rmempty = true f.rmempty = true
function f.cfgvalue() function f.cfgvalue()
return nixio.fs.readfile(adbinput) or "" return fs.readfile(adbinput) or ""
end end
function f.write(self, section, data) function f.write(self, section, data)
return nixio.fs.writefile(adbinput, "\n" .. util.trim(data:gsub("\r\n", "\n")) .. "\n") return fs.writefile(adbinput, "\n" .. util.trim(data:gsub("\r\n", "\n")) .. "\n")
end end
function s.handle(self, state, data) function s.handle(self, state, data)

View file

@ -22,66 +22,77 @@ end
-%> -%>
<style type="text/css"> <style type="text/css">
table.cbi-section-table th, .table.cbi-section-table .th,
table.cbi-section-table td, .table.cbi-section-table .td,
.cbi-section-table-cell, .cbi-section-table-cell,
.cbi-section-table-row, .cbi-section-table-row
.cbi-input-text
{ {
text-align:left; text-align:left;
vertical-align:top; vertical-align:top;
margin-right:auto; margin-right:auto;
margin-left:0px; margin-left:0px;
padding-left:2px;
line-height:20px;
}
.table.cbi-section-table .th
{
white-space:nowrap;
}
.table.cbi-section-table input
{
width:7em;
} }
.cbi-input-text .cbi-input-text
{ {
text-align:left;
padding-left:2px;
outline:none; outline:none;
box-shadow:none; box-shadow:none;
background:transparent; background:transparent;
padding-left:2px; height:20px;
line-height:25px;
height:25px;
width:10em; width:10em;
} }
</style> </style>
<%-
local anonclass = (not self.anonymous or self.sectiontitle) and "named" or "anonymous"
local titlename = ifattr(not self.anonymous or self.sectiontitle, "data-title", translate("Name"))
-%>
<fieldset class="cbi-section" id="cbi-<%=self.config%>-<%=self.sectiontype%>"> <fieldset class="cbi-section" id="cbi-<%=self.config%>-<%=self.sectiontype%>">
<% if self.title then -%> <% if self.title then -%>
<legend><%=self.title%></legend> <legend><%=self.title%></legend>
<%- end %> <%- end %>
<div class="cbi-section-descr"><%=self.description%></div> <div class="cbi-section-descr"><%=self.description%></div>
<div class="cbi-section-node"> <div class="cbi-section-node">
<table class="cbi-section-table"> <div class="table cbi-section-table">
<tr class="cbi-section-table-titles"> <div class="tr cbi-section-table-titles <%=anonclass%>"<%=titlename%>>
<%- if self.sectionhead then -%>
<th class="cbi-section-table-cell"><%=self.sectionhead%></th>
<%- else -%>
<th>&#160;</th>
<%- end -%>
<%- for i, k in pairs(self.children) do -%> <%- for i, k in pairs(self.children) do -%>
<th class="cbi-section-table-cell"<%=width(k)%>> <div class="th cbi-section-table-cell"<%=width(k)%>>
<%-=k.title-%> <%-=k.title-%>
</th> </div>
<%- end -%> <%- end -%>
</tr> </div>
<%- local isempty = true <%- local isempty = true
for i, k in ipairs(self:cfgsections()) do for i, k in ipairs(self:cfgsections()) do
section = k local section = k
local sectionname = striptags((type(self.sectiontitle) == "function") and self:sectiontitle(section) or k)
local sectiontitle = ifattr(sectionname and (not self.anonymous or self.sectiontitle), "data-title", sectionname)
isempty = false isempty = false
scope = { valueheader = "cbi/cell_valueheader", valuefooter = "cbi/cell_valuefooter" } scope = { valueheader = "cbi/cell_valueheader", valuefooter = "cbi/cell_valuefooter" }
-%> -%>
<tr class="cbi-section-table-row" id="cbi-<%=self.config%>-<%=section%>"> <div class="tr cbi-section-table-row" id="cbi-<%=self.config%>-<%=section%>"<%=sectiontitle%>>
<th><%=k%></th>
<%- <%-
for k, node in ipairs(self.children) do for k, node in ipairs(self.children) do
node:render(section, scope or {}) node:render(section, scope or {})
end end
if not scope.cbid:match("adb_src_cat") then if not scope.cbid:match("adb_src_cat") then
-%> -%>
<td class="cbi-value-field">&#160;</td> <div class="td cbi-value-field">&#160;</div>
<%- end -%> <%- end -%>
</tr> </div>
<%- end -%> <%- end -%>
</table> </div>
</div> </div>
</fieldset> </fieldset>

View file

@ -5,7 +5,6 @@ This is free software, licensed under the Apache License, Version 2.0
<%+header%> <%+header%>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript"> <script type="text/javascript">
//<![CDATA[ //<![CDATA[
var stxhr = new XHR(); var stxhr = new XHR();
@ -35,7 +34,7 @@ This is free software, licensed under the Apache License, Version 2.0
else else
{ {
input.style.display = 'none'; input.style.display = 'none';
output.innerHTML = '<span class="error"><%:Invalid domain specified!%></span>'; output.innerHTML = '<span class="error"><%:Blocklist not found!%></span>';
} }
} }
); );

View file

@ -49,9 +49,7 @@ msgstr ""
msgid "Blocklist Sources" msgid "Blocklist Sources"
msgstr "Fonti lista di Blocco" msgstr "Fonti lista di Blocco"
msgid "" msgid "Blocklist not found!"
"Builds an additional 'Jail' list (/tmp/adb_list.jail) to block access to all "
"domains except those listed in the whitelist file.<br />"
msgstr "" msgstr ""
msgid "Categories" msgid "Categories"
@ -169,9 +167,6 @@ msgstr ""
msgid "Input file not found, please check your configuration." msgid "Input file not found, please check your configuration."
msgstr "File di input non trovato, per favore controlla la tua configurazione." msgstr "File di input non trovato, per favore controlla la tua configurazione."
msgid "Invalid domain specified!"
msgstr "Dominio invalido specificato!"
msgid "Last Run" msgid "Last Run"
msgstr "Ultimo Avvio" msgstr "Ultimo Avvio"
@ -280,10 +275,8 @@ msgstr ""
msgid "Target directory for the generated blocklist 'adb_list.overall'." msgid "Target directory for the generated blocklist 'adb_list.overall'."
msgstr "Directory per la lista di blocco generata 'adb_list.overall'." msgstr "Directory per la lista di blocco generata 'adb_list.overall'."
msgid "The file size is too large for online editing in LuCI (&gt; 512 KB)." msgid "The file size is too large for online editing in LuCI (&ge; 100 KB)."
msgstr "" msgstr ""
"La grandezza del file è troppo grande per modificarla online in LuCI (&gt; "
"512 KB)."
msgid "" msgid ""
"This form allows you to modify the content of the adblock blacklist (%s)." "This form allows you to modify the content of the adblock blacklist (%s)."

View file

@ -51,6 +51,9 @@ msgstr "バックアップ モード"
msgid "Blocklist Sources" msgid "Blocklist Sources"
msgstr "ブロックリスト提供元" msgstr "ブロックリスト提供元"
msgid "Blocklist not found!"
msgstr ""
msgid "" msgid ""
"Builds an additional 'Jail' list (/tmp/adb_list.jail) to block access to all " "Builds an additional 'Jail' list (/tmp/adb_list.jail) to block access to all "
"domains except those listed in the whitelist file.<br />" "domains except those listed in the whitelist file.<br />"
@ -185,9 +188,6 @@ msgstr "ホワイトリスト ファイルへのフルパスです。"
msgid "Input file not found, please check your configuration." msgid "Input file not found, please check your configuration."
msgstr "入力ファイルが見つかりません。設定を確認してください。" msgstr "入力ファイルが見つかりません。設定を確認してください。"
msgid "Invalid domain specified!"
msgstr "無効なドメインが指定されています!"
msgid "Last Run" msgid "Last Run"
msgstr "最終実行" msgstr "最終実行"
@ -304,10 +304,10 @@ msgstr ""
msgid "Target directory for the generated blocklist 'adb_list.overall'." msgid "Target directory for the generated blocklist 'adb_list.overall'."
msgstr "生成されたブロックリスト 'adb_list.overall' の保存先ディレクトリです。" msgstr "生成されたブロックリスト 'adb_list.overall' の保存先ディレクトリです。"
msgid "The file size is too large for online editing in LuCI (&gt; 512 KB)." msgid "The file size is too large for online editing in LuCI (&ge; 100 KB)."
msgstr "" msgstr ""
"ファイル サイズが大きすぎる512 KB超ため、 LuCI 上でオンライン編集できませ" "LuCI上でのオンライン編集を行うには、ファイルサイズが大きすぎます (&ge; 100 "
"。" "KB)。"
msgid "" msgid ""
"This form allows you to modify the content of the adblock blacklist (%s)." "This form allows you to modify the content of the adblock blacklist (%s)."

View file

@ -52,9 +52,7 @@ msgstr ""
msgid "Blocklist Sources" msgid "Blocklist Sources"
msgstr "Fontes de listas de bloqueio" msgstr "Fontes de listas de bloqueio"
msgid "" msgid "Blocklist not found!"
"Builds an additional 'Jail' list (/tmp/adb_list.jail) to block access to all "
"domains except those listed in the whitelist file.<br />"
msgstr "" msgstr ""
msgid "Categories" msgid "Categories"
@ -169,9 +167,6 @@ msgstr ""
msgid "Input file not found, please check your configuration." msgid "Input file not found, please check your configuration."
msgstr "Arquivo de entrada não encontrado, por favor cheque sua configuração." msgstr "Arquivo de entrada não encontrado, por favor cheque sua configuração."
msgid "Invalid domain specified!"
msgstr "Domínio especificado inválido!"
msgid "Last Run" msgid "Last Run"
msgstr "" msgstr ""
@ -274,9 +269,8 @@ msgstr ""
msgid "Target directory for the generated blocklist 'adb_list.overall'." msgid "Target directory for the generated blocklist 'adb_list.overall'."
msgstr "" msgstr ""
msgid "The file size is too large for online editing in LuCI (&gt; 512 KB)." msgid "The file size is too large for online editing in LuCI (&ge; 100 KB)."
msgstr "" msgstr ""
"O tamanho do arquivo é muito grande para edição online no LuCI (&gt; 512 KB)."
msgid "" msgid ""
"This form allows you to modify the content of the adblock blacklist (%s)." "This form allows you to modify the content of the adblock blacklist (%s)."

View file

@ -53,6 +53,9 @@ msgstr "Режим сохранения бекапа"
msgid "Blocklist Sources" msgid "Blocklist Sources"
msgstr "Источники списков блокировки" msgstr "Источники списков блокировки"
msgid "Blocklist not found!"
msgstr ""
msgid "" msgid ""
"Builds an additional 'Jail' list (/tmp/adb_list.jail) to block access to all " "Builds an additional 'Jail' list (/tmp/adb_list.jail) to block access to all "
"domains except those listed in the whitelist file.<br />" "domains except those listed in the whitelist file.<br />"
@ -186,9 +189,6 @@ msgstr "Полный путь к файлу Белого списка."
msgid "Input file not found, please check your configuration." msgid "Input file not found, please check your configuration."
msgstr "Config файл не найден, настройте config файл." msgstr "Config файл не найден, настройте config файл."
msgid "Invalid domain specified!"
msgstr "Задан недопустимый домен!"
msgid "Last Run" msgid "Last Run"
msgstr "Последнее время запуска" msgstr "Последнее время запуска"
@ -306,9 +306,8 @@ msgstr ""
msgid "Target directory for the generated blocklist 'adb_list.overall'." msgid "Target directory for the generated blocklist 'adb_list.overall'."
msgstr "Назначить папку для создания списка блокировки 'adb_list.overall'." msgstr "Назначить папку для создания списка блокировки 'adb_list.overall'."
msgid "The file size is too large for online editing in LuCI (&gt; 512 KB)." msgid "The file size is too large for online editing in LuCI (&ge; 100 KB)."
msgstr "" msgstr ""
"Размер файла слишком большой, для онлайн редактирования в LuCI (&gt; 512 KB)."
msgid "" msgid ""
"This form allows you to modify the content of the adblock blacklist (%s)." "This form allows you to modify the content of the adblock blacklist (%s)."

View file

@ -39,9 +39,7 @@ msgstr ""
msgid "Blocklist Sources" msgid "Blocklist Sources"
msgstr "Källor för blockeringslistor" msgstr "Källor för blockeringslistor"
msgid "" msgid "Blocklist not found!"
"Builds an additional 'Jail' list (/tmp/adb_list.jail) to block access to all "
"domains except those listed in the whitelist file.<br />"
msgstr "" msgstr ""
msgid "Categories" msgid "Categories"
@ -160,9 +158,6 @@ msgid "Input file not found, please check your configuration."
msgstr "" msgstr ""
"Inmatningsfilen kunde inte hittas, var vänlig kontrollera din konfiguration." "Inmatningsfilen kunde inte hittas, var vänlig kontrollera din konfiguration."
msgid "Invalid domain specified!"
msgstr "Ogiltig domän angiven!"
msgid "Last Run" msgid "Last Run"
msgstr "Kördes senast" msgstr "Kördes senast"
@ -263,8 +258,8 @@ msgstr ""
msgid "Target directory for the generated blocklist 'adb_list.overall'." msgid "Target directory for the generated blocklist 'adb_list.overall'."
msgstr "" msgstr ""
msgid "The file size is too large for online editing in LuCI (&gt; 512 KB)." msgid "The file size is too large for online editing in LuCI (&ge; 100 KB)."
msgstr "Filstorleken är för stor för online-redigering i LuCi (&gt; 512 KB)." msgstr ""
msgid "" msgid ""
"This form allows you to modify the content of the adblock blacklist (%s)." "This form allows you to modify the content of the adblock blacklist (%s)."

View file

@ -39,9 +39,7 @@ msgstr ""
msgid "Blocklist Sources" msgid "Blocklist Sources"
msgstr "" msgstr ""
msgid "" msgid "Blocklist not found!"
"Builds an additional 'Jail' list (/tmp/adb_list.jail) to block access to all "
"domains except those listed in the whitelist file.<br />"
msgstr "" msgstr ""
msgid "Categories" msgid "Categories"
@ -152,9 +150,6 @@ msgstr ""
msgid "Input file not found, please check your configuration." msgid "Input file not found, please check your configuration."
msgstr "" msgstr ""
msgid "Invalid domain specified!"
msgstr ""
msgid "Last Run" msgid "Last Run"
msgstr "" msgstr ""
@ -255,7 +250,7 @@ msgstr ""
msgid "Target directory for the generated blocklist 'adb_list.overall'." msgid "Target directory for the generated blocklist 'adb_list.overall'."
msgstr "" msgstr ""
msgid "The file size is too large for online editing in LuCI (&gt; 512 KB)." msgid "The file size is too large for online editing in LuCI (&ge; 100 KB)."
msgstr "" msgstr ""
msgid "" msgid ""

View file

@ -16,7 +16,7 @@ msgstr ""
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"
msgid "'Jail' Blocklist Creation" msgid "'Jail' Blocklist Creation"
msgstr "" msgstr "“Jail” 拦截名单创建"
msgid "-------" msgid "-------"
msgstr "-------" msgstr "-------"
@ -48,14 +48,12 @@ msgid "Backup Directory"
msgstr "备份目录" msgstr "备份目录"
msgid "Backup Mode" msgid "Backup Mode"
msgstr "" msgstr "备份模式"
msgid "Blocklist Sources" msgid "Blocklist Sources"
msgstr "拦截列表来源" msgstr "拦截列表来源"
msgid "" msgid "Blocklist not found!"
"Builds an additional 'Jail' list (/tmp/adb_list.jail) to block access to all "
"domains except those listed in the whitelist file.<br />"
msgstr "" msgstr ""
msgid "Categories" msgid "Categories"
@ -79,6 +77,7 @@ msgid ""
"Create compressed blocklist backups, they will be used in case of download " "Create compressed blocklist backups, they will be used in case of download "
"errors or during startup in backup mode." "errors or during startup in backup mode."
msgstr "" msgstr ""
"创建压缩的拦截列表备份,它们将在下载错误或备份模式启动期间使用。"
msgid "DNS Backend (DNS Directory)" msgid "DNS Backend (DNS Directory)"
msgstr "DNS 后端DNS 目录)" msgstr "DNS 后端DNS 目录)"
@ -95,7 +94,7 @@ msgid ""
msgstr "启动期间不要自动更新 blocklists改用 blocklists 的备份。" msgstr "启动期间不要自动更新 blocklists改用 blocklists 的备份。"
msgid "Download Utility" msgid "Download Utility"
msgstr "" msgstr "下载工具"
msgid "Download Utility (SSL Library)" msgid "Download Utility (SSL Library)"
msgstr "下载实用程序SSL 库)" msgstr "下载实用程序SSL 库)"
@ -110,10 +109,10 @@ msgid "Edit Whitelist"
msgstr "编辑白名单" msgstr "编辑白名单"
msgid "Email Notification" msgid "Email Notification"
msgstr "" msgstr "Email 提醒"
msgid "Email Notification Count" msgid "Email Notification Count"
msgstr "" msgstr "Email 提醒计数"
msgid "Enable Adblock" msgid "Enable Adblock"
msgstr "启用 Adblock" msgstr "启用 Adblock"
@ -125,6 +124,7 @@ msgid ""
"Enable memory intense overall sort / duplicate removal on low memory devices " "Enable memory intense overall sort / duplicate removal on low memory devices "
"(&lt; 64 MB free RAM)" "(&lt; 64 MB free RAM)"
msgstr "" msgstr ""
"在低内存设备上启用积极的内存整体排序/重复移除(&lt; 64 MB 空闲内存)"
msgid "Enable verbose debug logging in case of any processing error." msgid "Enable verbose debug logging in case of any processing error."
msgstr "在出现任何处理错误的情况下启用详细调试日志记录。" msgstr "在出现任何处理错误的情况下启用详细调试日志记录。"
@ -136,25 +136,29 @@ msgid "Extra Options"
msgstr "额外选项" msgstr "额外选项"
msgid "Flush DNS Cache" msgid "Flush DNS Cache"
msgstr "" msgstr "清空 DNS 缓存"
msgid "Flush DNS Cache after adblock processing." msgid "Flush DNS Cache after adblock processing."
msgstr "" msgstr "在 adblock 进程启动后清空 DNS 缓存。"
msgid "" msgid ""
"For SSL protected blocklist sources you need a suitable SSL library, e.g. " "For SSL protected blocklist sources you need a suitable SSL library, e.g. "
"'libustream-ssl' or 'built-in'." "'libustream-ssl' or 'built-in'."
msgstr "" msgstr ""
"对受 SSL 保护的拦截列表源,您需要一个合适的 SSL 库,如 “libustream-ssl” 或 "
"“built-in”。"
msgid "" msgid ""
"For further information <a href=\"%s\" target=\"_blank\">check the online " "For further information <a href=\"%s\" target=\"_blank\">check the online "
"documentation</a>" "documentation</a>"
msgstr "" msgstr ""
"进一步信息<a href=\"%s\" target=\"_blank\">请访问在线文档"
msgid "" msgid ""
"For further performance improvements you can raise this value, e.g. '8' or " "For further performance improvements you can raise this value, e.g. '8' or "
"'16' should be safe." "'16' should be safe."
msgstr "" msgstr ""
"为了进一步提高性能您可以提高此值例如8 或 16 应该是安全的。"
msgid "Force Local DNS" msgid "Force Local DNS"
msgstr "强制本地 DNS" msgstr "强制本地 DNS"
@ -163,14 +167,11 @@ msgid "Force Overall Sort"
msgstr "强制整体排序" msgstr "强制整体排序"
msgid "Full path to the whitelist file." msgid "Full path to the whitelist file."
msgstr "" msgstr "白名单文件的全路径。"
msgid "Input file not found, please check your configuration." msgid "Input file not found, please check your configuration."
msgstr "输入文件未找到,请检查您的配置。" msgstr "输入文件未找到,请检查您的配置。"
msgid "Invalid domain specified!"
msgstr "无效域名!"
msgid "Last Run" msgid "Last Run"
msgstr "最后运行" msgstr "最后运行"
@ -178,6 +179,7 @@ msgid ""
"List of available network interfaces. Usually the startup will be triggered " "List of available network interfaces. Usually the startup will be triggered "
"by the 'wan' interface.<br />" "by the 'wan' interface.<br />"
msgstr "" msgstr ""
"可用网络接口列表。通常启动将由 “wan” 接口触发。<br />"
msgid "" msgid ""
"List of supported DNS backends with their default list export directory.<br /" "List of supported DNS backends with their default list export directory.<br /"
@ -185,13 +187,13 @@ msgid ""
msgstr "支持的 DNS 后端列表及其默认列表导出目录。<br />" msgstr "支持的 DNS 后端列表及其默认列表导出目录。<br />"
msgid "List of supported and fully pre-configured download utilities." msgid "List of supported and fully pre-configured download utilities."
msgstr "" msgstr "支持和完全预配置的下载工具列表。"
msgid "Loading" msgid "Loading"
msgstr "加载中" msgstr "加载中"
msgid "Max. Download Queue" msgid "Max. Download Queue"
msgstr "" msgstr "最大下载队列"
msgid "No" msgid "No"
msgstr "否" msgstr "否"
@ -201,7 +203,7 @@ msgid ""
msgstr "在默认设置并不适合您时的额外选项。" msgstr "在默认设置并不适合您时的额外选项。"
msgid "Overall Domains" msgid "Overall Domains"
msgstr "" msgstr "域名总览"
msgid "Overview" msgid "Overview"
msgstr "总览" msgstr "总览"
@ -230,6 +232,7 @@ msgid ""
"Raise the minimum email notification count, to get emails if the overall " "Raise the minimum email notification count, to get emails if the overall "
"count is less or equal to the given limit (default 0),<br />" "count is less or equal to the given limit (default 0),<br />"
msgstr "" msgstr ""
"如果总数小于或等于给定限制(默认为 0请提高最小电子邮件通知数以获取电子邮件。"
msgid "Redirect all DNS queries from 'lan' zone to the local resolver." msgid "Redirect all DNS queries from 'lan' zone to the local resolver."
msgstr "将所有 DNS 查询从“lan”区域重定向到本地解析器。" msgstr "将所有 DNS 查询从“lan”区域重定向到本地解析器。"
@ -250,11 +253,13 @@ msgid ""
"Send notification emails in case of a processing error or if domain count is " "Send notification emails in case of a processing error or if domain count is "
"&le; 0.<br />" "&le; 0.<br />"
msgstr "" msgstr ""
"如果发生错误或域计数 &le; 0发送通知电子邮件。<br />"
msgid "" msgid ""
"Size of the download queue to handle downloads &amp; list processing in " "Size of the download queue to handle downloads &amp; list processing in "
"parallel (default '4').<br />" "parallel (default '4').<br />"
msgstr "" msgstr ""
"处理下载队列的大小 amp; 并行处理列表(默认 “4”。<br />"
msgid "Startup Trigger" msgid "Startup Trigger"
msgstr "启动触发器" msgstr "启动触发器"
@ -269,12 +274,14 @@ msgid ""
"Target directory for adblock backups. Please use only non-volatile disks, e." "Target directory for adblock backups. Please use only non-volatile disks, e."
"g. an external usb stick." "g. an external usb stick."
msgstr "" msgstr ""
"adblock 备份的目标目录。 请仅使用非易失性磁盘,例如:一个外置 U 盘。"
msgid "Target directory for the generated blocklist 'adb_list.overall'." msgid "Target directory for the generated blocklist 'adb_list.overall'."
msgstr "生成的 blocklist 'adb_list.overall'的目标目录。" msgstr "生成的 blocklist 'adb_list.overall'的目标目录。"
msgid "The file size is too large for online editing in LuCI (&gt; 512 KB)." msgid "The file size is too large for online editing in LuCI (&ge; 100 KB)."
msgstr "文件大小太大,无法在 LuCI&gt; 512 KB中进行在线编辑。" msgstr ""
"文件过大,无法使用 LuCI 的在线编辑(&ge; 100 KB。"
msgid "" msgid ""
"This form allows you to modify the content of the adblock blacklist (%s)." "This form allows you to modify the content of the adblock blacklist (%s)."
@ -319,7 +326,7 @@ msgid "Waiting for command to complete..."
msgstr "正在执行命令..." msgstr "正在执行命令..."
msgid "Whitelist File" msgid "Whitelist File"
msgstr "" msgstr "白名单文件"
msgid "Yes" msgid "Yes"
msgstr "是" msgstr "是"
@ -328,6 +335,7 @@ msgid ""
"You can use this restrictive blocklist manually e.g. for guest wifi or " "You can use this restrictive blocklist manually e.g. for guest wifi or "
"kidsafe configurations." "kidsafe configurations."
msgstr "" msgstr ""
"您可以手动使用此限制性拦截列表,例如:为客人提供 wifi 或 kidsafe 配置。"
msgid "disabled" msgid "disabled"
msgstr "已禁用" msgstr "已禁用"
@ -335,7 +343,7 @@ msgstr "已禁用"
msgid "" msgid ""
"e.g. to receive an email notification with every adblock update set this " "e.g. to receive an email notification with every adblock update set this "
"value to 150000." "value to 150000."
msgstr "" msgstr "例如:要接收每个 adblock 更新的电子邮件通知时将此值设置为150000。"
msgid "enabled" msgid "enabled"
msgstr "已启用" msgstr "已启用"
@ -350,7 +358,18 @@ msgid "paused"
msgstr "已暂停" msgstr "已暂停"
msgid "running" msgid "running"
msgstr "" msgstr "运行中"
#~ msgid "Invalid domain specified!"
#~ msgstr "无效域名!"
#~ msgid "Available blocklist sources."
#~ msgstr "可用的 blocklist 来源。"
#~ msgid ""
#~ "List URLs and Shallalist category selections are configurable in the "
#~ "'Advanced' section.<br />"
#~ msgstr "列表 URL 和 Shallalist 类别选择可在“高级”选项卡中配置。<br />"
#~ msgid "Available blocklist sources." #~ msgid "Available blocklist sources."
#~ msgstr "可用的 blocklist 来源。" #~ msgstr "可用的 blocklist 来源。"

View file

@ -53,9 +53,7 @@ msgstr ""
msgid "Blocklist Sources" msgid "Blocklist Sources"
msgstr "攔截列表來源" msgstr "攔截列表來源"
msgid "" msgid "Blocklist not found!"
"Builds an additional 'Jail' list (/tmp/adb_list.jail) to block access to all "
"domains except those listed in the whitelist file.<br />"
msgstr "" msgstr ""
msgid "Categories" msgid "Categories"
@ -168,9 +166,6 @@ msgstr ""
msgid "Input file not found, please check your configuration." msgid "Input file not found, please check your configuration."
msgstr "輸入檔案未找到,請檢查您的配置。" msgstr "輸入檔案未找到,請檢查您的配置。"
msgid "Invalid domain specified!"
msgstr "無效域名!"
msgid "Last Run" msgid "Last Run"
msgstr "最後執行" msgstr "最後執行"
@ -273,8 +268,8 @@ msgstr ""
msgid "Target directory for the generated blocklist 'adb_list.overall'." msgid "Target directory for the generated blocklist 'adb_list.overall'."
msgstr "生成的 blocklist 'adb_list.overall'的目標目錄。" msgstr "生成的 blocklist 'adb_list.overall'的目標目錄。"
msgid "The file size is too large for online editing in LuCI (&gt; 512 KB)." msgid "The file size is too large for online editing in LuCI (&ge; 100 KB)."
msgstr "檔案大小太大,無法在 LuCI&gt; 512 KB中進行線上編輯。" msgstr ""
msgid "" msgid ""
"This form allows you to modify the content of the adblock blacklist (%s)." "This form allows you to modify the content of the adblock blacklist (%s)."

View file

@ -11,9 +11,9 @@ LUCI_DESCRIPTION:=Provides Web UI (found under System/Advanced Reboot) to reboot
an altnerative partition. Also provides Web UI to shut down (power off) your device. Supported dual-partition\ an altnerative partition. Also provides Web UI to shut down (power off) your device. Supported dual-partition\
routers are listed at https://github.com/stangri/openwrt-luci/blob/luci-app-advanced-reboot/applications/luci-app-advanced-reboot/README.md routers are listed at https://github.com/stangri/openwrt-luci/blob/luci-app-advanced-reboot/applications/luci-app-advanced-reboot/README.md
LUCI_DEPENDS:=+luci LUCI_DEPENDS:=+luci-mod-admin-full
LUCI_PKGARCH:=all LUCI_PKGARCH:=all
PKG_RELEASE:=27 PKG_RELEASE:=32
include ../../luci.mk include ../../luci.mk

View file

@ -14,6 +14,7 @@ Currently supported dual-partition devices include:
- Linksys WRT1900ACv2 - Linksys WRT1900ACv2
- Linksys WRT1900ACS - Linksys WRT1900ACS
- Linksys WRT3200ACM - Linksys WRT3200ACM
- Linksys WRT32X
- ZyXEL NBG6817 - ZyXEL NBG6817
If you're interested in having your device supported, please post in [LEDE Project Forum Support Thread](https://forum.lede-project.org/t/web-ui-to-reboot-to-another-partition-dual-partition-routers/3423). If you're interested in having your device supported, please post in [LEDE Project Forum Support Thread](https://forum.lede-project.org/t/web-ui-to-reboot-to-another-partition-dual-partition-routers/3423).
@ -34,4 +35,4 @@ opkg install luci-app-advanced-reboot
- Some devices allow you to trigger reboot to an alternative partition by interrupting boot 3 times in a row (by resetting/switching off the device or pulling power). As these methods might be different for different devices, do your own homework. - Some devices allow you to trigger reboot to an alternative partition by interrupting boot 3 times in a row (by resetting/switching off the device or pulling power). As these methods might be different for different devices, do your own homework.
## Thanks ## Thanks
I'd like to thank everyone who helped create, test and troubleshoot this package. Without contributions from [@hnyman](https://github.com/hnyman), [@jpstyves](https://github.com/jpstyves) and [@slh](https://github.com/pkgadd) it wouldn't have been possible. I'd like to thank everyone who helped create, test and troubleshoot this package. Without help from [@hnyman](https://github.com/hnyman), [@jpstyves](https://github.com/jpstyves) and many contributions from [@slh](https://github.com/pkgadd) it wouldn't have been possible.

View file

@ -3,25 +3,26 @@
module("luci.controller.advanced_reboot", package.seeall) module("luci.controller.advanced_reboot", package.seeall)
-- device_name, board_name, part1, part2, offset, env_var_1, value_1_1, value_1_2, env_var_2, value_2_1, value_2_2
devices = { devices = {
-- deviceName, boardName, partition1, partition2, offset, envVar1, envVar1Value1, envVar1Value2, envVar2, envVar2Value1, envVar2Value2
{"Linksys EA3500", "linksys-audi", "mtd3", "mtd5", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"}, {"Linksys EA3500", "linksys-audi", "mtd3", "mtd5", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"},
{"Linksys E4200v2/EA4500", "linksys-viper", "mtd3", "mtd5", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"}, {"Linksys E4200v2/EA4500", "linksys-viper", "mtd3", "mtd5", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"},
{"Linksys EA8500", "ea8500", "mtd13", "mtd15", 32, "boot_part", 1, 2}, {"Linksys EA8500", "ea8500", "mtd13", "mtd15", 32, "boot_part", 1, 2},
-- {"Linksys EA9500", "linksys,panamera", "mtd3", "mtd6", 28, "boot_part", 1, 2}, -- {"Linksys EA9500", "linksys-panamera", "mtd3", "mtd6", 28, "boot_part", 1, 2},
{"Linksys WRT1200AC", "linksys-caiman", "mtd4", "mtd6", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"}, {"Linksys WRT1200AC", "linksys-caiman", "mtd4", "mtd6", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"},
{"Linksys WRT1900AC", "linksys-mamba", "mtd4", "mtd6", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"}, {"Linksys WRT1900AC", "linksys-mamba", "mtd4", "mtd6", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"},
{"Linksys WRT1900ACv2", "linksys-cobra", "mtd4", "mtd6", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"}, {"Linksys WRT1900ACv2", "linksys-cobra", "mtd4", "mtd6", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"},
{"Linksys WRT1900ACS", "linksys-shelby", "mtd4", "mtd6", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"}, {"Linksys WRT1900ACS", "linksys-shelby", "mtd4", "mtd6", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"},
{"Linksys WRT3200ACM", "linksys-rango", "mtd5", "mtd7", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"}, {"Linksys WRT3200ACM", "linksys-rango", "mtd5", "mtd7", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"},
{"ZyXEL NBG6817","nbg6817","mmcblk0p4","mmcblk0p7",32,nil,255,1} {"Linksys WRT32X", "linksys-venom", "mtd5", "mtd7", nil, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"},
{"ZyXEL NBG6817","nbg6817","mmcblk0p4","mmcblk0p7", 32, nil, 255, 1}
} }
errorMessage = "" errorMessage = nil
device_board_name = luci.util.trim(luci.sys.exec("cat /tmp/sysinfo/board_name")) rom_board_name = luci.util.trim(luci.sys.exec("cat /tmp/sysinfo/board_name"))
for i=1, #devices do for i=1, #devices do
table_board_name = devices[i][2]:gsub('%p','') device_board_name = devices[i][2]:gsub('%p','')
if device_board_name and device_board_name:gsub('%p',''):match(table_board_name) then if rom_board_name and rom_board_name:gsub('%p',''):match(device_board_name) then
device_name = devices[i][1] device_name = devices[i][1]
partition_one_mtd = devices[i][3] or nil partition_one_mtd = devices[i][3] or nil
partition_two_mtd = devices[i][4] or nil partition_two_mtd = devices[i][4] or nil
@ -40,16 +41,20 @@ for i=1, #devices do
partition_two_label = luci.util.trim(luci.sys.exec("dd if=/dev/" .. partition_two_mtd .. " bs=1 skip=" .. partition_skip .. " count=25" .. " 2>/dev/null")) partition_two_label = luci.util.trim(luci.sys.exec("dd if=/dev/" .. partition_two_mtd .. " bs=1 skip=" .. partition_skip .. " count=25" .. " 2>/dev/null"))
n, partition_two_version = string.match(partition_two_label, '(Linux)-([%d|.]+)') n, partition_two_version = string.match(partition_two_label, '(Linux)-([%d|.]+)')
end end
if string.find(partition_one_label, "LEDE") then partition_one_os = "LEDE" end if partition_one_label and string.find(partition_one_label, "LEDE") then partition_one_os = "LEDE" end
if string.find(partition_one_label, "OpenWrt") then partition_one_os = "OpenWrt" end if partition_one_label and string.find(partition_one_label, "OpenWrt") then partition_one_os = "OpenWrt" end
if string.find(partition_one_label, "Linksys") then partition_one_os = "Linksys" end if partition_one_label and string.find(partition_one_label, "Linksys") then partition_one_os = "Linksys" end
if string.find(partition_two_label, "LEDE") then partition_two_os = "LEDE" end if partition_two_label and string.find(partition_two_label, "LEDE") then partition_two_os = "LEDE" end
if string.find(partition_two_label, "OpenWrt") then partition_two_os = "OpenWrt" end if partition_two_label and string.find(partition_two_label, "OpenWrt") then partition_two_os = "OpenWrt" end
if string.find(partition_two_label, "Linksys") then partition_two_os = "Linksys" end if partition_two_label and string.find(partition_two_label, "Linksys") then partition_two_os = "Linksys" end
if device_name and device_name == "ZyXEL NBG6817" then if device_name and device_name == "ZyXEL NBG6817" then
if not partition_one_os then partition_one_os = "ZyXEL" end if not partition_one_os then partition_one_os = "ZyXEL" end
if not partition_two_os then partition_two_os = "ZyXEL" end if not partition_two_os then partition_two_os = "ZyXEL" end
end end
if device_name and device_name == "Linksys WRT32X" then
if not partition_one_os then partition_one_os = "Unknown/Compressed" end
if not partition_two_os then partition_two_os = "Unknown/Compressed" end
end
if not partition_one_os then partition_one_os = "Unknown" end if not partition_one_os then partition_one_os = "Unknown" end
if not partition_two_os then partition_two_os = "Unknown" end if not partition_two_os then partition_two_os = "Unknown" end
if partition_one_os and partition_one_version then partition_one_os = partition_one_os .. " (Linux " .. partition_one_version .. ")" end if partition_one_os and partition_one_version then partition_one_os = partition_one_os .. " (Linux " .. partition_one_version .. ")" end
@ -75,7 +80,6 @@ end
function index() function index()
entry({"admin", "system", "advanced_reboot"}, template("advanced_reboot/advanced_reboot"), _("Advanced Reboot"), 90) entry({"admin", "system", "advanced_reboot"}, template("advanced_reboot/advanced_reboot"), _("Advanced Reboot"), 90)
entry({"admin", "system", "advanced_reboot", "reboot"}, post("action_reboot")) entry({"admin", "system", "advanced_reboot", "reboot"}, post("action_reboot"))
-- if device_name then entry({"admin", "system", "advanced_reboot", "altreboot"}, post("action_altreboot")) end
entry({"admin", "system", "advanced_reboot", "alternative_reboot"}, post("action_altreboot")) entry({"admin", "system", "advanced_reboot", "alternative_reboot"}, post("action_altreboot"))
entry({"admin", "system", "advanced_reboot", "power_off"}, post("action_poweroff")) entry({"admin", "system", "advanced_reboot", "power_off"}, post("action_poweroff"))
end end
@ -93,18 +97,10 @@ end
function action_altreboot() function action_altreboot()
local uci = require "luci.model.uci".cursor() local uci = require "luci.model.uci".cursor()
local zyxelFlagPartition, zyxelBootFlag, zyxelNewBootFlag, errorCode, curEnvSetting, newEnvSetting local zyxelFlagPartition, zyxelBootFlag, zyxelNewBootFlag, errorCode, curEnvSetting, newEnvSetting
errorMessage = "" errorMessage = nil
errorCode = 0 errorCode = 0
if luci.http.formvalue("cancel") then if luci.http.formvalue("cancel") then
luci.http.redirect(luci.dispatcher.build_url('admin/system/advanced_reboot')) luci.http.redirect(luci.dispatcher.build_url('admin/system/advanced_reboot'))
-- luci.template.render("advanced_reboot/advanced_reboot",{
-- device_name=device_name,
-- boot_envvar1_partition_one=boot_envvar1_partition_one,
-- partition_one_os=partition_one_os,
-- boot_envvar1_partition_two=boot_envvar1_partition_two,
-- partition_two_os=partition_two_os,
-- current_partition=current_partition,
-- errorMessage = luci.i18n.translate("Alternative reboot cancelled.")})
return return
end end
local step = tonumber(luci.http.formvalue("step") or 1) local step = tonumber(luci.http.formvalue("step") or 1)
@ -161,7 +157,7 @@ function action_altreboot()
end end
end end
end end
if errorMessage == "" then if not errorMessage then
luci.template.render("admin_system/applyreboot", { luci.template.render("admin_system/applyreboot", {
title = luci.i18n.translate("Rebooting..."), title = luci.i18n.translate("Rebooting..."),
msg = luci.i18n.translate("The system is rebooting to an alternative partition now.<br /> DO NOT POWER OFF THE DEVICE!<br /> Wait a few minutes before you try to reconnect. It might be necessary to renew the address of your computer to reach the device again, depending on your settings."), msg = luci.i18n.translate("The system is rebooting to an alternative partition now.<br /> DO NOT POWER OFF THE DEVICE!<br /> Wait a few minutes before you try to reconnect. It might be necessary to renew the address of your computer to reach the device again, depending on your settings."),
@ -170,6 +166,7 @@ function action_altreboot()
luci.sys.reboot() luci.sys.reboot()
else else
luci.template.render("advanced_reboot/advanced_reboot",{ luci.template.render("advanced_reboot/advanced_reboot",{
rom_board_name=rom_board_name,
device_name=device_name, device_name=device_name,
boot_envvar1_partition_one=boot_envvar1_partition_one, boot_envvar1_partition_one=boot_envvar1_partition_one,
partition_one_os=partition_one_os, partition_one_os=partition_one_os,

View file

@ -21,24 +21,24 @@
<%- if device_name then -%> <%- if device_name then -%>
<fieldset class="cbi-section"> <fieldset class="cbi-section">
<legend><%=device_name%><%: Partitions%></legend> <legend><%=device_name%><%: Partitions%></legend>
<table class="cbi-section-table" id="partitions"> <div class="table cbi-section-table" id="partitions">
<tr class="cbi-section-table-titles"> <div class="tr cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Partition%></th> <div class="th cbi-section-table-cell"><%:Partition%></div>
<th class="cbi-section-table-cell"><%:Status%></th> <div class="th cbi-section-table-cell"><%:Status%></div>
<th class="cbi-section-table-cell"><%:Firmware/OS (Kernel)%></th> <div class="th cbi-section-table-cell"><%:Firmware/OS (Kernel)%></div>
<th class="cbi-section-table-cell"><%:Action%></th> <div class="th cbi-section-table-cell"><%:Action%></div>
</tr> </div>
<tr class="cbi-section-table-row"> <div class="tr cbi-section-table-row">
<td> <div class="td">
<%=string.format("%X", boot_envvar1_partition_one)%> <%=string.format("%X", boot_envvar1_partition_one)%>
</td> </div>
<td> <div class="td">
<%- if boot_envvar1_partition_one == current_partition then -%><%:Current%><%- else -%><%:Alternative%><%- end -%> <%- if boot_envvar1_partition_one == current_partition then -%><%:Current%><%- else -%><%:Alternative%><%- end -%>
</td> </div>
<td> <div class="td">
<%=partition_one_os%> <%=partition_one_os%>
</td> </div>
<td> <div class="td">
<%- if boot_envvar1_partition_one == current_partition then -%> <%- if boot_envvar1_partition_one == current_partition then -%>
<form method="post" action="<%=url('admin/system/advanced_reboot/reboot')%>"> <form method="post" action="<%=url('admin/system/advanced_reboot/reboot')%>">
<input type="hidden" name="token" value="<%=token%>" /> <input type="hidden" name="token" value="<%=token%>" />
@ -50,19 +50,19 @@
<input id="altreboot-button" type="submit" class="cbi-button cbi-button-apply" value="<%:Reboot to alternative partition...%>" /> <input id="altreboot-button" type="submit" class="cbi-button cbi-button-apply" value="<%:Reboot to alternative partition...%>" />
</form> </form>
<%- end -%> <%- end -%>
</td> </div>
</tr> </div>
<tr class="cbi-section-table-row"> <div class="tr cbi-section-table-row">
<td> <div class="td">
<%=string.format("%X", boot_envvar1_partition_two)%> <%=string.format("%X", boot_envvar1_partition_two)%>
</td> </div>
<td> <div class="td">
<%- if boot_envvar1_partition_two == current_partition then -%><%:Current%><%- else -%><%:Alternative%><%- end -%> <%- if boot_envvar1_partition_two == current_partition then -%><%:Current%><%- else -%><%:Alternative%><%- end -%>
</td> </div>
<td> <div class="td">
<%=partition_two_os%> <%=partition_two_os%>
</td> </div>
<td> <div class="td">
<%- if boot_envvar1_partition_two == current_partition then -%> <%- if boot_envvar1_partition_two == current_partition then -%>
<form method="post" action="<%=url('admin/system/advanced_reboot/reboot')%>"> <form method="post" action="<%=url('admin/system/advanced_reboot/reboot')%>">
<input type="hidden" name="token" value="<%=token%>" /> <input type="hidden" name="token" value="<%=token%>" />
@ -74,12 +74,16 @@
<input id="altreboot-button" type="submit" class="cbi-button cbi-button-apply" value="<%:Reboot to alternative partition...%>" /> <input id="altreboot-button" type="submit" class="cbi-button cbi-button-apply" value="<%:Reboot to alternative partition...%>" />
</form> </form>
<%- end -%> <%- end -%>
</td> </div>
</tr> </div>
</table> </div>
</fieldset> </fieldset>
<%- else -%> <%- else -%>
<p class="alert-message warning"><%:Warning: This system does not have two partitions!%></p> <%- if rom_board_name then -%>
<p class="alert-message warning"><%=pcdata(translatef("Warning: Device (%s) is unknown or isn't a dual-partition device!", rom_board_name))%></p>
<%- else -%>
<p class="alert-message warning"><%:Warning: Unable to obtain device information!%></p>
<%- end -%>
<%- end -%> <%- end -%>
<hr /> <hr />

View file

@ -1,6 +1,9 @@
msgid "" msgid ""
msgstr "Content-Type: text/plain; charset=UTF-8" msgstr "Content-Type: text/plain; charset=UTF-8"
msgid ") is unknown or isn't a dual-partition device!"
msgstr ""
msgid "Action" msgid "Action"
msgstr "" msgstr ""
@ -10,9 +13,6 @@ msgstr ""
msgid "Alternative" msgid "Alternative"
msgstr "" msgstr ""
msgid "Alternative reboot cancelled."
msgstr ""
msgid "Cancel" msgid "Cancel"
msgstr "" msgstr ""
@ -113,14 +113,17 @@ msgid ""
"device." "device."
msgstr "" msgstr ""
msgid "Warning: There are unsaved changes that will get lost on reboot!" msgid "Warning: Device ("
msgstr "" msgstr ""
msgid "Warning: This system does not have two partitions!" msgid "Warning: There are unsaved changes that will get lost on reboot!"
msgstr "" msgstr ""
msgid "Warning: This system does not support powering off!" msgid "Warning: This system does not support powering off!"
msgstr "" msgstr ""
msgid "Warning: Unable to obtain device information!"
msgstr ""
msgid "to" msgid "to"
msgstr "" msgstr ""

View file

@ -7,29 +7,21 @@
if (st && tb && tx) if (st && tb && tx)
{ {
/* clear all rows */ /* clear all rows */
while( tb.rows.length > 1 ) while (tb.firstElementChild !== tb.lastElementChild)
tb.deleteRow(1); tb.removeChild(tb.lastElementChild);
for( var i = 0; i < st.leases.length; i++ ) for (var i = 0; i < st.leases.length; i++)
{ {
var tr = tb.insertRow(-1); tb.appendChild(E('<div class="tr cbi-section-table-row cbi-rowstyle-%d">'.format((i % 2) + 1), [
tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1); E('<div class="td">', st.leases[i].addr),
E('<div class="td">', '%t'.format(st.leases[i].age))
tr.insertCell(-1).innerHTML = st.leases[i].addr; ]));
tr.insertCell(-1).innerHTML = String.format('%t', st.leases[i].age);
} }
if( tb.rows.length == 1 ) if (tb.firstElementChild === tb.lastElementChild)
{ tb.appendChild(E('<div class="tr cbi-section-table-row"><div class="td"><em><br /><%:There are no active leases.%></em></div></div>'));
var tr = tb.insertRow(-1);
tr.className = 'cbi-section-table-row';
var td = tr.insertCell(-1); if (st.uid == '00:00:00:00:00:00:00:00')
td.colSpan = 2;
td.innerHTML = '<em><br /><%:There are no active leases.%></em>';
}
if( st.uid == '00:00:00:00:00:00:00:00' )
tx.innerHTML = '<%:The AHCP Service is not running.%>'; tx.innerHTML = '<%:The AHCP Service is not running.%>';
else else
tx.innerHTML = String.format('<%:The AHCP Service is running with ID %s.%>', st.uid); tx.innerHTML = String.format('<%:The AHCP Service is running with ID %s.%>', st.uid);
@ -41,13 +33,13 @@
<fieldset class="cbi-section"> <fieldset class="cbi-section">
<legend><%:Active AHCP Leases%></legend> <legend><%:Active AHCP Leases%></legend>
<p id="ahcpd_status_text"></p> <p id="ahcpd_status_text"></p>
<table class="cbi-section-table" id="ahcpd_status_table"> <div class="table cbi-section-table" id="ahcpd_status_table">
<tr class="cbi-section-table-titles"> <div class="tr cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Address%></th> <div class="th cbi-section-table-cell"><%:Address%></div>
<th class="cbi-section-table-cell"><%:Age%></th> <div class="th cbi-section-table-cell"><%:Age%></div>
</tr> </div>
<tr class="cbi-section-table-row"> <div class="tr cbi-section-table-row">
<td colspan="5"><em><br /><%:Collecting data...%></em></td> <div class="td" colspan="5"><em><br /><%:Collecting data...%></em></div>
</tr> </div>
</table> </div>
</fieldset> </fieldset>

View file

@ -58,7 +58,6 @@
<form method="post" action="<%=url('admin/asterisk/dialplans')%>" enctype="multipart/form-data"> <form method="post" action="<%=url('admin/asterisk/dialplans')%>" enctype="multipart/form-data">
<div> <div>
<script type="text/javascript" src="/luci-static/resources/cbi.js"></script>
<input type="hidden" name="cbi.submit" value="1" /> <input type="hidden" name="cbi.submit" value="1" />
<input type="submit" value="Save" class="hidden" /> <input type="submit" value="Save" class="hidden" />
</div> </div>
@ -79,23 +78,23 @@
<% for i, plan in pairs(ast.dialplan.plans()) do %> <% for i, plan in pairs(ast.dialplan.plans()) do %>
<div class="cbi-section-node"> <div class="cbi-section-node">
<table class="cbi-section-table"> <div class="table cbi-section-table">
<tr class="cbi-section-table-titles"> <div class="tr cbi-section-table-titles">
<th style="text-align: left; padding: 3px" class="cbi-section-table-cell"> <div style="text-align: left; padding: 3px" class="th cbi-section-table-cell">
<big>Dialplan <em><%=plan.name%></em></big> <big>Dialplan <em><%=plan.name%></em></big>
</th> </div>
<td> <div class="td">
<a href="<%=url('admin/asterisk/dialplans')%>?delplan=<%=plan.name%>"> <a href="<%=url('admin/asterisk/dialplans')%>?delplan=<%=plan.name%>">
<img style="border:none" alt="Remove this dialplan" title="Remove this dialplan" src="/luci-static/resources/cbi/remove.gif" /> <img style="border:none" alt="Remove this dialplan" title="Remove this dialplan" src="/luci-static/resources/cbi/remove.gif" />
</a> </a>
</td> </div>
</tr> </div>
<!-- dialzones --> <!-- dialzones -->
<% local zones_used = { }; local row = 0 %> <% local zones_used = { }; local row = 0 %>
<% for i, zone in ipairs(plan.zones) do zones_used[zone.name] = true %> <% for i, zone in ipairs(plan.zones) do zones_used[zone.name] = true %>
<tr class="cbi-section-table-row <%=rowstyle(row)%>"> <div class="tr cbi-section-table-row <%=rowstyle(row)%>">
<td style="text-align: left; padding: 3px" class="cbi-section-table-cell"> <div style="text-align: left; padding: 3px" class="td cbi-section-table-cell">
<strong>&#x2514; Dialzone <em><%=zone.name%></em></strong> (<%=zone.description%>) <strong>&#x2514; Dialzone <em><%=zone.name%></em></strong> (<%=zone.description%>)
<p style="padding-left: 1em; margin-bottom:0"> <p style="padding-left: 1em; margin-bottom:0">
Lines: Lines:
@ -107,24 +106,24 @@
Matches: Matches:
<%=format_matches(zone)%> <%=format_matches(zone)%>
</p> </p>
</td> </div>
<td style="width:5%" class="cbi-value-field"> <div style="width:5%" class="td cbi-value-field">
<a href="<%=url('admin/asterisk/dialplans/out', zone.name)%>"> <a href="<%=url('admin/asterisk/dialplans/out', zone.name)%>">
<img style="border:none" alt="Edit dialzone" title="Edit dialzone" src="/luci-static/resources/cbi/edit.gif" /> <img style="border:none" alt="Edit dialzone" title="Edit dialzone" src="/luci-static/resources/cbi/edit.gif" />
</a> </a>
<a href="<%=url('admin/asterisk/dialplans')%>?delzone.<%=plan.name%>=<%=zone.name%>"> <a href="<%=url('admin/asterisk/dialplans')%>?delzone.<%=plan.name%>=<%=zone.name%>">
<img style="border:none" alt="Remove from this dialplan" title="Remove from this dialplan" src="/luci-static/resources/cbi/remove.gif" /> <img style="border:none" alt="Remove from this dialplan" title="Remove from this dialplan" src="/luci-static/resources/cbi/remove.gif" />
</a> </a>
</td> </div>
</tr> </div>
<% row = row + 1; end %> <% row = row + 1; end %>
<!-- /dialzones --> <!-- /dialzones -->
<!-- voicemail --> <!-- voicemail -->
<% local boxes_used = { } %> <% local boxes_used = { } %>
<% for ext, box in luci.util.kspairs(plan.voicemailboxes) do boxes_used[box.id] = true %> <% for ext, box in luci.util.kspairs(plan.voicemailboxes) do boxes_used[box.id] = true %>
<tr class="cbi-section-table-row <%=rowstyle(row)%>"> <div class="tr cbi-section-table-row <%=rowstyle(row)%>">
<td style="text-align: left; padding: 3px" class="cbi-section-table-cell"> <div style="text-align: left; padding: 3px" class="td cbi-section-table-cell">
<strong>&#x2514; Voicemailbox <em><%=box.id%></em></strong> (<%=box.name%>) <strong>&#x2514; Voicemailbox <em><%=box.id%></em></strong> (<%=box.name%>)
<p style="padding-left: 1em; margin-bottom:0"> <p style="padding-left: 1em; margin-bottom:0">
Owner: <%=box.name%> | Owner: <%=box.name%> |
@ -132,44 +131,44 @@
Pager: <%=#box.page > 0 and box.page or 'n/a'%><br /> Pager: <%=#box.page > 0 and box.page or 'n/a'%><br />
Matches: <%=format_matches(ext)%> Matches: <%=format_matches(ext)%>
</p> </p>
</td> </div>
<td style="width:5%" class="cbi-value-field"> <div style="width:5%" class="td cbi-value-field">
<a href="<%=url('admin/asterisk/voicemail/mailboxes')%>"> <a href="<%=url('admin/asterisk/voicemail/mailboxes')%>">
<img style="border:none" alt="Manage mailboxes ..." title="Manage mailboxes ..." src="/luci-static/resources/cbi/edit.gif" /> <img style="border:none" alt="Manage mailboxes ..." title="Manage mailboxes ..." src="/luci-static/resources/cbi/edit.gif" />
</a> </a>
<a href="<%=url('admin/asterisk/dialplans')%>?delvbox.<%=plan.name%>=<%=ext%>"> <a href="<%=url('admin/asterisk/dialplans')%>?delvbox.<%=plan.name%>=<%=ext%>">
<img style="border:none" alt="Remove from this dialplan" title="Remove from this dialplan" src="/luci-static/resources/cbi/remove.gif" /> <img style="border:none" alt="Remove from this dialplan" title="Remove from this dialplan" src="/luci-static/resources/cbi/remove.gif" />
</a> </a>
</td> </div>
</tr> </div>
<% row = row + 1; end %> <% row = row + 1; end %>
<!-- /voicemail --> <!-- /voicemail -->
<!-- meetme --> <!-- meetme -->
<% local rooms_used = { } %> <% local rooms_used = { } %>
<% for ext, room in luci.util.kspairs(plan.meetmerooms) do rooms_used[room.room] = true %> <% for ext, room in luci.util.kspairs(plan.meetmerooms) do rooms_used[room.room] = true %>
<tr class="cbi-section-table-row <%=rowstyle(row)%>"> <div class="tr cbi-section-table-row <%=rowstyle(row)%>">
<td style="text-align: left; padding: 3px" class="cbi-section-table-cell"> <div style="text-align: left; padding: 3px" class="td cbi-section-table-cell">
<strong>&#x2514; MeetMe Room <em><%=room.room%></em></strong> <strong>&#x2514; MeetMe Room <em><%=room.room%></em></strong>
<% if room.description and #room.description > 0 then %> (<%=room.description%>)<% end %> <% if room.description and #room.description > 0 then %> (<%=room.description%>)<% end %>
<p style="padding-left: 1em; margin-bottom:0"> <p style="padding-left: 1em; margin-bottom:0">
Matches: <%=format_matches(ext)%> Matches: <%=format_matches(ext)%>
</p> </p>
</td> </div>
<td style="width:5%" class="cbi-value-field"> <div style="width:5%" class="td cbi-value-field">
<a href="<%=url('admin/asterisk/meetme/rooms')%>"> <a href="<%=url('admin/asterisk/meetme/rooms')%>">
<img style="border:none" alt="Manage conferences ..." title="Manage conferences ..." src="/luci-static/resources/cbi/edit.gif" /> <img style="border:none" alt="Manage conferences ..." title="Manage conferences ..." src="/luci-static/resources/cbi/edit.gif" />
</a> </a>
<a href="<%=url('admin/asterisk/dialplans')%>?delmeetme.<%=plan.name%>=<%=ext%>"> <a href="<%=url('admin/asterisk/dialplans')%>?delmeetme.<%=plan.name%>=<%=ext%>">
<img style="border:none" alt="Remove from this dialplan" title="Remove from this dialplan" src="/luci-static/resources/cbi/remove.gif" /> <img style="border:none" alt="Remove from this dialplan" title="Remove from this dialplan" src="/luci-static/resources/cbi/remove.gif" />
</a> </a>
</td> </div>
</tr> </div>
<% row = row + 1; end %> <% row = row + 1; end %>
<!-- /meetme --> <!-- /meetme -->
<tr class="cbi-section-table-row"> <div class="tr cbi-section-table-row">
<td style="text-align: left; padding: 3px" class="cbi-section-table-cell" colspan="2"> <div style="text-align: left; padding: 3px" class="td cbi-section-table-cell" colspan="2">
<hr style="margin-bottom:0.5em; border-width:0 0 1px 0" /> <hr style="margin-bottom:0.5em; border-width:0 0 1px 0" />
Add Dialzone:<br /> Add Dialzone:<br />
@ -213,10 +212,10 @@
<br /><br /> <br /><br />
<input type="submit" class="cbi-button cbi-button-add" value="Add item &raquo;" title="Add item ..."/> <input type="submit" class="cbi-button cbi-button-add" value="Add item &raquo;" title="Add item ..."/>
</td> </div>
</tr> </div>
</table> </div>
<div class="cbi-section-create cbi-tblsection-create"></div> <div class="cbi-section-create cbi-tblsection-create"></div>
</div> </div>

View file

@ -49,7 +49,6 @@
<form method="post" action="<%=url('admin/asterisk/dialplans/zones')%>" enctype="multipart/form-data"> <form method="post" action="<%=url('admin/asterisk/dialplans/zones')%>" enctype="multipart/form-data">
<div> <div>
<script type="text/javascript" src="/luci-static/resources/cbi.js"></script>
<input type="hidden" name="cbi.submit" value="1" /> <input type="hidden" name="cbi.submit" value="1" />
<input type="submit" value="Save" class="hidden" /> <input type="submit" value="Save" class="hidden" />
</div> </div>
@ -66,59 +65,59 @@
<!-- tblsection --> <!-- tblsection -->
<fieldset class="cbi-section" id="cbi-asterisk-sip"> <fieldset class="cbi-section" id="cbi-asterisk-sip">
<div class="cbi-section-node"> <div class="cbi-section-node">
<table class="cbi-section-table"> <div class="table cbi-section-table">
<tr class="cbi-section-table-titles"> <div class="tr cbi-section-table-titles">
<th style="text-align: left; padding: 3px" class="cbi-section-table-cell" colspan="6"> <div style="text-align: left; padding: 3px" class="th cbi-section-table-cell" colspan="6">
<h3>Dialzone Overview</h3> <h3>Dialzone Overview</h3>
</th> </div>
</tr> </div>
<tr class="cbi-section-table-descr"> <div class="tr cbi-section-table-descr">
<th style="width: 5%; text-align:right" class="cbi-section-table-cell">Name</th> <div style="width: 5%; text-align:right" class="th cbi-section-table-cell">Name</div>
<th style="width: 5%; text-align:right" class="cbi-section-table-cell">Prepend</th> <div style="width: 5%; text-align:right" class="th cbi-section-table-cell">Prepend</div>
<th style="width: 20%; text-align:left" class="cbi-section-table-cell">- Match</th> <div style="width: 20%; text-align:left" class="th cbi-section-table-cell">- Match</div>
<th style="text-align:left" class="cbi-section-table-cell">Trunk</th> <div style="text-align:left" class="th cbi-section-table-cell">Trunk</div>
<th style="width: 35%; text-align:left" class="cbi-section-table-cell">Description</th> <div style="width: 35%; text-align:left" class="th cbi-section-table-cell">Description</div>
<th style="width: 4%; text-align:left" class="cbi-section-table-cell"></th> <div style="width: 4%; text-align:left" class="th cbi-section-table-cell"></div>
</tr> </div>
<% for i, rule in pairs(ast.dialzone.zones()) do %> <% for i, rule in pairs(ast.dialzone.zones()) do %>
<tr class="cbi-section-table-row <%=rowstyle(i)%>"> <div class="tr cbi-section-table-row <%=rowstyle(i)%>">
<td style="text-align:right" class="cbi-value-field"> <div style="text-align:right" class="td cbi-value-field">
<%=rule.name%> <%=rule.name%>
</td> </div>
<td style="text-align:right" class="cbi-value-field"> <div style="text-align:right" class="td cbi-value-field">
<% for _ in ipairs(rule.matches) do %> <% for _ in ipairs(rule.matches) do %>
<%=rule.addprefix and digit_pattern(rule.addprefix)%>&#160;<br /> <%=rule.addprefix and digit_pattern(rule.addprefix)%>&#160;<br />
<% end %> <% end %>
</td> </div>
<td style="text-align:left" class="cbi-value-field"> <div style="text-align:left" class="td cbi-value-field">
<% for _, m in ipairs(rule.matches) do %> <% for _, m in ipairs(rule.matches) do %>
<%=rule.localprefix and "%s " % digit_pattern(rule.localprefix)%> <%=rule.localprefix and "%s " % digit_pattern(rule.localprefix)%>
<%=digit_pattern(m)%><br /> <%=digit_pattern(m)%><br />
<% end %> <% end %>
</td> </div>
<td style="text-align:left" class="cbi-value-field"> <div style="text-align:left" class="td cbi-value-field">
<%=ast.tools.hyperlinks( <%=ast.tools.hyperlinks(
rule.trunks, function(v) rule.trunks, function(v)
return luci.dispatcher.build_url("admin", "asterisk", "trunks", "%s") % v:lower() return luci.dispatcher.build_url("admin", "asterisk", "trunks", "%s") % v:lower()
end end
)%> )%>
</td> </div>
<td style="text-align:left" class="cbi-value-field"> <div style="text-align:left" class="td cbi-value-field">
<%=rule.description or rule.name%> <%=rule.description or rule.name%>
</td> </div>
<td style="text-align:left" class="cbi-value-field"> <div style="text-align:left" class="td cbi-value-field">
<a href="<%=url('admin/asterisk/dialplans/out', rule.name)%>"> <a href="<%=url('admin/asterisk/dialplans/out', rule.name)%>">
<img style="border:none" alt="Edit entry" title="Edit entry" src="/luci-static/resources/cbi/edit.gif" /> <img style="border:none" alt="Edit entry" title="Edit entry" src="/luci-static/resources/cbi/edit.gif" />
</a> </a>
<a href="<%=url('admin/asterisk/dialplans/zones')%>?delzone=<%=rule.name%>"> <a href="<%=url('admin/asterisk/dialplans/zones')%>?delzone=<%=rule.name%>">
<img style="border:none" alt="Delete entry" title="Delete entry" src="/luci-static/resources/cbi/remove.gif" /> <img style="border:none" alt="Delete entry" title="Delete entry" src="/luci-static/resources/cbi/remove.gif" />
</a> </a>
</td> </div>
</tr> </div>
<% end %> <% end %>
</table> </div>
<div class="cbi-section-create cbi-tblsection-create"></div> <div class="cbi-section-create cbi-tblsection-create"></div>
</div> </div>
<br /> <br />
@ -133,26 +132,26 @@
<br /><span style="color:red">Invalid name given!</span><br /> <br /><span style="color:red">Invalid name given!</span><br />
<% end -%> <% end -%>
<table> <div class="table">
<tr> <div class="tr">
<td style="padding:3px"> <div class="td" style="padding:3px">
<label for="create1">1) Name</label><br /> <label for="create1">1) Name</label><br />
<input type="text" class="cbi-section-create-name" id="create1" name="newzone_name" style="width:200px" /> <input type="text" class="cbi-section-create-name" id="create1" name="newzone_name" style="width:200px" />
<br /><br /> <br /><br />
<label for="create2">2) Number Match</label><br /> <label for="create2">2) Number Match</label><br />
<input type="text" class="cbi-section-create-name" id="create2" name="newzone_match" style="width:200px" /> <input type="text" class="cbi-section-create-name" id="create2" name="newzone_match" style="width:200px" />
</td> </div>
<td style="padding:3px"> <div class="td" style="padding:3px">
<label for="create3">3) Trunks</label><br /> <label for="create3">3) Trunks</label><br />
<select class="cbi-input-select" multiple="multiple" id="create3" name="newzone_uses" size="4" style="width:200px"> <select class="cbi-input-select" multiple="multiple" id="create3" name="newzone_uses" size="4" style="width:200px">
<% for i, t in ipairs(find_trunks()) do %> <% for i, t in ipairs(find_trunks()) do %>
<option value="<%=t[1]%>"><%=t[2]%></option> <option value="<%=t[1]%>"><%=t[2]%></option>
<% end %> <% end %>
</select> </select>
</td> </div>
</tr> </div>
</table> </div>
<br /> <br />
<input type="submit" class="cbi-button cbi-button-add" name="newzone" value="Add entry" title="Add entry"/> <input type="submit" class="cbi-button cbi-button-add" name="newzone" value="Add entry" title="Add entry"/>

View file

@ -14,7 +14,8 @@ $Id$
local wa = require "luci.tools.webadmin" local wa = require "luci.tools.webadmin"
local net = require "luci.model.network".init() local net = require "luci.model.network".init()
local ifaces = net:get_interfaces() local sys = require "luci.sys"
local ifaces = sys.net:devices()
m = Map("bcp38", translate("BCP38"), m = Map("bcp38", translate("BCP38"),
translate("This function blocks packets with private address destinations " .. translate("This function blocks packets with private address destinations " ..
@ -37,10 +38,17 @@ a.rmempty = false
n = s:option(ListValue, "interface", translate("Interface name"), translate("Interface to apply the blocking to " .. n = s:option(ListValue, "interface", translate("Interface name"), translate("Interface to apply the blocking to " ..
"(should be the upstream WAN interface).")) "(should be the upstream WAN interface)."))
for _, iface in ipairs(ifaces) do for _, iface in ipairs(ifaces) do
if iface:is_up() then if not (iface == "lo" or iface:match("^ifb.*")) then
n:value(iface:name()) local nets = net:get_interface(iface)
end nets = nets and nets:get_networks() or {}
for k, v in pairs(nets) do
nets[k] = nets[k].sid
end
nets = table.concat(nets, ",")
n:value(iface, ((#nets > 0) and "%s (%s)" % {iface, nets} or iface))
end
end end
n.rmempty = false n.rmempty = false

View file

@ -34,7 +34,6 @@
<%+header%> <%+header%>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[ <script type="text/javascript">//<![CDATA[
var stxhr = new XHR(); var stxhr = new XHR();

View file

@ -82,7 +82,6 @@ $Id$
<hr/> <hr/>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[ <script type="text/javascript">//<![CDATA[
var capture_running = 0; var capture_running = 0;

View file

@ -19,7 +19,8 @@ PKG_VERSION:=2.4.9
PKG_RELEASE:=3 PKG_RELEASE:=3
PKG_LICENSE:=Apache-2.0 PKG_LICENSE:=Apache-2.0
PKG_MAINTAINER:=Christian Schoenebeck <christian.schoenebeck@gmail.com> PKG_MAINTAINER:=Christian Schoenebeck <christian.schoenebeck@gmail.com>, \
Ansuel Smith <ansuelsmth@gmail.com>
# LuCI specific settings # LuCI specific settings
LUCI_TITLE:=LuCI Support for Dynamic DNS Client (ddns-scripts) LUCI_TITLE:=LuCI Support for Dynamic DNS Client (ddns-scripts)

View file

@ -21,7 +21,6 @@ luci_helper = "/usr/lib/ddns/dynamic_dns_lucihelper.sh"
local srv_name = "ddns-scripts" local srv_name = "ddns-scripts"
local srv_ver_min = "2.7.7" -- minimum version of service required local srv_ver_min = "2.7.7" -- minimum version of service required
local srv_ver_cmd = luci_helper .. [[ -V | awk {'print $2'}]]
local app_name = "luci-app-ddns" local app_name = "luci-app-ddns"
local app_title = "Dynamic DNS" local app_title = "Dynamic DNS"
local app_version = "2.4.9-1" local app_version = "2.4.9-1"
@ -29,7 +28,6 @@ local app_version = "2.4.9-1"
function index() function index()
local nxfs = require "nixio.fs" -- global definitions not available local nxfs = require "nixio.fs" -- global definitions not available
local sys = require "luci.sys" -- in function index() local sys = require "luci.sys" -- in function index()
local ddns = require "luci.tools.ddns" -- ddns multiused functions
local muci = require "luci.model.uci" local muci = require "luci.model.uci"
-- no config create an empty one -- no config create an empty one
@ -81,33 +79,40 @@ end
-- Standardized application/service functions -- Standardized application/service functions
function app_title_main() function app_title_main()
return [[<a href="javascript:alert(']] tmp = {}
.. I18N.translate("Version Information") tmp[#tmp+1] = [[<a href="javascript:alert(']]
.. [[\n\n]] .. app_name tmp[#tmp+1] = I18N.translate("Version Information")
.. [[\n\t]] .. I18N.translate("Version") .. [[:\t]] .. app_version tmp[#tmp+1] = [[\n\n]] .. app_name
.. [[\n\n]] .. srv_name .. [[ ]] .. I18N.translate("required") .. [[:]] tmp[#tmp+1] = [[\n]] .. I18N.translate("Version") .. [[: ]] .. app_version
.. [[\n\t]] .. I18N.translate("Version") .. [[:\t]] tmp[#tmp+1] = [[\n\n]] .. srv_name .. [[ ]] .. I18N.translate("required") .. [[:]]
.. srv_ver_min .. [[ ]] .. I18N.translate("or higher") tmp[#tmp+1] = [[\n]] .. I18N.translate("Version") .. [[: ]]
.. [[\n\n]] .. srv_name .. [[ ]] .. I18N.translate("installed") .. [[:]] tmp[#tmp+1] = srv_ver_min .. [[ ]] .. I18N.translate("or higher")
.. [[\n\t]] .. I18N.translate("Version") .. [[:\t]] tmp[#tmp+1] = [[\n\n]] .. srv_name .. [[ ]] .. I18N.translate("installed") .. [[:]]
.. (service_version() or I18N.translate("NOT installed")) tmp[#tmp+1] = [[\n]] .. I18N.translate("Version") .. [[: ]]
.. [[\n\n]] tmp[#tmp+1] = (service_version() or I18N.translate("NOT installed"))
.. [[')">]] tmp[#tmp+1] = [[\n\n]]
.. I18N.translate(app_title) tmp[#tmp+1] = [[')">]]
.. [[</a>]] tmp[#tmp+1] = I18N.translate(app_title)
tmp[#tmp+1] = [[</a>]]
return table.concat(tmp)
end end
function service_version() function service_version()
local ver = nil
local srv_ver_cmd = luci_helper .. " -V | awk {'print $2'} "
ver = UTIL.exec(srv_ver_cmd) local ver
if #ver > 0 then return ver end
if IPKG then
IPKG.list_installed(srv_name, function(n, v, d) ver = IPKG.info(srv_name)[srv_name].Version
if v and (#v > 0) then ver = v end else
end ver = UTIL.exec(srv_ver_cmd)
) end
return ver
if ver and #ver > 0 then return ver or nil end
end end
function service_ok() function service_ok()
return IPKG.compare_versions((service_version() or "0"), ">=", srv_ver_min) return IPKG.compare_versions((service_version() or "0"), ">=", srv_ver_min)
end end

View file

@ -172,7 +172,7 @@ local function _option_used(option, urlscript)
end end
-- function to verify if option is valid -- function to verify if option is valid
local function _option_validate(self, value) local function _option_validate(self, value, optional)
-- section is globally defined here be calling agrument (see above) -- section is globally defined here be calling agrument (see above)
local fusev6 = usev6:formvalue(section) or "0" local fusev6 = usev6:formvalue(section) or "0"
local fsvc4 = svc4:formvalue(section) or "-" local fsvc4 = svc4:formvalue(section) or "-"
@ -204,6 +204,7 @@ local function _option_validate(self, value)
if used < 1 then return "" end if used < 1 then return "" end
-- needed but no data then return error -- needed but no data then return error
if not value or (#value == 0) then if not value or (#value == 0) then
if optional then return nil end
return nil, err_tab_basic(self) .. translate("missing / required") return nil, err_tab_basic(self) .. translate("missing / required")
end end
return value return value
@ -292,6 +293,10 @@ function luh.parse(self, section, novld)
end end
-- use_ipv6 -- ################################################################ -- use_ipv6 -- ################################################################
--We call it globally as it's called 11 times even outside specific function, saves 11 os.execute slow command!
local has_ipv6 = DDNS.env_info("has_ipv6")
usev6 = ns:taboption("basic", ListValue, "use_ipv6", usev6 = ns:taboption("basic", ListValue, "use_ipv6",
translate("IP address version"), translate("IP address version"),
translate("Defines which IP address 'IPv4/IPv6' is send to the DDNS provider") ) translate("Defines which IP address 'IPv4/IPv6' is send to the DDNS provider") )
@ -300,16 +305,16 @@ usev6.default = "0"
usev6:value("0", translate("IPv4-Address") ) usev6:value("0", translate("IPv4-Address") )
function usev6.cfgvalue(self, section) function usev6.cfgvalue(self, section)
local value = AbstractValue.cfgvalue(self, section) or "0" local value = AbstractValue.cfgvalue(self, section) or "0"
if DDNS.has_ipv6 or (value == "1" and not DDNS.has_ipv6) then if has_ipv6 or (value == "1" and not has_ipv6) then
self:value("1", translate("IPv6-Address") ) self:value("1", translate("IPv6-Address") )
end end
if value == "1" and not DDNS.has_ipv6 then if value == "1" and not has_ipv6 then
self.description = err_ipv6_basic self.description = err_ipv6_basic
end end
return value return value
end end
function usev6.validate(self, value) function usev6.validate(self, value)
if (value == "1" and DDNS.has_ipv6) or value == "0" then if (value == "1" and has_ipv6) or value == "0" then
return value return value
end end
return nil, err_tab_basic(self) .. err_ipv6_plain return nil, err_tab_basic(self) .. err_ipv6_plain
@ -360,7 +365,7 @@ svc6 = ns:taboption("basic", ListValue, "ipv6_service_name",
translate("DDNS Service provider") .. " [IPv6]" ) translate("DDNS Service provider") .. " [IPv6]" )
svc6.default = "-" svc6.default = "-"
svc6:depends("use_ipv6", "1") -- only show on IPv6 svc6:depends("use_ipv6", "1") -- only show on IPv6
if not DDNS.has_ipv6 then if not has_ipv6 then
svc6.description = err_ipv6_basic svc6.description = err_ipv6_basic
end end
function svc6.cfgvalue(self, section) function svc6.cfgvalue(self, section)
@ -374,7 +379,7 @@ function svc6.cfgvalue(self, section)
end end
function svc6.validate(self, value) function svc6.validate(self, value)
if usev6:formvalue(section) == "1" then -- do only on IPv6 if usev6:formvalue(section) == "1" then -- do only on IPv6
if DDNS.has_ipv6 then return value end if has_ipv6 then return value end
return nil, err_tab_basic(self) .. err_ipv6_plain return nil, err_tab_basic(self) .. err_ipv6_plain
else else
return "" -- suppress validate error return "" -- suppress validate error
@ -509,18 +514,18 @@ pe = ns:taboption("basic", Value, "param_enc",
translate("Optional Encoded Parameter"), translate("Optional Encoded Parameter"),
translate("Optional: Replaces [PARAMENC] in Update-URL (URL-encoded)") ) translate("Optional: Replaces [PARAMENC] in Update-URL (URL-encoded)") )
function pe.validate(self, value) function pe.validate(self, value)
return _option_validate(self, value) return _option_validate(self, value, true)
end end
function pe.parse(self, section, novld) function pe.parse(self, section, novld)
DDNS.value_parse(self, section, novld) DDNS.value_parse(self, section, novld)
end end
-- IPv4/IPv6 - param_enc -- ################################################### -- IPv4/IPv6 - param_opt -- ###################################################
po = ns:taboption("basic", Value, "param_opt", po = ns:taboption("basic", Value, "param_opt",
translate("Optional Parameter"), translate("Optional Parameter"),
translate("Optional: Replaces [PARAMOPT] in Update-URL (NOT URL-encoded)") ) translate("Optional: Replaces [PARAMOPT] in Update-URL (NOT URL-encoded)") )
function po.validate(self, value) function po.validate(self, value)
return _option_validate(self, value) return _option_validate(self, value, true)
end end
function po.parse(self, section, novld) function po.parse(self, section, novld)
DDNS.value_parse(self, section, novld) DDNS.value_parse(self, section, novld)
@ -586,13 +591,17 @@ end
svc6:value("-", translate("-- custom --") ) svc6:value("-", translate("-- custom --") )
-- IPv4/IPv6 - use_https -- ################################################### -- IPv4/IPv6 - use_https -- ###################################################
if DDNS.has_ssl or ( ( m:get(section, "use_https") or "0" ) == "1" ) then
--We call it globally as it's called 4 times outside specific function.
local has_ssl = DDNS.env_info("has_ssl")
if has_ssl or ( ( m:get(section, "use_https") or "0" ) == "1" ) then
https = ns:taboption("basic", Flag, "use_https", https = ns:taboption("basic", Flag, "use_https",
translate("Use HTTP Secure") ) translate("Use HTTP Secure") )
https.orientation = "horizontal" https.orientation = "horizontal"
function https.cfgvalue(self, section) function https.cfgvalue(self, section)
local value = AbstractValue.cfgvalue(self, section) local value = AbstractValue.cfgvalue(self, section)
if not DDNS.has_ssl and value == "1" then if not has_ssl and value == "1" then
self.description = bold_on .. font_red .. self.description = bold_on .. font_red ..
translate("HTTPS not supported") .. font_off .. "<br />" .. translate("HTTPS not supported") .. font_off .. "<br />" ..
translate("please disable") .. " !" .. bold_off translate("please disable") .. " !" .. bold_off
@ -602,7 +611,7 @@ if DDNS.has_ssl or ( ( m:get(section, "use_https") or "0" ) == "1" ) then
return value return value
end end
function https.validate(self, value) function https.validate(self, value)
if (value == "1" and DDNS.has_ssl ) or value == "0" then return value end if (value == "1" and has_ssl ) or value == "0" then return value end
return nil, err_tab_basic(self) .. translate("HTTPS not supported") .. " !" return nil, err_tab_basic(self) .. translate("HTTPS not supported") .. " !"
end end
function https.write(self, section, value) function https.write(self, section, value)
@ -616,7 +625,7 @@ if DDNS.has_ssl or ( ( m:get(section, "use_https") or "0" ) == "1" ) then
end end
-- IPv4/IPv6 - cacert -- ###################################################### -- IPv4/IPv6 - cacert -- ######################################################
if DDNS.has_ssl then if has_ssl then
cert = ns:taboption("basic", Value, "cacert", cert = ns:taboption("basic", Value, "cacert",
translate("Path to CA-Certificate"), translate("Path to CA-Certificate"),
translate("directory or path/file") .. "<br />" .. translate("directory or path/file") .. "<br />" ..
@ -706,7 +715,7 @@ src6:value("network", translate("Network"))
src6:value("web", translate("URL")) src6:value("web", translate("URL"))
src6:value("interface", translate("Interface")) src6:value("interface", translate("Interface"))
src6:value("script", translate("Script")) src6:value("script", translate("Script"))
if not DDNS.has_ipv6 then if not has_ipv6 then
src6.description = err_ipv6_other src6.description = err_ipv6_other
end end
function src6.cfgvalue(self, section) function src6.cfgvalue(self, section)
@ -715,7 +724,7 @@ end
function src6.validate(self, value) function src6.validate(self, value)
if usev6:formvalue(section) ~= "1" then if usev6:formvalue(section) ~= "1" then
return "" -- ignore on IPv4 selected return "" -- ignore on IPv4 selected
elseif not DDNS.has_ipv6 then elseif not has_ipv6 then
return nil, err_tab_adv(self) .. err_ipv6_plain return nil, err_tab_adv(self) .. err_ipv6_plain
elseif not _verify_ip_source() then elseif not _verify_ip_source() then
return nil, err_tab_adv(self) .. return nil, err_tab_adv(self) ..
@ -794,7 +803,7 @@ ipn6 = ns:taboption("advanced", ListValue, "ipv6_network",
ipn6:depends("ipv6_source", "network") ipn6:depends("ipv6_source", "network")
ipn6.default = "wan6" ipn6.default = "wan6"
WADM.cbi_add_networks(ipn6) WADM.cbi_add_networks(ipn6)
if DDNS.has_ipv6 then if has_ipv6 then
ipn6.description = translate("Defines the network to read systems IPv6-Address from") ipn6.description = translate("Defines the network to read systems IPv6-Address from")
else else
ipn6.description = err_ipv6_other ipn6.description = err_ipv6_other
@ -808,7 +817,7 @@ function ipn6.validate(self, value)
-- ignore if IPv4 selected OR -- ignore if IPv4 selected OR
-- ignore everything except "network" -- ignore everything except "network"
return "" return ""
elseif DDNS.has_ipv6 then elseif has_ipv6 then
return value return value
else else
return nil, err_tab_adv(self) .. err_ipv6_plain return nil, err_tab_adv(self) .. err_ipv6_plain
@ -881,7 +890,7 @@ iurl6 = ns:taboption("advanced", Value, "ipv6_url",
translate("URL to detect") .. " [IPv6]" ) translate("URL to detect") .. " [IPv6]" )
iurl6:depends("ipv6_source", "web") iurl6:depends("ipv6_source", "web")
iurl6.default = "http://checkipv6.dyndns.com" iurl6.default = "http://checkipv6.dyndns.com"
if DDNS.has_ipv6 then if has_ipv6 then
iurl6.description = translate("Defines the Web page to read systems IPv6-Address from") iurl6.description = translate("Defines the Web page to read systems IPv6-Address from")
else else
iurl6.description = err_ipv6_other iurl6.description = err_ipv6_other
@ -895,7 +904,7 @@ function iurl6.validate(self, value)
-- ignore if IPv4 selected OR -- ignore if IPv4 selected OR
-- ignore everything except "web" -- ignore everything except "web"
return "" return ""
elseif not DDNS.has_ipv6 then elseif not has_ipv6 then
return nil, err_tab_adv(self) .. err_ipv6_plain return nil, err_tab_adv(self) .. err_ipv6_plain
elseif not value or #value == 0 then elseif not value or #value == 0 then
return nil, err_tab_adv(self) .. translate("missing / required") return nil, err_tab_adv(self) .. translate("missing / required")
@ -1051,7 +1060,7 @@ eif6:depends("ipv6_source", "web")
eif6:depends("ipv6_source", "script") eif6:depends("ipv6_source", "script")
eif6.default = "wan6" eif6.default = "wan6"
WADM.cbi_add_networks(eif6) WADM.cbi_add_networks(eif6)
if not DDNS.has_ipv6 then if not has_ipv6 then
eif6.description = err_ipv6_other eif6.description = err_ipv6_other
else else
eif6.description = translate("Network on which the ddns-updater scripts will be started") eif6.description = translate("Network on which the ddns-updater scripts will be started")
@ -1065,7 +1074,7 @@ function eif6.validate(self, value)
or fsrc6 == "network" or fsrc6 == "network"
or fsrc6 == "interface" then or fsrc6 == "interface" then
return "" -- ignore IPv4, network, interface return "" -- ignore IPv4, network, interface
elseif not DDNS.has_ipv6 then elseif not has_ipv6 then
return nil, err_tab_adv(self) .. err_ipv6_plain return nil, err_tab_adv(self) .. err_ipv6_plain
else else
return value return value
@ -1084,10 +1093,13 @@ function eif6.write(self, section, value)
end end
function eif6.parse(self, section, novld) function eif6.parse(self, section, novld)
DDNS.value_parse(self, section, novld) DDNS.value_parse(self, section, novld)
end end
-- IPv4/IPv6 - bind_network -- ################################################ -- IPv4/IPv6 - bind_network -- ################################################
if DDNS.has_bindnet or ( ( m:get(section, "bind_network") or "" ) ~= "" ) then
local has_bindnet = DDNS.env_info("has_bindnet")
if has_bindnet or ( ( m:get(section, "bind_network") or "" ) ~= "" ) then
bnet = ns:taboption("advanced", ListValue, "bind_network", bnet = ns:taboption("advanced", ListValue, "bind_network",
translate("Bind Network") ) translate("Bind Network") )
bnet:depends("ipv4_source", "web") bnet:depends("ipv4_source", "web")
@ -1097,7 +1109,7 @@ if DDNS.has_bindnet or ( ( m:get(section, "bind_network") or "" ) ~= "" ) then
WADM.cbi_add_networks(bnet) WADM.cbi_add_networks(bnet)
function bnet.cfgvalue(self, section) function bnet.cfgvalue(self, section)
local value = AbstractValue.cfgvalue(self, section) local value = AbstractValue.cfgvalue(self, section)
if not DDNS.has_bindnet and value ~= "" then if not has_bindnet and value ~= "" then
self.description = bold_on .. font_red .. self.description = bold_on .. font_red ..
translate("Binding to a specific network not supported") .. font_off .. "<br />" .. translate("Binding to a specific network not supported") .. font_off .. "<br />" ..
translate("please set to 'default'") .. " !" .. bold_off translate("please set to 'default'") .. " !" .. bold_off
@ -1108,7 +1120,7 @@ if DDNS.has_bindnet or ( ( m:get(section, "bind_network") or "" ) ~= "" ) then
return value return value
end end
function bnet.validate(self, value) function bnet.validate(self, value)
if ( (value ~= "") and DDNS.has_bindnet ) or (value == "") then return value end if ( (value ~= "") and has_bindnet ) or (value == "") then return value end
return nil, err_tab_adv(self) .. translate("Binding to a specific network not supported") .. " !" return nil, err_tab_adv(self) .. translate("Binding to a specific network not supported") .. " !"
end end
function bnet.parse(self, section, novld) function bnet.parse(self, section, novld)
@ -1119,13 +1131,16 @@ end
-- IPv4 + IPv6 - force_ipversion -- ########################################### -- IPv4 + IPv6 - force_ipversion -- ###########################################
-- optional to force wget/curl and host to use only selected IP version -- optional to force wget/curl and host to use only selected IP version
-- command parameter "-4" or "-6" -- command parameter "-4" or "-6"
if DDNS.has_forceip or ( ( m:get(section, "force_ipversion") or "0" ) ~= "0" ) then
local has_forceip = DDNS.env_info("has_forceip")
if has_forceip or ( ( m:get(section, "force_ipversion") or "0" ) ~= "0" ) then
fipv = ns:taboption("advanced", Flag, "force_ipversion", fipv = ns:taboption("advanced", Flag, "force_ipversion",
translate("Force IP Version") ) translate("Force IP Version") )
fipv.orientation = "horizontal" fipv.orientation = "horizontal"
function fipv.cfgvalue(self, section) function fipv.cfgvalue(self, section)
local value = AbstractValue.cfgvalue(self, section) local value = AbstractValue.cfgvalue(self, section)
if not DDNS.has_forceip and value ~= "0" then if not has_forceip and value ~= "0" then
self.description = bold_on .. font_red .. self.description = bold_on .. font_red ..
translate("Force IP Version not supported") .. font_off .. "<br />" .. translate("Force IP Version not supported") .. font_off .. "<br />" ..
translate("please disable") .. " !" .. bold_off translate("please disable") .. " !" .. bold_off
@ -1135,14 +1150,17 @@ if DDNS.has_forceip or ( ( m:get(section, "force_ipversion") or "0" ) ~= "0" ) t
return value return value
end end
function fipv.validate(self, value) function fipv.validate(self, value)
if (value == "1" and DDNS.has_forceip) or value == "0" then return value end if (value == "1" and has_forceip) or value == "0" then return value end
return nil, err_tab_adv(self) .. translate("Force IP Version not supported") return nil, err_tab_adv(self) .. translate("Force IP Version not supported")
end end
end end
-- IPv4 + IPv6 - dns_server -- ################################################ -- IPv4 + IPv6 - dns_server -- ################################################
-- optional DNS Server to use resolving my IP -- optional DNS Server to use resolving my IP
if DDNS.has_dnsserver or ( ( m:get(section, "dns_server") or "" ) ~= "" ) then
local has_dnsserver = DDNS.env_info("has_dnsserver")
if has_dnsserver or ( ( m:get(section, "dns_server") or "" ) ~= "" ) then
dns = ns:taboption("advanced", Value, "dns_server", dns = ns:taboption("advanced", Value, "dns_server",
translate("DNS-Server"), translate("DNS-Server"),
translate("OPTIONAL: Use non-default DNS-Server to detect 'Registered IP'.") .. "<br />" .. translate("OPTIONAL: Use non-default DNS-Server to detect 'Registered IP'.") .. "<br />" ..
@ -1152,7 +1170,7 @@ if DDNS.has_dnsserver or ( ( m:get(section, "dns_server") or "" ) ~= "" ) then
-- if .datatype is set, then it is checked before calling this function -- if .datatype is set, then it is checked before calling this function
if not value or (#value == 0) then if not value or (#value == 0) then
return "" -- ignore on empty return "" -- ignore on empty
elseif not DDNS.has_dnsserver then elseif not has_dnsserver then
return nil, err_tab_adv(self) .. translate("Specifying a DNS-Server is not supported") return nil, err_tab_adv(self) .. translate("Specifying a DNS-Server is not supported")
elseif not DTYP.host(value) then elseif not DTYP.host(value) then
return nil, err_tab_adv(self) .. translate("use hostname, FQDN, IPv4- or IPv6-Address") return nil, err_tab_adv(self) .. translate("use hostname, FQDN, IPv4- or IPv6-Address")
@ -1179,13 +1197,16 @@ if DDNS.has_dnsserver or ( ( m:get(section, "dns_server") or "" ) ~= "" ) then
end end
-- IPv4 + IPv6 - force_dnstcp -- ############################################## -- IPv4 + IPv6 - force_dnstcp -- ##############################################
if DDNS.has_bindhost or ( ( m:get(section, "force_dnstcp") or "0" ) ~= "0" ) then
local has_bindhost = DDNS.env_info("has_bindhost")
if has_bindhost or ( ( m:get(section, "force_dnstcp") or "0" ) ~= "0" ) then
tcp = ns:taboption("advanced", Flag, "force_dnstcp", tcp = ns:taboption("advanced", Flag, "force_dnstcp",
translate("Force TCP on DNS") ) translate("Force TCP on DNS") )
tcp.orientation = "horizontal" tcp.orientation = "horizontal"
function tcp.cfgvalue(self, section) function tcp.cfgvalue(self, section)
local value = AbstractValue.cfgvalue(self, section) local value = AbstractValue.cfgvalue(self, section)
if not DDNS.has_bindhost and value ~= "0" then if not has_bindhost and value ~= "0" then
self.description = bold_on .. font_red .. self.description = bold_on .. font_red ..
translate("DNS requests via TCP not supported") .. font_off .. "<br />" .. translate("DNS requests via TCP not supported") .. font_off .. "<br />" ..
translate("please disable") .. " !" .. bold_off translate("please disable") .. " !" .. bold_off
@ -1195,7 +1216,7 @@ if DDNS.has_bindhost or ( ( m:get(section, "force_dnstcp") or "0" ) ~= "0" ) the
return value return value
end end
function tcp.validate(self, value) function tcp.validate(self, value)
if (value == "1" and DDNS.has_bindhost ) or value == "0" then if (value == "1" and has_bindhost ) or value == "0" then
return value return value
end end
return nil, err_tab_adv(self) .. translate("DNS requests via TCP not supported") return nil, err_tab_adv(self) .. translate("DNS requests via TCP not supported")
@ -1204,13 +1225,16 @@ end
-- IPv4 + IPv6 - proxy -- ##################################################### -- IPv4 + IPv6 - proxy -- #####################################################
-- optional Proxy to use for http/https requests [user:password@]proxyhost[:port] -- optional Proxy to use for http/https requests [user:password@]proxyhost[:port]
if DDNS.has_proxy or ( ( m:get(section, "proxy") or "" ) ~= "" ) then
local has_proxy = DDNS.env_info("has_proxy")
if has_proxy or ( ( m:get(section, "proxy") or "" ) ~= "" ) then
pxy = ns:taboption("advanced", Value, "proxy", pxy = ns:taboption("advanced", Value, "proxy",
translate("PROXY-Server") ) translate("PROXY-Server") )
pxy.placeholder="user:password@myproxy.lan:8080" pxy.placeholder="user:password@myproxy.lan:8080"
function pxy.cfgvalue(self, section) function pxy.cfgvalue(self, section)
local value = AbstractValue.cfgvalue(self, section) local value = AbstractValue.cfgvalue(self, section)
if not DDNS.has_proxy and value ~= "" then if not has_proxy and value ~= "" then
self.description = bold_on .. font_red .. self.description = bold_on .. font_red ..
translate("PROXY-Server not supported") .. font_off .. "<br />" .. translate("PROXY-Server not supported") .. font_off .. "<br />" ..
translate("please remove entry") .. "!" .. bold_off translate("please remove entry") .. "!" .. bold_off
@ -1226,7 +1250,7 @@ if DDNS.has_proxy or ( ( m:get(section, "proxy") or "" ) ~= "" ) then
-- if .datatype is set, then it is checked before calling this function -- if .datatype is set, then it is checked before calling this function
if not value or (#value == 0) then if not value or (#value == 0) then
return "" -- ignore on empty return "" -- ignore on empty
elseif DDNS.has_proxy then elseif has_proxy then
local ipv6 = usev6:formvalue(section) or "0" local ipv6 = usev6:formvalue(section) or "0"
local force = fipv:formvalue(section) or "0" local force = fipv:formvalue(section) or "0"
local command = CTRL.luci_helper .. [[ -]] local command = CTRL.luci_helper .. [[ -]]

View file

@ -48,7 +48,7 @@ if not SYS.init.enabled("ddns") then
end end
-- No IPv6 support -- No IPv6 support
if not DDNS.has_ipv6 then if not DDNS.env_info("has_ipv6") then
local v6 = s:option(DummyValue, "_no_ipv6") local v6 = s:option(DummyValue, "_no_ipv6")
v6.titleref = 'http://www.openwrt.org" target="_blank' v6.titleref = 'http://www.openwrt.org" target="_blank'
v6.rawhtml = true v6.rawhtml = true
@ -60,7 +60,7 @@ if not DDNS.has_ipv6 then
end end
-- No HTTPS support -- No HTTPS support
if not DDNS.has_ssl then if not DDNS.env_info("has_ssl") then
local sl = s:option(DummyValue, "_no_https") local sl = s:option(DummyValue, "_no_https")
sl.titleref = DISP.build_url("admin", "system", "packages") sl.titleref = DISP.build_url("admin", "system", "packages")
sl.rawhtml = true sl.rawhtml = true
@ -74,7 +74,7 @@ if not DDNS.has_ssl then
end end
-- No bind_network -- No bind_network
if not DDNS.has_bindnet then if not DDNS.env_info("has_bindnet") then
local bn = s:option(DummyValue, "_no_bind_network") local bn = s:option(DummyValue, "_no_bind_network")
bn.titleref = DISP.build_url("admin", "system", "packages") bn.titleref = DISP.build_url("admin", "system", "packages")
bn.rawhtml = true bn.rawhtml = true
@ -90,7 +90,7 @@ if not DDNS.has_bindnet then
end end
-- currently only cURL possibly without proxy support -- currently only cURL possibly without proxy support
if not DDNS.has_proxy then if not DDNS.env_info("has_proxy") then
local px = s:option(DummyValue, "_no_proxy") local px = s:option(DummyValue, "_no_proxy")
px.titleref = DISP.build_url("admin", "system", "packages") px.titleref = DISP.build_url("admin", "system", "packages")
px.rawhtml = true px.rawhtml = true
@ -104,7 +104,7 @@ if not DDNS.has_proxy then
end end
-- "Force IP Version not supported" -- "Force IP Version not supported"
if not DDNS.has_forceip then if not DDNS.env_info("has_forceip") then
local fi = s:option(DummyValue, "_no_force_ip") local fi = s:option(DummyValue, "_no_force_ip")
fi.titleref = DISP.build_url("admin", "system", "packages") fi.titleref = DISP.build_url("admin", "system", "packages")
fi.rawhtml = true fi.rawhtml = true
@ -112,11 +112,11 @@ if not DDNS.has_forceip then
translate("Force IP Version not supported") .. bold_off translate("Force IP Version not supported") .. bold_off
local value = translate("BusyBox's nslookup and Wget do not support to specify " .. local value = translate("BusyBox's nslookup and Wget do not support to specify " ..
"the IP version to use for communication with DDNS Provider!") "the IP version to use for communication with DDNS Provider!")
if not (DDNS.has_wgetssl or DDNS.has_curl or DDNS.has_fetch) then if not (DDNS.env_info("has_wgetssl") or DDNS.env_info("has_curl") or DDNS.env_info("has_fetch")) then
value = value .. "<br />- " .. value = value .. "<br />- " ..
translate("You should install 'wget' or 'curl' or 'uclient-fetch' package.") translate("You should install 'wget' or 'curl' or 'uclient-fetch' package.")
end end
if not DDNS.has_bindhost then if not DDNS.env_info("has_bindhost") then
value = value .. "<br />- " .. value = value .. "<br />- " ..
translate("You should install 'bind-host' or 'knot-host' or 'drill' package for DNS requests.") translate("You should install 'bind-host' or 'knot-host' or 'drill' package for DNS requests.")
end end
@ -124,7 +124,7 @@ if not DDNS.has_forceip then
end end
-- "DNS requests via TCP not supported" -- "DNS requests via TCP not supported"
if not DDNS.has_bindhost then if not DDNS.env_info("has_bindhost") then
local dt = s:option(DummyValue, "_no_dnstcp") local dt = s:option(DummyValue, "_no_dnstcp")
dt.titleref = DISP.build_url("admin", "system", "packages") dt.titleref = DISP.build_url("admin", "system", "packages")
dt.rawhtml = true dt.rawhtml = true
@ -137,7 +137,7 @@ if not DDNS.has_bindhost then
end end
-- nslookup compiled with musl produce problems when using -- nslookup compiled with musl produce problems when using
if not DDNS.has_dnsserver then if not DDNS.env_info("has_dnsserver") then
local ds = s:option(DummyValue, "_no_dnsserver") local ds = s:option(DummyValue, "_no_dnsserver")
ds.titleref = DISP.build_url("admin", "system", "packages") ds.titleref = DISP.build_url("admin", "system", "packages")
ds.rawhtml = true ds.rawhtml = true
@ -151,7 +151,7 @@ if not DDNS.has_dnsserver then
end end
-- certificates installed -- certificates installed
if DDNS.has_ssl and not DDNS.has_cacerts then if DDNS.env_info("has_ssl") and not DDNS.env_info("has_cacerts") then
local ca = s:option(DummyValue, "_no_certs") local ca = s:option(DummyValue, "_no_certs")
ca.titleref = DISP.build_url("admin", "system", "packages") ca.titleref = DISP.build_url("admin", "system", "packages")
ca.rawhtml = true ca.rawhtml = true

View file

@ -1,21 +1,20 @@
-- Copyright 2014-2018 Christian Schoenebeck <christian dot schoenebeck at gmail dot com> -- Copyright 2014-2018 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
-- Licensed to the public under the Apache License 2.0. -- Licensed to the public under the Apache License 2.0.
local NXFS = require "nixio.fs"
local DISP = require "luci.dispatcher" local DISP = require "luci.dispatcher"
local HTTP = require "luci.http" local HTTP = require "luci.http"
local SYS = require "luci.sys" local SYS = require "luci.sys"
local CTRL = require "luci.controller.ddns" -- this application's controller local CTRL = require "luci.controller.ddns" -- this application's controller
local DDNS = require "luci.tools.ddns" -- ddns multiused functions local DDNS = require "luci.tools.ddns" -- ddns multiused functions
local show_hints = not (DDNS.has_ipv6 -- IPv6 support local show_hints = not (DDNS.env_info("has_ipv6") -- IPv6 support
and DDNS.has_ssl -- HTTPS support and DDNS.env_info("has_ssl") -- HTTPS support
and DDNS.has_proxy -- Proxy support and DDNS.env_info("has_proxy") -- Proxy support
and DDNS.has_bindhost -- DNS TCP support and DDNS.env_info("has_bindhost") -- DNS TCP support
and DDNS.has_forceip -- Force IP version and DDNS.env_info("has_forceip") -- Force IP version
and DDNS.has_dnsserver -- DNS server support and DDNS.env_info("has_dnsserver") -- DNS server support
and DDNS.has_bindnet -- Bind to network/interface and DDNS.env_info("has_bindnet") -- Bind to network/interface
and DDNS.has_cacerts -- certificates installed at /etc/ssl/certs and DDNS.env_info("has_cacerts") -- certificates installed at /etc/ssl/certs
) )
local not_enabled = not SYS.init.enabled("ddns") local not_enabled = not SYS.init.enabled("ddns")
local need_update = not CTRL.service_ok() local need_update = not CTRL.service_ok()

View file

@ -5,37 +5,135 @@ module("luci.tools.ddns", package.seeall)
local NX = require "nixio" local NX = require "nixio"
local NXFS = require "nixio.fs" local NXFS = require "nixio.fs"
local OPKG = require "luci.model.ipkg"
local UCI = require "luci.model.uci" local UCI = require "luci.model.uci"
local SYS = require "luci.sys" local SYS = require "luci.sys"
local UTIL = require "luci.util"
local function _check_certs() function env_info(type)
local _, v = NXFS.glob("/etc/ssl/certs/*.crt")
if ( v == 0 ) then _, v = NXFS.glob("/etc/ssl/certs/*.pem") end if ( type == "has_ssl" ) or ( type == "has_proxy" ) or ( type == "has_forceip" )
return (v > 0) or ( type == "has_bindnet" ) or ( type == "has_fetch" )
or ( type == "has_wgetssl" ) or ( type == "has_curl" )
or ( type == "has_curlssl" ) or ( type == "has_curlpxy" )
or ( type == "has_fetchssl" ) or ( type == "has_bbwget" ) then
local function has_wgetssl()
return (SYS.call( [[which wget-ssl >/dev/null 2>&1]] ) == 0) -- and true or nil
end
local function has_curlssl()
return (SYS.call( [[$(which curl) -V 2>&1 | grep "Protocols:" | grep -qF "https"]] ) ~= 0)
end
local function has_fetch()
return (SYS.call( [[which uclient-fetch >/dev/null 2>&1]] ) == 0)
end
local function has_fetchssl()
return NXFS.access("/lib/libustream-ssl.so")
end
local function has_curl()
return (SYS.call( [[which curl >/dev/null 2>&1]] ) == 0)
end
local function has_curlpxy()
return (SYS.call( [[grep -i "all_proxy" /usr/lib/libcurl.so* >/dev/null 2>&1]] ) == 0)
end
local function has_bbwget()
return (SYS.call( [[$(which wget) -V 2>&1 | grep -iqF "busybox"]] ) == 0)
end
if type == "has_wgetssl" then
return has_wgetssl()
elseif type == "has_curl" then
return has_curl()
elseif type == "has_curlssl" then
return has_curlssl()
elseif type == "has_curlpxy" then
return has_curlpxy()
elseif type == "has_fetch" then
return has_fetch()
elseif type == "has_fetchssl" then
return has_fetchssl()
elseif type == "has_bbwget" then
return has_bbwget()
elseif type == "has_ssl" then
if has_wgetssl() then return true end
if has_curlssl() then return true end
if (has_fetch() and has_fetchssl()) then return true end
return false
elseif type == "has_proxy" then
if has_wgetssl() then return true end
if has_curlpxy() then return true end
if has_fetch() then return true end
if has_bbwget() then return true end
return false
elseif type == "has_forceip" then
if has_wgetssl() then return true end
if has_curl() then return true end
if has_fetch() then return true end -- only really needed for transfer
return false
elseif type == "has_bindnet" then
if has_curl() then return true end
if has_wgetssl() then return true end
return false
end
elseif ( type == "has_dnsserver" ) or ( type == "has_bindhost" ) or ( type == "has_hostip" ) or ( type == "has_nslookup" ) then
local function has_bindhost()
if (SYS.call( [[which host >/dev/null 2>&1]] ) == 0) then return true end
if (SYS.call( [[which host >/dev/null 2>&1]] ) == 0) then return true end
if (SYS.call( [[which khost >/dev/null 2>&1]] ) == 0) then return true end
if (SYS.call( [[which drill >/dev/null 2>&1]] ) == 0) then return true end
return false
end
local function has_hostip()
return (SYS.call( [[which hostip >/dev/null 2>&1]] ) == 0)
end
local function has_nslookup()
return (SYS.call( [[$(which nslookup) localhost 2>&1 | grep -qF "(null)"]] ) ~= 0)
end
if type == "has_bindhost" then
return has_bindhost()
elseif type == "has_hostip" then
return has_hostip()
elseif type == "has_nslookup" then
return has_nslookup()
elseif tyep == "has_dnsserver" then
if has_bindhost() then return true end
if has_hostip() then return true end
if has_nslookup() then return true end
return false
end
elseif type == "has_ipv6" then
return (NXFS.access("/proc/net/ipv6_route") and NXFS.access("/usr/sbin/ip6tables"))
elseif type == "has_cacerts" then
--old _check_certs() local function
local _, v = NXFS.glob("/etc/ssl/certs/*.crt")
if ( v == 0 ) then _, v = NXFS.glob("/etc/ssl/certs/*.pem") end
return (v > 0)
else
return
end
end end
has_wgetssl = (SYS.call( [[which wget-ssl >/dev/null 2>&1]] ) == 0) -- and true or nil
has_curl = (SYS.call( [[which curl >/dev/null 2>&1]] ) == 0)
has_curlssl = (SYS.call( [[$(which curl) -V 2>&1 | grep "Protocols:" | grep -qF "https"]] ) ~= 0)
has_curlpxy = (SYS.call( [[grep -i "all_proxy" /usr/lib/libcurl.so* >/dev/null 2>&1]] ) == 0)
has_fetch = (SYS.call( [[which uclient-fetch >/dev/null 2>&1]] ) == 0)
has_fetchssl = NXFS.access("/lib/libustream-ssl.so")
has_bbwget = (SYS.call( [[$(which wget) -V 2>&1 | grep -iqF "busybox"]] ) == 0)
has_bindhost = (SYS.call( [[which host >/dev/null 2>&1]] ) == 0)
or (SYS.call( [[which khost >/dev/null 2>&1]] ) == 0)
or (SYS.call( [[which drill >/dev/null 2>&1]] ) == 0)
has_hostip = (SYS.call( [[which hostip >/dev/null 2>&1]] ) == 0)
has_nslookup = (SYS.call( [[$(which nslookup) localhost 2>&1 | grep -qF "(null)"]] ) ~= 0)
has_ipv6 = (NXFS.access("/proc/net/ipv6_route") and NXFS.access("/usr/sbin/ip6tables"))
has_ssl = (has_wgetssl or has_curlssl or (has_fetch and has_fetchssl))
has_proxy = (has_wgetssl or has_curlpxy or has_fetch or has_bbwget)
has_forceip = (has_wgetssl or has_curl or has_fetch) -- only really needed for transfer
has_dnsserver = (has_bindhost or has_hostip or has_nslookup)
has_bindnet = (has_wgetssl or has_curl)
has_cacerts = _check_certs()
-- function to calculate seconds from given interval and unit -- function to calculate seconds from given interval and unit
function calc_seconds(interval, unit) function calc_seconds(interval, unit)
if not tonumber(interval) then if not tonumber(interval) then

View file

@ -1,4 +1,3 @@
<!-- ++ BEGIN ++ Dynamic DNS ++ system_status.htm ++ --> <!-- ++ BEGIN ++ Dynamic DNS ++ system_status.htm ++ -->
<script type="text/javascript">//<![CDATA[ <script type="text/javascript">//<![CDATA[
// helper to move status data to the relevant // helper to move status data to the relevant
@ -10,8 +9,8 @@
if ( !(tbl) ) { return; } if ( !(tbl) ) { return; }
// clear all rows // clear all rows
while (tbl.rows.length > 1) while (tbl.firstElementChild !== tbl.lastElementChild)
tbl.deleteRow(1); tbl.removeChild(tbl.lastElementChild);
// variable for Modulo-Division use to set cbi-rowstyle-? (0 or 1) // variable for Modulo-Division use to set cbi-rowstyle-? (0 or 1)
var i = -1; var i = -1;
@ -21,22 +20,22 @@
if (data[0].enabled == 0) { if (data[0].enabled == 0) {
var txt = '<strong><font color="red"><%:DDNS Autostart disabled%></font>' ; var txt = '<strong><font color="red"><%:DDNS Autostart disabled%></font>' ;
var url = '<a href="' + data[0].url_up + '"><%:enable here%></a></strong>' ; var url = '<a href="' + data[0].url_up + '"><%:enable here%></a></strong>' ;
var tr = tbl.insertRow(-1); tbl.appendChild(E('<div class="tr cbi-section-table-row cbi-rowstyle-%d">'.format(((j + i) % 2) + 1), [
tr.className = 'cbi-section-table-row cbi-rowstyle-' + (((j + i) % 2) + 1); E('<div class="td">', [ txt," - ", url ])
var td = tr.insertCell(-1); ]));
td.colSpan = 2 ;
td.innerHTML = txt + " - " + url
tr.insertCell(-1).colSpan = 3 ;
i++ ; i++ ;
} }
var configuration;
var next_update;
var lookup;
var registered_ip;
var network;
for( j = 1; j < data.length; j++ ) for( j = 1; j < data.length; j++ )
{ {
var tr = tbl.insertRow(-1);
tr.className = 'cbi-section-table-row cbi-rowstyle-' + (((j + i) % 2) + 1) ;
// configuration // configuration
tr.insertCell(-1).innerHTML = '<strong>' + data[j].section + '</strong>' ; configuration = data[j].section;
// pid // pid
// data[j].pid ignored here // data[j].pid ignored here
@ -47,66 +46,74 @@
// next update // next update
switch (data[j].datenext) { switch (data[j].datenext) {
case "_empty_": case "_empty_":
tr.insertCell(-1).innerHTML = '<em><%:Unknown error%></em>' ; next_update = '<em><%:Unknown error%></em>';
break; break;
case "_stopped_": case "_stopped_":
tr.insertCell(-1).innerHTML = '<em><%:Stopped%></em>' ; next_update = '<em><%:Stopped%></em>';
break; break;
case "_disabled_": case "_disabled_":
tr.insertCell(-1).innerHTML = '<em><%:Disabled%></em>' ; next_update = '<em><%:Disabled%></em>';
break; break;
case "_noupdate_": case "_noupdate_":
tr.insertCell(-1).innerHTML = '<em><%:Update error%></em>' ; next_update = '<em><%:Update error%></em>';
break; break;
case "_runonce_": case "_runonce_":
tr.insertCell(-1).innerHTML = '<em><%:Run once%></em>' ; next_update = '<em><%:Run once%></em>';
break; break;
case "_verify_": case "_verify_":
tr.insertCell(-1).innerHTML = '<em><%:Verify%></em>'; next_update = '<em><%:Verify%></em>';
break; break;
default: default:
tr.insertCell(-1).innerHTML = data[j].datenext ; next_update = data[j].datenext;
break; break;
} }
// lookup // lookup
if (data[j].lookup == "_nolookup_") if (data[j].lookup == "_nolookup_")
tr.insertCell(-1).innerHTML = '<em><%:config error%></em>'; lookup = '<em><%:config error%></em>';
else else
tr.insertCell(-1).innerHTML = data[j].lookup; lookup = data[j].lookup;
// registered IP // registered IP
switch (data[j].reg_ip) { switch (data[j].reg_ip) {
case "_nolookup_": case "_nolookup_":
tr.insertCell(-1).innerHTML = '<em><%:Config error%></em>'; registered_ip = '<em><%:config error%></em>';
break; break;
case "_nodata_": case "_nodata_":
tr.insertCell(-1).innerHTML = '<em><%:No data%></em>'; registered_ip = '<em><%:No data%></em>';
break; break;
case "_noipv6_": case "_noipv6_":
tr.insertCell(-1).innerHTML = '<em><%:IPv6 not supported%></em>'; registered_ip = '<em><%:IPv6 not supported%></em>';
break; break;
default: default:
tr.insertCell(-1).innerHTML = data[j].reg_ip; registered_ip = data[j].reg_ip;
break; break;
} }
// monitored interface // monitored interface
if (data[j].iface == "_nonet_") if (data[j].iface == "_nonet_")
tr.insertCell(-1).innerHTML = '<em><%:Config error%></em>'; network = '<em><%:Config error%></em>';
else else
tr.insertCell(-1).innerHTML = data[j].iface; network = data[j].iface;
tbl.appendChild(E('<div class="tr cbi-section-table-row cbi-rowstyle-%d">'.format(((j + i) % 2) + 1), [
E('<div class="td">', [ E('<strong>', configuration) ]),
E('<div class="td">', next_update),
E('<div class="td">', lookup),
E('<div class="td">', registered_ip),
E('<div class="td">', network)
]));
} }
if (tbl.rows.length == 1 || (data[0].enabled == 0 && tbl.rows.length == 2) ) { if (tbl.firstElementChild === tbl.lastElementChild || (data[0].enabled == 0 && tbl.childNodes.length == 2) ) {
var br = '<br />'; var br = '<br />';
if (tbl.rows.length > 1) var msg = '<%:There is no service configured.%>';
if (tbl.firstElementChild !== tbl.lastElementChild)
br = ''; br = '';
var tr = tbl.insertRow(-1); msg = br + msg;
tr.className = "cbi-section-table-row"; tbl.appendChild(E('<div class="tr cbi-section-table-row">', [
var td = tr.insertCell(-1); E('<div class="td">', [ E('<em>', msg) ])
td.colSpan = 5; ]));
td.innerHTML = '<em>' + br + '<%:There is no service configured.%></em>' ;
} }
} }
@ -128,17 +135,17 @@
<fieldset class="cbi-section" id="ddns_status_section"> <fieldset class="cbi-section" id="ddns_status_section">
<legend><a href="<%=url([[admin]], [[services]], [[ddns]])%>"><%:Dynamic DNS%></a></legend> <legend><a href="<%=url([[admin]], [[services]], [[ddns]])%>"><%:Dynamic DNS%></a></legend>
<table class="cbi-section-table" id="ddns_status_table"> <div class="table cbi-section-table" id="ddns_status_table">
<tr class="cbi-section-table-titles"> <div class="tr cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Configuration%></th> <div class="th cbi-section-table-cell"><%:Configuration%></div>
<th class="cbi-section-table-cell"><%:Next Update%></th> <div class="th cbi-section-table-cell"><%:Next Update%></div>
<th class="cbi-section-table-cell"><%:Lookup Hostname%></th> <div class="th cbi-section-table-cell"><%:Lookup Hostname%></div>
<th class="cbi-section-table-cell"><%:Registered IP%></th> <div class="th cbi-section-table-cell"><%:Registered IP%></div>
<th class="cbi-section-table-cell"><%:Network%></th> <div class="th cbi-section-table-cell"><%:Network%></div>
</tr> </div>
<tr class="cbi-section-table-row"> <div class="tr cbi-section-table-row">
<td colspan="5"><em><br /><%:Collecting data...%></em></td> <div class="td"><em><br /><%:Collecting data...%></em></div>
</tr> </div>
</table> </div>
</fieldset> </fieldset>
<!-- ++ END ++ Dynamic DNS ++ system_status.htm ++ --> <!-- ++ END ++ Dynamic DNS ++ system_status.htm ++ -->

View file

@ -55,6 +55,7 @@ o = s:option(Value, "src", translate("Source zone"))
o.nocreate = true o.nocreate = true
o.default = "wan" o.default = "wan"
o.template = "cbi/firewall_zonelist" o.template = "cbi/firewall_zonelist"
o.rmempty = false
o = s:option(DynamicList, "src_mac", o = s:option(DynamicList, "src_mac",
@ -88,6 +89,10 @@ o.rmempty = true
o.datatype = "neg(portrange)" o.datatype = "neg(portrange)"
o.placeholder = translate("any") o.placeholder = translate("any")
o:depends("proto", "tcp")
o:depends("proto", "udp")
o:depends("proto", "tcp udp")
o:depends("proto", "tcpudp")
o = s:option(Value, "src_dip", o = s:option(Value, "src_dip",
translate("External IP address"), translate("External IP address"),
@ -108,7 +113,10 @@ o = s:option(Value, "src_dport", translate("External port"),
"destination port or port range on this host")) "destination port or port range on this host"))
o.datatype = "neg(portrange)" o.datatype = "neg(portrange)"
o:depends("proto", "tcp")
o:depends("proto", "udp")
o:depends("proto", "tcp udp")
o:depends("proto", "tcpudp")
o = s:option(Value, "dest", translate("Internal zone")) o = s:option(Value, "dest", translate("Internal zone"))
o.nocreate = true o.nocreate = true
@ -133,6 +141,10 @@ o = s:option(Value, "dest_port",
o.placeholder = translate("any") o.placeholder = translate("any")
o.datatype = "portrange" o.datatype = "portrange"
o:depends("proto", "tcp")
o:depends("proto", "udp")
o:depends("proto", "tcp udp")
o:depends("proto", "tcpudp")
o = s:option(Flag, "reflection", translate("Enable NAT Loopback")) o = s:option(Flag, "reflection", translate("Enable NAT Loopback"))
o.rmempty = true o.rmempty = true

View file

@ -54,7 +54,7 @@ function s.parse(self, ...)
if created then if created then
m.uci:save("firewall") m.uci:save("firewall")
luci.http.redirect(ds.build_url( luci.http.redirect(ds.build_url(
"admin/network/firewall/redirect", created "admin/network/firewall/forwards", created
)) ))
end end
end end
@ -63,8 +63,9 @@ function s.filter(self, sid)
return (self.map:get(sid, "target") ~= "SNAT") return (self.map:get(sid, "target") ~= "SNAT")
end end
function s.sectiontitle(self, sid)
ft.opt_name(s, DummyValue, translate("Name")) return (self.map:get(sid, "name") or translate("Unnamed forward"))
end
local function forward_proto_txt(self, s) local function forward_proto_txt(self, s)
@ -103,7 +104,6 @@ end
match = s:option(DummyValue, "match", translate("Match")) match = s:option(DummyValue, "match", translate("Match"))
match.rawhtml = true match.rawhtml = true
match.width = "50%"
function match.cfgvalue(self, s) function match.cfgvalue(self, s)
return "<small>%s<br />%s<br />%s</small>" % { return "<small>%s<br />%s<br />%s</small>" % {
forward_proto_txt(self, s), forward_proto_txt(self, s),
@ -115,7 +115,6 @@ end
dest = s:option(DummyValue, "dest", translate("Forward to")) dest = s:option(DummyValue, "dest", translate("Forward to"))
dest.rawhtml = true dest.rawhtml = true
dest.width = "40%"
function dest.cfgvalue(self, s) function dest.cfgvalue(self, s)
local z = ft.fmt_zone(self.map:get(s, "dest"), translate("any zone")) local z = ft.fmt_zone(self.map:get(s, "dest"), translate("any zone"))
local a = ft.fmt_ip(self.map:get(s, "dest_ip"), translate("any host")) local a = ft.fmt_ip(self.map:get(s, "dest_ip"), translate("any host"))
@ -129,6 +128,6 @@ function dest.cfgvalue(self, s)
end end
end end
ft.opt_enabled(s, Flag, translate("Enable")).width = "1%" ft.opt_enabled(s, Flag, translate("Enable"))
return m return m

View file

@ -115,6 +115,10 @@ elseif rule_type == "redirect" then
o.datatype = "neg(portrange)" o.datatype = "neg(portrange)"
o.placeholder = translate("any") o.placeholder = translate("any")
o:depends("proto", "tcp")
o:depends("proto", "udp")
o:depends("proto", "tcp udp")
o:depends("proto", "tcpudp")
o = s:option(Value, "dest", translate("Destination zone")) o = s:option(Value, "dest", translate("Destination zone"))
o.nocreate = true o.nocreate = true
@ -139,6 +143,10 @@ elseif rule_type == "redirect" then
o.placeholder = translate("any") o.placeholder = translate("any")
o.datatype = "neg(portrange)" o.datatype = "neg(portrange)"
o:depends("proto", "tcp")
o:depends("proto", "udp")
o:depends("proto", "tcp udp")
o:depends("proto", "tcpudp")
o = s:option(Value, "src_dip", o = s:option(Value, "src_dip",
translate("SNAT IP address"), translate("SNAT IP address"),
@ -163,6 +171,10 @@ elseif rule_type == "redirect" then
o.rmempty = true o.rmempty = true
o.placeholder = translate('Do not rewrite') o.placeholder = translate('Do not rewrite')
o:depends("proto", "tcp")
o:depends("proto", "udp")
o:depends("proto", "tcp udp")
o:depends("proto", "tcpudp")
s:option(Value, "extra", s:option(Value, "extra",
translate("Extra arguments"), translate("Extra arguments"),
@ -212,7 +224,13 @@ else
end end
o = s:option(DynamicList, "icmp_type", translate("Match ICMP type")) o = s:option(DropDown, "icmp_type", translate("Match ICMP type"))
o.multiple = true
o.display = 10
o.dropdown = 10
o.custom = true
o.cast = "table"
o:value("", "any") o:value("", "any")
o:value("echo-reply") o:value("echo-reply")
o:value("destination-unreachable") o:value("destination-unreachable")
@ -251,11 +269,13 @@ else
o:value("address-mask-request") o:value("address-mask-request")
o:value("address-mask-reply") o:value("address-mask-reply")
o:depends("proto", "icmp")
o = s:option(Value, "src", translate("Source zone")) o = s:option(Value, "src", translate("Source zone"))
o.nocreate = true o.nocreate = true
o.allowany = true o.allowany = true
o.default = "wan" o.allowlocal = "src"
o.template = "cbi/firewall_zonelist" o.template = "cbi/firewall_zonelist"
@ -269,7 +289,7 @@ else
o = s:option(Value, "src_ip", translate("Source address")) o = s:option(Value, "src_ip", translate("Source address"))
o.datatype = "neg(ipmask)" o.datatype = "list(neg(ipmask))"
o.placeholder = translate("any") o.placeholder = translate("any")
luci.sys.net.ipv4_hints(function(ip, name) luci.sys.net.ipv4_hints(function(ip, name)
@ -281,16 +301,29 @@ else
o.datatype = "list(neg(portrange))" o.datatype = "list(neg(portrange))"
o.placeholder = translate("any") o.placeholder = translate("any")
o:depends("proto", "tcp")
o:depends("proto", "udp")
o:depends("proto", "tcp udp")
o:depends("proto", "tcpudp")
o = s:option(Value, "dest", translate("Destination zone")) o = s:option(Value, "dest_local", translate("Output zone"))
o.nocreate = true
o.allowany = true
o.template = "cbi/firewall_zonelist"
o.alias = "dest"
o:depends("src", "")
o = s:option(Value, "dest_remote", translate("Destination zone"))
o.nocreate = true o.nocreate = true
o.allowany = true o.allowany = true
o.allowlocal = true o.allowlocal = true
o.template = "cbi/firewall_zonelist" o.template = "cbi/firewall_zonelist"
o.alias = "dest"
o:depends({["src"] = "", ["!reverse"] = true})
o = s:option(Value, "dest_ip", translate("Destination address")) o = s:option(Value, "dest_ip", translate("Destination address"))
o.datatype = "neg(ipmask)" o.datatype = "list(neg(ipmask))"
o.placeholder = translate("any") o.placeholder = translate("any")
luci.sys.net.ipv4_hints(function(ip, name) luci.sys.net.ipv4_hints(function(ip, name)
@ -302,6 +335,10 @@ else
o.datatype = "list(neg(portrange))" o.datatype = "list(neg(portrange))"
o.placeholder = translate("any") o.placeholder = translate("any")
o:depends("proto", "tcp")
o:depends("proto", "udp")
o:depends("proto", "tcp udp")
o:depends("proto", "tcpudp")
o = s:option(ListValue, "target", translate("Action")) o = s:option(ListValue, "target", translate("Action"))
o.default = "ACCEPT" o.default = "ACCEPT"
@ -316,9 +353,9 @@ else
translate("Passes additional arguments to iptables. Use with care!")) translate("Passes additional arguments to iptables. Use with care!"))
end end
o = s:option(MultiValue, "weekdays", translate("Week Days")) o = s:option(DropDown, "weekdays", translate("Week Days"))
o.oneline = true o.multiple = true
o.widget = "checkbox" o.display = 5
o:value("Sun", translate("Sunday")) o:value("Sun", translate("Sunday"))
o:value("Mon", translate("Monday")) o:value("Mon", translate("Monday"))
o:value("Tue", translate("Tuesday")) o:value("Tue", translate("Tuesday"))
@ -327,9 +364,9 @@ o:value("Thu", translate("Thursday"))
o:value("Fri", translate("Friday")) o:value("Fri", translate("Friday"))
o:value("Sat", translate("Saturday")) o:value("Sat", translate("Saturday"))
o = s:option(MultiValue, "monthdays", translate("Month Days")) o = s:option(DropDown, "monthdays", translate("Month Days"))
o.oneline = true o.multiple = true
o.widget = "checkbox" o.display = 15
for i = 1,31 do for i = 1,31 do
o:value(translate(i)) o:value(translate(i))
end end

View file

@ -72,7 +72,9 @@ function s.parse(self, ...)
end end
end end
ft.opt_name(s, DummyValue, translate("Name")) function s.sectiontitle(self, sid)
return (self.map:get(sid, "name") or translate("Unnamed rule"))
end
local function rule_proto_txt(self, s) local function rule_proto_txt(self, s)
local f = self.map:get(s, "family") local f = self.map:get(s, "family")
@ -89,17 +91,31 @@ local function rule_proto_txt(self, s)
end end
local function rule_src_txt(self, s) local function rule_src_txt(self, s)
local z = ft.fmt_zone(self.map:get(s, "src"), translate("any zone")) local z = ft.fmt_zone(self.map:get(s, "src"))
local a = ft.fmt_ip(self.map:get(s, "src_ip"), translate("any host"))
local p = ft.fmt_port(self.map:get(s, "src_port")) local p = ft.fmt_port(self.map:get(s, "src_port"))
local m = ft.fmt_mac(self.map:get(s, "src_mac")) local m = ft.fmt_mac(self.map:get(s, "src_mac"))
if p and m then -- Forward/Input
return translatef("From %s in %s with source %s and %s", a, z, p, m) if z and #z > 0 then
elseif p or m then local a = ft.fmt_ip(self.map:get(s, "src_ip"), translate("any host"))
return translatef("From %s in %s with source %s", a, z, p or m) if p and m then
return translatef("From %s in %s with source %s and %s", a, z, p, m)
elseif p or m then
return translatef("From %s in %s with source %s", a, z, p or m)
else
return translatef("From %s in %s", a, z)
end
-- Output
else else
return translatef("From %s in %s", a, z) local a = ft.fmt_ip(self.map:get(s, "src_ip"), translate("any router IP"))
if p and m then
return translatef("From %s on <var>this device</var> with source %s and %s", a, p, m)
elseif p or m then
return translatef("From %s on <var>this device</var> with source %s", a, p or m)
else
return translatef("From %s on <var>this device</var>", a)
end
end end
end end
@ -145,7 +161,6 @@ end
match = s:option(DummyValue, "match", translate("Match")) match = s:option(DummyValue, "match", translate("Match"))
match.rawhtml = true match.rawhtml = true
match.width = "70%"
function match.cfgvalue(self, s) function match.cfgvalue(self, s)
return "<small>%s<br />%s<br />%s</small>" % { return "<small>%s<br />%s<br />%s</small>" % {
rule_proto_txt(self, s), rule_proto_txt(self, s),
@ -156,9 +171,8 @@ end
target = s:option(DummyValue, "target", translate("Action")) target = s:option(DummyValue, "target", translate("Action"))
target.rawhtml = true target.rawhtml = true
target.width = "20%"
function target.cfgvalue(self, s) function target.cfgvalue(self, s)
local t = ft.fmt_target(self.map:get(s, "target"), self.map:get(s, "dest")) local t = ft.fmt_target(self.map:get(s, "target"), self.map:get(s, "src"), self.map:get(s, "dest"))
local l = ft.fmt_limit(self.map:get(s, "limit"), local l = ft.fmt_limit(self.map:get(s, "limit"),
self.map:get(s, "limit_burst")) self.map:get(s, "limit_burst"))
@ -169,7 +183,7 @@ function target.cfgvalue(self, s)
end end
end end
ft.opt_enabled(s, Flag, translate("Enable")).width = "1%" ft.opt_enabled(s, Flag, translate("Enable"))
-- --
@ -226,11 +240,12 @@ function s.filter(self, sid)
return (self.map:get(sid, "target") == "SNAT") return (self.map:get(sid, "target") == "SNAT")
end end
ft.opt_name(s, DummyValue, translate("Name")) function s.sectiontitle(self, sid)
return (self.map:get(sid, "name") or translate("Unnamed SNAT"))
end
match = s:option(DummyValue, "match", translate("Match")) match = s:option(DummyValue, "match", translate("Match"))
match.rawhtml = true match.rawhtml = true
match.width = "70%"
function match.cfgvalue(self, s) function match.cfgvalue(self, s)
return "<small>%s<br />%s<br />%s</small>" % { return "<small>%s<br />%s<br />%s</small>" % {
rule_proto_txt(self, s), rule_proto_txt(self, s),
@ -241,7 +256,6 @@ end
snat = s:option(DummyValue, "via", translate("Action")) snat = s:option(DummyValue, "via", translate("Action"))
snat.rawhtml = true snat.rawhtml = true
snat.width = "20%"
function snat.cfgvalue(self, s) function snat.cfgvalue(self, s)
local a = ft.fmt_ip(self.map:get(s, "src_dip")) local a = ft.fmt_ip(self.map:get(s, "src_dip"))
local p = ft.fmt_port(self.map:get(s, "src_dport")) local p = ft.fmt_port(self.map:get(s, "src_dport"))
@ -253,7 +267,7 @@ function snat.cfgvalue(self, s)
end end
end end
ft.opt_enabled(s, Flag, translate("Enable")).width = "1%" ft.opt_enabled(s, Flag, translate("Enable"))
return m return m

View file

@ -101,9 +101,12 @@ end
function net.write(self, section, value) function net.write(self, section, value)
zone:clear_networks() zone:clear_networks()
local n local net
for n in ut.imatch(value) do for net in ut.imatch(value) do
zone:add_network(n) local n = nw:get_network(net) or nw:add_network(net, { proto = "none" })
if n then
zone:add_network(n:name())
end
end end
end end

View file

@ -62,6 +62,11 @@ s.anonymous = true
s.addremove = true s.addremove = true
s.extedit = ds.build_url("admin", "network", "firewall", "zones", "%s") s.extedit = ds.build_url("admin", "network", "firewall", "zones", "%s")
function s.sectiontitle(self, sid)
local z = fw:get_zone(sid)
return z:name()
end
function s.create(self) function s.create(self)
local z = fw:new_zone() local z = fw:new_zone()
if z then if z then

View file

@ -198,8 +198,18 @@ function fmt_limit(limit, burst)
end end
end end
function fmt_target(x, dest) function fmt_target(x, src, dest)
if dest and #dest > 0 then if not src or #src == 0 then
if x == "ACCEPT" then
return _("Accept output")
elseif x == "REJECT" then
return _("Refuse output")
elseif x == "NOTRACK" then
return _("Do not track output")
else --if x == "DROP" then
return _("Discard output")
end
elseif dest and #dest > 0 then
if x == "ACCEPT" then if x == "ACCEPT" then
return _("Accept forward") return _("Accept forward")
elseif x == "REJECT" then elseif x == "REJECT" then

View file

@ -18,95 +18,91 @@
vals[#vals+1] = '%s (%s)' %{ ip, name } vals[#vals+1] = '%s (%s)' %{ ip, name }
end) end)
-%> -%>
<div class="cbi-section-create cbi-tblsection-create">
<br />
<table class="cbi-section-table" style="width:810px; margin-left:5px">
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell" colspan="8"><%:New port forward%>:</th>
</tr>
<tr class="cbi-section-table-descr">
<th class="cbi-section-table-cell"><%:Name%></th>
<th class="cbi-section-table-cell"><%:Protocol%></th>
<th class="cbi-section-table-cell"><%:External zone%></th>
<th class="cbi-section-table-cell"><%:External port%></th>
<th class="cbi-section-table-cell"><%:Internal zone%></th>
<th class="cbi-section-table-cell"><%:Internal IP address%></th>
<th class="cbi-section-table-cell"><%:Internal port%></th>
<th class="cbi-section-table-cell"></th>
</tr>
<tr class="cbi-section-table-row">
<td class="cbi-section-table-cell">
<input type="text" class="cbi-input-text" id="_newfwd.name" name="_newfwd.name" placeholder="<%:New port forward%>" />
</td>
<td class="cbi-section-table-cell" style="width:110px">
<select class="cbi-input-select" id="_newfwd.proto" name="_newfwd.proto">
<option value="tcp udp">TCP+UDP</option>
<option value="tcp">TCP</option>
<option value="udp">UDP</option>
<option value="other"><%:Other...%></option>
</select>
</td>
<td class="cbi-section-table-cell" style="width:55px">
<select class="cbi-input-select" id="_newfwd.extzone" name="_newfwd.extzone">
<% for _, z in ipairs(ezl) do -%><option value="<%=z:name()%>"><%=z:name()%></option><%- end %>
</select>
</td>
<td class="cbi-section-table-cell" style="width:110px">
<input type="text" class="cbi-input-text" id="_newfwd.extport" name="_newfwd.extport" data-type="portrange" data-optional="true" />
</td>
<td class="cbi-section-table-cell" style="width:55px">
<select class="cbi-input-select" id="_newfwd.intzone" name="_newfwd.intzone">
<% for _, z in ipairs(izl) do -%><option value="<%=z:name()%>"><%=z:name()%></option><%- end %>
</select>
</td>
<td class="cbi-section-table-cell" style="width:110px">
<input type="text" class="cbi-input-text" id="_newfwd.intaddr" name="_newfwd.intaddr" data-type="host" data-optional="true"<%=
ifattr(#keys > 0, "data-choices", {keys, vals})
%>/>
</td>
<td class="cbi-section-table-cell" style="width:110px">
<input type="text" class="cbi-input-text" id="_newfwd.intport" name="_newfwd.intport" data-type="portrange" data-optional="true" />
</td>
<td class="cbi-section-table-cell">
<input type="submit" class="cbi-button cbi-button-add" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" value="<%:Add%>" />
</td>
</tr>
</table>
<script type="text/javascript">//<![CDATA[ <h4><%:New port forward%></h4>
cbi_bind(document.getElementById('_newfwd.extport'), 'blur', <div class="table">
function() { <div class="tr table-titles">
var n = document.getElementById('_newfwd.name'); <div class="th"><%:Name%></div>
var p = document.getElementById('_newfwd.proto'); <div class="th"><%:Protocol%></div>
var i = document.getElementById('_newfwd.intport'); <div class="th"><%:External zone%></div>
var hints = { <div class="th"><%:External port%></div>
/* port name 0=both, 1=tcp, 2=udp, 3=other */ <div class="th"><%:Internal zone%></div>
21: [ 'FTP', 1 ], <div class="th"><%:Internal IP address%></div>
22: [ 'SSH', 1 ], <div class="th"><%:Internal port%></div>
53: [ 'DNS', 0 ], <div class="th"></div>
80: [ 'HTTP', 1 ], </div>
443: [ 'HTTPS', 1 ], <div class="tr">
3389: [ 'RDP', 1 ], <div class="td">
5900: [ 'VNC', 1 ], <input type="text" class="cbi-input-text" id="_newfwd.name" name="_newfwd.name" placeholder="<%:New port forward%>" />
}; </div>
<div class="td">
if (!this.className.match(/invalid/)) <select class="cbi-input-select" id="_newfwd.proto" name="_newfwd.proto">
{ <option value="tcp udp">TCP+UDP</option>
if (!i.value) i.value = this.value; <option value="tcp">TCP</option>
<option value="udp">UDP</option>
var hint = hints[this.value || 0] || hints[i.value || 0]; <option value="other"><%:Other...%></option>
if (hint) </select>
{ </div>
p.selectedIndex = hint[1]; <div class="td">
<select class="cbi-input-select" id="_newfwd.extzone" name="_newfwd.extzone">
if (!n.value) <% for _, z in ipairs(ezl) do -%><option value="<%=z:name()%>"><%=z:name()%></option><%- end %>
n.value = hint[0]; </select>
} </div>
else if (!n.value) <div class="td">
{ <input type="text" class="cbi-input-text" id="_newfwd.extport" name="_newfwd.extport" data-type="portrange" data-optional="true" />
n.value = 'Forward' + this.value; </div>
} <div class="td">
} <select class="cbi-input-select" id="_newfwd.intzone" name="_newfwd.intzone">
}); <% for _, z in ipairs(izl) do -%><option value="<%=z:name()%>"><%=z:name()%></option><%- end %>
//]]></script> </select>
</div>
<div class="td">
<input type="text" class="cbi-input-text" id="_newfwd.intaddr" name="_newfwd.intaddr" data-type="host" data-optional="true"<%=
ifattr(#keys > 0, "data-choices", {keys, vals})
%>/>
</div>
<div class="td">
<input type="text" class="cbi-input-text" id="_newfwd.intport" name="_newfwd.intport" data-type="portrange" data-optional="true" />
</div>
<div class="td bottom">
<input type="submit" class="cbi-button cbi-button-add" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" value="<%:Add%>" />
</div>
</div>
</div> </div>
<script type="text/javascript">//<![CDATA[
cbi_bind(document.getElementById('_newfwd.extport'), 'blur',
function() {
var n = document.getElementById('_newfwd.name');
var p = document.getElementById('_newfwd.proto');
var i = document.getElementById('_newfwd.intport');
var hints = {
/* port name 0=both, 1=tcp, 2=udp, 3=other */
21: [ 'FTP', 1 ],
22: [ 'SSH', 1 ],
53: [ 'DNS', 0 ],
80: [ 'HTTP', 1 ],
443: [ 'HTTPS', 1 ],
3389: [ 'RDP', 1 ],
5900: [ 'VNC', 1 ],
};
if (!this.className.match(/invalid/))
{
if (!i.value) i.value = this.value;
var hint = hints[this.value || 0] || hints[i.value || 0];
if (hint)
{
p.selectedIndex = hint[1];
if (!n.value)
n.value = hint[0];
}
else if (!n.value)
{
n.value = 'Forward' + this.value;
}
}
});
//]]></script>

View file

@ -5,112 +5,105 @@
local zones = fw:get_zones() local zones = fw:get_zones()
%> %>
<div class="cbi-section-create cbi-tblsection-create"> <% if wz then %>
<% if wz then %> <h4><%:Open ports on router%></h4>
<br /> <div class="table">
<table class="cbi-section-table" style="margin-left:5px"> <div class="tr cbi-section-table-titles">
<tr class="cbi-section-table-titles"> <div class="th"><%:Name%></div>
<th class="cbi-section-table-cell left" colspan="4"><%:Open ports on router%>:</th> <div class="th"><%:Protocol%></div>
</tr> <div class="th"><%:External port%></div>
<tr class="cbi-section-table-descr"> <div class="th"></div>
<th class="cbi-section-table-cell"><%:Name%></th> </div>
<th class="cbi-section-table-cell"><%:Protocol%></th> <div class="tr">
<th class="cbi-section-table-cell"><%:External port%></th> <div class="td">
<th class="cbi-section-table-cell"></th> <input type="text" class="cbi-input-text" id="_newopen.name" name="_newopen.name" placeholder="<%:New input rule%>" />
</tr> </div>
<tr class="cbi-section-table-row"> <div class="td">
<td class="cbi-section-table-cell" style="width:130px"> <select class="cbi-input-select" id="_newopen.proto" name="_newopen.proto">
<input type="text" class="cbi-input-text" id="_newopen.name" name="_newopen.name" placeholder="<%:New input rule%>" /> <option value="tcp udp">TCP+UDP</option>
</td> <option value="tcp">TCP</option>
<td class="cbi-section-table-cell" style="width:110px"> <option value="udp">UDP</option>
<select class="cbi-input-select" id="_newopen.proto" name="_newopen.proto"> <option value="other"><%:Other...%></option>
<option value="tcp udp">TCP+UDP</option> </select>
<option value="tcp">TCP</option> </div>
<option value="udp">UDP</option> <div class="td">
<option value="other"><%:Other...%></option> <input type="text" class="cbi-input-text" id="_newopen.extport" name="_newopen.extport" />
</select> </div>
</td> <div class="td bottom">
<td class="cbi-section-table-cell" style="width:110px"> <input type="submit" class="cbi-button cbi-button-add" name="_newopen.submit" value="<%:Add%>" />
<input type="text" class="cbi-input-text" id="_newopen.extport" name="_newopen.extport" /> </div>
</td> </div>
<td class="cbi-section-table-cell left"> </div>
<input type="submit" class="cbi-button cbi-button-add" name="_newopen.submit" value="<%:Add%>" /> <% end %>
</td> <% if #zones > 1 then %>
</tr> <h4><%:New forward rule%></h4>
</table> <div class="table">
<% end %> <div class="tr cbi-section-table-titles">
<% if #zones > 1 then %> <div class="th"><%:Name%></div>
<table class="cbi-section-table" style="margin-left:5px"> <div class="th"><%:Source zone%></div>
<tr class="cbi-section-table-titles"> <div class="th"><%:Destination zone%></div>
<th class="cbi-section-table-cell left" colspan="6"><br /><%:New forward rule%>:</th> <div class="th"></div>
</tr> </div>
<tr class="cbi-section-table-descr"> <div class="tr">
<th class="cbi-section-table-cell"><%:Name%></th> <div class="td">
<th class="cbi-section-table-cell"><%:Source zone%></th> <input type="text" class="cbi-input-text" id="_newfwd.name" name="_newfwd.name" placeholder="<%:New forward rule%>" />
<th class="cbi-section-table-cell"><%:Destination zone%></th> </div>
<th class="cbi-section-table-cell"></th> <div class="td">
</tr> <select class="cbi-input-text" id="_newfwd.src" name="_newfwd.src">
<tr class="cbi-section-table-row"> <% local k, v; for k, v in ipairs(fw:get_zones()) do -%>
<td class="cbi-section-table-cell" style="width:130px"> <option<%=ifattr(v:name() == "wan", "selected", "selected")%> value="<%=v:name()%>"><%=v:name()%></option>
<input type="text" class="cbi-input-text" id="_newfwd.name" name="_newfwd.name" placeholder="<%:New forward rule%>" /> <%- end %>
</td> </select>
<td class="cbi-section-table-cell" style="width:110px"> </div>
<select class="cbi-input-text" id="_newfwd.src" name="_newfwd.src"> <div class="td">
<% local k, v; for k, v in ipairs(fw:get_zones()) do -%> <select class="cbi-input-text" id="_newfwd.dest" name="_newfwd.dest">
<option<%=ifattr(v:name() == "wan", "selected", "selected")%> value="<%=v:name()%>"><%=v:name()%></option> <% local k, v; for k, v in ipairs(fw:get_zones()) do -%>
<%- end %> <option<%=ifattr(v:name() == "lan", "selected", "selected")%> value="<%=v:name()%>"><%=v:name()%></option>
</select> <%- end %>
</td> </select>
<td class="cbi-section-table-cell" style="width:110px"> </div>
<select class="cbi-input-text" id="_newfwd.dest" name="_newfwd.dest"> <div class="td bottom">
<% local k, v; for k, v in ipairs(fw:get_zones()) do -%> <input type="submit" class="cbi-button cbi-button-link" name="_newfwd.submit" value="<%:Add and edit...%>" />
<option<%=ifattr(v:name() == "lan", "selected", "selected")%> value="<%=v:name()%>"><%=v:name()%></option> </div>
<%- end %> </div>
</select> </div>
</td> <% else %>
<td class="cbi-section-table-cell left"> <input type="submit" class="cbi-button cbi-button-add" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" value="<%:Add%>" />
<input type="submit" class="cbi-button cbi-button-link" name="_newfwd.submit" value="<%:Add and edit...%>" /> <% end %>
</td>
</tr>
</table>
<% else %>
<input type="submit" class="cbi-button cbi-button-add" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" value="<%:Add%>" />
<% end %>
<% if wz then %> <% if wz then %>
<script type="text/javascript">//<![CDATA[ <script type="text/javascript">//<![CDATA[
cbi_validate_field('_newopen.extport', true, 'list(neg(portrange))'); cbi_validate_field('_newopen.extport', true, 'list(neg(portrange))');
cbi_bind(document.getElementById('_newopen.extport'), 'blur', cbi_bind(document.getElementById('_newopen.extport'), 'blur',
function() { function() {
var n = document.getElementById('_newopen.name'); var n = document.getElementById('_newopen.name');
var p = document.getElementById('_newopen.proto'); var p = document.getElementById('_newopen.proto');
var hints = { var hints = {
/* port name 0=both, 1=tcp, 2=udp, 3=other */ /* port name 0=both, 1=tcp, 2=udp, 3=other */
22: [ 'SSH', 1 ], 22: [ 'SSH', 1 ],
53: [ 'DNS', 0 ], 53: [ 'DNS', 0 ],
80: [ 'HTTP', 1 ], 80: [ 'HTTP', 1 ],
443: [ 'HTTPS', 1 ], 443: [ 'HTTPS', 1 ],
}; };
if (!this.className.match(/invalid/)) if (!this.className.match(/invalid/))
{
var hint = hints[this.value || 0];
if (hint)
{ {
var hint = hints[this.value || 0]; p.selectedIndex = hint[1];
if (hint)
{
p.selectedIndex = hint[1];
if (!n.value) if (!n.value)
n.value = hint[0]; n.value = hint[0];
}
else if (!n.value && this.value)
{
n.value = 'Open' + this.value;
}
} }
}); else if (!n.value && this.value)
{
n.value = 'Open' + this.value;
}
}
});
cbi_validate_field('cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>', true, 'uciname'); cbi_validate_field('cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>', true, 'uciname');
//]]></script> //]]></script>
<% end %> <% end %>
</div>

View file

@ -12,53 +12,48 @@
end end
%> %>
<div class="cbi-section-create cbi-tblsection-create"> <% if #zones > 1 then %>
<% if #zones > 1 then %> <h4><%:New source NAT%></h4>
<br /> <div class="table">
<table class="cbi-section-table" style="width:700px; margin-left:5px"> <div class="tr cbi-section-table-titles">
<tr class="cbi-section-table-titles"> <div class="th"><%:Name%></div>
<th class="cbi-section-table-cell left" colspan="6"><%:New source NAT%>:</th> <div class="th"><%:Source zone%></div>
</tr> <div class="th"><%:Destination zone%></div>
<tr class="cbi-section-table-descr"> <div class="th"><%:To source IP%></div>
<th class="cbi-section-table-cell"><%:Name%></th> <div class="th"><%:To source port%></div>
<th class="cbi-section-table-cell"><%:Source zone%></th> <div class="th"></div>
<th class="cbi-section-table-cell"><%:Destination zone%></th> </div>
<th class="cbi-section-table-cell"><%:To source IP%></th> <div class="tr">
<th class="cbi-section-table-cell"><%:To source port%></th> <div class="td">
<th class="cbi-section-table-cell"></th> <input type="text" class="cbi-input-text" id="_newsnat.name" name="_newsnat.name" placeholder="<%:New SNAT rule%>" />
</tr> </div>
<tr class="cbi-section-table-row"> <div class="td">
<td class="cbi-section-table-cell"> <select class="cbi-input-text" id="_newsnat.src" name="_newsnat.src">
<input type="text" class="cbi-input-text" id="_newsnat.name" name="_newsnat.name" placeholder="<%:New SNAT rule%>" /> <% local k, v; for k, v in ipairs(fw:get_zones()) do -%>
</td> <option<%=ifattr(v:name() == "lan", "selected", "selected")%> value="<%=v:name()%>"><%=v:name()%></option>
<td class="cbi-section-table-cell" style="width:110px"> <%- end %>
<select class="cbi-input-text" id="_newsnat.src" name="_newsnat.src"> </select>
<% local k, v; for k, v in ipairs(fw:get_zones()) do -%> </div>
<option<%=ifattr(v:name() == "lan", "selected", "selected")%> value="<%=v:name()%>"><%=v:name()%></option> <div class="td">
<%- end %> <select class="cbi-input-text" id="_newsnat.dest" name="_newsnat.dest">
</select> <% local k, v; for k, v in ipairs(fw:get_zones()) do -%>
</td> <option<%=ifattr(v:name() == "wan", "selected", "selected")%> value="<%=v:name()%>"><%=v:name()%></option>
<td class="cbi-section-table-cell" style="width:110px"> <%- end %>
<select class="cbi-input-text" id="_newsnat.dest" name="_newsnat.dest"> </select>
<% local k, v; for k, v in ipairs(fw:get_zones()) do -%> </div>
<option<%=ifattr(v:name() == "wan", "selected", "selected")%> value="<%=v:name()%>"><%=v:name()%></option> <div class="td">
<%- end %> <input type="text" class="cbi-input-text" id="_newsnat.dip" name="_newsnat.dip" placeholder="<%:Do not rewrite%>" data-type="ip4addr" data-optional="true"<%=
</select> ifattr(#keys > 0, "data-choices", { keys, vals })
</td> %> />
<td class="cbi-section-table-cell" style="width:110px"> </div>
<input type="text" class="cbi-input-text" id="_newsnat.dip" name="_newsnat.dip" placeholder="<%:Do not rewrite%>" data-type="ip4addr" data-optional="true"<%= <div class="td">
ifattr(#keys > 0, "data-choices", { keys, vals }) <input type="text" class="cbi-input-text" id="_newsnat.dport" name="_newsnat.dport" placeholder="<%:Do not rewrite%>" data-type="portrange" data-optional="true" />
%> /> </div>
</td> <div class="td bottom">
<td class="cbi-section-table-cell" style="width:110px"> <input type="submit" class="cbi-button cbi-button-link" name="_newsnat.submit" value="<%:Add and edit...%>" />
<input type="text" class="cbi-input-text" id="_newsnat.dport" name="_newsnat.dport" placeholder="<%:Do not rewrite%>" data-type="portrange" data-optional="true" /> </div>
</td> </div>
<td class="cbi-section-table-cell"> </div>
<input type="submit" class="cbi-button cbi-button-link" name="_newsnat.submit" value="<%:Add and edit...%>" /> <% else %>
</td> <input type="submit" class="cbi-button cbi-button-add" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" value="<%:Add%>" />
</tr> <% end %>
</table>
<% else %>
<input type="submit" class="cbi-button cbi-button-add" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>.<%=section%>" value="<%:Add%>" />
<% end %>
</div>

View file

@ -48,6 +48,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "Acció" msgstr "Acció"
@ -106,6 +109,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "No reescriguis" msgstr "No reescriguis"
@ -115,6 +121,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "Descarta els paquets invàlids" msgstr "Descarta els paquets invàlids"
@ -181,6 +190,15 @@ msgstr "Des de %s en %s amb origen %s"
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "Des de %s en %s amb orígens %s i %s" msgstr "Des de %s en %s amb orígens %s i %s"
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "Ajusts generals" msgstr "Ajusts generals"
@ -314,6 +332,9 @@ msgstr "Altre..."
msgid "Output" msgid "Output"
msgstr "Sortida" msgstr "Sortida"
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "Passa paràmetres addicionals al iptables. Utilitzeu-ho amb cura!" msgstr "Passa paràmetres addicionals al iptables. Utilitzeu-ho amb cura!"
@ -531,6 +552,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "" msgstr ""
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "Via %s" msgstr "Via %s"

View file

@ -44,6 +44,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "Akce" msgstr "Akce"
@ -101,6 +104,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "Nepřepisovat" msgstr "Nepřepisovat"
@ -110,6 +116,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "Zahazovat neplatné pakety" msgstr "Zahazovat neplatné pakety"
@ -176,6 +185,15 @@ msgstr "Z %s v %s se zdrojovou %s"
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "Z %s v %s se zdrojovou %s a %s" msgstr "Z %s v %s se zdrojovou %s a %s"
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "Obecné nastavení" msgstr "Obecné nastavení"
@ -309,6 +327,9 @@ msgstr "Ostatní ..."
msgid "Output" msgid "Output"
msgstr "Výstup" msgstr "Výstup"
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "Předává další argumenty iptables. Používat opatrně!" msgstr "Předává další argumenty iptables. Používat opatrně!"
@ -526,6 +547,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "" msgstr ""
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "Prostřednictvím %s" msgstr "Prostřednictvím %s"

View file

@ -46,6 +46,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "Aktion" msgstr "Aktion"
@ -104,6 +107,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "Nicht umschreiben" msgstr "Nicht umschreiben"
@ -113,6 +119,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "Ungültige Pakete verwerfen" msgstr "Ungültige Pakete verwerfen"
@ -179,6 +188,15 @@ msgstr "Von %s in %s mit Quell-%s"
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "Von %s in %s mit Quell-%s und %s" msgstr "Von %s in %s mit Quell-%s und %s"
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "Allgemein" msgstr "Allgemein"
@ -307,6 +325,9 @@ msgstr "Anderes..."
msgid "Output" msgid "Output"
msgstr "Ausgang" msgstr "Ausgang"
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "" msgstr ""
"Gibt zusätzliche Kommandozeilenargumente an iptables weiter. Mit Vorsicht " "Gibt zusätzliche Kommandozeilenargumente an iptables weiter. Mit Vorsicht "
@ -530,6 +551,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "" msgstr ""
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "Über %s" msgstr "Über %s"

View file

@ -46,6 +46,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "Ενέργεια" msgstr "Ενέργεια"
@ -101,6 +104,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "" msgstr ""
@ -110,6 +116,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "Αγνόηση μη-έγκυρων πακετών" msgstr "Αγνόηση μη-έγκυρων πακετών"
@ -177,6 +186,15 @@ msgstr ""
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "" msgstr ""
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "Γενικές Ρυθμίσεις" msgstr "Γενικές Ρυθμίσεις"
@ -306,6 +324,9 @@ msgstr "Άλλο..."
msgid "Output" msgid "Output"
msgstr "Έξοδος" msgstr "Έξοδος"
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "" msgstr ""
@ -498,6 +519,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "" msgstr ""
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "" msgstr ""

View file

@ -44,6 +44,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "Action" msgstr "Action"
@ -98,6 +101,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "" msgstr ""
@ -107,6 +113,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "Drop invalid packets" msgstr "Drop invalid packets"
@ -177,6 +186,15 @@ msgstr ""
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "" msgstr ""
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "" msgstr ""
@ -305,6 +323,9 @@ msgstr ""
msgid "Output" msgid "Output"
msgstr "Output" msgstr "Output"
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "" msgstr ""
@ -525,6 +546,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "" msgstr ""
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "" msgstr ""

View file

@ -47,6 +47,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "Acción" msgstr "Acción"
@ -105,6 +108,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "No reescribir" msgstr "No reescribir"
@ -114,6 +120,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "Descartar paquetes no válidos" msgstr "Descartar paquetes no válidos"
@ -180,6 +189,15 @@ msgstr "Desde %s en %s con origen %s"
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "Desde %s en %s con origen %s y %s" msgstr "Desde %s en %s con origen %s y %s"
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "Configuración general" msgstr "Configuración general"
@ -312,6 +330,9 @@ msgstr "Otros..."
msgid "Output" msgid "Output"
msgstr "Salida" msgstr "Salida"
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "Pasa más parámetros a IPTables. ¡Usar con cuidado!" msgstr "Pasa más parámetros a IPTables. ¡Usar con cuidado!"
@ -529,6 +550,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "" msgstr ""
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "Vía %s" msgstr "Vía %s"

View file

@ -46,6 +46,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "Action" msgstr "Action"
@ -100,6 +103,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "" msgstr ""
@ -109,6 +115,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "Supprimer les paquets invalides" msgstr "Supprimer les paquets invalides"
@ -179,6 +188,15 @@ msgstr ""
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "" msgstr ""
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "Paramètres généraux" msgstr "Paramètres généraux"
@ -307,6 +325,9 @@ msgstr "Autre..."
msgid "Output" msgid "Output"
msgstr "Sortie" msgstr "Sortie"
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "" msgstr ""
@ -551,6 +572,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "" msgstr ""
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "" msgstr ""

View file

@ -41,6 +41,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "" msgstr ""
@ -95,6 +98,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "" msgstr ""
@ -104,6 +110,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "" msgstr ""
@ -170,6 +179,15 @@ msgstr ""
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "" msgstr ""
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "" msgstr ""
@ -296,6 +314,9 @@ msgstr ""
msgid "Output" msgid "Output"
msgstr "" msgstr ""
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "" msgstr ""
@ -483,6 +504,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "" msgstr ""
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "" msgstr ""

View file

@ -44,6 +44,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "Művelet" msgstr "Művelet"
@ -102,6 +105,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "Ne írja felül" msgstr "Ne írja felül"
@ -111,6 +117,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "Érvénytelen csomagok eldobása" msgstr "Érvénytelen csomagok eldobása"
@ -177,6 +186,15 @@ msgstr "%s felől %s-ben %s forrással"
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "%s felől %s-ben %s és %s forrással" msgstr "%s felől %s-ben %s és %s forrással"
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "Általános beállítások" msgstr "Általános beállítások"
@ -313,6 +331,9 @@ msgstr "Egyéb..."
msgid "Output" msgid "Output"
msgstr "Kimenet" msgstr "Kimenet"
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "" msgstr ""
"További argumentumok küldése az iptables részére. Használja körültekintően!" "További argumentumok küldése az iptables részére. Használja körültekintően!"
@ -533,6 +554,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "" msgstr ""
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "%s-en át" msgstr "%s-en át"

View file

@ -46,6 +46,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "Azione" msgstr "Azione"
@ -104,6 +107,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "Non riscrivere" msgstr "Non riscrivere"
@ -113,6 +119,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "Scarta pacchetti invalidi" msgstr "Scarta pacchetti invalidi"
@ -179,6 +188,15 @@ msgstr "Da %s a %s con sorgente %s"
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "Da %s a %s con sorgente %s e %s" msgstr "Da %s a %s con sorgente %s e %s"
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "Opzioni Generali" msgstr "Opzioni Generali"
@ -311,6 +329,9 @@ msgstr "Altri..."
msgid "Output" msgid "Output"
msgstr "" msgstr ""
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "Passa comandi addizionali a iptables. Usare con cura!" msgstr "Passa comandi addizionali a iptables. Usare con cura!"
@ -549,6 +570,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "Martedì" msgstr "Martedì"
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "" msgstr ""

View file

@ -47,6 +47,9 @@ msgstr "転送を許可"
msgid "Accept input" msgid "Accept input"
msgstr "入力を許可" msgstr "入力を許可"
msgid "Accept output"
msgstr "出力を許可"
msgid "Action" msgid "Action"
msgstr "動作" msgstr "動作"
@ -105,6 +108,9 @@ msgstr "転送を破棄"
msgid "Discard input" msgid "Discard input"
msgstr "入力を破棄" msgstr "入力を破棄"
msgid "Discard output"
msgstr "出力を破棄"
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "リライトしない" msgstr "リライトしない"
@ -114,6 +120,9 @@ msgstr "転送を追跡しない"
msgid "Do not track input" msgid "Do not track input"
msgstr "入力を追跡しない" msgstr "入力を追跡しない"
msgid "Do not track output"
msgstr "出力を追跡しない"
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "無効なパケットを遮断する" msgstr "無効なパケットを遮断する"
@ -175,10 +184,19 @@ msgid "From %s in %s"
msgstr "送信元 %s (%s)" msgstr "送信元 %s (%s)"
msgid "From %s in %s with source %s" msgid "From %s in %s with source %s"
msgstr "送信元 %s (%s) , 送信元 %s" msgstr "送信元 %s (%s) , %s"
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "送信元 %s (%s) , 送信元 %s, 送信元 %s" msgstr "送信元 %s (%s) , %s, %s"
msgid "From %s on <var>this device</var>"
msgstr "送信元 %s (<var>デバイス</var>)"
msgid "From %s on <var>this device</var> with source %s"
msgstr "送信元 %s, %s (<var>デバイス</var>)"
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr "送信元 %s, %s, %s (<var>デバイス</var>)"
msgid "General Settings" msgid "General Settings"
msgstr "一般設定" msgstr "一般設定"
@ -316,6 +334,9 @@ msgstr "その他のプロトコル"
msgid "Output" msgid "Output"
msgstr "送信" msgstr "送信"
msgid "Output zone"
msgstr "出力ゾーン"
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "" msgstr ""
"iptablesにパススルーする追加の引数を設定してください。ただし、注意して設定し" "iptablesにパススルーする追加の引数を設定してください。ただし、注意して設定し"
@ -566,6 +587,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "火曜日" msgstr "火曜日"
msgid "Unnamed SNAT"
msgstr "名称未設定の SNAT"
msgid "Unnamed forward"
msgstr "名称未設定の転送"
msgid "Unnamed rule"
msgstr "名称未設定のルール"
msgid "Via %s" msgid "Via %s"
msgstr "経由 %s" msgstr "経由 %s"

View file

@ -46,6 +46,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "" msgstr ""
@ -103,6 +106,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "" msgstr ""
@ -112,6 +118,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "" msgstr ""
@ -178,6 +187,15 @@ msgstr ""
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "" msgstr ""
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "" msgstr ""
@ -304,6 +322,9 @@ msgstr ""
msgid "Output" msgid "Output"
msgstr "" msgstr ""
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "iptables 명령에 추가 인자들을 더합니다. 조심해 사용하세요!" msgstr "iptables 명령에 추가 인자들을 더합니다. 조심해 사용하세요!"
@ -517,6 +538,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "화요일" msgstr "화요일"
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "" msgstr ""

View file

@ -40,6 +40,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "" msgstr ""
@ -94,6 +97,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "" msgstr ""
@ -103,6 +109,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "" msgstr ""
@ -169,6 +178,15 @@ msgstr ""
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "" msgstr ""
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "" msgstr ""
@ -295,6 +313,9 @@ msgstr ""
msgid "Output" msgid "Output"
msgstr "" msgstr ""
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "" msgstr ""
@ -482,6 +503,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "" msgstr ""
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "" msgstr ""

View file

@ -41,6 +41,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "Handling" msgstr "Handling"
@ -98,6 +101,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "Ikke omskriv" msgstr "Ikke omskriv"
@ -107,6 +113,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "Forkast ugyldige pakker" msgstr "Forkast ugyldige pakker"
@ -174,6 +183,15 @@ msgstr "Fra %s i %s med kilde %s"
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "Fra %s i %s med kilde %s og %s" msgstr "Fra %s i %s med kilde %s og %s"
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "Generelle Innstillinger" msgstr "Generelle Innstillinger"
@ -308,6 +326,9 @@ msgstr "Andre..."
msgid "Output" msgid "Output"
msgstr "Utdata" msgstr "Utdata"
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "Sender flere argumenter til iptables. Bruk med forsiktighet!" msgstr "Sender flere argumenter til iptables. Bruk med forsiktighet!"
@ -527,6 +548,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "" msgstr ""
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "Via %s" msgstr "Via %s"

View file

@ -48,6 +48,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "Działanie" msgstr "Działanie"
@ -105,6 +108,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "Nie przepisuj" msgstr "Nie przepisuj"
@ -114,6 +120,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "Porzuć wadliwe pakiety" msgstr "Porzuć wadliwe pakiety"
@ -183,6 +192,15 @@ msgstr "Z %s w %s ze źródłem %s"
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "Z %s w %s ze źródłem %s i %s" msgstr "Z %s w %s ze źródłem %s i %s"
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "Ustawienia ogólne" msgstr "Ustawienia ogólne"
@ -316,6 +334,9 @@ msgstr "Inne..."
msgid "Output" msgid "Output"
msgstr "Wyjście (Output)" msgstr "Wyjście (Output)"
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "" msgstr ""
"Przekazuje dodatkowe argumenty do iptables. Zachowaj szczególną ostrożność!" "Przekazuje dodatkowe argumenty do iptables. Zachowaj szczególną ostrożność!"
@ -540,6 +561,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "" msgstr ""
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "Przez %s" msgstr "Przez %s"

View file

@ -46,6 +46,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "Ação" msgstr "Ação"
@ -103,6 +106,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "Não sobrescreva" msgstr "Não sobrescreva"
@ -112,6 +118,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "Descartar pacotes inválidos" msgstr "Descartar pacotes inválidos"
@ -178,6 +187,15 @@ msgstr "Vindo de %s em %s com origem %s"
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "Vindo de %s em %s com origem %s e %s" msgstr "Vindo de %s em %s com origem %s e %s"
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "Configurações Gerais" msgstr "Configurações Gerais"
@ -313,6 +331,9 @@ msgstr "Outro..."
msgid "Output" msgid "Output"
msgstr "Saída" msgstr "Saída"
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "Passa argumentos adicionais para o iptables. Use com cuidado!" msgstr "Passa argumentos adicionais para o iptables. Use com cuidado!"
@ -530,6 +551,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "Terça-feira" msgstr "Terça-feira"
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "Via %s" msgstr "Via %s"

View file

@ -46,6 +46,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "Acção" msgstr "Acção"
@ -104,6 +107,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "Não re-escrever" msgstr "Não re-escrever"
@ -113,6 +119,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "Cancelar pacotes inválidos" msgstr "Cancelar pacotes inválidos"
@ -179,6 +188,15 @@ msgstr "De %s em %s com origem %s"
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "De %s em %s com origem %s e %s" msgstr "De %s em %s com origem %s e %s"
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "Definições Gerais" msgstr "Definições Gerais"
@ -314,6 +332,9 @@ msgstr "Outro..."
msgid "Output" msgid "Output"
msgstr "Saída" msgstr "Saída"
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "Passa argumentos adicionais para o iptables. Usar com cuidado!" msgstr "Passa argumentos adicionais para o iptables. Usar com cuidado!"
@ -515,6 +536,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "" msgstr ""
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "Via %s" msgstr "Via %s"

View file

@ -45,6 +45,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "Acţiune" msgstr "Acţiune"
@ -99,6 +102,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "Nu rescrie" msgstr "Nu rescrie"
@ -108,6 +114,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "Descarcă pachetele invalide" msgstr "Descarcă pachetele invalide"
@ -174,6 +183,15 @@ msgstr ""
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "" msgstr ""
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "Setari generale" msgstr "Setari generale"
@ -300,6 +318,9 @@ msgstr "Altele..."
msgid "Output" msgid "Output"
msgstr "Ieşire" msgstr "Ieşire"
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "" msgstr ""
@ -487,6 +508,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "" msgstr ""
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "" msgstr ""

View file

@ -48,6 +48,9 @@ msgstr "Принять перенаправление"
msgid "Accept input" msgid "Accept input"
msgstr "Принять входящий трафик" msgstr "Принять входящий трафик"
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "Действие" msgstr "Действие"
@ -106,6 +109,9 @@ msgstr "Отключить перенаправление"
msgid "Discard input" msgid "Discard input"
msgstr "Отключить входящий трафик" msgstr "Отключить входящий трафик"
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "Не перезаписывать" msgstr "Не перезаписывать"
@ -115,6 +121,9 @@ msgstr "Не отслеживать перенаправление"
msgid "Do not track input" msgid "Do not track input"
msgstr "Не отслеживать входящий трафик" msgstr "Не отслеживать входящий трафик"
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "Не пропускать<br />некорректные пакеты" msgstr "Не пропускать<br />некорректные пакеты"
@ -181,6 +190,15 @@ msgstr "Из %s в %s с источником %s"
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "Из %s в %s с источниками %s и %s" msgstr "Из %s в %s с источниками %s и %s"
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "Основные настройки" msgstr "Основные настройки"
@ -318,6 +336,9 @@ msgstr "Другое..."
msgid "Output" msgid "Output"
msgstr "Исходящий трафик" msgstr "Исходящий трафик"
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "" msgstr ""
"Передаёт дополнительные аргументы таблице iptables. Используйте с " "Передаёт дополнительные аргументы таблице iptables. Используйте с "
@ -537,6 +558,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "Вторник" msgstr "Вторник"
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "Через %s" msgstr "Через %s"

View file

@ -41,6 +41,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "" msgstr ""
@ -95,6 +98,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "" msgstr ""
@ -104,6 +110,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "" msgstr ""
@ -170,6 +179,15 @@ msgstr ""
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "" msgstr ""
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "" msgstr ""
@ -296,6 +314,9 @@ msgstr ""
msgid "Output" msgid "Output"
msgstr "" msgstr ""
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "" msgstr ""
@ -483,6 +504,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "" msgstr ""
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "" msgstr ""

View file

@ -42,6 +42,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "Åtgärd" msgstr "Åtgärd"
@ -96,6 +99,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "Skriv inte om igen" msgstr "Skriv inte om igen"
@ -105,6 +111,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "Släpp ogiltiga paket" msgstr "Släpp ogiltiga paket"
@ -171,6 +180,15 @@ msgstr "Från %s i %s med källa %s"
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "Från %s i %s med källa %s och %s" msgstr "Från %s i %s med källa %s och %s"
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "Generella inställningar" msgstr "Generella inställningar"
@ -302,6 +320,9 @@ msgstr "Andra..."
msgid "Output" msgid "Output"
msgstr "Utmatning" msgstr "Utmatning"
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "" msgstr ""
@ -489,6 +510,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "Tisdag" msgstr "Tisdag"
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "Via %s" msgstr "Via %s"

View file

@ -34,6 +34,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "" msgstr ""
@ -88,6 +91,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "" msgstr ""
@ -97,6 +103,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "" msgstr ""
@ -163,6 +172,15 @@ msgstr ""
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "" msgstr ""
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "" msgstr ""
@ -289,6 +307,9 @@ msgstr ""
msgid "Output" msgid "Output"
msgstr "" msgstr ""
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "" msgstr ""
@ -476,6 +497,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "" msgstr ""
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "" msgstr ""

View file

@ -41,6 +41,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "" msgstr ""
@ -95,6 +98,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "" msgstr ""
@ -104,6 +110,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "" msgstr ""
@ -170,6 +179,15 @@ msgstr ""
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "" msgstr ""
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "" msgstr ""
@ -296,6 +314,9 @@ msgstr ""
msgid "Output" msgid "Output"
msgstr "" msgstr ""
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "" msgstr ""
@ -483,6 +504,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "" msgstr ""
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "" msgstr ""

View file

@ -1,7 +1,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"PO-Revision-Date: 2012-12-29 12:53+0200\n" "PO-Revision-Date: 2018-07-01 23:45+0300\n"
"Last-Translator: Yurii <yuripet@gmail.com>\n" "Last-Translator: Yurii <yuripet@gmail.com>\n"
"Language-Team: none\n" "Language-Team: none\n"
"Language: uk\n" "Language: uk\n"
@ -10,7 +10,6 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" "10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Generator: Pootle 2.0.6\n"
msgid "%s in %s" msgid "%s in %s"
msgstr "%s у %s" msgstr "%s у %s"
@ -22,13 +21,13 @@ msgid "%s, %s in %s"
msgstr "%s, %s у %s" msgstr "%s, %s у %s"
msgid "(Unnamed Entry)" msgid "(Unnamed Entry)"
msgstr "(Запис без імені)" msgstr "(Запис без назви)"
msgid "(Unnamed Rule)" msgid "(Unnamed Rule)"
msgstr "(Правило без імені)" msgstr "(Правило без назви)"
msgid "(Unnamed SNAT)" msgid "(Unnamed SNAT)"
msgstr "(SNAT без імені)" msgstr "(SNAT без назви)"
msgid "<var>%d</var> pkts. per <var>%s</var>" msgid "<var>%d</var> pkts. per <var>%s</var>"
msgstr "<var>%d</var> пакетів за <var>%s</var>" msgstr "<var>%d</var> пакетів за <var>%s</var>"
@ -40,10 +39,13 @@ msgid "<var>%s</var> and limit to %s"
msgstr "<var>%s</var> з лімітом %s" msgstr "<var>%s</var> з лімітом %s"
msgid "Accept forward" msgid "Accept forward"
msgstr "" msgstr "Приймати переспрямовування"
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr "Приймати вхідний"
msgid "Accept output"
msgstr "Приймати вихідний"
msgid "Action" msgid "Action"
msgstr "Дія" msgstr "Дія"
@ -58,10 +60,10 @@ msgid "Advanced Settings"
msgstr "Розширені настройки" msgstr "Розширені настройки"
msgid "Allow forward from <em>source zones</em>:" msgid "Allow forward from <em>source zones</em>:"
msgstr "Дозволити спрямовування від <em>зон-джерел</em>:" msgstr "Дозволити переспрямовування від <em>зон джерела</em>:"
msgid "Allow forward to <em>destination zones</em>:" msgid "Allow forward to <em>destination zones</em>:"
msgstr "Дозволити спрямовування до <em>зон призначення</em>:" msgstr "Дозволити переспрямовування до <em>зон призначення</em>:"
msgid "Any" msgid "Any"
msgstr "Будь-який" msgstr "Будь-який"
@ -95,22 +97,28 @@ msgid "Destination zone"
msgstr "Зона призначення" msgstr "Зона призначення"
msgid "Disable" msgid "Disable"
msgstr "" msgstr "Вимкнути"
msgid "Discard forward" msgid "Discard forward"
msgstr "" msgstr "Відкидати переспрямовування"
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr "Відкидати вхідний"
msgid "Discard output"
msgstr "Відкидати вихідний"
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "Не перезаписувати" msgstr "Не перезаписувати"
msgid "Do not track forward" msgid "Do not track forward"
msgstr "" msgstr "Не відслідковувати переспрямовування"
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr "Не відслідковувати вхідний"
msgid "Do not track output"
msgstr "Не відслідковувати вихідний"
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "Відкидати помилкові пакети" msgstr "Відкидати помилкові пакети"
@ -149,7 +157,7 @@ msgid "Firewall - Custom Rules"
msgstr "Брандмауер — Настроювані правила" msgstr "Брандмауер — Настроювані правила"
msgid "Firewall - Port Forwards" msgid "Firewall - Port Forwards"
msgstr "Брандмауер — Спрямовування портів" msgstr "Брандмауер — Переспрямовування портів"
msgid "Firewall - Traffic Rules" msgid "Firewall - Traffic Rules"
msgstr "Брандмауер — Правила трафіка" msgstr "Брандмауер — Правила трафіка"
@ -161,22 +169,31 @@ msgid "Force connection tracking"
msgstr "Увімкнути відстеження з'єднань" msgstr "Увімкнути відстеження з'єднань"
msgid "Forward" msgid "Forward"
msgstr "Спрямовування" msgstr "Переспрямовування"
msgid "Forward to" msgid "Forward to"
msgstr "спрямовування до" msgstr "переспрямовування до"
msgid "Friday" msgid "Friday"
msgstr "" msgstr "П'ятниця"
msgid "From %s in %s" msgid "From %s in %s"
msgstr "%s у %s" msgstr "%s у %s"
msgid "From %s in %s with source %s" msgid "From %s in %s with source %s"
msgstr "%s у %s з вихідним %s" msgstr "%s у %s з джерелом %s"
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "%s у %s з вихідним %s та %s" msgstr "%s у %s з джерелом %s та %s"
msgid "From %s on <var>this device</var>"
msgstr "Від %s на <var>цьому пристрої</var>"
msgid "From %s on <var>this device</var> with source %s"
msgstr "Від %s на <var>цьому пристрої</var> з джерелом %s"
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr "Від %s на <var>цьому пристрої</var> з джерелом %s та %s"
msgid "General Settings" msgid "General Settings"
msgstr "Загальні настройки" msgstr "Загальні настройки"
@ -185,13 +202,13 @@ msgid "Hardware flow offloading"
msgstr "" msgstr ""
msgid "IP" msgid "IP"
msgstr "" msgstr "IP-адреса"
msgid "IP range" msgid "IP range"
msgstr "" msgstr "Діапазон IP"
msgid "IPs" msgid "IPs"
msgstr "" msgstr "IP-адреси"
msgid "IPv4" msgid "IPv4"
msgstr "IPv4" msgstr "IPv4"
@ -212,7 +229,7 @@ msgid "Input"
msgstr "Вхідний" msgstr "Вхідний"
msgid "Inter-Zone Forwarding" msgid "Inter-Zone Forwarding"
msgstr "Спрямовування крізь зони" msgstr "Переспрямовування між зонами"
msgid "Internal IP address" msgid "Internal IP address"
msgstr "Внутрішня IP-адреса" msgstr "Внутрішня IP-адреса"
@ -227,10 +244,10 @@ msgid "Limit log messages"
msgstr "Обмеження повідомлень журналу" msgstr "Обмеження повідомлень журналу"
msgid "MAC" msgid "MAC"
msgstr "" msgstr "MAC-адреса"
msgid "MACs" msgid "MACs"
msgstr "" msgstr "MAC-адреси"
msgid "MSS clamping" msgid "MSS clamping"
msgstr "Затискання MSS" msgstr "Затискання MSS"
@ -246,8 +263,8 @@ msgstr "Зіставляти ICMP типу"
msgid "Match forwarded traffic to the given destination port or port range." msgid "Match forwarded traffic to the given destination port or port range."
msgstr "" msgstr ""
"Зіставляти трафік, що спрямовується на заданий порт призначення або діапазон " "Зіставляти трафік, що переспрямовується на заданий порт призначення або "
"портів." "діапазон портів."
msgid "" msgid ""
"Match incoming traffic directed at the given destination port or port range " "Match incoming traffic directed at the given destination port or port range "
@ -264,10 +281,10 @@ msgstr ""
"діапазоні портів вузла клієнта." "діапазоні портів вузла клієнта."
msgid "Monday" msgid "Monday"
msgstr "" msgstr "Понеділок"
msgid "Month Days" msgid "Month Days"
msgstr "" msgstr "Дні місяця"
msgid "Name" msgid "Name"
msgstr "Ім'я" msgstr "Ім'я"
@ -276,13 +293,13 @@ msgid "New SNAT rule"
msgstr "Нове правило SNAT" msgstr "Нове правило SNAT"
msgid "New forward rule" msgid "New forward rule"
msgstr "Нове правило спрямовування" msgstr "Нове правило переспрямовування"
msgid "New input rule" msgid "New input rule"
msgstr "Нове вхідне правило" msgstr "Нове вхідне правило"
msgid "New port forward" msgid "New port forward"
msgstr "Нове спрямовування порту" msgstr "Нове переспрямовування порту"
msgid "New source NAT" msgid "New source NAT"
msgstr "Новий NAT джерела" msgstr "Новий NAT джерела"
@ -312,18 +329,21 @@ msgstr "Інше..."
msgid "Output" msgid "Output"
msgstr "Вихідний" msgstr "Вихідний"
msgid "Output zone"
msgstr "Вихідна зона"
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "" msgstr ""
"Передача додаткових аргументів для IPTables. Використовуйте з обережністю!" "Передача додаткових аргументів для IPTables. Використовуйте з обережністю!"
msgid "Port Forwards" msgid "Port Forwards"
msgstr "Спрямовування портів" msgstr "Переспрямовування портів"
msgid "" msgid ""
"Port forwarding allows remote computers on the Internet to connect to a " "Port forwarding allows remote computers on the Internet to connect to a "
"specific computer or service within the private LAN." "specific computer or service within the private LAN."
msgstr "" msgstr ""
"Спрямовування портів дозволяє віддаленим комп'ютерам з Інтернету " "Переспрямовування портів дозволяє віддаленим комп'ютерам з Інтернету "
"підключатися до певного комп'ютера або служби у приватній мережі." "підключатися до певного комп'ютера або служби у приватній мережі."
msgid "Protocol" msgid "Protocol"
@ -338,22 +358,28 @@ msgid "Redirect matched incoming traffic to the specified internal host"
msgstr "Переспрямувати відповідний вхідний трафік на заданий внутрішній вузол" msgstr "Переспрямувати відповідний вхідний трафік на заданий внутрішній вузол"
msgid "Refuse forward" msgid "Refuse forward"
msgstr "" msgstr "Відхиляти переспрямовування"
msgid "Refuse input" msgid "Refuse input"
msgstr "" msgstr "Відхиляти вхідний"
msgid "Refuse output"
msgstr "Відхиляти вихідний"
msgid "Requires hardware NAT support. Implemented at least for mt7621"
msgstr "Необхідна апаратна підтримка NAT. Впроваджено принаймні для mt7621"
msgid "Requires hardware NAT support. Implemented at least for mt7621" msgid "Requires hardware NAT support. Implemented at least for mt7621"
msgstr "" msgstr ""
msgid "Restart Firewall" msgid "Restart Firewall"
msgstr "" msgstr "Перезавантажити брандмауер"
msgid "Restrict Masquerading to given destination subnets" msgid "Restrict Masquerading to given destination subnets"
msgstr "Обмежити підміну заданими підмережами призначення" msgstr "Обмежити підміну заданими підмережами призначення"
msgid "Restrict Masquerading to given source subnets" msgid "Restrict Masquerading to given source subnets"
msgstr "Обмежити підміну заданими вихідними підмережами" msgstr "Обмежити підміну заданими підмережами джерела"
msgid "Restrict to address family" msgid "Restrict to address family"
msgstr "Обмежити сімейство протоколів" msgstr "Обмежити сімейство протоколів"
@ -369,19 +395,22 @@ msgstr ""
"порожнім, щоб переписувати тільки IP-адресу." "порожнім, щоб переписувати тільки IP-адресу."
msgid "Rewrite to source %s" msgid "Rewrite to source %s"
msgstr "перезапис на вихідний %s" msgstr "перезапис на джерело %s"
msgid "Rewrite to source %s, %s" msgid "Rewrite to source %s, %s"
msgstr "перезапис на вихідний %s, %s" msgstr "перезапис на джерело %s, %s"
msgid "Routing/NAT Offloading"
msgstr "Розвантаження маршрутизації/NAT"
msgid "Routing/NAT Offloading" msgid "Routing/NAT Offloading"
msgstr "" msgstr ""
msgid "Rule is disabled" msgid "Rule is disabled"
msgstr "" msgstr "Правило вимкнено"
msgid "Rule is enabled" msgid "Rule is enabled"
msgstr "" msgstr "Правило ввімкнено"
msgid "SNAT IP address" msgid "SNAT IP address"
msgstr "IP-адреса SNAT" msgstr "IP-адреса SNAT"
@ -390,7 +419,13 @@ msgid "SNAT port"
msgstr "Порт SNAT" msgstr "Порт SNAT"
msgid "Saturday" msgid "Saturday"
msgstr "" msgstr "Субота"
msgid "Software based offloading for routing/NAT"
msgstr "Програмне розвантаження для маршрутизації/NAT"
msgid "Software flow offloading"
msgstr "Програмне розвантаження потоку"
msgid "Software based offloading for routing/NAT" msgid "Software based offloading for routing/NAT"
msgstr "" msgstr ""
@ -423,22 +458,22 @@ msgid "Source port"
msgstr "Порт джерела" msgstr "Порт джерела"
msgid "Source zone" msgid "Source zone"
msgstr "Зона-джерело" msgstr "Зона джерела"
msgid "Start Date (yyyy-mm-dd)" msgid "Start Date (yyyy-mm-dd)"
msgstr "" msgstr "Дата початку (рррр-мм-дд)"
msgid "Start Time (hh:mm:ss)" msgid "Start Time (hh:mm:ss)"
msgstr "" msgstr "Час початку (гг:хх:сс)"
msgid "Stop Date (yyyy-mm-dd)" msgid "Stop Date (yyyy-mm-dd)"
msgstr "" msgstr "Дата зупинки (рррр-мм-дд)"
msgid "Stop Time (hh:mm:ss)" msgid "Stop Time (hh:mm:ss)"
msgstr "" msgstr "Час зупинки (гг:хх:сс)"
msgid "Sunday" msgid "Sunday"
msgstr "" msgstr "Неділя"
msgid "" msgid ""
"The firewall creates zones over your network interfaces to control network " "The firewall creates zones over your network interfaces to control network "
@ -455,19 +490,21 @@ msgid ""
"rule is <em>unidirectional</em>, e.g. a forward from lan to wan does " "rule is <em>unidirectional</em>, e.g. a forward from lan to wan does "
"<em>not</em> imply a permission to forward from wan to lan as well." "<em>not</em> imply a permission to forward from wan to lan as well."
msgstr "" msgstr ""
"Опції, наведені нижче, управляють політиками спрямовування між цією (%s) та " "Опції, наведені нижче, керують політиками переспрямовування між цією (%s) та "
"іншими зонами. <em>Зони призначення</em> покриваються трафіком, що " "іншими зонами. <em>Зони призначення</em> покриваються переспрямованим "
"<strong>виходить з %q</strong>. <em>Зони-джерела</em> покриваються трафіком " "трафіком, що <strong>виходить з %q</strong>. <em>Зони джерела</em> "
"з інших зон, <strong>спрямованим на %q</strong>. Правила спрямування є " "покриваються трафіком з інших зон, <strong>переспрямованим на %q</strong>. "
"<em>односпрямованим</em>, тобто, спрямування від LAN до WAN <em>не</em> " "Правило переспрямовування є <em>односпрямованим</em>, тобто, спрямовування "
"означає, що є також дозвіл спрямовувати від WAN в LAN." "від LAN до WAN <em>не</em> означає, що є також дозвіл спрямовувати від WAN "
"до LAN."
msgid "" msgid ""
"This page allows you to change advanced properties of the port forwarding " "This page allows you to change advanced properties of the port forwarding "
"entry. In most cases there is no need to modify those settings." "entry. In most cases there is no need to modify those settings."
msgstr "" msgstr ""
"На цій сторінці можна змінити додаткові властивості елемента спрямовування " "На цій сторінці можна змінити додаткові властивості елемента "
"портів. У більшості випадків змінювати ці параметри немає необхідності." "переспрямовування портів. У більшості випадків змінювати ці параметри немає "
"потреби."
msgid "" msgid ""
"This page allows you to change advanced properties of the traffic rule " "This page allows you to change advanced properties of the traffic rule "
@ -476,7 +513,6 @@ msgstr ""
"На цій сторінці можна змінити додаткові властивості елемента правил трафіка, " "На цій сторінці можна змінити додаткові властивості елемента правил трафіка, "
"таких як відповідні параметри джерела та вузлів призначення." "таких як відповідні параметри джерела та вузлів призначення."
#, fuzzy
msgid "" msgid ""
"This section defines common properties of %q. The <em>input</em> and " "This section defines common properties of %q. The <em>input</em> and "
"<em>output</em> options set the default policies for traffic entering and " "<em>output</em> options set the default policies for traffic entering and "
@ -486,15 +522,15 @@ msgid ""
msgstr "" msgstr ""
"Цей розділ визначає загальні властивості %q. Параметри <em>вхідний</em> і " "Цей розділ визначає загальні властивості %q. Параметри <em>вхідний</em> і "
"<em>вихідний</em> задають типову політику для трафіку на вході й виході з " "<em>вихідний</em> задають типову політику для трафіку на вході й виході з "
"цієї зони, а параметр \"спрямовування\" описує політику спрямовування " "цієї зони, а параметр \"переспрямовування\" описує політику спрямовування "
"трафіку між різними мережами в межах зони. Пункт <em>вкриті мережі</em> " "трафіку між різними мережами в межах зони. Пункт <em>Покриті мережі</em> "
"визначає, які доступні мережі є членами цієї зони." "визначає, які доступні мережі є членами цієї зони."
msgid "Thursday" msgid "Thursday"
msgstr "" msgstr "Четвер"
msgid "Time in UTC" msgid "Time in UTC"
msgstr "" msgstr "Час в UTC"
msgid "To %s at %s on <var>this device</var>" msgid "To %s at %s on <var>this device</var>"
msgstr "%s на %s <var>цього пристрою</var>" msgstr "%s на %s <var>цього пристрою</var>"
@ -527,7 +563,16 @@ msgstr ""
"порти WAN на маршрутизаторі." "порти WAN на маршрутизаторі."
msgid "Tuesday" msgid "Tuesday"
msgstr "" msgstr "Вівторок"
msgid "Unnamed SNAT"
msgstr "SNAT без назви"
msgid "Unnamed forward"
msgstr "Переспрямовування без назви"
msgid "Unnamed rule"
msgstr "Правило без назви"
msgid "Via %s" msgid "Via %s"
msgstr "Через %s" msgstr "Через %s"
@ -536,10 +581,10 @@ msgid "Via %s at %s"
msgstr "Через %s на %s" msgstr "Через %s на %s"
msgid "Wednesday" msgid "Wednesday"
msgstr "" msgstr "Середа"
msgid "Week Days" msgid "Week Days"
msgstr "" msgstr "Дні тижня"
msgid "" msgid ""
"You may specify multiple by selecting \"-- custom --\" and then entering " "You may specify multiple by selecting \"-- custom --\" and then entering "
@ -552,7 +597,7 @@ msgid "Zone %q"
msgstr "Зона %q" msgstr "Зона %q"
msgid "Zone ⇒ Forwardings" msgid "Zone ⇒ Forwardings"
msgstr "Зона ⇒ Спрямовування" msgstr "Зона ⇒ Переспрямовування"
msgid "Zones" msgid "Zones"
msgstr "Зони" msgstr "Зони"
@ -573,7 +618,7 @@ msgid "any zone"
msgstr "будь-якій зоні" msgstr "будь-якій зоні"
msgid "day" msgid "day"
msgstr "" msgstr "день"
msgid "don't track" msgid "don't track"
msgstr "не відстеж." msgstr "не відстеж."
@ -582,31 +627,31 @@ msgid "drop"
msgstr "опускати" msgstr "опускати"
msgid "hour" msgid "hour"
msgstr "" msgstr "година"
msgid "minute" msgid "minute"
msgstr "" msgstr "хвилина"
msgid "not" msgid "not"
msgstr "" msgstr "не"
msgid "port" msgid "port"
msgstr "" msgstr "порт"
msgid "ports" msgid "ports"
msgstr "" msgstr "порти"
msgid "reject" msgid "reject"
msgstr "відкидати" msgstr "відкидати"
msgid "second" msgid "second"
msgstr "" msgstr "секунда"
msgid "traffic" msgid "traffic"
msgstr "" msgstr "трафік"
msgid "type" msgid "type"
msgstr "" msgstr "типом"
msgid "types" msgid "types"
msgstr "" msgstr "типами"

View file

@ -46,6 +46,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "Action" msgstr "Action"
@ -101,6 +104,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "" msgstr ""
@ -110,6 +116,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "Bỏ qua nhưng gói không hợp lý" msgstr "Bỏ qua nhưng gói không hợp lý"
@ -177,6 +186,15 @@ msgstr ""
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "" msgstr ""
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "" msgstr ""
@ -306,6 +324,9 @@ msgstr ""
msgid "Output" msgid "Output"
msgstr "Output" msgstr "Output"
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "" msgstr ""
@ -498,6 +519,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "" msgstr ""
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "" msgstr ""

View file

@ -44,6 +44,9 @@ msgstr "接受转发"
msgid "Accept input" msgid "Accept input"
msgstr "接受入站" msgstr "接受入站"
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "动作" msgstr "动作"
@ -100,6 +103,9 @@ msgstr "丢弃转发"
msgid "Discard input" msgid "Discard input"
msgstr "丢弃入站" msgstr "丢弃入站"
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "不重写" msgstr "不重写"
@ -109,6 +115,9 @@ msgstr "不跟踪转发"
msgid "Do not track input" msgid "Do not track input"
msgstr "不跟踪入站" msgstr "不跟踪入站"
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "丢弃无效数据包" msgstr "丢弃无效数据包"
@ -175,6 +184,15 @@ msgstr "来自 %s 位于 %s 源于 %s"
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "来自 %s 位于 %s 源端口 %s 源 MAC %s" msgstr "来自 %s 位于 %s 源端口 %s 源 MAC %s"
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "基本设置" msgstr "基本设置"
@ -301,6 +319,9 @@ msgstr "其它..."
msgid "Output" msgid "Output"
msgstr "出站数据" msgstr "出站数据"
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "传递到 iptables 的额外参数。小心使用!" msgstr "传递到 iptables 的额外参数。小心使用!"
@ -500,6 +521,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "星期二" msgstr "星期二"
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "通过 %s" msgstr "通过 %s"

View file

@ -44,6 +44,9 @@ msgstr ""
msgid "Accept input" msgid "Accept input"
msgstr "" msgstr ""
msgid "Accept output"
msgstr ""
msgid "Action" msgid "Action"
msgstr "動作" msgstr "動作"
@ -100,6 +103,9 @@ msgstr ""
msgid "Discard input" msgid "Discard input"
msgstr "" msgstr ""
msgid "Discard output"
msgstr ""
msgid "Do not rewrite" msgid "Do not rewrite"
msgstr "不重寫" msgstr "不重寫"
@ -109,6 +115,9 @@ msgstr ""
msgid "Do not track input" msgid "Do not track input"
msgstr "" msgstr ""
msgid "Do not track output"
msgstr ""
msgid "Drop invalid packets" msgid "Drop invalid packets"
msgstr "丟棄無效資料包" msgstr "丟棄無效資料包"
@ -175,6 +184,15 @@ msgstr "來自 %s 位於 %s 源於 %s"
msgid "From %s in %s with source %s and %s" msgid "From %s in %s with source %s and %s"
msgstr "來自 %s 位於 %s 源埠 %s 源 MAC %s" msgstr "來自 %s 位於 %s 源埠 %s 源 MAC %s"
msgid "From %s on <var>this device</var>"
msgstr ""
msgid "From %s on <var>this device</var> with source %s"
msgstr ""
msgid "From %s on <var>this device</var> with source %s and %s"
msgstr ""
msgid "General Settings" msgid "General Settings"
msgstr "基本設定" msgstr "基本設定"
@ -301,6 +319,9 @@ msgstr "其它..."
msgid "Output" msgid "Output"
msgstr "出站資料" msgstr "出站資料"
msgid "Output zone"
msgstr ""
msgid "Passes additional arguments to iptables. Use with care!" msgid "Passes additional arguments to iptables. Use with care!"
msgstr "傳遞到 iptables 的額外引數。小心使用!" msgstr "傳遞到 iptables 的額外引數。小心使用!"
@ -499,6 +520,15 @@ msgstr ""
msgid "Tuesday" msgid "Tuesday"
msgstr "星期二" msgstr "星期二"
msgid "Unnamed SNAT"
msgstr ""
msgid "Unnamed forward"
msgstr ""
msgid "Unnamed rule"
msgstr ""
msgid "Via %s" msgid "Via %s"
msgstr "通過 %s" msgstr "通過 %s"

View file

@ -11,7 +11,6 @@ local has_ping6 = fs.access("/bin/ping6") or fs.access("/usr/bin/ping6")
local has_traceroute6 = fs.access("/usr/bin/traceroute6") local has_traceroute6 = fs.access("/usr/bin/traceroute6")
%> %>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[ <script type="text/javascript">//<![CDATA[
var stxhr = new XHR(); var stxhr = new XHR();

View file

@ -5,13 +5,12 @@ XHR.poll(5, '<%=url('admin/telephony/status')%>', null,
var tb = document.getElementById('telephony_status_table'); var tb = document.getElementById('telephony_status_table');
if (st && tb) if (st && tb)
{ {
tb.deleteRow(1); tb.removeChild(tb.firstChild);
var tr = tb.insertRow(-1); tb.appendChild(E('<div class="tr cbi-section-table-row cbi-rowstyle-1">', [
tr.className = 'cbi-section-table-row cbi-rowstyle-1'; E('<div class="td">', st.status),
E('<div class="td">', st.line1),
tr.insertCell(-1).innerHTML = st.status; E('<div class="td">', st.line2)
tr.insertCell(-1).innerHTML = st.line1; ]));
tr.insertCell(-1).innerHTML = st.line2;
} }
} }
); );
@ -19,14 +18,14 @@ XHR.poll(5, '<%=url('admin/telephony/status')%>', null,
<fieldset class="cbi-section"> <fieldset class="cbi-section">
<legend><%:Current Telephony State%></legend> <legend><%:Current Telephony State%></legend>
<table class="cbi-section-table" id="telephony_status_table"> <div class="table cbi-section-table" id="telephony_status_table">
<tr class="cbi-section-table-titles"> <div class="tr cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Uplink%></th> <div class="th cbi-section-table-cell"><%:Uplink%></div>
<th class="cbi-section-table-cell"><%:Port1%></th> <div class="th cbi-section-table-cell"><%:Port1%></div>
<th class="cbi-section-table-cell"><%:Port2%></th> <div class="th cbi-section-table-cell"><%:Port2%></div>
</tr> </div>
<tr class="cbi-section-table-row"> <div class="tr cbi-section-table-row">
<td colspan="5"><em><br /><%:Collecting data...%></em></td> <div class="td" colspan="5"><em><br /><%:Collecting data...%></em></div>
</tr> </div>
</table> </div>
</fieldset> </fieldset>

View file

@ -7,7 +7,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
LUCI_TITLE:=LXC management Web UI LUCI_TITLE:=LXC management Web UI
LUCI_DEPENDS:=+luci-mod-admin-full +lxc +lxc-attach +lxc-console +lxc-create +liblxc +rpcd-mod-lxc +getopt LUCI_DEPENDS:=+luci-mod-admin-full +lxc +lxc-attach +lxc-console +lxc-create +liblxc +rpcd-mod-lxc +getopt +!LXC_BUSYBOX_OPTIONS:tar
LUCI_PKGARCH:=all LUCI_PKGARCH:=all
PKG_MAINTAINER:=Petar Koretic <petar.koretic@sartura.hr> PKG_MAINTAINER:=Petar Koretic <petar.koretic@sartura.hr>

View file

@ -14,74 +14,44 @@ Author: Petar Koretic <petar.koretic@sartura.hr>
]]-- ]]--
local uci = require "luci.model.uci"
local util = require "luci.util"
local nixio = require "nixio"
module("luci.controller.lxc", package.seeall) module("luci.controller.lxc", package.seeall)
function fork_exec(command) local uci = require "luci.model.uci".cursor()
local pid = nixio.fork() local util = require "luci.util"
if pid > 0 then local nx = require "nixio"
return local url = util.shellquote(uci:get("lxc", "lxc", "url"))
elseif pid == 0 then
-- change to root dir
nixio.chdir("/")
-- patch stdin, out, err to /dev/null
local null = nixio.open("/dev/null", "w+")
if null then
nixio.dup(null, nixio.stderr)
nixio.dup(null, nixio.stdout)
nixio.dup(null, nixio.stdin)
if null:fileno() > 2 then
null:close()
end
end
-- replace with target command
nixio.exec("/bin/sh", "-c", command)
end
end
function index() function index()
if not nixio.fs.access("/etc/config/lxc") then
return
end
page = node("admin", "services", "lxc") page = node("admin", "services", "lxc")
page.target = cbi("lxc") page.target = cbi("lxc")
page.title = _("LXC Containers") page.title = _("LXC Containers")
page.order = 70 page.order = 70
page = entry({"admin", "services", "lxc_create"}, call("lxc_create"), nil) entry({"admin", "services", "lxc_create"}, call("lxc_create"), nil).leaf = true
page.leaf = true entry({"admin", "services", "lxc_action"}, call("lxc_action"), nil).leaf = true
entry({"admin", "services", "lxc_get_downloadable"}, call("lxc_get_downloadable"), nil).leaf = true
page = entry({"admin", "services", "lxc_action"}, call("lxc_action"), nil) entry({"admin", "services", "lxc_configuration_get"}, call("lxc_configuration_get"), nil).leaf = true
page.leaf = true entry({"admin", "services", "lxc_configuration_set"}, call("lxc_configuration_set"), nil).leaf = true
page = entry({"admin", "services", "lxc_get_downloadable"}, call("lxc_get_downloadable"), nil)
page.leaf = true
page = entry({"admin", "services", "lxc_configuration_get"}, call("lxc_configuration_get"), nil)
page.leaf = true
page = entry({"admin", "services", "lxc_configuration_set"}, call("lxc_configuration_set"), nil)
page.leaf = true
end end
function lxc_get_downloadable() function lxc_get_downloadable()
local target = lxc_get_arch_target() local target = lxc_get_arch_target(url)
local ssl_status = lxc_get_ssl_status()
local templates = {} local templates = {}
local f = io.popen('sh /usr/share/lxc/templates/lxc-download --list --no-validate --server %s' local f = io.popen('sh /usr/share/lxc/templates/lxc-download --list %s --server %s 2>/dev/null'
% util.shellquote(uci.cursor():get("lxc", "lxc", "url")), 'r') %{ ssl_status, url }, 'r')
local line local line
for line in f:lines() do for line in f:lines() do
local dist, version, dist_target = line:match("^(%S+)%s+(%S+)%s+(%S+)%s+default%s+%S+$") local dist, version, dist_target = line:match("^(%S+)%s+(%S+)%s+(%S+)%s+default%s+%S+$")
if dist and version and dist_target == target then if dist and version and dist_target and dist_target == target then
templates[#templates+1] = "%s:%s" %{ dist, version } templates[#templates+1] = "%s:%s" %{ dist, version }
end end
end end
f:close() f:close()
luci.http.prepare_content("application/json") luci.http.prepare_content("application/json")
@ -90,24 +60,21 @@ end
function lxc_create(lxc_name, lxc_template) function lxc_create(lxc_name, lxc_template)
luci.http.prepare_content("text/plain") luci.http.prepare_content("text/plain")
local path = lxc_get_config_path()
if not pcall(dofile, "/etc/openwrt_release") then if not path then
return luci.http.write("1") return
end end
local ssl_status = lxc_get_ssl_status()
local lxc_dist, lxc_release = lxc_template:match("^(.+):(.+)$") local lxc_dist, lxc_release = lxc_template:match("^(.+):(.+)$")
luci.sys.call('/usr/bin/lxc-create --quiet --name %s --bdev best --template download -- --dist %s --release %s --arch %s --server %s %s'
%{ lxc_name, lxc_dist, lxc_release, lxc_get_arch_target(url), url, ssl_status })
luci.http.write(util.ubus("lxc", "create", { while (nx.fs.access(path .. lxc_name .. "/partial")) do
name = lxc_name, nx.nanosleep(1)
template = "download", end
args = {
"--server", uci.cursor():get("lxc", "lxc", "url"), luci.http.write("0")
"--no-validate",
"--dist", lxc_dist,
"--release", lxc_release,
"--arch", lxc_get_arch_target()
}
}))
end end
function lxc_action(lxc_action, lxc_name) function lxc_action(lxc_action, lxc_name)
@ -121,11 +88,28 @@ function lxc_get_config_path()
local f = io.open("/etc/lxc/lxc.conf", "r") local f = io.open("/etc/lxc/lxc.conf", "r")
local content = f:read("*all") local content = f:read("*all")
f:close() f:close()
local ret = content:match('^%s*lxc.lxcpath%s*=%s*([^%s]*)') local ret = content:match('^%s*lxc.lxcpath%s*=%s*([^%s]*)')
if ret then if ret then
return ret .. "/" if nx.fs.access(ret) then
local min_space = tonumber(uci:get("lxc", "lxc", "min_space")) or 100000
local free_space = tonumber(util.exec("df " ..ret.. " | awk '{if(NR==2)print $4}'"))
if free_space and free_space >= min_space then
local min_temp = tonumber(uci:get("lxc", "lxc", "min_temp")) or 100000
local free_temp = tonumber(util.exec("df /tmp | awk '{if(NR==2)print $4}'"))
if free_temp and free_temp >= min_temp then
return ret .. "/"
else
util.perror("lxc error: not enough temporary space (< " ..min_temp.. " KB)")
end
else
util.perror("lxc error: not enough space (< " ..min_space.. " KB)")
end
else
util.perror("lxc error: directory not found")
end
else else
return "/srv/lxc/" util.perror("lxc error: config path is empty")
end end
end end
@ -142,15 +126,16 @@ end
function lxc_configuration_set(lxc_name) function lxc_configuration_set(lxc_name)
luci.http.prepare_content("text/plain") luci.http.prepare_content("text/plain")
local lxc_configuration = luci.http.formvalue("lxc_configuration") local lxc_configuration = luci.http.formvalue("lxc_conf")
if lxc_configuration == nil then if lxc_configuration == nil then
return luci.http.write("1") util.perror("lxc error: config formvalue is empty")
return
end end
local f, err = io.open(lxc_get_config_path() .. lxc_name .. "/config","w+") local f, err = io.open(lxc_get_config_path() .. lxc_name .. "/config","w+")
if not f then if not f then
return luci.http.write("2") util.perror("lxc error: config file not found")
return
end end
f:write(lxc_configuration) f:write(lxc_configuration)
@ -159,22 +144,32 @@ function lxc_configuration_set(lxc_name)
luci.http.write("0") luci.http.write("0")
end end
function lxc_get_arch_target() function lxc_get_arch_target(url)
local target = nixio.uname().machine local target = nx.uname().machine
local target_map = { if url and url:match("images.linuxcontainers.org") then
armv5 = "armel", local target_map = {
armv6 = "armel", armv5 = "armel",
armv7 = "armhf", armv6 = "armel",
armv8 = "arm64", armv7 = "armhf",
x86_64 = "amd64" armv8 = "arm64",
} x86_64 = "amd64"
}
local k, v local k, v
for k, v in pairs(target_map) do for k, v in pairs(target_map) do
if target:find(k) then if target:find(k) then
return v return v
end
end end
end end
return target return target
end end
function lxc_get_ssl_status()
local ssl_enabled = uci:get("lxc", "lxc", "ssl_enabled")
local ssl_status = "--no-validate"
if ssl_enabled and ssl_enabled == "1" then
ssl_status = ""
end
return ssl_status
end

View file

@ -14,18 +14,35 @@ Author: Petar Koretic <petar.koretic@sartura.hr>
]]-- ]]--
local fs = require "nixio.fs" m = Map("lxc", translate("LXC Containers"),
translate("<b>Please note:</b> For LXC Containers you need a custom OpenWrt image.<br />")
.. translate("The image should include at least support for 'kernel cgroups', 'kernel namespaces' and 'miscellaneous LXC related options' plus 'kmod-veth' for optional network support."))
m:section(SimpleSection).template = "lxc"
m = Map("lxc", translate("LXC Containers")) s = m:section(TypedSection, "lxc", translate("Options"))
s.anonymous = true
if fs.access("/etc/config/lxc") then o1 = s:option(Value, "url", translate("Containers URL"))
m:section(SimpleSection).template = "lxc" o1:value("images.linuxcontainers.org")
o1:value("repo.turris.cz/lxc", "repo.turris.cz/lxc (SSL req.)")
o1.default = "images.linuxcontainers.org"
o1.rmempty = false
s = m:section(TypedSection, "lxc", translate("Options")) o2 = s:option(Flag, "ssl_enabled", translate("Enable SSL"),
s.anonymous = true translate("Enable optional SSL encryption support. This requires additional packages like 'wget', 'ca-certificates', 'gnupg' and 'gnupg-utils'."))
s.addremove = false o2.default = o2.disabled
o2.rmempty = false
s:option(Value, "url", translate("Containers URL")) o3 = s:option(Value, "min_space", translate("Free Space Threshold"),
end translate("Minimum required free space for LXC Container creation in KB"))
o3.default = "100000"
o3.datatype = "min(50000)"
o3.rmempty = false
o4 = s:option(Value, "min_temp", translate("Free Temp Threshold"),
translate("Minimum required free temp space for LXC Container creation in KB"))
o4.default = "100000"
o4.datatype = "min(50000)"
o4.rmempty = false
return m return m

View file

@ -14,346 +14,371 @@ Author: Petar Koretic <petar.koretic@sartura.hr>
-%> -%>
<fieldset class="cbi-section"> <%-
<legend><%:Available Containers%></legend> local nx = require "nixio"
<div class="cbi-section-node"> local target = nx.uname().machine
<table id="t_lxc_list" class="cbi-section-table"> -%>
<tr class="cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Name%></th>
<th class="cbi-section-table-cell"><%:Status%></th>
<th class="cbi-section-table-cell"><%:Actions%></th>
</tr>
</table>
</div>
</fieldset>
<fieldset class="cbi-section"> <div class="cbi-section">
<h3><%:Available Containers%></h3>
<div class="cbi-section-node">
<div class="table cbi-section-table" id="t_lxc_list">
<div class="tr cbi-section-table-titles">
<div class="th cbi-section-table-cell"><%:Name%></div>
<div class="th cbi-section-table-cell"><%:Status%></div>
<div class="th cbi-section-table-cell"><%:Actions%></div>
</div>
</div>
</div>
</div>
<div class="cbi-section">
<span id="lxc-list-output"></span> <span id="lxc-list-output"></span>
</fieldset> </div>
<hr/> <hr />
<fieldset class="cbi-section"> <div class="cbi-section">
<legend><%:Create New Container%></legend> <h3><%:Create New Container%></h3>
<div class="cbi-section-node"> <div class="cbi-section-node">
<table id="t_lxc_create" class="cbi-section-table"> <div class="table cbi-section-table" id="t_lxc_create">
<tr class="cbi-section-table-titles"> <div class="tr cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Name%></th> <div class="th cbi-section-table-cell"><%:Name%></div>
<th class="cbi-section-table-cell"><%:Template%></th> <div class="th cbi-section-table-cell"><%:Template%></div>
<th class="cbi-section-table-cell"><%:Actions%></th> <div class="th cbi-section-table-cell"><%:Actions%></div>
</tr> </div>
<tr id="tr_holder"> <div class="tr cbi-section-table-row" id="div_create">
<td> <div class="td"><input class="cbi-input-text" type="text" id="tx_name" placeholder="<%:Enter new name%>" value='' /></div>
<input type="text" id="tx_name" placeholder="<%:Enter new name%>" value='' /> <div class="td"><select id="s_template" class="cbi-input-select cbi-button"></select></div>
</td> <div class="td">
<td> <input type="button" id="bt_create" value="<%:Create%>" onclick="lxc_create()" class="cbi-button cbi-button-add" />
<select id="s_template" class="cbi-input-select cbi-button">
</select>
</td>
<td>
<input type="button" id="bt_create" value="<%:Create%>" onclick="lxc_create(tr_holder)" class="cbi-button cbi-button-add" />
<span id="lxc-add-loader" style="display:inline-block; width:16px; height:16px; margin:0 5px"></span> <span id="lxc-add-loader" style="display:inline-block; width:16px; height:16px; margin:0 5px"></span>
</td> </div>
</tr> </div>
</table> </div>
</div> </div>
</fieldset> </div>
<fieldset class="cbi-section"> <div class="cbi-section">
<span id="lxc-add-output"></span> <span id="lxc-add-output"></span>
</fieldset> </div>
<hr/> <hr />
<script type="text/javascript" src="<%=resource%>/cbi.js"></script> <script type="text/javascript">
<script type="text/javascript">//<![CDATA[ //<![CDATA[
window.img = { "red" : "<%=resource%>/cbi/red.gif", "green" : "<%=resource%>/cbi/green.gif", "purple" : "<%=resource%>/cbi/purple.gif" };
window.states = { "STOPPED" : "red", "RUNNING" : "green", "FROZEN" : "purple" };
window.img = { "red" : "<%=resource%>/cbi/red.gif", "green" : "<%=resource%>/cbi/green.gif", "purple" : "<%=resource%>/cbi/purple.gif" } var t_lxc_list = document.getElementById('t_lxc_list');
window.states = { "STOPPED" : "red", "RUNNING" : "green", "FROZEN" : "purple"} var loader_html = '<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" width="16" height="16" style="vertical-align:middle" />';
var output_list = document.getElementById("lxc-list-output");
var output_add = document.getElementById("lxc-add-output");
var loader_add = document.getElementById("lxc-add-loader");
var div_create = document.getElementById("div_create");
var bt_create = div_create.querySelector("#bt_create");
var t_lxc_list = document.getElementById('t_lxc_list'); bt_create.disabled = true;
var loader_html = '<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" width="16" height="16" style="vertical-align:middle" /> '; info_message(output_add, "Template download in progress, please be patient!");
var timeout_msg = 0
var output_list = document.getElementById("lxc-list-output")
var output_add = document.getElementById("lxc-add-output")
var loader_add = document.getElementById("lxc-add-loader")
function lxc_create(tr) function lxc_create()
{ {
var lxc_name = tr.querySelector("#tx_name").value.trim() var lxc_name = div_create.querySelector("#tx_name").value.replace(/[\s!@#$%^&*()+=\[\]{};':"\\|,<>\/?]/g,'');
var lxc_template = tr.querySelector("#s_template").value var lxc_template = div_create.querySelector("#s_template").value;
var bt_create = tr.querySelector("#bt_create")
if (t_lxc_list.querySelector("[data-id='" + lxc_name + "']") != null) if (t_lxc_list.querySelector("[data-id='" + lxc_name + "']") != null)
return info_message(output_add, "Container with that name already exists!", 4000) {
return info_message(output_add, "Container with that name already exists!", 2000);
}
bt_create.disabled = true bt_create.disabled = true;
output_add.innerHTML = '' output_add.innerHTML = '';
if (!lxc_template)
{
return set_no_template();
}
if (!lxc_name || !lxc_name.length) if (!lxc_name || !lxc_name.length)
{ {
bt_create.disabled = false bt_create.disabled = false;
return info_message(output_add, "Name cannot be empty!", 4000) return info_message(output_add, "The 'Name' field must not be empty!", 2000);
} }
loading(loader_add) loading(loader_add);
new XHR().get('<%=luci.dispatcher.build_url("admin", "services")%>/lxc_create/' + '%h/%h'.format(lxc_name, lxc_template) , null, new XHR().get('<%=luci.dispatcher.build_url("admin", "services")%>/lxc_create/' + '%h/%h'.format(lxc_name, lxc_template) , null,
function(x) function(x)
{ {
bt_create.disabled = false bt_create.disabled = false;
loading(loader_add, 0) loading(loader_add, 0);
if (!x) if (!x)
info_message(output_add, "Container creation failed!") {
info_message(output_add, "Container creation failed!", 2000);
}
}) })
} }
function lxc_create_template(lxc_name, lxc_state) function lxc_create_template(lxc_name, lxc_state)
{ {
var info_row = t_lxc_list.querySelector("#empty") if (document.getElementById(lxc_name))
if (info_row) {
t_lxc_list.deleteRow(1) return;
}
var actions = '' info_message(output_list, "");
actions += '<input type="button" onclick="action_handler(this)" data-action="start" value="<%:Start%>" class="cbi-button cbi-button-apply" />' var actions = '';
actions+= '<input type="button" onclick="action_handler(this)" data-action="stop" value="<%:Stop%>" class="cbi-button cbi-button-reset" />' actions += '<input type="button" onclick="action_handler(this)" data-action="start" value="<%:Start%>" class="cbi-button cbi-button-apply" />';
actions+= '<input type="button" onclick="action_handler(this)" data-action="destroy" value="<%:Delete%>" class="cbi-button cbi-button-remove" />' actions += '&#160;<input type="button" onclick="action_handler(this)" data-action="stop" value="<%:Stop%>" class="cbi-button cbi-button-reset" />';
actions+= ' <select class="cbi-input-select cbi-button" onchange="action_more_handler(this)">\ actions += '&#160;<input type="button" onclick="action_handler(this)" data-action="destroy" value="<%:Delete%>" class="cbi-button cbi-button-remove" />';
<option selected disabled>more</option>\ actions += '&#160;<select class="cbi-input-select cbi-button" style="width:10em" onchange="action_more_handler(this)">\
<option selected="selected" disabled="disabled">more</option>\
<option>configure</option>\ <option>configure</option>\
<option>freeze</option>\ <option>freeze</option>\
<option>unfreeze</option>\ <option>unfreeze</option>\
<option>reboot</option>\ <option>reboot</option>\
</select>' </select>';
actions+= '<span data-loader style="display:inline-block; width:16px; height:16px; margin:0 5px"></span>' actions += '<span data-loader="" style="display:inline-block; width:16px; height:16px; margin:0 5px"></span>';
var row = t_lxc_list.insertRow(-1) var div0 = document.createElement("div");
var cell = row.insertCell(-1) div0.className = "tr cbi-section-table-row";
cell.innerHTML = '%q%h%q'.format("<strong>", lxc_name, "</strong>") div0.id = lxc_name;
cell.width = "30%" div0.setAttribute("data-id", lxc_name);
cell.setAttribute("data-id", lxc_name)
cell = row.insertCell(-1) var div1 = document.createElement("div");
cell.width = "20%" div1.className = "td";
cell.innerHTML = "<img src='"+window.img[lxc_state]+"'/>" div1.style.width = "30%";
div1.innerHTML = '%q%h%q'.format("<strong>", lxc_name, "</strong>");
cell = row.insertCell(-1) var div2 = document.createElement("div");
cell.width = "50%" div2.className = "td";
cell.innerHTML = actions div2.style.width = "20%";
div2.innerHTML = "<img src='"+window.img[lxc_state]+"'/>";
var div3 = document.createElement("div");
div3.className = "td";
div3.style.width = "50%";
div3.innerHTML = actions;
document.getElementById("t_lxc_list").appendChild(div0);
div0.appendChild(div1);
div0.appendChild(div2);
div0.appendChild(div3);
} }
function action_handler(self) function action_handler(self)
{ {
var action = self.getAttribute("data-action"); var bt_action = self;
var action = self.dataset['action'];
var lxc_name = self.parentNode.parentNode.dataset['id'];
var status_img = self.parentNode.parentNode.querySelector('img');
var loader = self.parentNode.querySelector('[data-loader]');
var bt_action = self bt_action.disabled = true;
var lxc_name = self.parentNode.parentNode.children[0].getAttribute('data-id')
var status_img = self.parentNode.parentNode.querySelector('img')
var loader = self.parentNode.querySelector('[data-loader]')
bt_action.disabled = true
if (action == "stop") if (action == "stop")
{ {
loading(loader) loading(loader);
new XHR().get('<%=luci.dispatcher.build_url("admin", "services")%>/lxc_action/' + '%h/%h'.format(action, lxc_name), null, new XHR().get('<%=luci.dispatcher.build_url("admin", "services")%>/lxc_action/' + '%h/%h'.format(action, lxc_name), null,
function(x, ec) function(x, ec)
{ {
loading(loader, 0) loading(loader, 0);
bt_action.disabled = false bt_action.disabled = false;
if (!x || ec) if (!x || ec)
return info_message(output_list,"Action failed!") {
return info_message(output_list,"Action failed!", 2000);
set_status(status_img, "red") }
set_status(status_img, "red");
}); });
} }
else if (action == "start") else if (action == "start")
{ {
loading(loader) loading(loader);
new XHR().get('<%=luci.dispatcher.build_url("admin", "services")%>/lxc_action/' + '%h/%h'.format(action, lxc_name), null, new XHR().get('<%=luci.dispatcher.build_url("admin", "services")%>/lxc_action/' + '%h/%h'.format(action, lxc_name), null,
function(x, data) function(x, data)
{ {
loading(loader, 0) loading(loader, 0);
bt_action.disabled = false bt_action.disabled = false;
//FIXME: uncomment after fixing 'lxc-start' if (!x || data)
if (!x /*|| ec */) {
return info_message(output_list,"Action failed!") return info_message(output_list,"Action failed!", 2000);
}
//FIXME: uncomment after fixing 'lxc-start' set_status(status_img, "green");
//set_status(status_img, "green")
}); });
} }
else if (action == "destroy") else if (action == "destroy")
{ {
if (!confirm("This will completely remove LXC container from the disk. Are you sure? (container will be stopped if running)")) var div = self.parentNode.parentNode;
return var img = div.querySelector('img');
loading(loader) if (img.getAttribute('src') != window.img["red"])
{
bt_action.disabled = false;
return info_message(output_list,"Container is still running!", 2000);
}
if (!confirm("This will completely remove a stopped LXC container from disk. Are you sure?"))
{
bt_action.disabled = false;
return;
}
loading(loader);
new XHR().get('<%=luci.dispatcher.build_url("admin", "services")%>/lxc_action/' + '%h/%h'.format(action, lxc_name), null, new XHR().get('<%=luci.dispatcher.build_url("admin", "services")%>/lxc_action/' + '%h/%h'.format(action, lxc_name), null,
function(x, ec) function(x, ec)
{ {
loading(loader, 0) loading(loader, 0);
bt_action.disabled = false bt_action.disabled = false;
if (!x || ec) if (!x || ec)
return info_message(output_list,"Action failed!") {
return info_message(output_list,"Action failed!", 2000);
var row = self.parentNode.parentNode }
row.parentNode.removeChild(row) var div = self.parentNode.parentNode;
div.parentNode.removeChild(div);
}); });
} }
} }
function lxc_configure_handler(self) function lxc_configure_handler(self)
{ {
var td = self.parentNode var div = self.parentNode;
var textarea = td.querySelector('[data-id]') var textarea = div.querySelector('[data-id]');
var lxc_name = textarea.getAttribute('data-id') var lxc_name = textarea.dataset['id'];
var lxc_configuration = textarea.value var lxc_conf = textarea.value;
new XHR().post('<%=luci.dispatcher.build_url("admin", "services")%>/lxc_configuration_set/' + lxc_name, "lxc_configuration=" + encodeURIComponent(lxc_configuration) , new XHR().post('<%=luci.dispatcher.build_url("admin", "services")%>/lxc_configuration_set/' + lxc_name, "lxc_conf=" + encodeURIComponent(lxc_conf),
function(x) function(x)
{ {
if (!x || x.responseText != "0") if (!x || x.responseText != "0")
return info_message(output_list,"Action failed!") {
return info_message(output_list,"Action failed!", 2000);
info_message(output_list,"LXC configuration updated") }
var row = td.parentNode info_message(output_list,"LXC configuration updated", 2000);
row.parentNode.removeChild(row) var rmdiv = div.parentNode;
rmdiv.parentNode.removeChild(rmdiv);
}) })
} }
function lxc_rename_template(lxc_name) function lxc_configure_template(lxc_name, lxc_conf)
{ {
var h = '\ var h = '\
<input data-id="'+ lxc_name + '" type="text" placeholder="Enter new name" /> \ <textarea data-id="' + lxc_name + '" rows="20" style="width:600px;font-family:monospace;white-space:pre;overflow-wrap:normal;overflow-x:scroll;">'+ lxc_conf +'</textarea> \
<input data-id="bt_confirm" onclick="lxc_rename_handler(this)" type="button" class="cbi-button" value="Confirm" />' <input data-id="bt_confirm" onclick="lxc_configure_handler(this)" type="button" class="cbi-button" value="Confirm" />';
return h;
return h
}
function lxc_configure_template(lxc_name, lxc_configuration)
{
var h = '\
<textarea data-id="'+ lxc_name + '" rows="20" style="width:100%">'+ lxc_configuration +'</textarea> \
<input data-id="bt_confirm" onclick="lxc_configure_handler(this)" type="button" class="cbi-button" value="Confirm" />'
return h
} }
function action_more_handler(self) function action_more_handler(self)
{ {
var lxc_name = self.parentNode.parentNode.querySelector('[data-id]').getAttribute('data-id') var lxc_name = self.parentNode.parentNode.dataset['id'];
var loader = self.parentNode.parentNode.querySelector('[data-loader]') var loader = self.parentNode.querySelector('[data-loader]');
var option = self.options[self.selectedIndex].text;
self.value = "more";
var option = self.options[self.selectedIndex].text switch(option)
self.value = "more"
switch (option)
{ {
case "configure": case "configure":
var tr = document.createElement('tr') var div0 = document.createElement('div');
var row = self.parentNode.parentNode var div1 = self.parentNode.parentNode;
var next_row = row.nextSibling var next_div = div1.nextSibling;
if (next_row && next_row.getAttribute('data-action') !== null)
row.parentNode.removeChild(next_row) if (next_div && next_div.dataset['action'] !== null)
{
div1.parentNode.removeChild(next_div);
}
new XHR().get('<%=luci.dispatcher.build_url("admin", "services")%>/lxc_configuration_get/' + lxc_name, null, new XHR().get('<%=luci.dispatcher.build_url("admin", "services")%>/lxc_configuration_get/' + lxc_name, null,
function(x) function(x)
{ {
tr.innerHTML="<td colspan='" + row.cells.length + "'>" + lxc_configure_template(lxc_name, x.responseText) + "</td>" div0.innerHTML="<div>" + lxc_configure_template(lxc_name, x.responseText) + "</div>";
tr.setAttribute('data-action','') div0.setAttribute('data-action','');
row.parentNode.insertBefore(tr, row.nextSibling) div1.parentNode.insertBefore(div0, div1.nextSibling);
}) })
break;
break
case "freeze": case "freeze":
var tr = self.parentNode.parentNode var img = self.parentNode.parentNode.querySelector('img');
var img = tr.querySelector('img')
if(img.getAttribute('src') != window.img["green"]) if(img.getAttribute('src') != window.img["green"])
return info_message(output_list,"Container is not running!") {
return info_message(output_list,"Container is not running!", 2000);
}
loading(loader);
loading(loader)
new XHR().get('<%=luci.dispatcher.build_url("admin", "services")%>/lxc_action/' + '%h/%h'.format(option, lxc_name), null, new XHR().get('<%=luci.dispatcher.build_url("admin", "services")%>/lxc_action/' + '%h/%h'.format(option, lxc_name), null,
function(x, ec) function(x, ec)
{ {
loading(loader, 0) loading(loader, 0)
if (!x || ec) if (!x || ec)
return info_message(output_list,"Action failed!") {
return info_message(output_list,"Action failed!", 2000);
set_status(img, "purple") }
set_status(img, "purple");
}) })
break;
break
case "unfreeze": case "unfreeze":
var tr = self.parentNode.parentNode var img = self.parentNode.parentNode.querySelector('img');
var img = tr.querySelector('img')
if(img.getAttribute('src') != window.img["purple"]) if(img.getAttribute('src') != window.img["purple"])
return info_message(output_list,"Container is not frozen!") {
return info_message(output_list,"Container is not frozen!", 2000);
}
loading(loader);
loading(loader)
new XHR().get('<%=luci.dispatcher.build_url("admin", "services")%>/lxc_action/' + '%h/%h'.format(option, lxc_name), null, new XHR().get('<%=luci.dispatcher.build_url("admin", "services")%>/lxc_action/' + '%h/%h'.format(option, lxc_name), null,
function(x, ec) function(x, ec)
{ {
loading(loader, 0) loading(loader, 0);
if (!x || ec) if (!x || ec)
return info_message(output_list,"Action failed!") {
return info_message(output_list,"Action failed!", 2000);
set_status(img, "green") }
set_status(img, "green");
}) })
break;
break
case "reboot": case "reboot":
var tr = self.parentNode.parentNode var img = self.parentNode.parentNode.querySelector('img');
var img = tr.querySelector('img')
if(img.getAttribute('src') != window.img["green"]) if(img.getAttribute('src') != window.img["green"])
return info_message(output_list,"Container is not running!") {
return info_message(output_list,"Container is not running!", 2000);
}
if (!confirm("Are you sure?")) if (!confirm("Are you sure?"))
return {
return;
}
loading(loader);
loading(loader)
new XHR().get('<%=luci.dispatcher.build_url("admin", "services")%>/lxc_action/' + '%h/%h'.format(option, lxc_name), null, new XHR().get('<%=luci.dispatcher.build_url("admin", "services")%>/lxc_action/' + '%h/%h'.format(option, lxc_name), null,
function(x, ec) function(x, ec)
{ {
loading(loader, 0) loading(loader, 0)
if (!x || ec) if (!x || ec)
return info_message(output_list,"Action failed!") {
return info_message(output_list,"Action failed!", 2000);
info_message(output_list,"LXC rebooted") }
info_message(output_list,"LXC container rebooted", 2000);
}) })
break break;
} }
} }
function set_empty(t_lxc_list) function set_no_container()
{ {
if (document.getElementById('empty') !== null) info_message(output_list, "There are no containers available yet.");
return }
var row_count = t_lxc_list.rows.length; function set_no_template()
while(--row_count) t_lxc_list.deleteRow(row_count); {
bt_create.disabled = true;
var row = t_lxc_list.insertRow(-1); info_message(output_add, "There are no templates for your architecture (<%=target%>) available, please select another containers URL.");
row.id = 'empty'
var cell = row.insertCell(0);
cell.colSpan = 4;
cell.innerHTML = '<em><br />There are no containers available yet.</em>';
} }
function lxc_list_update() function lxc_list_update()
@ -361,90 +386,108 @@ Author: Petar Koretic <petar.koretic@sartura.hr>
XHR.poll(4, '<%=luci.dispatcher.build_url("admin", "services")%>/lxc_action/list', null, XHR.poll(4, '<%=luci.dispatcher.build_url("admin", "services")%>/lxc_action/list', null,
function(x, data) function(x, data)
{ {
if (!x) return; if (!x || !data)
{
return;
}
var lxc_count = Object.keys(data).length var lxc_count = Object.keys(data).length;
if (!data || !lxc_count) if (!lxc_count)
return set_empty(t_lxc_list) {
return set_no_container();
}
if (document.getElementById('empty') !== null) var lxcs = t_lxc_list.querySelectorAll('td[data-id]');
t_lxc_list.deleteRow(1); var lxc_name_div = {};
var lxcs = t_lxc_list.querySelectorAll('td[data-id]')
var lxc_name_table = {}
for (var i = 0, len = lxcs.length; i < len; i++) for (var i = 0, len = lxcs.length; i < len; i++)
{ {
var lxc_name = lxcs[i].getAttribute('data-id') var lxc_name = lxcs[i].dataset['id'];
if (!(lxc_name in data)) if (!(lxc_name in data))
{ {
var row = t_lxc_list.querySelector("[data-id='" + lxc_name + "']").parentNode var div = t_lxc_list.querySelector("[data-id='" + lxc_name + "']").parentNode;
row.parentNode.removeChild(row) div.parentNode.removeChild(div);
continue continue;
} }
lxc_name_div[lxc_name] = lxcs[i].parentNode.querySelector('img');
lxc_name_table[lxc_name] = lxcs[i].parentNode.querySelector('img')
} }
for(var key in data) for(var key in data)
{ {
var lxc_name = key var lxc_name = key;
var state = window.states[data[key]] var state = window.states[data[key]];
if (!(lxc_name in lxc_name_table)) if (!(lxc_name in lxc_name_div))
lxc_create_template(lxc_name, state) {
lxc_create_template(lxc_name, state);
else if (state != get_status(lxc_name_table[lxc_name])) }
set_status(lxc_name_table[lxc_name], state) else if (state != get_status(lxc_name_div[lxc_name]))
{
set_status(lxc_name_div[lxc_name], state);
}
} }
}) })
} }
function loading(elem, state) function loading(elem, state)
{ {
state = (typeof state === 'undefined') ? 1 : state state = (typeof state === 'undefined') ? 1 : state;
if (state === 1) if (state === 1)
elem.innerHTML = loader_html {
elem.innerHTML = loader_html;
}
else else
setTimeout(function() { elem.innerHTML = ''}, 1000) {
setTimeout(function() { elem.innerHTML = ''}, 2000);
}
} }
function set_status(elem, state) function set_status(elem, state)
{ {
state = (typeof state === 'undefined') ? 1 : state state = (typeof state === 'undefined') ? 1 : state;
setTimeout(function() { elem.setAttribute('src', window.img[state])}, 300);
setTimeout(function() { elem.setAttribute('src', window.img[state])}, 300)
} }
function get_status(elem) function get_status(elem)
{ {
var src = elem.getAttribute('src') var src = elem.getAttribute('src');
for (var i in img) for (var i in img)
{ {
if (img[i] == src) if (img[i] == src)
return i {
return i;
}
} }
} }
function info_message(output, msg, timeout) function info_message(output, msg, timeout)
{ {
timeout = timeout || 3000 timeout = timeout || 0;
output.innerHTML = msg output.innerHTML = '<em>' + msg + '</em>';
clearTimeout(timeout_msg) if (timeout > 0)
timeout_msg = setTimeout(function(){ output.innerHTML=""}, timeout); {
setTimeout(function(){ output.innerHTML=""}, timeout);
}
} }
lxc_list_update()
new XHR().get('<%=luci.dispatcher.build_url("admin", "services")%>/lxc_get_downloadable', null, new XHR().get('<%=luci.dispatcher.build_url("admin", "services")%>/lxc_get_downloadable', null,
function(x, data) function(x, data)
{ {
if (!x) return; if (!x)
{
return;
}
if (!data)
{
return set_no_template();
}
var lxc_count = Object.keys(data).length;
if (!lxc_count)
{
return set_no_template();
}
var lxc_count = Object.keys(data).length
if (!data || !lxc_count) return;
var select = document.getElementById("s_template"); var select = document.getElementById("s_template");
for(var key in data) for(var key in data)
{ {
@ -453,6 +496,11 @@ Author: Petar Koretic <petar.koretic@sartura.hr>
option.text = data[key].replace(/[_:]/g, ' '); option.text = data[key].replace(/[_:]/g, ' ');
select.add(option, -1); select.add(option, -1);
} }
info_message(output_add, "");
bt_create.disabled = false;
}) })
//]]></script> lxc_list_update();
//]]>
</script>

View file

@ -138,10 +138,12 @@ function diagnosticsData(interface, task)
local number = getInterfaceNumber(interface) local number = getInterfaceNumber(interface)
local uci = require "luci.model.uci".cursor(nil, "/var/state") local uci = require "luci.model.uci".cursor(nil, "/var/state")
local device = uci:get("network", interface, "ifname") local nw = require "luci.model.network".init()
local network = nw:get_network(interface)
local device = network and network:ifname()
luci.http.prepare_content("text/plain") luci.http.prepare_content("text/plain")
if device ~= "" then if device then
if task == "ping_gateway" then if task == "ping_gateway" then
local gateway = get_gateway(interface) local gateway = get_gateway(interface)
if gateway ~= nil then if gateway ~= nil then

View file

@ -13,7 +13,6 @@
<li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/status/mwan/troubleshooting")%>"><%:Troubleshooting%></a></li> <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/status/mwan/troubleshooting")%>"><%:Troubleshooting%></a></li>
</ul> </ul>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[ <script type="text/javascript">//<![CDATA[
XHR.poll(5, '<%=luci.dispatcher.build_url("admin", "status", "mwan", "detailed_status")%>', null, XHR.poll(5, '<%=luci.dispatcher.build_url("admin", "status", "mwan", "detailed_status")%>', null,
function(x) function(x)

View file

@ -25,7 +25,6 @@
) )
%> %>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[ <script type="text/javascript">//<![CDATA[
var stxhr = new XHR(); var stxhr = new XHR();

View file

@ -13,7 +13,6 @@
<li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/status/mwan/troubleshooting")%>"><%:Troubleshooting%></a></li> <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/status/mwan/troubleshooting")%>"><%:Troubleshooting%></a></li>
</ul> </ul>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<div class="cbi-map"> <div class="cbi-map">
<%+mwan/overview_status_interface%> <%+mwan/overview_status_interface%>

View file

@ -13,7 +13,6 @@
<li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/status/mwan/troubleshooting")%>"><%:Troubleshooting%></a></li> <li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/status/mwan/troubleshooting")%>"><%:Troubleshooting%></a></li>
</ul> </ul>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[ <script type="text/javascript">//<![CDATA[
XHR.poll(15, '<%=luci.dispatcher.build_url("admin", "status", "mwan", "troubleshooting_display")%>', null, XHR.poll(15, '<%=luci.dispatcher.build_url("admin", "status", "mwan", "troubleshooting_display")%>', null,
function(x) function(x)

View file

@ -57,7 +57,7 @@ msgid "Destination port"
msgstr "目标端口" msgstr "目标端口"
msgid "Detail" msgid "Detail"
msgstr "" msgstr "详细"
msgid "Diagnostics" msgid "Diagnostics"
msgstr "诊断" msgstr "诊断"
@ -76,7 +76,7 @@ msgid "Enter value in hex, starting with <code>0x</code>"
msgstr "输入十六进制值,以 <code>0x</code> 开头" msgstr "输入十六进制值,以 <code>0x</code> 开头"
msgid "Execute" msgid "Execute"
msgstr "" msgstr "执行"
msgid "Expect interface state on up event" msgid "Expect interface state on up event"
msgstr "在 up 事件发生时的预期接口状态" msgstr "在 up 事件发生时的预期接口状态"
@ -103,7 +103,7 @@ msgid "Hotplug ifup"
msgstr "Hotplug ifup" msgstr "Hotplug ifup"
msgid "INFO: MWAN not running" msgid "INFO: MWAN not running"
msgstr "" msgstr "信息MWAN 没有运行"
msgid "IPset" msgid "IPset"
msgstr "IPset" msgstr "IPset"
@ -154,28 +154,28 @@ msgid "Local source interface"
msgstr "本地源接口" msgstr "本地源接口"
msgid "MWAN - Globals" msgid "MWAN - Globals"
msgstr "" msgstr "MWAN - 全局"
msgid "MWAN - Interfaces" msgid "MWAN - Interfaces"
msgstr "" msgstr "MWAN - 接口"
msgid "MWAN - Members" msgid "MWAN - Members"
msgstr "" msgstr "MWAN - 成员"
msgid "MWAN - Notification" msgid "MWAN - Notification"
msgstr "" msgstr "MWAN - 通知"
msgid "MWAN - Policies" msgid "MWAN - Policies"
msgstr "" msgstr "MWAN - 策略"
msgid "MWAN - Rules" msgid "MWAN - Rules"
msgstr "" msgstr "MWAN - 规则"
msgid "MWAN Interface Configuration - %s" msgid "MWAN Interface Configuration - %s"
msgstr "MWAN 接口配置 - %s" msgstr "MWAN 接口配置 - %s"
msgid "MWAN Interfaces" msgid "MWAN Interfaces"
msgstr "" msgstr "MWAN 接口"
msgid "MWAN Member Configuration - %s" msgid "MWAN Member Configuration - %s"
msgstr "MWAN 成员配置 - %s" msgstr "MWAN 成员配置 - %s"
@ -187,13 +187,13 @@ msgid "MWAN Rule Configuration - %s"
msgstr "MWAN 规则配置 - %s" msgstr "MWAN 规则配置 - %s"
msgid "MWAN Status - Detail" msgid "MWAN Status - Detail"
msgstr "" msgstr "MWAN Status - 详细"
msgid "MWAN Status - Diagnostics" msgid "MWAN Status - Diagnostics"
msgstr "" msgstr "MWAN Status - 诊断"
msgid "MWAN Status - Troubleshooting" msgid "MWAN Status - Troubleshooting"
msgstr "" msgstr "MWAN Status - 故障排除"
msgid "" msgid ""
"MWAN supports up to 252 physical and/or logical interfaces<br />MWAN " "MWAN supports up to 252 physical and/or logical interfaces<br />MWAN "
@ -265,7 +265,7 @@ msgid "No MWAN interfaces found"
msgstr "没有找到 MWAN 接口" msgstr "没有找到 MWAN 接口"
msgid "Notification" msgid "Notification"
msgstr "" msgstr "通知"
msgid "Offline" msgid "Offline"
msgstr "离线" msgstr "离线"
@ -312,8 +312,8 @@ msgstr ""
"“策略”把成员进行分组,告诉 MWAN 如何分配“规则”中使用这一策略的流量<br />拥有" "“策略”把成员进行分组,告诉 MWAN 如何分配“规则”中使用这一策略的流量<br />拥有"
"较低跃点数的成员将会被优先使用。拥有相同跃点数的成员把流量进行负载均衡。<br /" "较低跃点数的成员将会被优先使用。拥有相同跃点数的成员把流量进行负载均衡。<br /"
">进行负载均衡的成员之间拥有较高比重的成员将会被分配到更多流量。<br />名称允许" ">进行负载均衡的成员之间拥有较高比重的成员将会被分配到更多流量。<br />名称允许"
"包括A-Z、a-z、0-9、_ 但是不能有空格。名称应该在 15 个字符以内<br />策略不应" "包括 A-Z、a-z、0-9、_ 但是不能有空格。名称应该在 15 个字符以内<br />策略不应"
"与接口、成员、规则中的任意一个设置项使用相同的名称" "与接口、成员、规则中的任意一个设置项使用相同的名称"
msgid "Policy" msgid "Policy"
msgstr "策略" msgstr "策略"
@ -344,6 +344,11 @@ msgid ""
"z, 0-9, _ and no spaces<br />Rules may not share the same name as configured " "z, 0-9, _ and no spaces<br />Rules may not share the same name as configured "
"interfaces, members or policies" "interfaces, members or policies"
msgstr "" msgstr ""
"规则指定哪些流量将使用特定的 MWAN 策略<br />规则基于 IP 地址,端口或协议<br /"
">规则从上到下匹配<br />匹配规则以下的规则被忽略<br />不符合任何规则的流量将使"
"用主路由表进行路由<br />目的地为已知(非默认)网络的流量由主路由表处理<br />"
"流量符合规则,但该策略的所有 WAN 接口关闭后都会被失效<br />名称可包含字符 A-"
"Za-z0-9_和空格<br />规则不能与配置的接口、成员或策略共享相同的名称"
msgid "Seconds. Acceptable values: 1-1000000. Defaults to 600 if not set" msgid "Seconds. Acceptable values: 1-1000000. Defaults to 600 if not set"
msgstr "单位为秒。接受的值1-1000000。留空则使用默认值 600 秒" msgstr "单位为秒。接受的值1-1000000。留空则使用默认值 600 秒"
@ -364,7 +369,7 @@ msgid "Supports CIDR notation (eg \"192.168.100.0/24\") without quotes"
msgstr "支持 CIDR 记法(例如:\"192.168.100.0/24\")不含引号" msgstr "支持 CIDR 记法(例如:\"192.168.100.0/24\")不含引号"
msgid "Task" msgid "Task"
msgstr "" msgstr "任务"
msgid "There are currently %d of %d supported interfaces configured" msgid "There are currently %d of %d supported interfaces configured"
msgstr "当前已配置 %d 个接口,最大支持 %d 个" msgstr "当前已配置 %d 个接口,最大支持 %d 个"
@ -395,6 +400,14 @@ msgid ""
"Physical device name which interface went up or down (e.g. \"eth0\" or " "Physical device name which interface went up or down (e.g. \"eth0\" or "
"\"wwan0\")<br /><br />" "\"wwan0\")<br /><br />"
msgstr "" msgstr ""
"这里允许您修改“/etc/mwan3.user”的内容。<br />该文件在 sysupgrade 期间也会保"
"留。<br /><br />注意:<br />该文件会作为 shell 脚本解释。<br />脚本的第一行必"
"须是 &#34;#!/bin/sh&#34;,不带引号。<br />以 # 开头的行是注释,不会执行。"
"<br />将您的自定义 mwan3 动作放在这里,他们将<br />在启用 mwan3 的接口上<br /"
">在 netifd hotplug 接口事件时执行。<br /><br />有三个主要的环境变量传递给这个"
"脚本。<br /><br />$ACTION “ifup” 或 “ifdown”<br />$INTERFACE 启动或停止的接口"
"名(例如 “wan” 或 “wwan”<br />$DEVICE 启动或停止接口的物理设备名(例如 "
"“eth0” 或 “wwan0”<br /><br />"
msgid "Tracking hostname or IP address" msgid "Tracking hostname or IP address"
msgstr "跟踪的主机或 IP 地址" msgstr "跟踪的主机或 IP 地址"
@ -421,35 +434,35 @@ msgid ""
msgstr "使用该接口的 IP 地址作为路由器本身发起的流量的源 IP 地址" msgstr "使用该接口的 IP 地址作为路由器本身发起的流量的源 IP 地址"
msgid "View the content of /etc/protocols for protocol description" msgid "View the content of /etc/protocols for protocol description"
msgstr "" msgstr "查看协议描述的 /etc/protocols 的内容"
msgid "WARNING: %d interfaces are configured exceeding the maximum of %d!" msgid "WARNING: %d interfaces are configured exceeding the maximum of %d!"
msgstr "警告:已配置 %d 个接口,超过最大值 %d" msgstr "警告:已配置 %d 个接口,超过最大值 %d"
msgid "WARNING: Interface %s are not found in /etc/config/network" msgid "WARNING: Interface %s are not found in /etc/config/network"
msgstr "" msgstr "警告:接口 %s 在 /etc/config/network 中未找到"
msgid "WARNING: Interface %s has a duplicate metric %s configured" msgid "WARNING: Interface %s has a duplicate metric %s configured"
msgstr "" msgstr "警告:接口 %s 的 metric %s 配置重复"
msgid "" msgid ""
"WARNING: Interface %s has a higher reliability requirement than tracking " "WARNING: Interface %s has a higher reliability requirement than tracking "
"hosts (%d)" "hosts (%d)"
msgstr "" msgstr "警告:接口 %s 比跟踪主机具有更高的可靠性要求(%d"
msgid "WARNING: Interface %s has no default route in the main routing table" msgid "WARNING: Interface %s has no default route in the main routing table"
msgstr "" msgstr "警告:接口 %s 在主路由表中没有默认的路由"
msgid "WARNING: Policy %s has exceeding the maximum name of 15 characters" msgid "WARNING: Policy %s has exceeding the maximum name of 15 characters"
msgstr "" msgstr "警告:策略 %s 名称超过 15 个字符"
msgid "" msgid ""
"WARNING: Rule %s have a port configured with no or improper protocol " "WARNING: Rule %s have a port configured with no or improper protocol "
"specified!" "specified!"
msgstr "" msgstr "警告:规则 %s 有一个端口配置没有指定或协议不正确!"
msgid "Waiting for command to complete..." msgid "Waiting for command to complete..."
msgstr "" msgstr "正在等待命令完成..."
msgid "Weight" msgid "Weight"
msgstr "比重" msgstr "比重"

View file

@ -5,7 +5,6 @@
<%+header%> <%+header%>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<h2 name="content"><%:Netlink Bandwidth Monitor - Backup / Restore %></h2> <h2 name="content"><%:Netlink Bandwidth Monitor - Backup / Restore %></h2>

View file

@ -195,7 +195,6 @@
<%+header%> <%+header%>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript" src="<%=resource%>/nlbw.chart.min.js"></script> <script type="text/javascript" src="<%=resource%>/nlbw.chart.min.js"></script>
<script type="text/javascript">//<![CDATA[ <script type="text/javascript">//<![CDATA[

View file

@ -38,70 +38,70 @@
<fieldset class="cbi-section"> <fieldset class="cbi-section">
<legend><%:Recognized Clients%></legend> <legend><%:Recognized Clients%></legend>
<div class="cbi-section-node"> <div class="cbi-section-node">
<table class="cbi-section-table"> <div class="table cbi-section-table">
<tr class="cbi-section-table-titles"> <div class="tr cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Hostname%></th> <div class="th cbi-section-table-cell"><%:Hostname%></div>
<th class="cbi-section-table-cell"><%:IPv4%></th> <div class="th cbi-section-table-cell"><%:IPv4%></div>
<th class="cbi-section-table-cell"><%:MAC%></th> <div class="th cbi-section-table-cell"><%:MAC%></div>
<th class="cbi-section-table-cell"><%:Manufacturer%></th> <div class="th cbi-section-table-cell"><%:Manufacturer%></div>
<th class="cbi-section-table-cell"><%:Model%></th> <div class="th cbi-section-table-cell"><%:Model%></div>
<th class="cbi-section-table-cell"><%:Class%></th> <div class="th cbi-section-table-cell"><%:Class%></div>
</tr> </div>
<% <%
for i,v in ipairs(devdump) do for i,v in ipairs(devdump) do
if v.DeviceProfileUuid ~= "" then if v.DeviceProfileUuid ~= "" then
%> %>
<tr class="cbi-section-table-row cbi-rowstyle-<%=(style and 1 or 2)%>"> <div class="tr cbi-section-table-row cbi-rowstyle-<%=(style and 1 or 2)%>">
<td class="cbi-value-field"><%=v.Hostname%></td> <div class="td cbi-value-field"><%=v.Hostname%></div>
<td class="cbi-value-field"><%=v.Ipv4Address%></td> <div class="td cbi-value-field"><%=v.Ipv4Address%></div>
<td class="cbi-value-field"><a href="/cgi-bin/clientdetails?mac=<%=v.MacAddress%>"><%=v.MacAddress%></a></td> <div class="td cbi-value-field"><a href="/cgi-bin/clientdetails?mac=<%=v.MacAddress%>"><%=v.MacAddress%></a></div>
<td class="cbi-value-field"><%=devicevalues[v.DeviceProfileUuid].Manufacturer%></td> <div class="td cbi-value-field"><%=devicevalues[v.DeviceProfileUuid].Manufacturer%></div>
<td class="cbi-value-field"><%=devicevalues[v.DeviceProfileUuid].Model%></td> <div class="td cbi-value-field"><%=devicevalues[v.DeviceProfileUuid].Model%></div>
<td class="cbi-value-field"><%=devicevalues[v.DeviceProfileUuid].ThingClass%></td> <div class="td cbi-value-field"><%=devicevalues[v.DeviceProfileUuid].ThingClass%></div>
</tr> </div>
<% <%
style=false style=false
end end
end end
%> %>
</table> </div>
</div> </div>
</fieldset> </fieldset>
<br /> <br />
<fieldset class="cbi-section"> <fieldset class="cbi-section">
<legend><%:Unrecognized Clients%></legend> <legend><%:Unrecognized Clients%></legend>
<div class="cbi-section-node"> <div class="cbi-section-node">
<table class="cbi-section-table"> <div class="table cbi-section-table">
<tr class="cbi-section-table-titles"> <div class="tr cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Hostname%></th> <div class="th cbi-section-table-cell"><%:Hostname%></div>
<th class="cbi-section-table-cell"><%:IPv4%></th> <div class="th cbi-section-table-cell"><%:IPv4%></div>
<th class="cbi-section-table-cell"><%:MAC%></th> <div class="th cbi-section-table-cell"><%:MAC%></div>
<th class="cbi-section-table-cell"><%:Manufacturer%></th> <div class="th cbi-section-table-cell"><%:Manufacturer%></div>
<th class="cbi-section-table-cell"><%:Model%></th> <div class="th cbi-section-table-cell"><%:Model%></div>
<th class="cbi-section-table-cell"><%:DhcpVendor%></th> <div class="th cbi-section-table-cell"><%:DhcpVendor%></div>
<th class="cbi-section-table-cell"><%:DhcpHostname%></th> <div class="th cbi-section-table-cell"><%:DhcpHostname%></div>
</tr> </div>
<% <%
for i,v in ipairs(devdump) do for i,v in ipairs(devdump) do
if v.DeviceProfileUuid == "" then if v.DeviceProfileUuid == "" then
%> %>
<tr class="cbi-section-table-row cbi-rowstyle-<%=(style and 1 or 2)%>"> <div class="tr cbi-section-table-row cbi-rowstyle-<%=(style and 1 or 2)%>">
<td class="cbi-value-field"><%=v.Hostname%></td> <div class="td cbi-value-field"><%=v.Hostname%></div>
<td class="cbi-value-field"><%=v.Ipv4Address%></td> <div class="td cbi-value-field"><%=v.Ipv4Address%></div>
<td class="cbi-value-field"><a href="/cgi-bin/clientdetails?mac=<%=v.MacAddress%>"><%=v.MacAddress%></a></td> <div class="td cbi-value-field"><a href="/cgi-bin/clientdetails?mac=<%=v.MacAddress%>"><%=v.MacAddress%></a></div>
<td class="cbi-value-field"><%=v.SsdpManufacturer%></td> <div class="td cbi-value-field"><%=v.SsdpManufacturer%></div>
<td class="cbi-value-field"><%=v.SsdpModelName%></td> <div class="td cbi-value-field"><%=v.SsdpModelName%></div>
<td class="cbi-value-field"><%=v.DhcpVendor1%></td> <div class="td cbi-value-field"><%=v.DhcpVendor1%></div>
<td class="cbi-value-field"><%=v.DhcpHostname%></td> <div class="td cbi-value-field"><%=v.DhcpHostname%></div>
</tr> </div>
<% <%
style=false style=false
end end
end end
%> %>
</table> </div>
</div> </div>
</fieldset> </fieldset>

View file

@ -5,8 +5,8 @@
function(x) function(x)
{ {
var tb = document.getElementById('ocserv_status_table'); var tb = document.getElementById('ocserv_status_table');
if (tb && (idx < tb.rows.length)) if (tb && (idx + 1 < tb.childNodes.length))
tb.rows[0].parentNode.removeChild(tb.rows[idx]); tb.removeChild(tb.childNodes[idx + 1]);
} }
); );
} }
@ -18,38 +18,28 @@
if (st && tb) if (st && tb)
{ {
/* clear all rows */ /* clear all rows */
while( tb.rows.length > 1 ) while (tb.firstElementChild !== tb.lastElementChild)
tb.deleteRow(1); tb.removeChild(tb.lastElementChild);
for( var i = 0; i < st.length; i++ ) for (var i = 0; i < st.length; i++)
{ {
var tr = tb.insertRow(-1); tb.appendChild(E('<div class="tr cbi-section-table-row cbi-rowstyle-%d">'.format((i % 2) + 1), [
tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1); E('<div class="td">', st[i].user),
E('<div class="td">', st[i].group),
tr.insertCell(-1).innerHTML = st[i].user; E('<div class="td">', st[i].vpn_ip),
tr.insertCell(-1).innerHTML = st[i].group; E('<div class="td">', st[i].ip),
tr.insertCell(-1).innerHTML = st[i].vpn_ip; E('<div class="td">', st[i].device),
tr.insertCell(-1).innerHTML = st[i].ip; E('<div class="td">', st[i].time),
tr.insertCell(-1).innerHTML = st[i].device; E('<div class="td">', st[i].cipher),
tr.insertCell(-1).innerHTML = st[i].time; E('<div class="td">', st[i].status),
tr.insertCell(-1).innerHTML = st[i].cipher; E('<div class="td">',
tr.insertCell(-1).innerHTML = st[i].status; E('<input class="cbi-button cbi-input-remove" type="button" value="<%:Disconnect%>" onclick="ocserv_disconnect(%d)" />'
.format(st[i].id)))
tr.insertCell(-1).innerHTML = String.format( ]));
'<input class="cbi-button cbi-input-remove" type="button" value="<%:Disconnect%>" onclick="ocserv_disconnect(%d)" />',
st[i].id
);
} }
if( tb.rows.length == 1 ) if (tb.firstElementChild === tb.lastElementChild)
{ tb.appendChild(E('<div class="tr cbi-section-table-row"><div class="td"><em><br /><%:There are no active users.%></em></div></div>'));
var tr = tb.insertRow(-1);
tr.className = 'cbi-section-table-row';
var td = tr.insertCell(-1);
td.colSpan = 5;
td.innerHTML = '<em><br /><%:There are no active users.%></em>';
}
} }
} }
); );
@ -57,20 +47,21 @@
<fieldset class="cbi-section"> <fieldset class="cbi-section">
<legend><%:Active OpenConnect Users%></legend> <legend><%:Active OpenConnect Users%></legend>
<table class="cbi-section-table" id="ocserv_status_table"> <div class="table cbi-section-table" id="ocserv_status_table">
<tr class="cbi-section-table-titles"> <div class="tr cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:User%></th> <div class="th cbi-section-table-cell"><%:User%></div>
<th class="cbi-section-table-cell"><%:Group%></th> <div class="th cbi-section-table-cell"><%:Group%></div>
<th class="cbi-section-table-cell"><%:IP Address%></th> <div class="th cbi-section-table-cell"><%:IP Address%></div>
<th class="cbi-section-table-cell"><%:VPN IP Address%></th> <div class="th cbi-section-table-cell"><%:VPN IP Address%></div>
<th class="cbi-section-table-cell"><%:Device%></th> <div class="th cbi-section-table-cell"><%:Device%></div>
<th class="cbi-section-table-cell"><%:Time%></th> <div class="th cbi-section-table-cell"><%:Time%></div>
<th class="cbi-section-table-cell"><%:Cipher%></th> <div class="th cbi-section-table-cell"><%:Cipher%></div>
<th class="cbi-section-table-cell"><%:Status%></th> <div class="th cbi-section-table-cell"><%:Status%></div>
<th class="cbi-section-table-cell">&#160;</th> <div class="th cbi-section-table-cell">&#160;</div>
</tr> </div>
<tr class="cbi-section-table-row"> <div class="tr cbi-section-table-row">
<td colspan="5"><em><br /><%:Collecting data...%></em></td> <div class="td" colspan="5"><em><br /><%:Collecting data...%></em></div>
</tr> </div>
</table> </div>
</fieldset> </fieldset>

View file

@ -118,7 +118,6 @@ end
<%+header%> <%+header%>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[ <script type="text/javascript">//<![CDATA[
XHR.poll(10 , '<%=REQUEST_URI%>', { status: 1 }, XHR.poll(10 , '<%=REQUEST_URI%>', { status: 1 },
@ -132,11 +131,11 @@ end
{ {
var service = info[idx]; var service = info[idx];
s += String.format( s += String.format(
'<tr class="cbi-section-table-row cbi-rowstyle-'+(1 + (idx % 2))+'">' + '<div class="tr cbi-section-table-row cbi-rowstyle-'+(1 + (idx % 2))+'">' +
'<td class="cbi-section-table-titles"><a href="%s">%s</a></td>' + '<div class="td cbi-section-table-titles"><a href="%s">%s</a></div>' +
'<td class="cbi-section-table-titles">%s</td>' + '<div class="td cbi-section-table-titles">%s</div>' +
'<td class="cbi-section-table-titles"><a href="http://%s/cgi-bin-status.html">%s</a></td>' + '<div class="td cbi-section-table-titles"><a href="http://%s/cgi-bin-status.html">%s</a></div>' +
'</tr>', '</div>',
service.url, service.descr, service.proto, service.origin_link, service.origin || '?' service.url, service.descr, service.proto, service.origin_link, service.origin || '?'
); );
} }
@ -153,16 +152,16 @@ end
<fieldset class="cbi-section"> <fieldset class="cbi-section">
<legend><%:Internal services%></legend> <legend><%:Internal services%></legend>
<table class="cbi-section-table"> <div class="table cbi-section-table">
<thead> <div class="thead">
<tr class="cbi-section-table-titles"> <div class="tr cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Url%></th> <div class="th cbi-section-table-cell"><%:Url%></div>
<th class="cbi-section-table-cell"><%:Protocol%></th> <div class="th cbi-section-table-cell"><%:Protocol%></div>
<th class="cbi-section-table-cell"><%:Source%></th> <div class="th cbi-section-table-cell"><%:Source%></div>
</tr> </div>
</thead> </div>
<tbody id="olsr_services"> <div class="tbody" id="olsr_services">
<% <%
for k, line in ipairs(services) do for k, line in ipairs(services) do
local field = {} local field = {}
@ -178,15 +177,15 @@ end
local url, proto, descr, origin = pcdata(field[1]), pcdata(field[2]), utl.trim(pcdata(field[3])), pcdata(field[4]) local url, proto, descr, origin = pcdata(field[1]), pcdata(field[2]), utl.trim(pcdata(field[3])), pcdata(field[4])
%> %>
<tr class="cbi-section-table-row cbi-rowstyle-<%=i%>"> <div class="tr cbi-section-table-row cbi-rowstyle-<%=i%>">
<td class="cbi-section-table-titles"><a href="<%=url%>"><%=descr%></a></td> <div class="td cbi-section-table-titles"><a href="<%=url%>"><%=descr%></a></div>
<td class="cbi-section-table-titles"><%=proto%></td> <div class="td cbi-section-table-titles"><%=proto%></div>
<td class="cbi-section-table-titles"><a href="http://<%=origin_link%>/cgi-bin-status.html"><%=origin%></a></td> <div class="td cbi-section-table-titles"><a href="http://<%=origin_link%>/cgi-bin-status.html"><%=origin%></a></div>
</tr> </div>
<% i = ((i % 2) + 1) <% i = ((i % 2) + 1)
end %> end %>
</tbody> </div>
</table> </div>
<br /> <br />
<%=last_update%> <%=last_update%>
</fieldset> </fieldset>

View file

@ -11,7 +11,7 @@ cat<<EOF
</HEAD> </HEAD>
<BODY> <BODY>
<script langauge='JavaScript1.2' type='text/javascript'> <script language='JavaScript1.2' type='text/javascript'>
EOF EOF
# sed + txtinfo plugin # sed + txtinfo plugin

View file

@ -28,7 +28,6 @@ end
<%+header%> <%+header%>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[ <script type="text/javascript">//<![CDATA[
XHR.poll(10, '<%=REQUEST_URI%>', { status: 1 }, XHR.poll(10, '<%=REQUEST_URI%>', { status: 1 },
function(x, info) function(x, info)
@ -41,7 +40,7 @@ XHR.poll(10, '<%=REQUEST_URI%>', { status: 1 },
{ {
var hna = info[idx]; var hna = info[idx];
var linkgw = '' var linkgw = ''
s += '<tr class="cbi-section-table-row cbi-rowstyle-'+(1 + (idx % 2))+' proto-' + hna.proto + '">' s += '<div class="tr cbi-section-table-row cbi-rowstyle-'+(1 + (idx % 2))+' proto-' + hna.proto + '">'
if (hna.proto == '6') { if (hna.proto == '6') {
linkgw = '<a href="http://[' + hna.gateway + ']/cgi-bin-status.html">' + hna.gateway + '</a>' linkgw = '<a href="http://[' + hna.gateway + ']/cgi-bin-status.html">' + hna.gateway + '</a>'
} else { } else {
@ -61,11 +60,11 @@ XHR.poll(10, '<%=REQUEST_URI%>', { status: 1 },
} }
s += String.format( s += String.format(
'<td class="cbi-section-table-cell">%s</td>' + '<div class="td cbi-section-table-cell">%s</div>' +
'<td class="cbi-section-table-cell">%s</td>' + '<div class="td cbi-section-table-cell">%s</div>' +
'<td class="cbi-section-table-cell">%s</td>', hna.destination + '/' + hna.genmask, linkgw + hostname, validity '<div class="td cbi-section-table-cell">%s</div>', hna.destination + '/' + hna.genmask, linkgw + hostname, validity
) )
s += '</tr>' s += '</div>'
} }
hnadiv.innerHTML = s; hnadiv.innerHTML = s;
} }
@ -79,21 +78,21 @@ XHR.poll(10, '<%=REQUEST_URI%>', { status: 1 },
<fieldset class="cbi-section"> <fieldset class="cbi-section">
<legend><%:Overview of currently active OLSR host net announcements%></legend> <legend><%:Overview of currently active OLSR host net announcements%></legend>
<table class="cbi-section-table"> <div class="table cbi-section-table">
<thead> <div class="thead">
<tr class="cbi-section-table-titles"> <div class="tr cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Announced network%></th> <div class="th cbi-section-table-cell"><%:Announced network%></div>
<th class="cbi-section-table-cell"><%:OLSR gateway%></th> <div class="th cbi-section-table-cell"><%:OLSR gateway%></div>
<th class="cbi-section-table-cell"><%:Validity Time%></th> <div class="th cbi-section-table-cell"><%:Validity Time%></div>
</tr> </div>
</thead> </div>
<tbody id="olsrd_hna"> <div class="tbody" id="olsrd_hna">
<% for k, route in ipairs(hna) do %> <% for k, route in ipairs(hna) do %>
<tr class="cbi-section-table-row cbi-rowstyle-<%=i%> proto-<%=hna[k].proto%>"> <div class="tr cbi-section-table-row cbi-rowstyle-<%=i%> proto-<%=hna[k].proto%>">
<td class="cbi-section-table-cell"><%=hna[k].destination%>/<%=hna[k].genmask%> </td> <div class="td cbi-section-table-cell"><%=hna[k].destination%>/<%=hna[k].genmask%> </div>
<td class="cbi-section-table-cell"> <div class="td cbi-section-table-cell">
<% if hna[k].proto == '6' then %> <% if hna[k].proto == '6' then %>
<a href="http://[<%=hna[k].gateway%>]/cgi-bin-status.html"><%=hna[k].gateway%></a> <a href="http://[<%=hna[k].gateway%>]/cgi-bin-status.html"><%=hna[k].gateway%></a>
<% else %> <% else %>
@ -102,20 +101,20 @@ XHR.poll(10, '<%=REQUEST_URI%>', { status: 1 },
<% if hna[k].hostname then %> <% if hna[k].hostname then %>
/ <a href="http://<%=hna[k].hostname%>/cgi-bin-status.html"><%=hna[k].hostname%></a> / <a href="http://<%=hna[k].hostname%>/cgi-bin-status.html"><%=hna[k].hostname%></a>
<% end %> <% end %>
</td> </div>
<% if hna[k].validityTime then <% if hna[k].validityTime then
validity = hna[k].validityTime .. 's' validity = hna[k].validityTime .. 's'
else else
validity = '-' validity = '-'
end %> end %>
<td class="cbi-section-table-cell"><%=validity%></td> <div class="td cbi-section-table-cell"><%=validity%></div>
</tr> </div>
<% i = ((i % 2) + 1) <% i = ((i % 2) + 1)
end %> end %>
</tbody> </div>
</table> </div>
</fieldset> </fieldset>
<%+status-olsr/common_js%> <%+status-olsr/common_js%>

View file

@ -18,31 +18,31 @@ local i = 1
<fieldset class="cbi-section"> <fieldset class="cbi-section">
<legend><%:Overview of interfaces where OLSR is running%></legend> <legend><%:Overview of interfaces where OLSR is running%></legend>
<table class="cbi-section-table"> <div class="table cbi-section-table">
<tr> <div class="tr">
<th class="cbi-section-table-cell"><%:Interface%></th> <div class="th cbi-section-table-cell"><%:Interface%></div>
<th class="cbi-section-table-cell"><%:State%></th> <div class="th cbi-section-table-cell"><%:State%></div>
<th class="cbi-section-table-cell"><%:MTU%></th> <div class="th cbi-section-table-cell"><%:MTU%></div>
<th class="cbi-section-table-cell"><%:WLAN%></th> <div class="th cbi-section-table-cell"><%:WLAN%></div>
<th class="cbi-section-table-cell"><%:Source address%></th> <div class="th cbi-section-table-cell"><%:Source address%></div>
<th class="cbi-section-table-cell"><%:Netmask%></th> <div class="th cbi-section-table-cell"><%:Netmask%></div>
<th class="cbi-section-table-cell"><%:Broadcast address%></th> <div class="th cbi-section-table-cell"><%:Broadcast address%></div>
</tr> </div>
<% for k, iface in ipairs(iface) do %> <% for k, iface in ipairs(iface) do %>
<tr class="cbi-section-table-row cbi-rowstyle-<%=i%> proto-<%=iface.proto%>"> <div class="tr cbi-section-table-row cbi-rowstyle-<%=i%> proto-<%=iface.proto%>">
<td class="cbi-section-table-cell"><%=iface.name%></td> <div class="td cbi-section-table-cell"><%=iface.name%></div>
<td class="cbi-section-table-cell"><%=iface.state%></td> <div class="td cbi-section-table-cell"><%=iface.state%></div>
<td class="cbi-section-table-cell"><%=iface.olsrMTU%></td> <div class="td cbi-section-table-cell"><%=iface.olsrMTU%></div>
<td class="cbi-section-table-cell"><%=iface.wireless and luci.i18n.translate('yes') or luci.i18n.translate('no')%></td> <div class="td cbi-section-table-cell"><%=iface.wireless and luci.i18n.translate('yes') or luci.i18n.translate('no')%></div>
<td class="cbi-section-table-cell"><%=iface.ipv4Address or iface.ipv6Address%></td> <div class="td cbi-section-table-cell"><%=iface.ipv4Address or iface.ipv6Address%></div>
<td class="cbi-section-table-cell"><%=iface.netmask%></td> <div class="td cbi-section-table-cell"><%=iface.netmask%></div>
<td class="cbi-section-table-cell"><%=iface.broadcast or iface.multicast%></td> <div class="td cbi-section-table-cell"><%=iface.broadcast or iface.multicast%></div>
</tr> </div>
<% i = ((i % 2) + 1) <% i = ((i % 2) + 1)
end %> end %>
</table> </div>
</fieldset> </fieldset>
<%+status-olsr/common_js%> <%+status-olsr/common_js%>
<%+footer%> <%+footer%>

View file

@ -15,11 +15,11 @@ local i = 1
<div id="togglebuttons"></div> <div id="togglebuttons"></div>
<fieldset class="cbi-section"> <fieldset class="cbi-section">
<legend><%:Overview of known multiple interface announcements%></legend> <legend><%:Overview of known multiple interface announcements%></legend>
<table class="cbi-section-table"> <div class="table cbi-section-table">
<tr class="cbi-section-table-titles"> <div class="tr cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:OLSR node%></th> <div class="th cbi-section-table-cell"><%:OLSR node%></div>
<th class="cbi-section-table-cell" ><%:Secondary OLSR interfaces%></th> <div class="th cbi-section-table-cell" ><%:Secondary OLSR interfaces%></div>
</tr> </div>
<% for k, mid in ipairs(mids) do <% for k, mid in ipairs(mids) do
local aliases = '' local aliases = ''
@ -37,14 +37,14 @@ local i = 1
end end
%> %>
<tr class="cbi-section-table-row cbi-rowstyle-<%=i%> proto-<%=mid.proto%>"> <div class="tr cbi-section-table-row cbi-rowstyle-<%=i%> proto-<%=mid.proto%>">
<td class="cbi-section-table-cell"><a href="http://<%=host%>/cgi-bin-status.html"><%=mid.ipAddress%></a></td> <div class="td cbi-section-table-cell"><a href="http://<%=host%>/cgi-bin-status.html"><%=mid.ipAddress%></a></div>
<td class="cbi-section-table-cell"><%=aliases%></td> <div class="td cbi-section-table-cell"><%=aliases%></div>
</tr> </div>
<% i = ((i % 2) + 1) <% i = ((i % 2) + 1)
end %> end %>
</table> </div>
</fieldset> </fieldset>
<%+status-olsr/common_js%> <%+status-olsr/common_js%>
<%+footer%> <%+footer%>

View file

@ -48,7 +48,6 @@ end
<%+header%> <%+header%>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[ <script type="text/javascript">//<![CDATA[
XHR.poll(10 , '<%=REQUEST_URI%>', { status: 1 }, XHR.poll(10 , '<%=REQUEST_URI%>', { status: 1 },
@ -64,36 +63,36 @@ end
if (neigh.proto == '6') { if (neigh.proto == '6') {
s += String.format( s += String.format(
'<tr class="cbi-section-table-row cbi-rowstyle-'+(1 + (idx % 2))+' proto-%s">' + '<div class="tr cbi-section-table-row cbi-rowstyle-'+(1 + (idx % 2))+' proto-%s">' +
'<td class="cbi-section-table-titles" style="background-color:%s"><a href="http://[%s]/cgi-bin-status.html">%s</a></td>', '<div class="td cbi-section-table-titles" style="background-color:%s"><a href="http://[%s]/cgi-bin-status.html">%s</a></div>',
neigh.proto, neigh.dfgcolor, neigh.rip, neigh.rip neigh.proto, neigh.dfgcolor, neigh.rip, neigh.rip
); );
} else { } else {
s += String.format( s += String.format(
'<tr class="cbi-section-table-row cbi-rowstyle-'+(1 + (idx % 2))+' proto-%s">' + '<div class="tr cbi-section-table-row cbi-rowstyle-'+(1 + (idx % 2))+' proto-%s">' +
'<td class="cbi-section-table-titles" style="background-color:%s"><a href="http://%s/cgi-bin-status.html">%s</a></td>', '<div class="td cbi-section-table-titles" style="background-color:%s"><a href="http://%s/cgi-bin-status.html">%s</a></div>',
neigh.proto, neigh.dfgcolor, neigh.rip, neigh.rip neigh.proto, neigh.dfgcolor, neigh.rip, neigh.rip
); );
} }
if (neigh.hn) { if (neigh.hn) {
s += String.format( s += String.format(
'<td class="cbi-section-table-titles" style="background-color:%s"><a href="http://%s/cgi-bin-status.html">%s</a></td>', '<div class="td cbi-section-table-titles" style="background-color:%s"><a href="http://%s/cgi-bin-status.html">%s</a></div>',
neigh.dfgcolor, neigh.hn, neigh.hn neigh.dfgcolor, neigh.hn, neigh.hn
); );
} else { } else {
s += String.format( s += String.format(
'<td class="cbi-section-table-titles" style="background-color:%s">?</td>', '<div class="td cbi-section-table-titles" style="background-color:%s">?</div>',
neigh.dfgcolor neigh.dfgcolor
); );
} }
s += String.format( s += String.format(
'<td class="cbi-section-table-titles" style="background-color:%s">%s</td>' + '<div class="td cbi-section-table-titles" style="background-color:%s">%s</div>' +
'<td class="cbi-section-table-titles" style="background-color:%s">%s</td>' + '<div class="td cbi-section-table-titles" style="background-color:%s">%s</div>' +
'<td class="cbi-section-table-titles" style="background-color:%s">%s</td>' + '<div class="td cbi-section-table-titles" style="background-color:%s">%s</div>' +
'<td class="cbi-section-table-titles" style="background-color:%s">%s</td>' + '<div class="td cbi-section-table-titles" style="background-color:%s">%s</div>' +
'<td class="cbi-section-table-titles" style="background-color:%s">%s</td>' + '<div class="td cbi-section-table-titles" style="background-color:%s">%s</div>' +
'<td class="cbi-section-table-titles" style="background-color:%s" title="Signal: %s Noise: %s">%s</td>' + '<div class="td cbi-section-table-titles" style="background-color:%s" title="Signal: %s Noise: %s">%s</div>' +
'</tr>', '</div>',
neigh.dfgcolor, neigh.ifn, neigh.dfgcolor, neigh.lip, neigh.dfgcolor, neigh.lq, neigh.dfgcolor, neigh.nlq, neigh.color, neigh.cost, neigh.snr_color, neigh.signal, neigh.noise, neigh.snr || '?' neigh.dfgcolor, neigh.ifn, neigh.dfgcolor, neigh.lip, neigh.dfgcolor, neigh.lq, neigh.dfgcolor, neigh.nlq, neigh.color, neigh.cost, neigh.snr_color, neigh.signal, neigh.noise, neigh.snr || '?'
); );
} }
@ -112,21 +111,21 @@ end
<fieldset class="cbi-section"> <fieldset class="cbi-section">
<legend><%:Overview of currently established OLSR connections%></legend> <legend><%:Overview of currently established OLSR connections%></legend>
<table class="cbi-section-table"> <div class="table cbi-section-table">
<thead> <div class="thead">
<tr class="cbi-section-table-titles"> <div class="tr cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Neighbour IP%></th> <div class="th cbi-section-table-cell"><%:Neighbour IP%></div>
<th class="cbi-section-table-cell"><%:Hostname%></th> <div class="th cbi-section-table-cell"><%:Hostname%></div>
<th class="cbi-section-table-cell"><%:Interface%></th> <div class="th cbi-section-table-cell"><%:Interface%></div>
<th class="cbi-section-table-cell"><%:Local interface IP%></th> <div class="th cbi-section-table-cell"><%:Local interface IP%></div>
<th class="cbi-section-table-cell">LQ</th> <div class="th cbi-section-table-cell">LQ</div>
<th class="cbi-section-table-cell">NLQ</th> <div class="th cbi-section-table-cell">NLQ</div>
<th class="cbi-section-table-cell">ETX</th> <div class="th cbi-section-table-cell">ETX</div>
<th class="cbi-section-table-cell">SNR</th> <div class="th cbi-section-table-cell">SNR</div>
</tr> </div>
</thead> </div>
<tbody id="olsr_neigh_table"> <div class="tbody" id="olsr_neigh_table">
<% local i = 1 <% local i = 1
for k, link in ipairs(links) do for k, link in ipairs(links) do
link.linkCost = tonumber(link.linkCost) or 0 link.linkCost = tonumber(link.linkCost) or 0
@ -147,25 +146,25 @@ end
end end
%> %>
<tr class="cbi-section-table-row cbi-rowstyle-<%=i%> proto-<%=link.proto%>"> <div class="tr cbi-section-table-row cbi-rowstyle-<%=i%> proto-<%=link.proto%>">
<% if link.proto == "6" then %> <% if link.proto == "6" then %>
<td class="cbi-section-table-titles" style="background-color:<%=defaultgw_color%>"><a href="http://[<%=link.remoteIP%>]/cgi-bin-status.html"><%=link.remoteIP%></a></td> <div class="td cbi-section-table-titles" style="background-color:<%=defaultgw_color%>"><a href="http://[<%=link.remoteIP%>]/cgi-bin-status.html"><%=link.remoteIP%></a></div>
<% else %> <% else %>
<td class="cbi-section-table-titles" style="background-color:<%=defaultgw_color%>"><a href="http://<%=link.remoteIP%>/cgi-bin-status.html"><%=link.remoteIP%></a></td> <div class="td cbi-section-table-titles" style="background-color:<%=defaultgw_color%>"><a href="http://<%=link.remoteIP%>/cgi-bin-status.html"><%=link.remoteIP%></a></div>
<% end %> <% end %>
<td class="cbi-section-table-titles" style="background-color:<%=defaultgw_color%>"><a href="http://<%=link.hostname%>/cgi-bin-status.html"><%=link.hostname%></a></td> <div class="td cbi-section-table-titles" style="background-color:<%=defaultgw_color%>"><a href="http://<%=link.hostname%>/cgi-bin-status.html"><%=link.hostname%></a></div>
<td class="cbi-section-table-titles" style="background-color:<%=defaultgw_color%>"><%=link.interface%></td> <div class="td cbi-section-table-titles" style="background-color:<%=defaultgw_color%>"><%=link.interface%></div>
<td class="cbi-section-table-titles" style="background-color:<%=defaultgw_color%>"><%=link.localIP%></td> <div class="td cbi-section-table-titles" style="background-color:<%=defaultgw_color%>"><%=link.localIP%></div>
<td class="cbi-section-table-titles" style="background-color:<%=defaultgw_color%>"><%=string.format("%.3f", link.linkQuality)%></td> <div class="td cbi-section-table-titles" style="background-color:<%=defaultgw_color%>"><%=string.format("%.3f", link.linkQuality)%></div>
<td class="cbi-section-table-titles" style="background-color:<%=defaultgw_color%>"><%=string.format("%.3f", link.neighborLinkQuality)%></td> <div class="td cbi-section-table-titles" style="background-color:<%=defaultgw_color%>"><%=string.format("%.3f", link.neighborLinkQuality)%></div>
<td class="cbi-section-table-titles" style="background-color:<%=color%>"><%=string.format("%.3f", link.linkCost)%></td> <div class="td cbi-section-table-titles" style="background-color:<%=color%>"><%=string.format("%.3f", link.linkCost)%></div>
<td class="cbi-section-table-titles" style="background-color:<%=snr_color%>" title="Signal: <%=link.signal%> Noise: <%=link.noise%>"><%=link.snr%></td> <div class="td cbi-section-table-titles" style="background-color:<%=snr_color%>" title="Signal: <%=link.signal%> Noise: <%=link.noise%>"><%=link.snr%></div>
</tr> </div>
<% <%
i = ((i % 2) + 1) i = ((i % 2) + 1)
end %> end %>
</tbody> </div>
</table> </div>
<br /> <br />
<%+status-olsr/legend%> <%+status-olsr/legend%>

View file

@ -45,7 +45,6 @@ end
<%+header%> <%+header%>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[ <script type="text/javascript">//<![CDATA[
XHR.poll(10, '<%=REQUEST_URI%>/json', { }, XHR.poll(10, '<%=REQUEST_URI%>/json', { },
@ -160,48 +159,48 @@ XHR.poll(10, '<%=REQUEST_URI%>/json', { },
<fieldset class="cbi-section"> <fieldset class="cbi-section">
<legend><%:Network%></legend> <legend><%:Network%></legend>
<table width="100%" cellspacing="10"> <div class="table" width="100%" cellspacing="10">
<tr><td width="33%"><%:Interfaces%></td><td> <div class="tr"><div class="td" width="33%"><%:Interfaces%></div><div class="td">
<a href="<%=REQUEST_URI%>/interfaces"> <a href="<%=REQUEST_URI%>/interfaces">
<span id="nr_ifaces">-<span> <span id="nr_ifaces">-<span>
</a> </a>
</td></tr> </div></div>
<tr><td width="33%"><%:Neighbors%></td><td> <div class="tr"><div class="td" width="33%"><%:Neighbors%></div><div class="td">
<a href="<%=REQUEST_URI%>/neighbors"> <a href="<%=REQUEST_URI%>/neighbors">
<span id="nr_neigh">-</span> <span id="nr_neigh">-</span>
</a> </a>
</td></tr> </div></div>
<tr><td width="33%"><%:Nodes%></td><td> <div class="tr"><div class="td" width="33%"><%:Nodes%></div><div class="td">
<a href="<%=REQUEST_URI%>/topology"> <a href="<%=REQUEST_URI%>/topology">
<span id="nr_nodes">-</span> <span id="nr_nodes">-</span>
</a> </a>
</td></tr> </div></div>
<tr><td width="33%"><%:HNA%></td><td> <div class="tr"><div class="td" width="33%"><%:HNA%></div><div class="td">
<a href="<%=REQUEST_URI%>/hna"> <a href="<%=REQUEST_URI%>/hna">
<span id="nr_hna">-</span> <span id="nr_hna">-</span>
</a> </a>
</td></tr> </div></div>
<tr><td width="33%"><%:Links total%></td><td> <div class="tr"><div class="td" width="33%"><%:Links total%></div><div class="td">
<a href="<%=REQUEST_URI%>/topology"> <a href="<%=REQUEST_URI%>/topology">
<span id="nr_topo">-</span> <span id="nr_topo">-</span>
</a> </a>
</td></tr> </div></div>
<tr><td width="33%"><%:Links per node (average)%></td><td> <div class="tr"><div class="td" width="33%"><%:Links per node (average)%></div><div class="td">
<span id="meshfactor">-</span> <span id="meshfactor">-</span>
</td></tr> </div></div>
</table> </div>
</fieldset> </fieldset>
<fieldset class="cbi-section"> <fieldset class="cbi-section">
<legend>OLSR <%:Configuration%></legend> <legend>OLSR <%:Configuration%></legend>
<table width="100%" cellspacing="10"> <div class="table" width="100%" cellspacing="10">
<tr><td width="33%"><%:Version%></td><td> <div class="tr"><div class="td" width="33%"><%:Version%></div><div class="td">
<span id="version">-<span> <span id="version">-<span>
</td></tr> </div></div>
<tr><td width="33%"><%:Download Config%></td><td> <div class="tr"><div class="td" width="33%"><%:Download Config%></div><div class="td">
<% if has_ipv4_conf then %> <% if has_ipv4_conf then %>
<a href="<%=REQUEST_URI%>?openwrt_v4">OpenWrt (IPv4)</a>, <a href="<%=REQUEST_URI%>?openwrt_v4">OpenWrt (IPv4)</a>,
<% end %> <% end %>
@ -214,8 +213,8 @@ XHR.poll(10, '<%=REQUEST_URI%>/json', { },
<% if has_ipv6_conf then %> <% if has_ipv6_conf then %>
<a href="<%=REQUEST_URI%>?conf_v6">OLSRD (IPv6)</a> <a href="<%=REQUEST_URI%>?conf_v6">OLSRD (IPv6)</a>
<% end %> <% end %>
</td></tr> </div></div>
</table> </div>
</fieldset> </fieldset>
<%+footer%> <%+footer%>

View file

@ -34,7 +34,6 @@ end
<%+header%> <%+header%>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[ <script type="text/javascript">//<![CDATA[
XHR.poll(20, '<%=REQUEST_URI%>', { status: 1 }, XHR.poll(20, '<%=REQUEST_URI%>', { status: 1 },
@ -50,9 +49,9 @@ XHR.poll(20, '<%=REQUEST_URI%>', { status: 1 },
var route = info[idx]; var route = info[idx];
s += String.format( s += String.format(
'<tr class="cbi-section-table-row cbi-rowstyle-'+(1 + (idx % 2))+' proto-%s">' + '<div class="tr cbi-section-table-row cbi-rowstyle-'+(1 + (idx % 2))+' proto-%s">' +
'<td class="cbi-section-table-cell">%s/%s</td>' + '<div class="td cbi-section-table-cell">%s/%s</div>' +
'<td class="cbi-section-table-cell">' + '<div class="td cbi-section-table-cell">' +
'<a href="http://%s/cgi-bin-status.html">%s</a>', '<a href="http://%s/cgi-bin-status.html">%s</a>',
route.proto, route.dest, route.genmask, route.gw, route.gw route.proto, route.dest, route.genmask, route.gw, route.gw
) )
@ -72,11 +71,11 @@ XHR.poll(20, '<%=REQUEST_URI%>', { status: 1 },
} }
s += String.format( s += String.format(
'</td>' + '</div>' +
'<td class="cbi-section-table-cell">%s</td>' + '<div class="td cbi-section-table-cell">%s</div>' +
'<td class="cbi-section-table-cell">%s</td>' + '<div class="td cbi-section-table-cell">%s</div>' +
'<td class="cbi-section-table-cell" style="background-color:%s">%s</td>' + '<div class="td cbi-section-table-cell" style="background-color:%s">%s</div>' +
'</tr>', '</div>',
route.interface, route.metric, route.color, route.etx || '?' route.interface, route.metric, route.color, route.etx || '?'
); );
} }
@ -96,27 +95,27 @@ XHR.poll(20, '<%=REQUEST_URI%>', { status: 1 },
<fieldset class="cbi-section"> <fieldset class="cbi-section">
<legend><%:Overview of currently known routes to other OLSR nodes%></legend> <legend><%:Overview of currently known routes to other OLSR nodes%></legend>
<table class="cbi-section-table"> <div class="table cbi-section-table">
<thead> <div class="thead">
<tr class="cbi-section-table-titles"> <div class="tr cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Announced network%></th> <div class="th cbi-section-table-cell"><%:Announced network%></div>
<th class="cbi-section-table-cell"><%:OLSR gateway%></th> <div class="th cbi-section-table-cell"><%:OLSR gateway%></div>
<th class="cbi-section-table-cell"><%:Interface%></th> <div class="th cbi-section-table-cell"><%:Interface%></div>
<th class="cbi-section-table-cell"><%:Metric%></th> <div class="th cbi-section-table-cell"><%:Metric%></div>
<th class="cbi-section-table-cell">ETX</th> <div class="th cbi-section-table-cell">ETX</div>
</tr> </div>
</thead> </div>
<tbody id="olsrd_routes"> <div class="tbody" id="olsrd_routes">
<% for k, route in ipairs(routes) do <% for k, route in ipairs(routes) do
ETX = tonumber(route.rtpMetricCost)/1024 or '0' ETX = tonumber(route.rtpMetricCost)/1024 or '0'
color = olsrtools.etx_color(ETX) color = olsrtools.etx_color(ETX)
%> %>
<tr class="cbi-section-table-row cbi-rowstyle-<%=i%> proto-<%=route.proto%>"> <div class="tr cbi-section-table-row cbi-rowstyle-<%=i%> proto-<%=route.proto%>">
<td class="cbi-section-table-cell"><%=route.destination%>/<%=route.genmask%></td> <div class="td cbi-section-table-cell"><%=route.destination%>/<%=route.genmask%></div>
<td class="cbi-section-table-cell"> <div class="td cbi-section-table-cell">
<% if route.proto == '6' then %> <% if route.proto == '6' then %>
<a href="http://[<%=route.gateway%>]/cgi-bin-status.html"><%=route.gateway%></a> <a href="http://[<%=route.gateway%>]/cgi-bin-status.html"><%=route.gateway%></a>
<% else %> <% else %>
@ -125,16 +124,16 @@ XHR.poll(20, '<%=REQUEST_URI%>', { status: 1 },
<% if route.hostname then %> <% if route.hostname then %>
/ <a href="http://<%=route.Hostname%>/cgi-bin-status.html"><%=route.hostname%></a> / <a href="http://<%=route.Hostname%>/cgi-bin-status.html"><%=route.hostname%></a>
<% end %> <% end %>
</td> </div>
<td class="cbi-section-table-cell"><%=route.networkInterface%></td> <div class="td cbi-section-table-cell"><%=route.networkInterface%></div>
<td class="cbi-section-table-cell"><%=route.metric%></td> <div class="td cbi-section-table-cell"><%=route.metric%></div>
<td class="cbi-section-table-cell" style="background-color:<%=color%>"><%=string.format("%.3f", ETX)%></td> <div class="td cbi-section-table-cell" style="background-color:<%=color%>"><%=string.format("%.3f", ETX)%></div>
</tr> </div>
<% <%
i = ((i % 2) + 1) i = ((i % 2) + 1)
end %> end %>
</tbody> </div>
</table> </div>
<%+status-olsr/legend%> <%+status-olsr/legend%>
</fieldset> </fieldset>

View file

@ -44,7 +44,6 @@ end
<%+header%> <%+header%>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[ <script type="text/javascript">//<![CDATA[
XHR.poll(10, '<%=REQUEST_URI%>', { status: 1 }, XHR.poll(10, '<%=REQUEST_URI%>', { status: 1 },
function(x, info) function(x, info)
@ -56,7 +55,7 @@ XHR.poll(10, '<%=REQUEST_URI%>', { status: 1 },
for (var idx = 0; idx < info.length; idx++) for (var idx = 0; idx < info.length; idx++)
{ {
var smartgw = info[idx]; var smartgw = info[idx];
s += '<tr class="cbi-section-table-row cbi-rowstyle-'+(1 + (idx % 2))+' proto-' + smartgw.proto + '">' s += '<div class="tr cbi-section-table-row cbi-rowstyle-'+(1 + (idx % 2))+' proto-' + smartgw.proto + '">'
if (smartgw.proto == '6') { if (smartgw.proto == '6') {
linkgw = '<a href="http://[' + smartgw.ipAddress + ']/cgi-bin-status.html">' + smartgw.ipAddress + '</a>' linkgw = '<a href="http://[' + smartgw.ipAddress + ']/cgi-bin-status.html">' + smartgw.ipAddress + '</a>'
} else { } else {
@ -64,18 +63,18 @@ XHR.poll(10, '<%=REQUEST_URI%>', { status: 1 },
} }
s += String.format( s += String.format(
'<td class="cbi-section-table-cell">%s</td>' + '<div class="td cbi-section-table-cell">%s</div>' +
'<td class="cbi-section-table-cell">%s</td>' + '<div class="td cbi-section-table-cell">%s</div>' +
'<td class="cbi-section-table-cell">%s</td>' + '<div class="td cbi-section-table-cell">%s</div>' +
'<td class="cbi-section-table-cell">%s</td>' + '<div class="td cbi-section-table-cell">%s</div>' +
'<td class="cbi-section-table-cell">%s</td>' + '<div class="td cbi-section-table-cell">%s</div>' +
'<td class="cbi-section-table-cell">%s</td>' + '<div class="td cbi-section-table-cell">%s</div>' +
'<td class="cbi-section-table-cell">%s</td>' + '<div class="td cbi-section-table-cell">%s</div>' +
'<td class="cbi-section-table-cell">%s</td>' + '<div class="td cbi-section-table-cell">%s</div>' +
'<td class="cbi-section-table-cell">%s</td>', '<div class="td cbi-section-table-cell">%s</div>',
linkgw, smartgw.status, smartgw.tcPathCost, smartgw.hopCount, smartgw.uplinkSpeed, smartgw.downlinkSpeed, smartgw.v4, smartgw.v6, smartgw.externalPrefix linkgw, smartgw.status, smartgw.tcPathCost, smartgw.hopCount, smartgw.uplinkSpeed, smartgw.downlinkSpeed, smartgw.v4, smartgw.v6, smartgw.externalPrefix
) )
s += '</tr>' s += '</div>'
} }
smartgwdiv.innerHTML = s; smartgwdiv.innerHTML = s;
} }
@ -94,23 +93,23 @@ XHR.poll(10, '<%=REQUEST_URI%>', { status: 1 },
<fieldset class="cbi-section"> <fieldset class="cbi-section">
<legend><%:Overview of smart gateways in this network%></legend> <legend><%:Overview of smart gateways in this network%></legend>
<table class="cbi-section-table"> <div class="table cbi-section-table">
<thead> <div class="thead">
<tr class="cbi-section-table-titles"> <div class="tr cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Gateway%></th> <div class="th cbi-section-table-cell"><%:Gateway%></div>
<th class="cbi-section-table-cell"><%:Status%></th> <div class="th cbi-section-table-cell"><%:Status%></div>
<th class="cbi-section-table-cell"><%:ETX%></th> <div class="th cbi-section-table-cell"><%:ETX%></div>
<th class="cbi-section-table-cell"><%:Hops%></th> <div class="th cbi-section-table-cell"><%:Hops%></div>
<th class="cbi-section-table-cell"><%:Uplink%></th> <div class="th cbi-section-table-cell"><%:Uplink%></div>
<th class="cbi-section-table-cell"><%:Downlink%></th> <div class="th cbi-section-table-cell"><%:Downlink%></div>
<th class="cbi-section-table-cell"><%:IPv4%></th> <div class="th cbi-section-table-cell"><%:IPv4%></div>
<th class="cbi-section-table-cell"><%:IPv6%></th> <div class="th cbi-section-table-cell"><%:IPv6%></div>
<th class="cbi-section-table-cell"><%:Prefix%></th> <div class="th cbi-section-table-cell"><%:Prefix%></div>
</tr> </div>
</thead> </div>
<tbody id="olsrd_smartgw"> <div class="tbody" id="olsrd_smartgw">
<% for k, gw in ipairs(gws) do <% for k, gw in ipairs(gws) do
gw.tcPathCost = tonumber(gw.tcPathCost)/1024 or 0 gw.tcPathCost = tonumber(gw.tcPathCost)/1024 or 0
@ -119,27 +118,27 @@ XHR.poll(10, '<%=REQUEST_URI%>', { status: 1 },
end end
%> %>
<tr class="cbi-section-table-row cbi-rowstyle-<%=i%> proto-<%=proto%>"> <div class="tr cbi-section-table-row cbi-rowstyle-<%=i%> proto-<%=proto%>">
<% if gw.proto == '6' then %> <% if gw.proto == '6' then %>
<td class="cbi-section-table-cell"><a href="http://[<%=gw.ipAddress%>]/cgi-bin-status.html"><%=gw.ipAddress%></a></td> <div class="td cbi-section-table-cell"><a href="http://[<%=gw.ipAddress%>]/cgi-bin-status.html"><%=gw.ipAddress%></a></div>
<% else %> <% else %>
<td class="cbi-section-table-cell"><a href="http://<%=gw.ipAddress%>/cgi-bin-status.html"><%=gw.ipAddress%></a></td> <div class="td cbi-section-table-cell"><a href="http://<%=gw.ipAddress%>/cgi-bin-status.html"><%=gw.ipAddress%></a></div>
<% end %> <% end %>
<td class="cbi-section-table-cell"><%=gw.ipv4Status or gw.ipv6Status or '-' %></td> <div class="td cbi-section-table-cell"><%=gw.ipv4Status or gw.ipv6Status or '-' %></div>
<td class="cbi-section-table-cell"><%=string.format("%.3f", gw.tcPathCost)%></td> <div class="td cbi-section-table-cell"><%=string.format("%.3f", gw.tcPathCost)%></div>
<td class="cbi-section-table-cell"><%=gw.hopCount%></td> <div class="td cbi-section-table-cell"><%=gw.hopCount%></div>
<td class="cbi-section-table-cell"><%=gw.uplinkSpeed%></td> <div class="td cbi-section-table-cell"><%=gw.uplinkSpeed%></div>
<td class="cbi-section-table-cell"><%=gw.downlinkSpeed%></td> <div class="td cbi-section-table-cell"><%=gw.downlinkSpeed%></div>
<td class="cbi-section-table-cell"><%=gw.ipv4 and luci.i18n.translate('yes') or luci.i18n.translate('no')%></td> <div class="td cbi-section-table-cell"><%=gw.ipv4 and luci.i18n.translate('yes') or luci.i18n.translate('no')%></div>
<td class="cbi-section-table-cell"><%=gw.ipv6 and luci.i18n.translate('yes') or luci.i18n.translate('no')%></td> <div class="td cbi-section-table-cell"><%=gw.ipv6 and luci.i18n.translate('yes') or luci.i18n.translate('no')%></div>
<td class="cbi-section-table-cell"><%=gw.externalPrefix%></td> <div class="td cbi-section-table-cell"><%=gw.externalPrefix%></div>
</tr> </div>
<% i = ((i % 2) + 1) <% i = ((i % 2) + 1)
end %> end %>
</tbody> </div>
</table> </div>
</fieldset> </fieldset>
<% else %> <% else %>

View file

@ -17,14 +17,14 @@ local olsrtools = require "luci.tools.olsr"
<fieldset class="cbi-section"> <fieldset class="cbi-section">
<legend><%:Overview of currently known OLSR nodes%></legend> <legend><%:Overview of currently known OLSR nodes%></legend>
<table class="cbi-section-table"> <div class="table cbi-section-table">
<tr class="cbi-section-table-titles"> <div class="tr cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:OLSR node%></th> <div class="th cbi-section-table-cell"><%:OLSR node%></div>
<th class="cbi-section-table-cell"><%:Last hop%></th> <div class="th cbi-section-table-cell"><%:Last hop%></div>
<th class="cbi-section-table-cell"><%:LQ%></th> <div class="th cbi-section-table-cell"><%:LQ%></div>
<th class="cbi-section-table-cell"><%:NLQ%></th> <div class="th cbi-section-table-cell"><%:NLQ%></div>
<th class="cbi-section-table-cell"><%:ETX%></th> <div class="th cbi-section-table-cell"><%:ETX%></div>
</tr> </div>
<% for k, route in ipairs(routes) do <% for k, route in ipairs(routes) do
local cost = string.format("%.3f", tonumber(route.tcEdgeCost/1024) or 0) local cost = string.format("%.3f", tonumber(route.tcEdgeCost/1024) or 0)
@ -33,28 +33,28 @@ local olsrtools = require "luci.tools.olsr"
local nlq = string.format("%.3f", tonumber(route.neighborLinkQuality) or 0) local nlq = string.format("%.3f", tonumber(route.neighborLinkQuality) or 0)
%> %>
<tr class="cbi-section-table-row cbi-rowstyle-<%=i%> proto-<%=route.proto%>"> <div class="tr cbi-section-table-row cbi-rowstyle-<%=i%> proto-<%=route.proto%>">
<% if route.proto == "6" then %> <% if route.proto == "6" then %>
<td class="cbi-section-table-cell"><a href="http://[<%=route.destinationIP%>]/cgi-bin-status.html"><%=route.destinationIP%></a></td> <div class="td cbi-section-table-cell"><a href="http://[<%=route.destinationIP%>]/cgi-bin-status.html"><%=route.destinationIP%></a></div>
<td class="cbi-section-table-cell"><a href="http://[<%=route.lastHopIP%>]/cgi-bin-status.html"><%=route.lastHopIP%></a></td> <div class="td cbi-section-table-cell"><a href="http://[<%=route.lastHopIP%>]/cgi-bin-status.html"><%=route.lastHopIP%></a></div>
<% else %> <% else %>
<td class="cbi-section-table-cell"><a href="http://<%=route.destinationIP%>/cgi-bin-status.html"><%=route.destinationIP%></a></td> <div class="td cbi-section-table-cell"><a href="http://<%=route.destinationIP%>/cgi-bin-status.html"><%=route.destinationIP%></a></div>
<td class="cbi-section-table-cell"><a href="http://<%=route.lastHopIP%>/cgi-bin-status.html"><%=route.lastHopIP%></a></td> <div class="td cbi-section-table-cell"><a href="http://<%=route.lastHopIP%>/cgi-bin-status.html"><%=route.lastHopIP%></a></div>
<%end%> <%end%>
<td class="cbi-section-table-cell"><%=lq%></td> <div class="td cbi-section-table-cell"><%=lq%></div>
<td class="cbi-section-table-cell"><%=nlq%></td> <div class="td cbi-section-table-cell"><%=nlq%></div>
<td class="cbi-section-table-cell" style="background-color:<%=color%>"><%=cost%></td> <div class="td cbi-section-table-cell" style="background-color:<%=color%>"><%=cost%></div>
</tr> </div>
<% i = ((i % 2) + 1) <% i = ((i % 2) + 1)
end %> end %>
</table> </div>
<%+status-olsr/legend%> <%+status-olsr/legend%>
</fieldset> </fieldset>

View file

@ -56,7 +56,7 @@ function s.create(self, name)
luci.cbi.CREATE_PREFIX .. self.config .. "." .. luci.cbi.CREATE_PREFIX .. self.config .. "." ..
self.sectiontype .. ".text" self.sectiontype .. ".text"
) )
if string.len(name)>3 and not name:match("[^a-zA-Z0-9_]") then if #name > 3 and not name:match("[^a-zA-Z0-9_]") then
uci:section( uci:section(
"openvpn", "openvpn", name, "openvpn", "openvpn", name,
uci:get_all( "openvpn_recipes", recipe ) uci:get_all( "openvpn_recipes", recipe )
@ -67,9 +67,11 @@ function s.create(self, name)
uci:save("openvpn") uci:save("openvpn")
luci.http.redirect( self.extedit:format(name) ) luci.http.redirect( self.extedit:format(name) )
else elseif #name > 0 then
self.invalid_cts = true self.invalid_cts = true
end end
return 0
end end
@ -103,10 +105,7 @@ function updown.cfgvalue(self, section)
end end
function updown.write(self, section, value) function updown.write(self, section, value)
if self.option == "stop" then if self.option == "stop" then
local pid = s.getPID(section) luci.sys.call("/etc/init.d/openvpn stop %s" % section)
if pid ~= nil then
sys.process.signal(pid,15)
end
else else
luci.sys.call("/etc/init.d/openvpn start %s" % section) luci.sys.call("/etc/init.d/openvpn start %s" % section)
end end
@ -126,5 +125,8 @@ function proto.cfgvalue(self, section)
return val or "udp" return val or "udp"
end end
function m.on_after_commit(self,map)
require("luci.sys").call('/etc/init.d/openvpn reload')
end
return m return m

View file

@ -2,12 +2,23 @@
<div class="errorbox"><%=pcdata(msg)%></div> <div class="errorbox"><%=pcdata(msg)%></div>
<%- end end -%> <%- end end -%>
<%-+cbi/apply_xhr-%>
<div class="cbi-map" id="cbi-<%=self.config%>"> <div class="cbi-map" id="cbi-<%=self.config%>">
<% if self.title and #self.title > 0 then %><h2 name="content"><%=self.title%></h2><% end %> <% if self.title and #self.title > 0 then %><h2 name="content"><%=self.title%></h2><% end %>
<% if self.description and #self.description > 0 then %><div class="cbi-map-descr"><%=self.description%></div><% end %> <% if self.description and #self.description > 0 then %><div class="cbi-map-descr"><%=self.description%></div><% end %>
<%- if firstmap and applymap then cbi_apply_xhr(self.config, parsechain, redirect) end -%> <%- if firstmap and (applymap or confirmmap) then -%>
<%+cbi/apply_widget%>
<% cbi_apply_widget() %>
<div class="alert-message" id="cbi_apply_status" style="display:none"></div>
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function() {
<% if confirmmap then -%>
uci_confirm(true, Date.now() + <%=confirmmap%> * 1000);
<%- else -%>
uci_apply(true);
<%- end %>
});
</script>
<%- end -%>
<% if self.tabbed then %> <% if self.tabbed then %>
<ul class="cbi-tabmenu map"> <ul class="cbi-tabmenu map">

View file

@ -7,7 +7,7 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
LUCI_TITLE:=Roaring Penguing PPPoE Server LUCI_TITLE:=Roaring Penguin PPPoE Server
LUCI_DEPENDS:=+rp-pppoe-server LUCI_DEPENDS:=+rp-pppoe-server
include ../../luci.mk include ../../luci.mk

View file

@ -1,24 +1,17 @@
<div class="cbi-section-create cbi-tblsection-create"> <div class="cbi-section-create cbi-tblsection-create">
<br /> <div>
<table class="cbi-section-table"> <select class="cbi-input-select" id="_newinst.type" name="_newinst.type">
<tr class="cbi-section-table-row"> <option value="_dummy">-- instance type --</option>
<td class="cbi-section-table-cell" style="width:140px"> <option value="ss_local">ss-local</option>
<select class="cbi-input-select" id="_newinst.type" name="_newinst.type"> <option value="ss_tunnel">ss-tunnel</option>
<option value="_dummy">-- instance type --</option> <option value="ss_redir">ss-redir</option>
<option value="ss_local">ss-local</option> <option value="ss_server">ss-server</option>
<option value="ss_tunnel">ss-tunnel</option> </select>
<option value="ss_redir">ss-redir</option> </div>
<option value="ss_server">ss-server</option> <div>
</select> <input type="text" class="cbi-input-text" id="_newinst.name" name="_newinst.name" placeholder="<%:Name%>"/>
</td> </div>
<td class="cbi-section-table-cell" style="width:110px"> <input type="submit" class="cbi-button cbi-button-add" name="cbi.cts.<%=self.config%>" value="<%:Add%>" />
<input type="text" class="cbi-input-text" id="_newinst.name" name="_newinst.name" placeholder="<%:Name%>"/>
</td>
<td class="cbi-section-table-cell left">
<input type="submit" class="cbi-button cbi-button-add" name="cbi.cts.<%=self.config%>" value="<%:Add%>" />
</td>
</tr>
</table>
</div> </div>
<script type="text/javascript">//<![CDATA[ <script type="text/javascript">//<![CDATA[
XHR.poll(5, '<%=url('admin/services/shadowsocks-libev/status')%>', null, XHR.poll(5, '<%=url('admin/services/shadowsocks-libev/status')%>', null,

View file

@ -134,7 +134,6 @@ end
<%+header%> <%+header%>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<script type="text/javascript">//<![CDATA[ <script type="text/javascript">//<![CDATA[
XHR.poll(10 , '<%=REQUEST_URI%>', { status: 1 }, XHR.poll(10 , '<%=REQUEST_URI%>', { status: 1 },
@ -145,19 +144,19 @@ end
{ {
var s = ''; var s = '';
if (info.length == undefined) { if (info.length == undefined) {
s += '<tr class="cbi-section-table-row"><td colspan="7" class="cbi-section-table-cell"><br /><em><%:No clients connected%></em><br /></td></tr>' s += '<div class="tr cbi-section-table-row"><div colspan="7" class="td cbi-section-table-cell"><br /><em><%:No clients connected%></em><br /></div></div>'
}; };
for (var idx = 0; idx < info.length; idx++) for (var idx = 0; idx < info.length; idx++)
{ {
var splash = info[idx]; var splash = info[idx];
s += String.format( s += String.format(
'<tr class="cbi-section-table-row cbi-rowstyle-'+(1 + (idx % 2))+'">' + '<div class="tr cbi-section-table-row cbi-rowstyle-'+(1 + (idx % 2))+'">' +
'<td class="cbi-section-table-cell">%s</td>' + '<div class="td cbi-section-table-cell">%s</div>' +
'<td class="cbi-section-table-cell">%s</td>' + '<div class="td cbi-section-table-cell">%s</div>' +
'<td class="cbi-section-table-cell">%s</td>' + '<div class="td cbi-section-table-cell">%s</div>' +
'<td class="cbi-section-table-cell">%s</td>' + '<div class="td cbi-section-table-cell">%s</div>' +
'<td class="cbi-section-table-cell">%s/%s</td>' + '<div class="td cbi-section-table-cell">%s/%s</div>' +
'<td class="cbi-section-table-cell">', '<div class="td cbi-section-table-cell">',
splash.hostname, splash.ip, splash.mac, splash.timeleft, splash.trafficin, splash.trafficout); splash.hostname, splash.ip, splash.mac, splash.timeleft, splash.trafficin, splash.trafficout);
<% if is_admin then %> <% if is_admin then %>
@ -185,7 +184,7 @@ end
<% else %> <% else %>
s += String.format('%s', splash.policy); s += String.format('%s', splash.policy);
<% end %> <% end %>
s += '</td></tr>' s += '</div></div>'
} }
tbody.innerHTML = s; tbody.innerHTML = s;
} }
@ -200,18 +199,18 @@ end
<legend><%:Active Clients%></legend> <legend><%:Active Clients%></legend>
<div class="cbi-section-node"> <div class="cbi-section-node">
<% if is_admin then %><form action="<%=REQUEST_URI%>" method="post"><input type="hidden" name="token" value="<%=token%>" /><% end %> <% if is_admin then %><form action="<%=REQUEST_URI%>" method="post"><input type="hidden" name="token" value="<%=token%>" /><% end %>
<table class="cbi-section-table"> <div class="table cbi-section-table">
<thead> <div class="thead">
<tr class="cbi-section-table-titles"> <div class="tr cbi-section-table-titles">
<th class="cbi-section-table-cell"><%:Hostname%></th> <div class="th cbi-section-table-cell"><%:Hostname%></div>
<th class="cbi-section-table-cell"><%:IP Address%></th> <div class="th cbi-section-table-cell"><%:IP Address%></div>
<th class="cbi-section-table-cell"><%:MAC Address%></th> <div class="th cbi-section-table-cell"><%:MAC Address%></div>
<th class="cbi-section-table-cell"><%:Time remaining%></th> <div class="th cbi-section-table-cell"><%:Time remaining%></div>
<th class="cbi-section-table-cell"><%:Traffic in/out%></th> <div class="th cbi-section-table-cell"><%:Traffic in/out%></div>
<th class="cbi-section-table-cell"><%:Policy%></th> <div class="th cbi-section-table-cell"><%:Policy%></div>
</tr> </div>
</thead> </div>
<tbody id="splash_table"> <div class="tbody" id="splash_table">
<%- <%-
local count = 0 local count = 0
@ -227,16 +226,16 @@ end
if c.ip then if c.ip then
count = count + 1 count = count + 1
-%> -%>
<tr class="cbi-section-table-row cbi-rowstyle-<%=2-(count%2)%>"> <div class="tr cbi-section-table-row cbi-rowstyle-<%=2-(count%2)%>">
<td class="cbi-section-table-cell"><%=c.hostname or "<em>" .. translate("unknown") .. "</em>"%></td> <div class="td cbi-section-table-cell"><%=c.hostname or "<em>" .. translate("unknown") .. "</em>"%></div>
<td class="cbi-section-table-cell"><%=c.ip or "<em>" .. translate("unknown") .. "</em>"%></td> <div class="td cbi-section-table-cell"><%=c.ip or "<em>" .. translate("unknown") .. "</em>"%></div>
<td class="cbi-section-table-cell"><%=showmac(c.mac)%></td> <div class="td cbi-section-table-cell"><%=showmac(c.mac)%></div>
<td class="cbi-section-table-cell"><%= <div class="td cbi-section-table-cell"><%=
(c.limit >= os.time()) and wat.date_format(c.limit-os.time()) or (c.limit >= os.time()) and wat.date_format(c.limit-os.time()) or
(c.policy ~= "normal") and "-" or "<em>" .. translate("expired") .. "</em>" (c.policy ~= "normal") and "-" or "<em>" .. translate("expired") .. "</em>"
%></td> %></div>
<td class="cbi-section-table-cell"><%=wat.byte_format(c.bytes_in)%> / <%=wat.byte_format(c.bytes_out)%></td> <div class="td cbi-section-table-cell"><%=wat.byte_format(c.bytes_in)%> / <%=wat.byte_format(c.bytes_out)%></div>
<td class="cbi-section-table-cell"> <div class="td cbi-section-table-cell">
<% if is_admin then %> <% if is_admin then %>
<select name="policy.<%=c.mac:lower()%>" style="width:200px"> <select name="policy.<%=c.mac:lower()%>" style="width:200px">
<option value="whitelist"<%=c.policy=="whitelist" and ' selected="selected"'%>><%:whitelisted%></option> <option value="whitelist"<%=c.policy=="whitelist" and ' selected="selected"'%>><%:whitelisted%></option>
@ -250,21 +249,21 @@ end
<% else %> <% else %>
<%=c.policy%> <%=c.policy%>
<% end %> <% end %>
</td> </div>
</tr> </div>
<%- <%-
end end
end end
if count == 0 then if count == 0 then
-%> -%>
<tr class="cbi-section-table-row"> <div class="tr cbi-section-table-row">
<td colspan="7" class="cbi-section-table-cell"> <div colspan="7" class="td cbi-section-table-cell">
<br /><em><%:No clients connected%></em><br /> <br /><em><%:No clients connected%></em><br />
</td> </div>
</tr> </div>
<%- end -%> <%- end -%>
</tbody> </div>
</table> </div>
<% if is_admin then %></form><% end %> <% if is_admin then %></form><% end %>
</div> </div>
</fieldset> </fieldset>

Some files were not shown because too many files have changed in this diff Show more