Merge pull request #1490 from dibdot/adblock
authorHannu Nyman <hannu.nyman@iki.fi>
Thu, 28 Dec 2017 17:23:37 +0000 (19:23 +0200)
committerGitHub <noreply@github.com>
Thu, 28 Dec 2017 17:23:37 +0000 (19:23 +0200)
luci-app-adblock: sync with adblock 3.4.0

57 files changed:
applications/luci-app-advanced-reboot/Makefile
applications/luci-app-advanced-reboot/README.md
applications/luci-app-advanced-reboot/luasrc/controller/advanced_reboot.lua
applications/luci-app-advanced-reboot/luasrc/view/advanced_reboot/advanced_reboot.htm
applications/luci-app-advanced-reboot/po/sv/luci-app-advanced-reboot.po
applications/luci-app-advanced-reboot/po/templates/luci-app-advanced-reboot.pot
applications/luci-app-attendedsysupgrade/luasrc/view/attendedsysupgrade.htm
applications/luci-app-attendedsysupgrade/root/usr/share/rpcd/acl.d/attendedsysupgrade.json
applications/luci-app-attendedsysupgrade/root/www/luci-static/resources/attendedsysupgrade.js [new file with mode: 0644]
applications/luci-app-mwan3/luasrc/model/cbi/mwan/memberconfig.lua
applications/luci-app-mwan3/po/ja/mwan3.po
applications/luci-app-mwan3/po/templates/mwan3.pot
applications/luci-app-mwan3/po/zh-cn/mwan3.po
applications/luci-app-mwan3/po/zh-tw/mwan3.po
applications/luci-app-travelmate/luasrc/controller/travelmate.lua
applications/luci-app-travelmate/luasrc/model/cbi/travelmate/overview_tab.lua
applications/luci-app-travelmate/luasrc/model/cbi/travelmate/wifi_add.lua
applications/luci-app-travelmate/luasrc/model/cbi/travelmate/wifi_edit.lua
applications/luci-app-travelmate/luasrc/view/travelmate/config_css.htm
applications/luci-app-travelmate/luasrc/view/travelmate/stations.htm
applications/luci-app-travelmate/luasrc/view/travelmate/wifi_scan.htm
applications/luci-app-travelmate/po/ja/travelmate.po
applications/luci-app-travelmate/po/pt-br/travelmate.po
applications/luci-app-travelmate/po/templates/travelmate.pot
applications/luci-app-upnp/po/ja/upnp.po
documentation/api/modules/nixio.fs.html
libs/luci-lib-nixio/docsrc/nixio.fs.lua
modules/luci-base/po/ca/base.po
modules/luci-base/po/cs/base.po
modules/luci-base/po/de/base.po
modules/luci-base/po/el/base.po
modules/luci-base/po/en/base.po
modules/luci-base/po/es/base.po
modules/luci-base/po/fr/base.po
modules/luci-base/po/he/base.po
modules/luci-base/po/hu/base.po
modules/luci-base/po/it/base.po
modules/luci-base/po/ja/base.po
modules/luci-base/po/ko/base.po
modules/luci-base/po/ms/base.po
modules/luci-base/po/no/base.po
modules/luci-base/po/pl/base.po
modules/luci-base/po/pt-br/base.po
modules/luci-base/po/pt/base.po
modules/luci-base/po/ro/base.po
modules/luci-base/po/ru/base.po
modules/luci-base/po/sk/base.po
modules/luci-base/po/sv/base.po
modules/luci-base/po/templates/base.pot
modules/luci-base/po/tr/base.po
modules/luci-base/po/uk/base.po
modules/luci-base/po/vi/base.po
modules/luci-base/po/zh-cn/base.po
modules/luci-base/po/zh-tw/base.po
modules/luci-mod-admin-full/luasrc/model/cbi/admin_system/fstab.lua
modules/luci-mod-admin-full/luasrc/view/admin_network/lease_status.htm
modules/luci-mod-admin-full/luasrc/view/admin_status/index.htm

index 3a886eb..5722b42 100644 (file)
@@ -7,13 +7,13 @@ PKG_LICENSE:=GPL-3.0+
 PKG_MAINTAINER:=Stan Grishin <stangri@melmac.net>
 
 LUCI_TITLE:=Advanced Linksys Reboot Web UI
-LUCI_DESCRIPTION:=Provides Web UI (found under System/Advanced Reboot) to reboot supported Linksys routers to\
+LUCI_DESCRIPTION:=Provides Web UI (found under System/Advanced Reboot) to reboot supported Linksys and ZyXEL routers to\
        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
 
 LUCI_DEPENDS:=+luci
 LUCI_PKGARCH:=all
-PKG_RELEASE:=23
+PKG_RELEASE:=25
 
 include ../../luci.mk
 
index ee87a00..cfee188 100644 (file)
@@ -5,15 +5,16 @@ This package allows you to reboot to an alternative partition on supported (dual
 
 ## Supported Devices
 Currently supported dual-partition devices include:
+- Linksys EA3500
+- Linksys E4200v2
+- Linksys EA4500
+- Linksys EA8500
 - Linksys WRT1200AC
 - Linksys WRT1900AC
 - Linksys WRT1900ACv2
 - Linksys WRT1900ACS
 - Linksys WRT3200ACM
-- Linksys E4200v2
-- Linksys EA4500
-- Linksys EA8500
-
+- 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).
 
 ## Screenshot (luci-app-advanced-reboot)
@@ -28,8 +29,8 @@ opkg install luci-app-advanced-reboot
 
 ## Notes/Known Issues
 - When you reboot to a different partition, your current settings (WiFi SSID/password, etc.) will not apply to a different partition. Different partitions might have completely different settings and even firmware.
-- If you reboot to a partition which doesn't allow you to switch boot partitions (like stock Linksys firmware), you might not be able to boot back to OpenWrt/LEDE Project unless you reflash it, loosing all the settings.
+- If you reboot to a partition which doesn't allow you to switch boot partitions (like stock vendor firmware), you might not be able to boot back to OpenWrt/LEDE Project unless you reflash it, loosing all the settings.
 - Some devices allow you to trigger reboot to 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
-I'd like to thank everyone who helped create, test and troubleshoot this package. Without contributions from [@hnyman](https://github.com/hnyman) and [@jpstyves](https://github.com/jpstyves) it wouldn't have been possible.
+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.
index 2b55217..13d1c73 100644 (file)
@@ -5,15 +5,18 @@ module("luci.controller.advanced_reboot", package.seeall)
 
 -- device, board_name, part1, part2, offset, env_var_1, value_1_1, value_1_2, env_var_2, value_2_1, value_2_2
 devices = {
+  {"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 EA8500", "ea8500", "mtd13", "mtd15", 32, "boot_part", 1, 2},
   {"Linksys WRT1200AC", "armada-385-linksys-caiman", "mtd4", "mtd6", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"},
   {"Linksys WRT1900AC", "armada-xp-linksys-mamba", "mtd4", "mtd6", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"},
   {"Linksys WRT1900ACv2", "armada-385-linksys-cobra", "mtd4", "mtd6", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"},
   {"Linksys WRT1900ACS", "armada-385-linksys-shelby", "mtd4", "mtd6", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"},
   {"Linksys WRT3200ACM", "armada-385-linksys-rango", "mtd5", "mtd7", 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}
+  {"ZyXEL NBG6817","nbg6817","mmcblk0p4","mmcblk0p7",32,nil,255,1}
 }
 
+errorMessage = ""
 board_name = luci.util.trim(luci.sys.exec("cat /tmp/sysinfo/board_name"))
 for i=1, #devices do
   if board_name and devices[i][2] == board_name then
@@ -41,14 +44,29 @@ for i=1, #devices do
     if 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 string.find(partition_two_label, "Linksys") then partition_two_os = "Linksys" end
+    if device_name and device_name == "ZyXEL NBG6817" then
+      if not partition_one_os then partition_one_os = "ZyXEL" end
+      if not partition_two_os then partition_two_os = "ZyXEL" end
+    end
     if not partition_one_os then partition_one_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_two_os and partition_two_version then partition_two_os = partition_two_os .. " (Linux " .. partition_two_version .. ")" end
-    if nixio.fs.access("/usr/sbin/fw_printenv") and nixio.fs.access("/usr/sbin/fw_setenv") then
-      current_partition = tonumber(luci.util.trim(luci.sys.exec("/usr/sbin/fw_printenv -n " .. boot_envvar1)))
-      other_partition = current_partition == boot_envvar1_partition_one and boot_envvar1_partition_two or boot_envvar1_partition_one
+
+    if device_name and device_name == "ZyXEL NBG6817" then
+      if not zyxelFlagPartition then zyxelFlagPartition = luci.util.trim(luci.sys.exec("source /lib/functions.sh; find_mtd_part 0:DUAL_FLAG")) end
+      if not zyxelFlagPartition then
+        errorMessage = errorMessage .. luci.i18n.translate("Unable to find Dual Boot Flag Partition." .. " ")
+        luci.util.perror(luci.i18n.translate("Unable to find Dual Boot Flag Partition."))
+      else
+        current_partition = tonumber(luci.sys.exec("dd if=" .. zyxelFlagPartition .. " bs=1 count=1 2>/dev/null | hexdump -n 1 -e '1/1 \"%d\"'"))
+      end
+    else
+      if nixio.fs.access("/usr/sbin/fw_printenv") and nixio.fs.access("/usr/sbin/fw_setenv") then
+        current_partition = tonumber(luci.util.trim(luci.sys.exec("/usr/sbin/fw_printenv -n " .. boot_envvar1)))
+      end
     end
+    other_partition = current_partition == boot_envvar1_partition_two and boot_envvar1_partition_one or boot_envvar1_partition_two
   end
 end
 
@@ -70,8 +88,19 @@ function action_reboot()
 end
 
 function action_altreboot()
+  local zyxelFlagPartition, zyxelBootFlag, zyxelNewBootFlag, errorCode, curEnvSetting, newEnvSetting
+  errorMessage = ""
+  errorCode = 0
   if luci.http.formvalue("cancel") then
     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
   end
   local step = tonumber(luci.http.formvalue("step") or 1)
@@ -79,21 +108,72 @@ function action_altreboot()
     if device_name and nixio.fs.access("/usr/sbin/fw_printenv") and nixio.fs.access("/usr/sbin/fw_setenv") then
       luci.template.render("advanced_reboot/alternative_reboot",{})
     else
-      luci.template.render("advanced_reboot/advanced_reboot",{})
+      luci.template.render("advanced_reboot/advanced_reboot",{errorMessage = luci.i18n.translate("No access to fw_printenv or fw_printenv!")})
     end
   elseif step == 2 then
-    luci.template.render("admin_system/applyreboot", {
-          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."),
-          addr  = luci.ip.new(uci.cursor():get("network", "lan", "ipaddr")) or "192.168.1.1"
-        })
-    if boot_envvar1 then env1 = tonumber(luci.util.trim(luci.sys.exec("/usr/sbin/fw_printenv -n " .. boot_envvar1))) end
-    if boot_envvar2 then env2 = luci.util.trim(luci.sys.exec("/usr/sbin/fw_printenv -n " .. boot_envvar2)) end
-    if env1 and env1 == boot_envvar1_partition_one then luci.sys.call("/usr/sbin/fw_setenv " .. boot_envvar1 .. " " .. boot_envvar1_partition_two) end
-    if env1 and env1 == boot_envvar1_partition_two then luci.sys.call("/usr/sbin/fw_setenv " .. boot_envvar1 .. " " .. boot_envvar1_partition_one) end
-    if env2 and env2 == boot_envvar2_partition_one then luci.sys.call("/usr/sbin/fw_setenv " .. boot_envvar2 .. " '" .. boot_envvar2_partition_two .. "'") end
-    if env2 and env2 == boot_envvar2_partition_two then luci.sys.call("/usr/sbin/fw_setenv " .. boot_envvar2 .. " '" .. boot_envvar2_partition_one .. "'") end
-    luci.sys.reboot()
+    if boot_envvar1 or boot_envvar2 then -- Linksys devices
+      if boot_envvar1 then
+        curEnvSetting = tonumber(luci.util.trim(luci.sys.exec("/usr/sbin/fw_printenv -n " .. boot_envvar1)))
+        if not curEnvSetting then
+          errorMessage = errorMessage .. luci.i18n.translate("Unable to obtain firmware environment variable") .. ": " .. boot_envvar1 .. ". "
+          luci.util.perror(luci.i18n.translate("Unable to obtain firmware environment variable") .. ": " .. boot_envvar1 .. ".")
+        else
+          newEnvSetting = curEnvSetting == boot_envvar1_partition_one and boot_envvar1_partition_two or boot_envvar1_partition_one
+          errorCode = luci.sys.call("/usr/sbin/fw_setenv " .. boot_envvar1 .. " " .. newEnvSetting)
+            if errorCode ~= 0 then
+              errorMessage = errorMessage .. luci.i18n.translate("Unable to set firmware environment variable") .. ": " .. boot_envvar1 .. " " .. luci.i18n.translate("to") .. " " .. newEnvSetting .. ". "
+              luci.util.perror(luci.i18n.translate("Unable to set firmware environment variable") .. ": " .. boot_envvar1 .. " " .. luci.i18n.translate("to") .. " " .. newEnvSetting .. ".")
+            end
+        end
+      end
+      if boot_envvar2 then
+        curEnvSetting = luci.util.trim(luci.sys.exec("/usr/sbin/fw_printenv -n " .. boot_envvar2))
+        if not curEnvSetting then
+          errorMessage = errorMessage .. luci.i18n.translate("Unable to obtain firmware environment variable") .. ": " .. boot_envvar2 .. ". "
+          luci.util.perror(luci.i18n.translate("Unable to obtain firmware environment variable") .. ": " .. boot_envvar2 .. ".")
+        else
+          newEnvSetting = curEnvSetting == boot_envvar2_partition_one and boot_envvar2_partition_two or boot_envvar2_partition_one
+          errorCode = luci.sys.call("/usr/sbin/fw_setenv " .. boot_envvar2 .. " '" .. newEnvSetting .. "'")
+          if errorCode ~= 0 then
+            errorMessage = errorMessage .. luci.i18n.translate("Unable to set firmware environment variable") .. ": " .. boot_envvar2 .. " " .. luci.i18n.translate("to") .. " " .. newEnvSetting .. ". "
+            luci.util.perror(luci.i18n.translate("Unable to set firmware environment variable") .. ": " .. boot_envvar2 .. " " .. luci.i18n.translate("to") .. " " .. newEnvSetting .. ".")
+          end
+        end
+      end
+    else -- NetGear device
+      if not zyxelFlagPartition then zyxelFlagPartition = luci.util.trim(luci.sys.exec("source /lib/functions.sh; find_mtd_part 0:DUAL_FLAG")) end
+      if not zyxelFlagPartition then
+        errorMessage = errorMessage .. luci.i18n.translate("Unable to find Dual Boot Flag Partition." .. " ")
+        luci.util.perror(luci.i18n.translate("Unable to find Dual Boot Flag Partition."))
+      else
+        zyxelBootFlag = tonumber(luci.sys.exec("dd if=" .. zyxelFlagPartition .. " bs=1 count=1 2>/dev/null | hexdump -n 1 -e '1/1 \"%d\"'"))
+        zyxelNewBootFlag = zyxelBootFlag and zyxelBootFlag == 1 and "\\xff" or "\\x01"
+        if zyxelNewBootFlag then
+          errorCode = luci.sys.call("printf \"" .. zyxelNewBootFlag .. "\" >" .. zyxelFlagPartition )
+          if errorCode ~= 0 then
+            errorMessage = errorMessage .. luci.i18n.translate("Unable to set Dual Boot Flag Partition entry for partition") .. ": " .. zyxelFlagPartition .. ". "
+            luci.util.perror(luci.i18n.translate("Unable to set Dual Boot Flag Partition entry for partition") .. ": " .. zyxelFlagPartition .. ".")
+          end
+        end
+      end
+    end
+    if errorMessage == "" then
+      luci.template.render("admin_system/applyreboot", {
+            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."),
+            addr  = luci.ip.new(uci.cursor():get("network", "lan", "ipaddr")) or "192.168.1.1"
+          })
+      luci.sys.reboot()
+    else
+      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 = errorMessage})
+    end
   end
 end
 
index 206d250..0629c84 100644 (file)
        <p class="alert-message warning"><%:Warning: There are unsaved changes that will get lost on reboot!%></p>
 <%- end -%>
 
+<%- if errorMessage and errorMessage ~= "" then -%>
+       <p class="alert-message warning"><%:ERROR: %><%=errorMessage%></p>
+<%- end -%>
+
 <%- if device_name then -%>
 <fieldset class="cbi-section">
   <legend><%=device_name%><%: Partitions%></legend>
@@ -26,7 +30,7 @@
     </tr>
     <tr class="cbi-section-table-row">
       <td>
-        <%=boot_envvar1_partition_one%>
+        <%=string.format("%X", boot_envvar1_partition_one)%>
       </td>
       <td>
         <%- if boot_envvar1_partition_one == current_partition then -%><%:Current%><%- else -%><%:Alternative%><%- end -%>
@@ -50,7 +54,7 @@
     </tr>
     <tr class="cbi-section-table-row">
       <td>
-        <%=boot_envvar1_partition_two%>
+        <%=string.format("%X", boot_envvar1_partition_two)%>
       </td>
       <td>
         <%- if boot_envvar1_partition_two == current_partition then -%><%:Current%><%- else -%><%:Alternative%><%- end -%>
index 20d77cb..e0e13cf 100644 (file)
@@ -10,6 +10,9 @@ msgstr "Avancerad omstart"
 msgid "Alternative"
 msgstr "Alternativ"
 
+msgid "Alternative reboot cancelled."
+msgstr ""
+
 msgid "Cancel"
 msgstr "Avbryt"
 
@@ -19,9 +22,15 @@ msgstr "Bekräfta"
 msgid "Current"
 msgstr "Nuvarande"
 
+msgid "ERROR:"
+msgstr ""
+
 msgid "Firmware/OS (Kernel)"
 msgstr "Inre mjukvara/OS (Kärna)"
 
+msgid "No access to fw_printenv or fw_printenv!"
+msgstr ""
+
 msgid "Partition"
 msgstr "Partition"
 
@@ -78,6 +87,18 @@ msgstr ""
 "inställningar så kan det vara nödvändigt att förnya din dators adress för "
 "att nå enheten igen."
 
+msgid "Unable to find Dual Boot Flag Partition."
+msgstr ""
+
+msgid "Unable to obtain firmware environment variable"
+msgstr ""
+
+msgid "Unable to set Dual Boot Flag Partition entry for partition"
+msgstr ""
+
+msgid "Unable to set firmware environment variable"
+msgstr ""
+
 msgid ""
 "WARNING: An alternative partition might have its own settings and completely "
 "different firmware.<br /><br /> As your network configuration and WiFi SSID/"
@@ -107,3 +128,6 @@ msgstr "Varning: Det här systemet har inte två partitioner!"
 
 msgid "Warning: This system does not support powering off!"
 msgstr "Varning: Det här systemet har inte stöd för avstängning!"
+
+msgid "to"
+msgstr ""
index 9c81089..47a81e1 100644 (file)
@@ -10,6 +10,9 @@ msgstr ""
 msgid "Alternative"
 msgstr ""
 
+msgid "Alternative reboot cancelled."
+msgstr ""
+
 msgid "Cancel"
 msgstr ""
 
@@ -19,9 +22,15 @@ msgstr ""
 msgid "Current"
 msgstr ""
 
+msgid "ERROR:"
+msgstr ""
+
 msgid "Firmware/OS (Kernel)"
 msgstr ""
 
+msgid "No access to fw_printenv or fw_printenv!"
+msgstr ""
+
 msgid "Partition"
 msgstr ""
 
@@ -75,6 +84,18 @@ msgid ""
 "again, depending on your settings."
 msgstr ""
 
+msgid "Unable to find Dual Boot Flag Partition."
+msgstr ""
+
+msgid "Unable to obtain firmware environment variable"
+msgstr ""
+
+msgid "Unable to set Dual Boot Flag Partition entry for partition"
+msgstr ""
+
+msgid "Unable to set firmware environment variable"
+msgstr ""
+
 msgid ""
 "WARNING: An alternative partition might have its own settings and completely "
 "different firmware.<br /><br /> As your network configuration and WiFi SSID/"
@@ -100,3 +121,6 @@ msgstr ""
 
 msgid "Warning: This system does not support powering off!"
 msgstr ""
+
+msgid "to"
+msgstr ""
index 847ad5c..0a8c65e 100644 (file)
     end
 
     apply_acls("/usr/share/rpcd/acl.d/attendedsysupgrade.json", luci.dispatcher.context.authsession)
-    apply_acls("/usr/share/rpcd/acl.d/packagelist.json", luci.dispatcher.context.authsession)
 %>
 <%+header%>
 <h2 name="content"><%:Attended Sysupgrade%></h2>
 <div class="cbi-map-descr">
-       Easily search and install new releases and package upgrades. Sysupgrade images are created on demand based on locally installed packages.
+       Easily search and install new releases and package upgrades. Sysupgrade firmware are created on demand based on locally installed packages.
 </div>
-<div style="display: none" id="upgrade_info" class="alert-message info"></div>
-<div style="display: none" id="upgrade_error" class="alert-message danger"></div>
+<div style="display: none" id="info_box" class="alert-message info"></div>
+<div style="display: none" id="error_box" class="alert-message danger"></div>
 <div style="display: none" id="packages" class="alert-message success"></div>
 <p>
 <textarea style="display: none; width: 100%;" id="edit_packages" rows="15"></textarea>
@@ -89,7 +88,7 @@
                <div class="cbi-selection-node">
                        <div class="cbi-value" id="keep_container" style="display: none">
                                <div class="cbi-section-descr">
-                                       Check "Keep settings" to retain the current configuration (requires a compatible firmware image).
+                                       Check "Keep settings" to retain the current configuration (requires a compatible firmware).
                                </div>
                                <label class="cbi-value-title" for="keep">Keep settings:</label>
                                <div class="cbi-value-field">
        </form>
 </fieldset>
 <script type="text/javascript">
-data = {};
-origin = document.location.href.replace(location.pathname, "")
-ubus_url = origin + "/ubus/"
-
-function set_server() {
-       data.url = document.getElementById("server").value;
-       ubus_call("uci", "set", { "config": "attendedsysupgrade", "section": "server", values: { "url": data.url } })
-       ubus_call("uci", "commit", { "config": "attendedsysupgrade" })
-       var server = document.getElementById("server")
-       server.type = 'button';
-       server.className = 'cbi-button cbi-button-edit';
-       server.parentElement.removeChild(document.getElementById("button_set"));
-       server.onclick = edit_server;
-}
-
-function edit_server() {
-       document.getElementById("server").type = 'text';
-       document.getElementById("server").onkeydown = function(event) {
-               if(event.key === 'Enter') {
-                       set_server();
-                       return false;
-               }
-       }
-       document.getElementById("server").className = '';
-       document.getElementById("server").onclick = null;
-
-       button_set = document.createElement("input");
-       button_set.type = "button";
-       button_set.value = "Save";
-       button_set.name = "button_set";
-       button_set.id = "button_set";
-       button_set.className = 'cbi-button cbi-button-edit';
-       button_set.style = 'background-image: url("/luci-static/resources/cbi/save.gif");'
-       button_set.onclick = set_server
-       document.getElementById("server").parentElement.appendChild(button_set);
-}
-
-function edit_packages() {
-       data.edit_packages = true
-       document.getElementById("edit_button").style.display = "none";
-       document.getElementById("edit_packages").value = data.packages.join("\n");
-       document.getElementById("edit_packages").style.display = "block";
-}
-
-// requests to the upgrade server
-function server_request(request_dict, path, callback) {
-       request_dict.distro = data.release.distribution;
-       request_dict.target = data.release.target.split("\/")[0];
-       request_dict.subtarget = data.release.target.split("\/")[1];
-       var request = new XMLHttpRequest();
-       request.open("POST", data.url + "/" + path, true);
-       request.setRequestHeader("Content-type", "application/json");
-       request.send(JSON.stringify(request_dict));
-       request.onerror = function(e) {
-               upgrade_error("upgrade server down")
-               document.getElementById("server_div").style.display = "block";
-       }
-       request.addEventListener('load', function(event) {
-               callback(request)
-       });
-}
-
-// initial setup, get system information
-function setup() {
+       data = {};
        data["ubus_rpc_session"] = "<%=luci.dispatcher.context.authsession%>"
-       ubus_call("packagelist", "list", {}, "packagelist");
-       ubus_call("system", "board", {}, "release");
-       ubus_call("system", "board", {}, "board_name");
-       ubus_call("system", "board", {}, "model");
-       uci_call({ "config": "attendedsysupgrade", "section": "server", "option": "url" })
-       uci_call({ "config": "attendedsysupgrade", "section": "client", "option": "upgrade_packages" })
-       uci_call({ "config": "attendedsysupgrade", "section": "client", "option": "advanced_mode" })
-       uci_call({ "config": "attendedsysupgrade", "section": "client", "option": "auto_search" })
-       setup_ready();
-}
-
-function setup_ready() {
-       if(ubus_counter != ubus_closed) {
-               setTimeout(setup_ready, 300)
-       } else {
-               if(data.auto_search == 1) {
-                       upgrade_check();
-               } else {
-                       document.getElementById("upgrade_button").style.display = "block";
-                       document.getElementById("server_div").style.display = "block";
-                       document.getElementById("server").value = data.url;
-               }
-       }
-}
-
-function uci_call(option) {
-       ubus_call("uci", "get", option, option["option"])
-}
-
-ubus_counter = 0;
-ubus_closed = 0;
-function ubus_call(command, argument, params, variable) {
-       request_data = {};
-       request_data.jsonrpc = "2.0";
-       request_data.id = ubus_counter;
-       request_data.method = "call";
-       request_data.params = [ data.ubus_rpc_session, command, argument, params ]
-       request_json = JSON.stringify(request_data)
-       ubus_counter++;
-       var request = new XMLHttpRequest();
-       request.open("POST", ubus_url, true);
-       request.setRequestHeader("Content-type", "application/json");
-       request.addEventListener('load', function(event) {
-               if(request.status === 200) {
-                       response = JSON.parse(request.responseText).result
-                       if(response[0] == 0) {
-                               if(response.length == 2) {
-                                       if(command === "uci") {
-                                               data[variable] = response[1].value
-                                       } else {
-                                               data[variable] = response[1][variable]
-                                       }
-                               }
-                       } else {
-                               upgrade_error("ubus call faild: " + request_json)
-                       }
-                       ubus_closed++;
-               }
-       });
-       request.send(request_json);
-}
-
-// shows notification if upgrade is available
-function upgrade_info(info_output, loading) {
-       document.getElementById("upgrade_info").style.display = "block";
-       if(loading) {
-               loading_image = '<img src="/luci-static/resources/icons/loading.gif" alt="Loading" style="vertical-align:middle">'
-       } else {
-               loading_image = ''
-       }
-       document.getElementById("upgrade_info").innerHTML = loading_image + info_output;
-}
-
-function upgrade_error(error_output) {
-       document.getElementById("upgrade_error").style.display = "block";
-       document.getElementById("upgrade_error").innerHTML = error_output;
-       document.getElementById("upgrade_info").style.display = "none";
-}
-
-// asks server for news upgrades, actually only based on relesae not packages
-function upgrade_check() {
-       document.getElementById("upgrade_error").style.display = "none";
-       document.getElementById("server_div").style.display = "none";
-       upgrade_info("Searching for upgrades", true);
-       request_dict = {}
-       request_dict.version = data.release.version;
-       request_dict.packages = data.packagelist;
-       // not only search for new release, but for new package versions as well
-       request_dict.upgrade_packages = data.upgrade_packages
-       server_request(request_dict, "api/upgrade-check", upgrade_check_callback)
-}
-
-// request the image, need merge with upgrade_request
-function upgrade_request() {
-       console.log("upgrade_request")
-       document.getElementById("upgrade_button").disabled = true;
-       document.getElementById("edit_packages").style.display = "none";
-       document.getElementById("edit_button").style.display = "none";
-       document.getElementById("keep_container").style.display = "none";
-       request_dict = {}
-       request_dict.version = data.latest_version;
-       request_dict.board = data.board_name
-
-       if(data.edit_packages == true) {
-               request_dict.packages = document.getElementById("edit_packages").value.split("\n")
-       } else {
-               request_dict.packages = data.packages;
-       }
-       request_dict.model = data.model
-       server_request(request_dict, "api/upgrade-request", upgrade_request_callback)
-}
-
-function upgrade_request_callback(response) {
-       if (response.status === 400) {
-               response_content = JSON.parse(response.responseText)
-               upgrade_error(response_content.error)
-       } else if (response.status === 500) {
-               response_content = JSON.parse(response.responseText)
-               upgrade_error(response_content.error)
-               if(response_content.log != undefined) {
-                       data.log_url = response_content.log
-               }
-       } else if (response.status === 503) {
-               upgrade_error("please wait. server overloaded")
-               // handle overload
-               setTimeout(upgrade_request, 30000)
-       } else if (response.status === 201) {
-               response_content = JSON.parse(response.responseText)
-               if(response_content.queue != undefined) {
-                       // in queue
-                       upgrade_info("please wait. you are in queue position " + response_content.queue, true)
-                       console.log("queued")
-               } else {
-                       upgrade_info("imagebuilder not ready, please wait", true)
-                       console.log("setting up imagebuilder")
-               }
-               setTimeout(upgrade_request, 5000)
-       } else if (response.status === 206) {
-               // building
-               console.log("building")
-               upgrade_info("building image", true)
-               setTimeout(upgrade_request, 5000)
-       } else if (response.status === 200) {
-               // ready to download
-               response_content = JSON.parse(response.responseText);
-               data.sysupgrade_url = response_content.sysupgrade;
-
-               info_output = "Image created"
-               if(data.advanced_mode == 1) {
-                       build_log = '</br><a target="_blank" href="' + data.sysupgrade_url + '.log">Build log</a>'
-                       info_output += build_log
-               }
-               upgrade_info(info_output);
-
-               document.getElementById("keep_container").style.display = "block";
-               var upgrade_button = document.getElementById("upgrade_button")
-               upgrade_button.disabled = false;
-               upgrade_button.style.display = "block";
-               upgrade_button.value = "Flash firmware";
-               upgrade_button.onclick = download_image;
-       }
-}
-
-// uploads received blob data to the server using cgi-io
-function upload_image(blob) {
-       var upload_request = new XMLHttpRequest();
-       var form_data  = new FormData();
-
-       form_data.append("sessionid", data.ubus_rpc_session)
-       form_data.append("filename", "/tmp/firmware.bin")
-       form_data.append("filemode", 755) // insecure?
-       form_data.append("filedata", blob)
-
-       upload_request.addEventListener('load', function(event) {
-               // this checksum should be parsed
-               upgrade_info("Flashing firmware", true)
-               ubus_call("rpc-sys", "upgrade_start", { "keep": document.getElementById("keep").checked }, 'message');
-               setTimeout(ping_ubus, 5000)
-               console.log(data.message);
-       });
-
-       upload_request.addEventListener('error', function(event) {
-               upgrade_info("uploading failed, please retry")
-       });
-
-       upload_request.open('POST', origin + '/cgi-bin/cgi-upload');
-       upload_request.send(form_data);
-}
-
-function ping_ubus() {
-       var request = new XMLHttpRequest();
-       request.open("GET", ubus_url, true);
-       request.addEventListener('error', function(event) {
-               upgrade_info("Rebooting", true);
-               setTimeout(ping_ubus, 1000)
-       });
-       request.addEventListener('load', function(event) {
-               upgrade_info("Success! Please reload web interface");
-               document.getElementById("upgrade_button").value = "reload page";
-               document.getElementById("upgrade_button").style.display = "block";
-               document.getElementById("upgrade_button").disabled = false;
-               document.getElementById("upgrade_button").onclick = function() { location.reload(); }
-       });
-       request.send();
-}
-
-// download image from server once the url was received by upgrade_request
-function download_image() {
-       console.log("download_image")
-       document.getElementById("keep_container").style.display = "none";
-       document.getElementById("upgrade_button").style.display = "none";
-       var download_request = new XMLHttpRequest();
-       download_request.open("GET", data.sysupgrade_url);
-       download_request.responseType = "arraybuffer";
-
-       download_request.onload = function () {
-               if (this.status === 200) {
-                       var blob = new Blob([download_request.response], {type: "application/octet-stream"});
-                       upload_image(blob)
-               }
-       };
-       upgrade_info("downloading image", true);
-       download_request.send();
-}
-
-function upgrade_check_callback(response_object) {
-       if (response_object.status === 500) {
-               // python crashed
-               upgrade_error("internal server error, please try again later")
-               console.log("upgrade server issue")
-       } else if (response_object.status === 502) {
-               // python part offline
-               upgrade_error("internal server error, please try again later")
-               console.log("upgrade server issue")
-       } else if (response_object.status === 503) {
-               // handle overload
-               upgrade_error("server overloaded, retry in 5 minutes")
-               console.log("server overloaded")
-               setTimeout(upgrade_request, 300000)
-       } else if (response_object.status === 201) {
-               upgrade_info("Setting up ImageBuilder", true)
-               console.log("setting up imagebuilder")
-               setTimeout(upgrade_request, 5000)
-       } else if (response_object.status === 204) {
-               // no upgrades
-               upgrade_info("No upgrades available")
-       } else if (response_object.status === 400) {
-               // bad request
-               console.log(response_object.responseText)
-               response_object_content = JSON.parse(response_object.responseText)
-               upgrade_error(response_object_content.error)
-       } else if (response_object.status === 200) {
-               // new release/upgrades
-               response_content = JSON.parse(response_object.responseText)
-
-               // create simple output to tell user whats going to be upgrade (release/packages)
-               info_output = ""
-               if(response_content.version != undefined) {
-                       info_output += "<h3>new upgrade available</h3>"
-                       info_output += data.release.version + " to " + response_content.version
-                       data.latest_version = response_content.version;
-               }
-               if(response_content.upgrades != undefined) {
-                       info_output += "<h3>package upgrades available</h3>"
-                       for (upgrade in response_content.upgrades) {
-                               info_output += "<b>" + upgrade + "</b>: " + response_content.upgrades[upgrade][1] + " to " + response_content.upgrades[upgrade][0] + "</br>"
-                       }
-               }
-               data.packages = response_content.packages
-               upgrade_info(info_output)
-
-               if(data.advanced_mode == 1) {
-                       document.getElementById("edit_button").style.display = "block";
-               }
-               var upgrade_button = document.getElementById("upgrade_button")
-               upgrade_button.value = "Request image";
-               upgrade_button.style.display = "block";
-               upgrade_button.disabled = false;
-               upgrade_button.onclick = upgrade_request;
-       }
-}
-document.onload = setup()
+       origin = document.location.href.replace(location.pathname, "")
+       ubus_url = origin + "/ubus/"
 </script>
-
+<script type="text/javascript" src="<%=resource%>/attendedsysupgrade.js"></script>
 <%+footer%>
index 97aa814..7549319 100644 (file)
@@ -4,10 +4,12 @@
                "read": {
                        "ubus": {
                                "rpc-sys": [
-                                       "upgrade_start"
+                                       "upgrade_start",
+                                       "packagelist"
                                ],
                                "system": [
-                                       "board"
+                                       "board",
+                                       "info"
                                ],
                                "uci": [
                                        "get", "set", "commit"
diff --git a/applications/luci-app-attendedsysupgrade/root/www/luci-static/resources/attendedsysupgrade.js b/applications/luci-app-attendedsysupgrade/root/www/luci-static/resources/attendedsysupgrade.js
new file mode 100644 (file)
index 0000000..c2fe81d
--- /dev/null
@@ -0,0 +1,402 @@
+function $(s) {
+       return document.getElementById(s.substring(1));
+}
+
+function show(s) {
+       $(s).style.display = 'block';
+}
+
+function hide(s) {
+       $(s).style.display = 'none';
+}
+
+function set_server() {
+       hide("#error_box");
+       data.url = $("#server").value;
+       ubus_call("uci", "set", { "config": "attendedsysupgrade", "section": "server", values: { "url": data.url } })
+       ubus_call("uci", "commit", { "config": "attendedsysupgrade" })
+       var server_button = $("#server")
+       server_button.type = 'button';
+       server_button.className = 'cbi-button cbi-button-edit';
+       server_button.parentElement.removeChild($("#button_set"));
+       server_button.onclick = edit_server;
+}
+
+function edit_server() {
+       $("#server").type = 'text';
+       $("#server").onkeydown = function(event) {
+               if(event.key === 'Enter') {
+                       set_server();
+                       return false;
+               }
+       }
+       $("#server").className = '';
+       $("#server").onclick = null;
+
+       button_set = document.createElement("input");
+       button_set.type = "button";
+       button_set.value = "Save";
+       button_set.name = "button_set";
+       button_set.id = "button_set";
+       button_set.className = 'cbi-button cbi-button-edit';
+       button_set.style = 'background-image: url("/luci-static/resources/cbi/save.gif");'
+       button_set.onclick = set_server
+       $("#server").parentElement.appendChild(button_set);
+}
+
+function edit_packages() {
+       data.edit_packages = true
+       hide("#edit_button");
+       $("#edit_packages").value = data.packages.join("\n");
+       show("#edit_packages");
+}
+
+// requests to the upgrade server
+function server_request(request_dict, path, callback) {
+       request_dict.distro = data.release.distribution;
+       request_dict.target = data.release.target.split("\/")[0];
+       request_dict.subtarget = data.release.target.split("\/")[1];
+       var request = new XMLHttpRequest();
+       request.open("POST", data.url + "/" + path, true);
+       request.setRequestHeader("Content-type", "application/json");
+       request.send(JSON.stringify(request_dict));
+       request.onerror = function(e) {
+               error_box("upgrade server down")
+               show("#server_div");
+       }
+       request.addEventListener('load', function(event) {
+               callback(request)
+       });
+}
+
+// initial setup, get system information
+function setup() {
+       ubus_call("rpc-sys", "packagelist", {}, "packages");
+       ubus_call("system", "board", {}, "release");
+       ubus_call("system", "board", {}, "board_name");
+       ubus_call("system", "board", {}, "model");
+       ubus_call("system", "info", {}, "memory");
+       uci_get({ "config": "attendedsysupgrade", "section": "server", "option": "url" })
+       uci_get({ "config": "attendedsysupgrade", "section": "client", "option": "upgrade_packages" })
+       uci_get({ "config": "attendedsysupgrade", "section": "client", "option": "advanced_mode" })
+       uci_get({ "config": "attendedsysupgrade", "section": "client", "option": "auto_search" })
+       setup_ready();
+}
+
+function setup_ready() {
+       // checks if a async ubus calls have finished
+       if(ubus_counter != ubus_closed) {
+               setTimeout(setup_ready, 300)
+       } else {
+               if(data.auto_search == 1) {
+                       upgrade_check();
+               } else {
+                       show("#upgrade_button");
+                       show("#server_div");
+                       $("#server").value = data.url;
+               }
+       }
+}
+
+function uci_get(option) {
+       // simple wrapper to get a uci value store in data.<option>
+       ubus_call("uci", "get", option, option["option"])
+}
+
+ubus_counter = 0;
+ubus_closed = 0;
+function ubus_call(command, argument, params, variable) {
+       var request_data = {};
+       request_data.jsonrpc = "2.0";
+       request_data.id = ubus_counter;
+       request_data.method = "call";
+       request_data.params = [ data.ubus_rpc_session, command, argument, params ]
+       request_json = JSON.stringify(request_data)
+       ubus_counter++;
+       var request = new XMLHttpRequest();
+       request.open("POST", ubus_url, true);
+       request.setRequestHeader("Content-type", "application/json");
+       request.onload = function(event) {
+               if(request.status === 200) {
+                       var response = JSON.parse(request.responseText)
+                       if(!("error" in response) && "result" in response) {
+                               if(response.result.length === 2) {
+                                       if(command === "uci") {
+                                               data[variable] = response.result[1].value
+                                       } else {
+                                               data[variable] = response.result[1][variable]
+                                       }
+                               }
+                       } else {
+                               error_box("<b>Ubus call faild:</b></br>Request: " + request_json + "</br>Response: " + JSON.stringify(response))
+                       }
+                       ubus_closed++;
+               }
+       }
+       request.send(request_json);
+}
+
+function info_box(info_output, loading) {
+       // Shows notification if upgrade is available
+       // If loading is true then an "processing" animation is added
+       show("#info_box");
+       var loading_image = '';
+       if(loading) {
+               loading_image = '<img src="/luci-static/resources/icons/loading.gif" alt="Loading" style="vertical-align:middle">';
+       }
+       $("#info_box").innerHTML = loading_image + info_output;
+}
+
+function error_box(error_output) {
+       // Shows erros in red box
+       show("#error_box");
+       $("#error_box").innerHTML = error_output;
+       hide("#info_box");
+}
+
+function upgrade_check() {
+       // Asks server for new firmware
+       // If data.upgrade_packages is set to true search for new package versions as well
+       hide("#error_box");
+       hide("#server_div");
+       info_box("Searching for upgrades", true);
+       var request_dict = {}
+       request_dict.version = data.release.version;
+       request_dict.packages = data.packages;
+       request_dict.upgrade_packages = data.upgrade_packages
+       server_request(request_dict, "api/upgrade-check", upgrade_check_callback)
+}
+
+function upgrade_check_callback(request_text) {
+       var request_json = JSON.parse(request_text)
+
+       // create simple output to tell user whats going to be upgrade (release/packages)
+       var info_output = ""
+       if(request_json.version != undefined) {
+               info_output += "<h3>New firmware release available</h3>"
+               info_output += data.release.version + " to " + request_json.version
+               data.latest_version = request_json.version;
+       }
+       if(request_json.upgrades != undefined) {
+               info_output += "<h3>Package upgrades available</h3>"
+               for (upgrade in request_json.upgrades) {
+                       info_output += "<b>" + upgrade + "</b>: " + request_json.upgrades[upgrade][1] + " to " + request_json.upgrades[upgrade][0] + "</br>"
+               }
+       }
+       data.packages = request_json.packages
+       info_box(info_output)
+
+       if(data.advanced_mode == 1) {
+               show("#edit_button");
+       }
+       var upgrade_button = $("#upgrade_button")
+       upgrade_button.value = "Request firmware";
+       upgrade_button.style.display = "block";
+       upgrade_button.disabled = false;
+       upgrade_button.onclick = upgrade_request;
+
+}
+
+function upgrade_request() {
+       // Request the image
+       // Needed values
+       // version/release
+       // board_name or model (server tries to find the corrent profile)
+       // packages
+       // The rest is added by server_request()
+       $("#upgrade_button").disabled = true;
+       hide("#edit_packages");
+       hide("#edit_button");
+       hide("#keep_container");
+
+       var request_dict = {}
+       request_dict.version = data.latest_version;
+       request_dict.board = data.board_name
+       request_dict.model = data.model
+
+       if(data.edit_packages == true) {
+               request_dict.packages = $("#edit_packages").value.split("\n")
+       } else {
+               request_dict.packages = data.packages;
+       }
+
+       server_request(request_dict, "api/upgrade-request", upgrade_request_callback)
+}
+
+function upgrade_request_callback(request) {
+       // ready to download
+       var request_json = JSON.parse(request);
+       data.sysupgrade_url = request_json.sysupgrade;
+
+       var filename_split = data.sysupgrade_url.split("/")
+       data.filename = filename_split[filename_split.length - 1]
+
+       info_output = "Firmware created</br><b>" + data.filename + "</b>"
+       if(data.advanced_mode == 1) {
+               info_output += '</br><a target="_blank" href="' + data.sysupgrade_url + '.log">Build log</a>'
+       }
+       info_box(info_output);
+
+       show("#keep_container");
+       var upgrade_button = $("#upgrade_button")
+       upgrade_button.disabled = false;
+       upgrade_button.style.display = "block";
+       upgrade_button.value = "Flash firmware";
+       upgrade_button.onclick = download_image;
+}
+
+function flash_image() {
+       // Flash image via rpc-sys upgrade_start
+       info_box("Flashing firmware. Don't unpower device", true)
+       ubus_call("rpc-sys", "upgrade_start", { "keep": $("#keep").checked }, 'message');
+       ping_max = 3600; // in seconds
+       setTimeout(ping_ubus, 10000)
+}
+
+function ping_ubus() {
+       // Tries to connect to ubus. If the connection fails the device is likely still rebooting.
+       // If more time than ping_max passes update may failed
+       if(ping_max > 0) {
+               ping_max--;
+               var request = new XMLHttpRequest();
+               request.open("GET", ubus_url, true);
+               request.addEventListener('error', function(event) {
+                       info_box("Rebooting device", true);
+                       setTimeout(ping_ubus, 1000)
+               });
+               request.addEventListener('load', function(event) {
+                       info_box("Success! Please reload web interface");
+                       $("#upgrade_button").value = "Reload page";
+                       show("#upgrade_button");
+                       $("#upgrade_button").disabled = false;
+                       $("#upgrade_button").onclick = function() { location.reload(); }
+               });
+               request.send();
+       } else {
+               error_box("Web interface could not reconnect to your device. Please reload web interface or check device manually")
+       }
+}
+
+function upload_image(blob) {
+       // Uploads received blob data to the server using cgi-io
+       var request = new XMLHttpRequest();
+       var form_data  = new FormData();
+
+       form_data.append("sessionid", data.ubus_rpc_session)
+       form_data.append("filename", "/tmp/firmware.bin")
+       form_data.append("filemode", 755) // insecure?
+       form_data.append("filedata", blob)
+
+       request.addEventListener('load', function(event) {
+               request_json = JSON.parse(request.responseText)
+               flash_image();
+       });
+
+       request.addEventListener('error', function(event) {
+               info_box("Upload of firmware failed, please retry by reloading web interface")
+       });
+
+       request.open('POST', origin + '/cgi-bin/cgi-upload');
+       request.send(form_data);
+}
+
+
+function download_image() {
+       // Download image from server once the url was received by upgrade_request
+       hide("#keep_container");
+       hide("#upgrade_button");
+       var download_request = new XMLHttpRequest();
+       download_request.open("GET", data.sysupgrade_url);
+       download_request.responseType = "arraybuffer";
+
+       download_request.onload = function () {
+               if (this.status === 200) {
+                       var blob = new Blob([download_request.response], {type: "application/octet-stream"});
+                       upload_image(blob)
+               }
+       };
+       info_box("Downloading firmware", true);
+       download_request.send();
+}
+
+function server_request(request_dict, path, callback) {
+       request_dict.distro = data.release.distribution;
+       request_dict.target = data.release.target.split("\/")[0];
+       request_dict.subtarget = data.release.target.split("\/")[1];
+       var request = new XMLHttpRequest();
+       request.open("POST", data.url + "/" + path, true);
+       request.setRequestHeader("Content-type", "application/json");
+       request.send(JSON.stringify(request_dict));
+       request.onerror = function(e) {
+               error_box("Upgrade server down or could not connect")
+               show("#server_div");
+       }
+       request.addEventListener('load', function(event) {
+               request_text = request.responseText;
+               if (request.status === 200) {
+                       callback(request_text)
+
+               } else if (request.status === 202) {
+                       var imagebuilder = request.getResponseHeader("X-Imagebuilder-Status");
+                       if(imagebuilder === "queue") {
+                               // in queue
+                               var queue = request.getResponseHeader("X-Build-Queue-Position");
+                               info_box("In build queue position " + queue, true)
+                               console.log("queued");
+                       } else if(imagebuilder === "initialize") {
+                               info_box("Setting up ImageBuilder", true)
+                               console.log("Setting up imagebuilder");
+                       } else if(imagebuilder === "building") {
+                               info_box("Building image", true);
+                               console.log("building");
+                       } else {
+                               // fallback if for some reasons the headers are missing e.g. browser blocks access
+                               info_box("Processing request", true);
+                               console.log(imagebuilder)
+                       }
+                       setTimeout(function() { server_request(request_dict, path, callback) }, 5000)
+
+               } else if (request.status === 204) {
+                       // no upgrades available
+                       info_box("No upgrades available")
+
+               } else if (request.status === 400) {
+                       // bad request
+                       request_json = JSON.parse(request_text)
+                       error_box(request_json.error)
+
+               } else if (request.status === 412) {
+                       // this is a bit generic
+                       error_box("Unsupported device, release, target, subtraget or board")
+
+               } else if (request.status === 413) {
+               error_box("No firmware created due to image size. Try again with less packages selected.")
+
+               } else if (request.status === 422) {
+                       error_box("Unknown package in request")
+
+               } else if (request.status === 500) {
+                       request_json = JSON.parse(request_text)
+
+                       error_box_content = "<b>Internal server error</b></br>"
+                       error_box_content += request_json.error
+                       if(request_json.log != undefined) {
+                               data.log_url = request_json.log
+                       }
+                       error_box(error_box_content)
+
+               } else if (request.status === 501) {
+                       error_box("No sysupgrade file produced, may not supported by modell.")
+
+               } else if (request.status === 502) {
+                       // python part offline
+                       error_box("Server down for maintenance")
+                       setTimeout(function() { server_request(request_dict, path, callback) }, 30000)
+               } else if (request.status === 503) {
+                       error_box("Server overloaded")
+                       setTimeout(function() { server_request(request_dict, path, callback) }, 30000)
+               }
+       });
+}
+document.onload = setup()
+
index eb6f417..dc2e0da 100644 (file)
@@ -27,8 +27,8 @@ interface = mwan_member:option(Value, "interface", translate("Interface"))
        cbi_add_interface(interface)
 
 metric = mwan_member:option(Value, "metric", translate("Metric"),
-       translate("Acceptable values: 1-1000. Defaults to 1 if not set"))
-       metric.datatype = "range(1, 1000)"
+       translate("Acceptable values: 1-256. Defaults to 1 if not set"))
+       metric.datatype = "range(1, 256)"
 
 weight = mwan_member:option(Value, "weight", translate("Weight"),
        translate("Acceptable values: 1-1000. Defaults to 1 if not set"))
index 34a9f1f..841a5e7 100644 (file)
@@ -37,6 +37,9 @@ msgstr ""
 msgid "Acceptable values: 1-1000. Defaults to 1 if not set"
 msgstr "利用可能な値: 1-1000。空欄の場合のデフォルトは1です。"
 
+msgid "Acceptable values: 1-256. Defaults to 1 if not set"
+msgstr "利用可能な値: 1-256。空欄の場合のデフォルトは1です。"
+
 msgid "Advanced"
 msgstr "詳細設定"
 
index ed9fdb1..a993a81 100644 (file)
@@ -24,6 +24,9 @@ msgstr ""
 msgid "Acceptable values: 1-1000. Defaults to 1 if not set"
 msgstr ""
 
+msgid "Acceptable values: 1-256. Defaults to 1 if not set"
+msgstr ""
+
 msgid "Advanced"
 msgstr ""
 
index d0b92a6..966f53c 100644 (file)
@@ -33,7 +33,10 @@ msgstr ""
 "取值范围:1-100。这个设置项指定了当多少个 IP 地址能够连通时接口会被认为在线"
 
 msgid "Acceptable values: 1-1000. Defaults to 1 if not set"
-msgstr "取值范围:1-100。如果不填写,默认值为 1"
+msgstr "取值范围:1-1000。如果不填写,默认值为 1"
+
+msgid "Acceptable values: 1-256. Defaults to 1 if not set"
+msgstr "取值范围:1-256。如果不填写,默认值为 1"
 
 msgid "Advanced"
 msgstr "高级"
index 04711ac..d4a652a 100644 (file)
@@ -33,7 +33,10 @@ msgstr ""
 "取值範圍:1-100。這個設定項指定了當多少個 IP 位址能夠連通時介面會被認為線上"
 
 msgid "Acceptable values: 1-1000. Defaults to 1 if not set"
-msgstr "取值範圍:1-100。如果不填寫,預設值為 1"
+msgstr "取值範圍:1-1000。如果不填寫,預設值為 1"
+
+msgid "Acceptable values: 1-256. Defaults to 1 if not set"
+msgstr "取值範圍:1-256。如果不填寫,預設值為 1"
 
 msgid "Advanced"
 msgstr "高階"
index a418a8e..efbe619 100644 (file)
@@ -3,9 +3,9 @@
 
 module("luci.controller.travelmate", package.seeall)
 
-local fs = require("nixio.fs")
-local util = require("luci.util")
-local i18n = require("luci.i18n")
+local fs    = require("nixio.fs")
+local util  = require("luci.util")
+local i18n  = require("luci.i18n")
 local templ = require("luci.template")
 
 function index()
@@ -30,6 +30,12 @@ function index()
 end
 
 function logread()
-       local logfile = util.trim(util.exec("logread -e 'travelmate'"))
+       local logfile
+
+       if nixio.fs.access("/var/log/messages") then
+               logfile = util.trim(util.exec("cat /var/log/messages | grep 'travelmate'"))
+       else
+               logfile = util.trim(util.exec("logread -e 'travelmate'"))
+       end
        templ.render("travelmate/logread", {title = i18n.translate("Travelmate Logfile"), content = logfile})
 end
index 27971df..e715a2b 100644 (file)
@@ -1,15 +1,17 @@
 -- Copyright 2017 Dirk Brenken (dev@brenken.org)
 -- This is free software, licensed under the Apache License, Version 2.0
 
-local fs = require("nixio.fs")
-local uci = require("luci.model.uci").cursor()
-local json = require("luci.jsonc")
-local nw = require("luci.model.network").init()
-local fw = require("luci.model.firewall").init()
+local fs       = require("nixio.fs")
+local uci      = require("luci.model.uci").cursor()
+local json     = require("luci.jsonc")
+local util     = require("luci.util")
+local nw       = require("luci.model.network").init()
+local fw       = require("luci.model.firewall").init()
+local dump     = util.ubus("network.interface", "dump", {})
 local trmiface = uci.get("travelmate", "global", "trm_iface") or "trm_wwan"
 local trminput = uci.get("travelmate", "global", "trm_rtfile") or "/tmp/trm_runtime.json"
-local uplink = uci.get("network", trmiface) or ""
-local parse = json.parse(fs.readfile(trminput) or "")
+local uplink   = uci.get("network", trmiface) or ""
+local parse    = json.parse(fs.readfile(trminput) or "")
 
 m = Map("travelmate", translate("Travelmate"),
        translate("Configuration of the travelmate package to to enable travel router functionality. ")
@@ -22,26 +24,24 @@ function m.on_after_commit(self)
        luci.http.redirect(luci.dispatcher.build_url("admin", "services", "travelmate"))
 end
 
-s = m:section(NamedSection, "global", "travelmate")
-
 -- Interface Wizard
 
 if uplink == "" then
-       dv = s:option(DummyValue, "", translate("Interface Wizard"))
-       dv.template = "cbi/nullsection"
+       ds = m:section(NamedSection, "global", "travelmate", translate("Interface Wizard"))
 
-       o = s:option(Value, "", translate("Uplink interface"))
+       o = ds:option(Value, "", translate("Uplink interface"))
        o.datatype = "and(uciname,rangelength(3,15))"
        o.default = trmiface
        o.rmempty = false
 
-       btn = s:option(Button, "trm_iface", translate("Create Uplink Interface"),
+       btn = ds:option(Button, "trm_iface", translate("Create Uplink Interface"),
                translate("Create a new wireless wan uplink interface, configure it to use dhcp and ")
                .. translate("add it to the wan zone of the firewall. This step has only to be done once."))
        btn.inputtitle = translate("Add Interface")
        btn.inputstyle = "apply"
        btn.disabled = false
-       function btn.write(self, section, value)
+
+       function btn.write(self, section)
                local iface = o:formvalue(section)
                if iface then
                        uci:set("travelmate", section, "trm_iface", iface)
@@ -67,6 +67,8 @@ end
 
 -- Main travelmate options
 
+s = m:section(NamedSection, "global", "travelmate")
+
 o1 = s:option(Flag, "trm_enabled", translate("Enable travelmate"))
 o1.default = o1.disabled
 o1.rmempty = false
@@ -76,19 +78,16 @@ o2 = s:option(Flag, "trm_automatic", translate("Enable 'automatic' mode"),
 o2.default = o2.enabled
 o2.rmempty = false
 
-btn = s:option(Button, "", translate("Manual Rescan"))
-btn:depends("trm_automatic", "")
-btn.inputtitle = translate("Rescan")
-btn.inputstyle = "find"
-btn.disabled = false
-function btn.write()
-       luci.sys.call("env -i /etc/init.d/travelmate start >/dev/null 2>&1")
-       luci.http.redirect(luci.dispatcher.build_url("admin", "services", "travelmate"))
+o3 = s:option(ListValue, "trm_iface", translate("Uplink / Trigger interface"),
+       translate("Name of the used uplink interface."))
+if dump then
+       local i, v
+       for i, v in ipairs(dump.interface) do
+               if v.interface ~= "loopback" and v.interface ~= "lan" then
+                       o3:value(v.interface)
+               end
+       end
 end
-
-o3 = s:option(Value, "trm_iface", translate("Uplink / Trigger interface"),
-       translate("Name of the uplink interface that triggers travelmate processing in 'manual' mode."))
-o3.datatype = "and(uciname,rangelength(3,15))"
 o3.default = trmiface
 o3.rmempty = false
 
@@ -98,16 +97,23 @@ o4.default = 2
 o4.datatype = "range(1,90)"
 o4.rmempty = false
 
-o5 = s:option(Flag, "trm_debug", translate("Enable verbose debug logging"))
-o5.default = o5.disabled
-o5.rmempty = false
+btn = s:option(Button, "", translate("Manual Rescan"),
+       translate("Force a manual uplink rescan / reconnect in 'trigger' mode."))
+btn:depends("trm_automatic", "")
+btn.inputtitle = translate("Rescan")
+btn.inputstyle = "find"
+btn.disabled = false
+
+function btn.write()
+       luci.sys.call("env -i /etc/init.d/travelmate start >/dev/null 2>&1")
+       luci.http.redirect(luci.dispatcher.build_url("admin", "services", "travelmate"))
+end
 
 -- Runtime information
 
-ds = s:option(DummyValue, "_dummy", translate("Runtime information"))
-ds.template = "cbi/nullsection"
+ds = m:section(NamedSection, "global", "travelmate", translate("Runtime Information"))
 
-dv1 = s:option(DummyValue, "status", translate("Online Status"))
+dv1 = ds:option(DummyValue, "status", translate("Online Status"))
 dv1.template = "travelmate/runtime"
 if parse == nil then
        dv1.value = translate("n/a")
@@ -117,7 +123,7 @@ else
        dv1.value = translate("not connected")
 end
 
-dv2 = s:option(DummyValue, "travelmate_version", translate("Travelmate version"))
+dv2 = ds:option(DummyValue, "travelmate_version", translate("Travelmate version"))
 dv2.template = "travelmate/runtime"
 if parse ~= nil then
        dv2.value = parse.data.travelmate_version or translate("n/a")
@@ -125,15 +131,15 @@ else
        dv2.value = translate("n/a")
 end
 
-dv3 = s:option(DummyValue, "station_ssid", translate("Station SSID"))
+dv3 = ds:option(DummyValue, "station_id", translate("Station ID (SSID/BSSID)"))
 dv3.template = "travelmate/runtime"
 if parse ~= nil then
-       dv3.value = parse.data.station_ssid or translate("n/a")
+       dv3.value = parse.data.station_id or translate("n/a")
 else
        dv3.value = translate("n/a")
 end
 
-dv4 = s:option(DummyValue, "station_interface", translate("Station Interface"))
+dv4 = ds:option(DummyValue, "station_interface", translate("Station Interface"))
 dv4.template = "travelmate/runtime"
 if parse ~= nil then
        dv4.value = parse.data.station_interface or translate("n/a")
@@ -141,7 +147,7 @@ else
        dv4.value = translate("n/a")
 end
 
-dv5 = s:option(DummyValue, "station_radio", translate("Station Radio"))
+dv5 = ds:option(DummyValue, "station_radio", translate("Station Radio"))
 dv5.template = "travelmate/runtime"
 if parse ~= nil then
        dv5.value = parse.data.station_radio or translate("n/a")
@@ -149,7 +155,7 @@ else
        dv5.value = translate("n/a")
 end
 
-dv6 = s:option(DummyValue, "last_rundate", translate("Last rundate"))
+dv6 = ds:option(DummyValue, "last_rundate", translate("Last rundate"))
 dv6.template = "travelmate/runtime"
 if parse ~= nil then
        dv6.value = parse.data.last_rundate or translate("n/a")
@@ -162,28 +168,32 @@ end
 e = m:section(NamedSection, "global", "travelmate", translate("Extra options"),
 translate("Options for further tweaking in case the defaults are not suitable for you."))
 
-e1 = e:option(Value, "trm_radio", translate("Radio selection"),
+e1 = e:option(Flag, "trm_debug", translate("Enable verbose debug logging"))
+e1.default = e1.disabled
+e1.rmempty = false
+
+e2 = e:option(Value, "trm_radio", translate("Radio selection"),
        translate("Restrict travelmate to a dedicated radio, e.g. 'radio0'."))
-e1.datatype = "and(uciname,rangelength(6,6))"
-e1.rmempty = true
+e2.datatype = "and(uciname,rangelength(6,6))"
+e2.rmempty = true
 
-e2 = e:option(Value, "trm_maxretry", translate("Connection Limit"),
+e3 = e:option(Value, "trm_maxretry", translate("Connection Limit"),
        translate("How many times should travelmate try to connect to an Uplink. ")
        .. translate("To disable this feature set it to '0' which means unlimited retries."))
-e2.default = 3
-e2.datatype = "range(0,30)"
-e2.rmempty = false
+e3.default = 3
+e3.datatype = "range(0,30)"
+e3.rmempty = false
 
-e3 = e:option(Value, "trm_maxwait", translate("Interface Timeout"),
+e4 = e:option(Value, "trm_maxwait", translate("Interface Timeout"),
        translate("How long should travelmate wait for a successful wlan interface reload."))
-e3.default = 30
-e3.datatype = "range(5,60)"
-e3.rmempty = false
+e4.default = 30
+e4.datatype = "range(5,60)"
+e4.rmempty = false
 
-e4 = e:option(Value, "trm_timeout", translate("Overall Timeout"),
+e5 = e:option(Value, "trm_timeout", translate("Overall Timeout"),
        translate("Timeout in seconds between retries in 'automatic' mode."))
-e4.default = 60
-e4.datatype = "range(60,300)"
-e4.rmempty = false
+e5.default = 60
+e5.datatype = "range(60,300)"
+e5.rmempty = false
 
 return m
index dcfa17c..a3dd0a2 100644 (file)
@@ -1,10 +1,12 @@
 -- Copyright 2017 Dirk Brenken (dev@brenken.org)
 -- This is free software, licensed under the Apache License, Version 2.0
 
-local fs = require("nixio.fs")
-local uci = require("luci.model.uci").cursor()
-local http = require("luci.http")
+local fs       = require("nixio.fs")
+local uci      = require("luci.model.uci").cursor()
+local http     = require("luci.http")
 local trmiface = uci.get("travelmate", "global", "trm_iface") or "trm_wwan"
+local encr_psk = {"psk", "psk2", "psk-mixed"}
+local encr_wpa = {"wpa", "wpa2", "wpa-mixed"}
 
 m = SimpleForm("add", translate("Add Wireless Uplink Configuration"))
 m.submit = translate("Save")
@@ -18,6 +20,7 @@ end
 m.hidden = {
        device      = http.formvalue("device"),
        ssid        = http.formvalue("ssid"),
+       bssid       = http.formvalue("bssid"),
        wep         = http.formvalue("wep"),
        wpa_suites  = http.formvalue("wpa_suites"),
        wpa_version = http.formvalue("wpa_version")
@@ -25,23 +28,100 @@ m.hidden = {
 
 if m.hidden.ssid ~= "" then
        wssid = m:field(Value, "ssid", translate("SSID"))
-       wssid.default = m.hidden.ssid
+       wssid.datatype = "rangelength(1,32)"
+       wssid.default = m.hidden.ssid or ""
 else
        wssid = m:field(Value, "ssid", translate("SSID (hidden)"))
 end
 
+bssid = m:field(Value, "bssid", translate("BSSID"))
+bssid.datatype = "macaddr"
+bssid.default = m.hidden.bssid or ""
+
 if (tonumber(m.hidden.wep) or 0) == 1 then
-       wkey = m:field(Value, "key", translate("WEP passphrase"),
-               translate("Specify the secret encryption key here."))
+       encr = m:field(ListValue, "encryption", translate("Encryption"))
+       encr:value("wep", "WEP")
+       encr:value("wep+open", "WEP Open System")
+       encr:value("wep+mixed", "WEP mixed")
+       encr:value("wep+shared", "WEP Shared Key")
+       encr.default = "wep+open"
+
+       wkey = m:field(Value, "key", translate("WEP-Passphrase"))
        wkey.password = true
        wkey.datatype = "wepkey"
-elseif (tonumber(m.hidden.wpa_version) or 0) > 0 and
-       (m.hidden.wpa_suites == "PSK" or m.hidden.wpa_suites == "PSK2")
-then
-       wkey = m:field(Value, "key", translate("WPA passphrase"),
-               translate("Specify the secret encryption key here."))
-       wkey.password = true
-       wkey.datatype = "wpakey"
+elseif (tonumber(m.hidden.wpa_version) or 0) > 0 then
+       if m.hidden.wpa_suites == "PSK" or m.hidden.wpa_suites == "PSK2" then
+               encr = m:field(ListValue, "encryption", translate("Encryption"))
+               encr:value("psk", "WPA PSK")
+               encr:value("psk-mixed", "WPA/WPA2 mixed")
+               encr:value("psk2", "WPA2 PSK")
+               encr.default = encr_psk[tonumber(m.hidden.wpa_version)] or "psk2"
+
+               ciph = m:field(ListValue, "cipher", translate("Cipher"))
+               ciph:value("auto", translate("Automatic"))
+               ciph:value("ccmp", translate("Force CCMP (AES)"))
+               ciph:value("tkip", translate("Force TKIP"))
+               ciph:value("tkip+ccmp", translate("Force TKIP and CCMP (AES)"))
+               ciph.default = "auto"
+
+               wkey = m:field(Value, "key", translate("WPA-Passphrase"))
+               wkey.password = true
+               wkey.datatype = "wpakey"
+       elseif m.hidden.wpa_suites == "802.1X" then
+               encr = m:field(ListValue, "encryption", translate("Encryption"))
+               encr:value("wpa", "WPA Enterprise")
+               encr:value("wpa-mixed", "WPA/WPA2 Enterprise mixed")
+               encr:value("wpa2", "WPA2 Enterprise")
+               encr.default = encr_wpa[tonumber(m.hidden.wpa_version)] or "wpa2"
+
+               ciph = m:field(ListValue, "cipher", translate("Cipher"))
+               ciph:value("auto", translate("Automatic"))
+               ciph:value("ccmp", translate("Force CCMP (AES)"))
+               ciph:value("tkip", translate("Force TKIP"))
+               ciph:value("tkip+ccmp", translate("Force TKIP and CCMP (AES)"))
+               ciph.default = "auto"
+
+               eaptype = m:field(ListValue, "eap_type", translate("EAP-Method"))
+               eaptype:value("tls", "TLS")
+               eaptype:value("ttls", "TTLS")
+               eaptype:value("peap", "PEAP")
+               eaptype:value("fast", "FAST")
+               eaptype.default = "peap"
+
+               authentication = m:field(ListValue, "auth", translate("Authentication"))
+               authentication:value("PAP")
+               authentication:value("CHAP")
+               authentication:value("MSCHAP")
+               authentication:value("MSCHAPV2")
+               authentication:value("EAP-GTC")
+               authentication:value("EAP-MD5")
+               authentication:value("EAP-MSCHAPV2")
+               authentication:value("EAP-TLS")
+               authentication.default = "EAP-MSCHAPV2"
+
+               ident = m:field(Value, "identity", translate("Identity"))
+
+               wkey = m:field(Value, "password", translate("Password"))
+               wkey.password = true
+               wkey.datatype = "wpakey"
+
+               cacert = m:field(Value, "ca_cert", translate("Path to CA-Certificate"))
+               cacert.rmempty = true
+
+               clientcert = m:field(Value, "client_cert", translate("Path to Client-Certificate"))
+               clientcert:depends("eap_type","tls")
+               clientcert.rmempty = true
+
+               privkey = m:field(Value, "priv_key", translate("Path to Private Key"))
+               privkey:depends("eap_type","tls")
+               privkey.rmempty = true
+
+               privkeypwd = m:field(Value, "priv_key_pwd", translate("Password of Private Key"))
+               privkeypwd:depends("eap_type","tls")
+               privkeypwd.datatype = "wpakey"
+               privkeypwd.password = true
+               privkeypwd.rmempty = true
+       end
 end
 
 function wssid.write(self, section, value)
@@ -50,15 +130,36 @@ function wssid.write(self, section, value)
                network  = trmiface,
                device   = m.hidden.device,
                ssid     = wssid:formvalue(section),
+               bssid    = bssid:formvalue(section),
                disabled = "1"
        })
+
        if (tonumber(m.hidden.wep) or 0) == 1 then
-               uci:set("wireless", newsection, "encryption", "wep-open")
-               uci:set("wireless", newsection, "key", "1")
-               uci:set("wireless", newsection, "key1", wkey:formvalue(section))
+               uci:set("wireless", newsection, "encryption", encr:formvalue(section))
+               uci:set("wireless", newsection, "key", wkey:formvalue(section) or "")
        elseif (tonumber(m.hidden.wpa_version) or 0) > 0 then
-               uci:set("wireless", newsection, "encryption", "psk2")
-               uci:set("wireless", newsection, "key", wkey:formvalue(section))
+               if m.hidden.wpa_suites == "PSK" or m.hidden.wpa_suites == "PSK2" then
+                       if ciph:formvalue(section) ~= "auto" then
+                               uci:set("wireless", newsection, "encryption", encr:formvalue(section) .. "+" .. ciph:formvalue(section))
+                       else
+                               uci:set("wireless", newsection, "encryption", encr:formvalue(section))
+                       end
+                       uci:set("wireless", newsection, "key", wkey:formvalue(section) or "")
+               elseif m.hidden.wpa_suites == "802.1X" then
+                       if ciph:formvalue(section) ~= "auto" then
+                               uci:set("wireless", newsection, "encryption", encr:formvalue(section) .. "+" .. ciph:formvalue(section))
+                       else
+                               uci:set("wireless", newsection, "encryption", encr:formvalue(section))
+                       end
+                       uci:set("wireless", newsection, "eap_type", eaptype:formvalue(section))
+                       uci:set("wireless", newsection, "auth", authentication:formvalue(section))
+                       uci:set("wireless", newsection, "identity", ident:formvalue(section) or "")
+                       uci:set("wireless", newsection, "password", wkey:formvalue(section) or "")
+                       uci:set("wireless", newsection, "ca_cert", cacert:formvalue(section) or "")
+                       uci:set("wireless", newsection, "client_cert", clientcert:formvalue(section) or "")
+                       uci:set("wireless", newsection, "priv_key", privkey:formvalue(section) or "")
+                       uci:set("wireless", newsection, "priv_key_pwd", privkeypwd:formvalue(section) or "")
+               end
        else
                uci:set("wireless", newsection, "encryption", "none")
        end
index c60ff22..b8e0f11 100644 (file)
@@ -1,8 +1,8 @@
 -- Copyright 2017 Dirk Brenken (dev@brenken.org)
 -- This is free software, licensed under the Apache License, Version 2.0
 
-local fs = require("nixio.fs")
-local uci = require("luci.model.uci").cursor()
+local fs   = require("nixio.fs")
+local uci  = require("luci.model.uci").cursor()
 local http = require("luci.http")
 
 m = SimpleForm("edit", translate("Edit Wireless Uplink Configuration"))
@@ -21,21 +21,108 @@ m.hidden = {
 local s = uci:get_all("wireless", m.hidden.cfg)
 if s ~= nil then
        wssid = m:field(Value, "ssid", translate("SSID"))
-       wssid.default = s.ssid
        wssid.datatype = "rangelength(1,32)"
-       if s.encryption and s.key then
-               wkey = m:field(Value, "key", translatef("Passphrase (%s)", s.encryption))
-       elseif s.encryption and s.password then
-               wkey = m:field(Value, "password", translatef("Passphrase (%s)", s.encryption))
+       wssid.default = s.ssid or ""
+
+       bssid = m:field(Value, "bssid", translate("BSSID"))
+       bssid.datatype = "macaddr"
+       bssid.default = s.bssid or ""
+
+       s.cipher = "auto"
+       if string.match(s.encryption, '\+') and not string.match(s.encryption, '^wep') then
+               s.pos = string.find(s.encryption, '\+')
+               s.cipher = string.sub(s.encryption, s.pos + 1)
+               s.encryption = string.sub(s.encryption, 0, s.pos - 1)
        end
-       if s.encryption and (s.key or s.password) then
-               wkey.password = true
-               wkey.default = s.key or s.password
-               if s.encryption == "wep" then
+
+       if s.encryption and s.encryption ~= "none" then
+               if string.match(s.encryption, '^wep') then
+                       encr = m:field(ListValue, "encryption", translate("Encryption"))
+                       encr:value("wep", "WEP")
+                       encr:value("wep+open", "WEP Open System")
+                       encr:value("wep+mixed", "WEP mixed")
+                       encr:value("wep+shared", "WEP Shared Key")
+                       encr.default = s.encryption
+
+                       wkey = m:field(Value, "key", translate("Passphrase"))
                        wkey.datatype = "wepkey"
-               else
+               elseif string.match(s.encryption, '^psk') then
+                       encr = m:field(ListValue, "encryption", translate("Encryption"))
+                       encr:value("psk", "WPA PSK")
+                       encr:value("psk-mixed", "WPA/WPA2 mixed")
+                       encr:value("psk2", "WPA2 PSK")
+                       encr.default = s.encryption
+
+                       ciph = m:field(ListValue, "cipher", translate("Cipher"))
+                       ciph:value("auto", translate("Automatic"))
+                       ciph:value("ccmp", translate("Force CCMP (AES)"))
+                       ciph:value("tkip", translate("Force TKIP"))
+                       ciph:value("tkip+ccmp", translate("Force TKIP and CCMP (AES)"))
+                       ciph.default = s.cipher
+
+                       wkey = m:field(Value, "key", translate("Passphrase"))
+                       wkey.datatype = "wpakey"
+               elseif string.match(s.encryption, '^wpa') then
+                       encr = m:field(ListValue, "encryption", translate("Encryption"))
+                       encr:value("wpa", "WPA Enterprise")
+                       encr:value("wpa-mixed", "WPA/WPA2 Enterprise mixed")
+                       encr:value("wpa2", "WPA2 Enterprise")
+                       encr.default = s.encryption
+
+                       ciph = m:field(ListValue, "cipher", translate("Cipher"))
+                       ciph:value("auto", translate("Automatic"))
+                       ciph:value("ccmp", translate("Force CCMP (AES)"))
+                       ciph:value("tkip", translate("Force TKIP"))
+                       ciph:value("tkip+ccmp", translate("Force TKIP and CCMP (AES)"))
+                       ciph.default = s.cipher
+
+                       eaptype = m:field(ListValue, "eap_type", translate("EAP-Method"))
+                       eaptype:value("tls", "TLS")
+                       eaptype:value("ttls", "TTLS")
+                       eaptype:value("peap", "PEAP")
+                       eaptype:value("fast", "FAST")
+                       eaptype.default = s.eap_type or "peap"
+
+                       authentication = m:field(ListValue, "auth", translate("Authentication"))
+                       authentication:value("PAP")
+                       authentication:value("CHAP")
+                       authentication:value("MSCHAP")
+                       authentication:value("MSCHAPV2")
+                       authentication:value("EAP-GTC")
+                       authentication:value("EAP-MD5")
+                       authentication:value("EAP-MSCHAPV2")
+                       authentication:value("EAP-TLS")
+                       authentication.default = s.auth or "EAP-MSCHAPV2"
+
+                       ident = m:field(Value, "identity", translate("Identity"))
+                       ident.default = s.identity or ""
+
+                       wkey = m:field(Value, "password", translate("Passphrase"))
                        wkey.datatype = "wpakey"
+
+                       cacert = m:field(Value, "ca_cert", translate("Path to CA-Certificate"))
+                       cacert.rmempty = true
+                       cacert.default = s.ca_cert or ""
+                       
+                       clientcert = m:field(Value, "client_cert", translate("Path to Client-Certificate"))
+                       clientcert:depends("eap_type","tls")
+                       clientcert.rmempty = true
+                       clientcert.default = s.client_cert or ""
+
+                       privkey = m:field(Value, "priv_key", translate("Path to Private Key"))
+                       privkey:depends("eap_type","tls")
+                       privkey.rmempty = true
+                       privkey.default = s.priv_key or ""
+
+                       privkeypwd = m:field(Value, "priv_key_pwd", translate("Password of Private Key"))
+                       privkeypwd:depends("eap_type","tls")
+                       privkeypwd.datatype = "wpakey"
+                       privkeypwd.password = true
+                       privkeypwd.rmempty = true
+                       privkeypwd.default = s.priv_key_pwd or ""
                end
+               wkey.password = true
+               wkey.default = s.key or s.password
        end
 else
        m.on_cancel()
@@ -43,10 +130,33 @@ end
 
 function wssid.write(self, section, value)
        uci:set("wireless", m.hidden.cfg, "ssid", wssid:formvalue(section))
-       if s.encryption and s.key then
-               uci:set("wireless", m.hidden.cfg, "key", wkey:formvalue(section))
-       elseif s.encryption and s.password then
-               uci:set("wireless", m.hidden.cfg, "password", wkey:formvalue(section))
+       uci:set("wireless", m.hidden.cfg, "bssid", bssid:formvalue(section))
+       if s.encryption and s.encryption ~= "none" then
+               if string.match(s.encryption, '^wep') then
+                       uci:set("wireless", m.hidden.cfg, "encryption", encr:formvalue(section))
+                       uci:set("wireless", m.hidden.cfg, "key", wkey:formvalue(section) or "")
+               elseif string.match(s.encryption, '^psk') then
+                       if ciph:formvalue(section) ~= "auto" then
+                               uci:set("wireless", m.hidden.cfg, "encryption", encr:formvalue(section) .. "+" .. ciph:formvalue(section))
+                       else
+                               uci:set("wireless", m.hidden.cfg, "encryption", encr:formvalue(section))
+                       end
+                       uci:set("wireless", m.hidden.cfg, "key", wkey:formvalue(section) or "")
+               elseif string.match(s.encryption, '^wpa') then
+                       if ciph:formvalue(section) ~= "auto" then
+                               uci:set("wireless", m.hidden.cfg, "encryption", encr:formvalue(section) .. "+" .. ciph:formvalue(section))
+                       else
+                               uci:set("wireless", m.hidden.cfg, "encryption", encr:formvalue(section))
+                       end
+                       uci:set("wireless", m.hidden.cfg, "eap_type", eaptype:formvalue(section))
+                       uci:set("wireless", m.hidden.cfg, "auth", authentication:formvalue(section))
+                       uci:set("wireless", m.hidden.cfg, "identity", ident:formvalue(section) or "")
+                       uci:set("wireless", m.hidden.cfg, "password", wkey:formvalue(section) or "")
+                       uci:set("wireless", m.hidden.cfg, "ca_cert", cacert:formvalue(section) or "")
+                       uci:set("wireless", m.hidden.cfg, "client_cert", clientcert:formvalue(section) or "")
+                       uci:set("wireless", m.hidden.cfg, "priv_key", privkey:formvalue(section) or "")
+                       uci:set("wireless", m.hidden.cfg, "priv_key_pwd", privkeypwd:formvalue(section) or "")
+               end
        end
        uci:save("wireless")
        uci:commit("wireless")
index 53493a1..2233a15 100644 (file)
@@ -6,5 +6,8 @@
                font-size: 12px;
                font-family: monospace;
                resize: none;
+               white-space: pre;
+               overflow-wrap: normal;
+               overflow-x: scroll;
        }
 </style>
index cbb6c18..11c36d4 100644 (file)
@@ -4,8 +4,8 @@ This is free software, licensed under the Apache License, Version 2.0
 -%>
 
 <%-
-  local write = io.write
-  local uci = require("luci.model.uci").cursor()
+  local write    = io.write
+  local uci      = require("luci.model.uci").cursor()
   local trmiface = uci:get("travelmate", "global", "trm_iface") or "trm_wwan"
 -%>
 
@@ -22,6 +22,7 @@ This is free software, licensed under the Apache License, Version 2.0
     <tr class="cbi-section-table-titles">
       <th class="cbi-section-table-cell" style="text-align:left"><%:Device%></th>
       <th class="cbi-section-table-cell" style="text-align:left"><%:SSID%></th>
+      <th class="cbi-section-table-cell" style="text-align:left"><%:BSSID%></th>
       <th class="cbi-section-table-cell" style="text-align:left"><%:Encryption%></th>
       <th class="cbi-section-table-cell" style="text-align:center" colspan="2"><%:Actions%></th>
     </tr>
@@ -30,9 +31,10 @@ This is free software, licensed under the Apache License, Version 2.0
     local iface = s.network or ""
     if iface == trmiface then
       local section = s['.name'] or ""
-      local device = s.device or ""
-      local ssid = s.ssid or ""
-      local encryption = s.encryption or ""
+      local device = s.device or "-"
+      local ssid = s.ssid or "-"
+      local bssid = s.bssid or "-"
+      local encryption = s.encryption or "-"
       local disabled = s.disabled or ""
       local style = "color:#000000"
       if disabled == "0" then
@@ -42,14 +44,15 @@ This is free software, licensed under the Apache License, Version 2.0
     <tr class="cbi-section-table-row cbi-rowstyle-1" style="<%=style%>">
       <td style="text-align:left"><%=device%></td>
       <td style="text-align:left"><%=ssid%></td>
+      <td style="text-align:left"><%=bssid%></td>
       <td style="text-align:left"><%=encryption%></td>
       <td class="cbi-value-field" style="width:70px;text-align:right">
-        <input class="cbi-button cbi-button-up" type="button" value="" onclick="location.href='<%=url('admin/services/travelmate/wifiorder')%>?cfg=<%=section%>;dir=up'" alt="<%:Move up%>" title="<%:Move up%>"/>
-        <input class="cbi-button cbi-button-down" type="button" value="" onclick="location.href='<%=url('admin/services/travelmate/wifiorder')%>?cfg=<%=section%>;dir=down'" alt="<%:Move down%>" title="<%:Move down%>"/>
+        <input class="cbi-button cbi-button-up" type="button" value="" onclick="location.href='<%=luci.dispatcher.build_url('admin/services/travelmate/wifiorder')%>?cfg=<%=section%>;dir=up'" alt="<%:Move up%>" title="<%:Move up%>"/>
+        <input class="cbi-button cbi-button-down" type="button" value="" onclick="location.href='<%=luci.dispatcher.build_url('admin/services/travelmate/wifiorder')%>?cfg=<%=section%>;dir=down'" alt="<%:Move down%>" title="<%:Move down%>"/>
       </td>
       <td class="cbi-value-field" style="width:150px;text-align:right">
-        <input type="button" class="cbi-button cbi-button-edit" onclick="location.href='<%=url('admin/services/travelmate/wifiedit')%>?cfg=<%=section%>'" title="<%:Edit this Uplink%>" value="<%:Edit%>"/>
-        <input type="button" class="cbi-button cbi-button-remove" onclick="location.href='<%=url('admin/services/travelmate/wifidelete')%>?cfg=<%=section%>'" title="<%:Delete this Uplink%>" value="<%:Delete%>"/>
+        <input type="button" class="cbi-button cbi-button-edit" onclick="location.href='<%=luci.dispatcher.build_url('admin/services/travelmate/wifiedit')%>?cfg=<%=section%>'" title="<%:Edit this Uplink%>" value="<%:Edit%>"/>
+        <input type="button" class="cbi-button cbi-button-remove" onclick="location.href='<%=luci.dispatcher.build_url('admin/services/travelmate/wifidelete')%>?cfg=<%=section%>'" title="<%:Delete this Uplink%>" value="<%:Delete%>"/>
       </td>
     </tr>
 <%
@@ -63,7 +66,7 @@ This is free software, licensed under the Apache License, Version 2.0
   uci:foreach("wireless", "wifi-device", function(s)
     local device = s[".name"]
 %>
-  <form class="inline" action="<%=url('admin/services/travelmate/wifiscan')%>" method="post">
+  <form class="inline" action="<%=luci.dispatcher.build_url('admin/services/travelmate/wifiscan')%>" method="post">
     <input type="hidden" name="device" value="<%=device%>"/>
     <input type="hidden" name="token" value="<%=token%>"/>
     <input type="submit" class="cbi-button cbi-button-find" title="<%:Find and join network on %><%=device%>" value="<%:Scan %><%=device%>"/>
index af90c18..a8f63a1 100644 (file)
@@ -7,7 +7,8 @@ This is free software, licensed under the Apache License, Version 2.0
     local sys = require("luci.sys")
     local utl = require("luci.util")
     local dev = luci.http.formvalue("device")
-    local iw = luci.sys.wifi.getiwinfo(dev)
+    local iw  = luci.sys.wifi.getiwinfo(dev)
+    local wpa_label = {translate("WPA"), translate("WPA2"), translate("WPA/WPA2")}
 
     if not iw then
         luci.http.redirect(luci.dispatcher.build_url("admin/services/travelmate/stations"))
@@ -17,7 +18,7 @@ This is free software, licensed under the Apache License, Version 2.0
         if info.wep == true then
             return translate("WEP")
         elseif info.wpa > 0 then
-            return translate("WPA / WPA2")
+            return "%s (%s/%s)" %{wpa_label[info.wpa], table.concat(info.auth_suites), table.concat(info.group_ciphers)}
         elseif info.enabled then
             return translate("Unknown")
         else
@@ -28,7 +29,7 @@ This is free software, licensed under the Apache License, Version 2.0
     function percent_wifi_signal(info)
         local qc = info.quality or 0
         local qm = info.quality_max or 0
-        if info.ssid and qc > 0 and qm > 0 then
+        if info.bssid and qc > 0 and qm > 0 then
             return math.floor((100 / qm) * qc)
         else
             return 0
@@ -44,13 +45,17 @@ This is free software, licensed under the Apache License, Version 2.0
         <table class="cbi-section-table" style="empty-cells:hide">
             <tr class="cbi-section-table-titles">
                 <th class="cbi-section-table-cell" style="text-align:left"><%:Uplink SSID%></th>
+                <th class="cbi-section-table-cell" style="text-align:left"><%:Uplink BSSID%></th>
                 <th class="cbi-section-table-cell" style="text-align:left"><%:Encryption%></th>
                 <th class="cbi-section-table-cell" style="text-align:left" colspan="2"><%:Signal strength%></th>
             </tr>
             <% for i, net in ipairs(iw.scanlist or { }) do %>
             <tr class="cbi-section-table-row cbi-rowstyle-1">
                 <td class="cbi-value-field" style="text-align:left">
-                    <strong><%=net.ssid and utl.pcdata(net.ssid) or "<em>%s</em>" % translate("hidden")%></strong>
+                    <%=net.ssid and utl.pcdata(net.ssid) or "<em>%s</em>" % translate("hidden")%>
+                </td>
+                <td class="cbi-value-field" style="text-align:left">
+                    <%=net.bssid and utl.pcdata(net.bssid)%>
                 </td>
                 <td class="cbi-value-field" style="text-align:left">
                     <%=format_wifi_encryption(net.encryption)%>
@@ -59,15 +64,16 @@ This is free software, licensed under the Apache License, Version 2.0
                     <%=percent_wifi_signal(net)%> %
                 </td>
                 <td class="cbi-value-field" style="width:100px;text-align:right">
-                    <form class="inline" action="<%=url('admin/services/travelmate/wifiadd')%>" method="post">
+                    <form class="inline" action="<%=luci.dispatcher.build_url('admin/services/travelmate/wifiadd')%>" method="post">
                         <input type="hidden" name="token" value="<%=token%>"/>
                         <input type="hidden" name="device" value="<%=utl.pcdata(dev)%>"/>
                         <input type="hidden" name="ssid" value="<%=utl.pcdata(net.ssid)%>"/>
+                        <input type="hidden" name="bssid" value="<%=utl.pcdata(net.bssid)%>"/>
                         <input type="hidden" name="wep" value="<%=net.encryption.wep and 1 or 0%>"/>
                         <% if net.encryption.wpa then %>
-                        <input type="hidden" name="wpa_version" value="<%=net.encryption.wpa%>"/>
-                        <% for _, v in ipairs(net.encryption.auth_suites) do %><input type="hidden" name="wpa_suites" value="<%=v%>"/>
-                        <% end; end %>
+                            <input type="hidden" name="wpa_version" value="<%=net.encryption.wpa%>"/>
+                            <% for _, v in ipairs(net.encryption.auth_suites) do %><input type="hidden" name="wpa_suites" value="<%=v%>"/><% end %>
+                        <% end %>
                         <input class="cbi-button cbi-button-apply" type="submit" value="<%:Add Uplink%>"/>
                     </form>
                 </td>
@@ -76,12 +82,12 @@ This is free software, licensed under the Apache License, Version 2.0
         </table>
     </fieldset>
 <div class="cbi-page-actions right">
-    <form class="inline" action="<%=url('admin/services/travelmate/wifiscan')%>" method="post">
+    <form class="inline" action="<%=luci.dispatcher.build_url('admin/services/travelmate/wifiscan')%>" method="post">
         <input type="hidden" name="token" value="<%=token%>"/>
         <input type="hidden" name="device" value="<%=utl.pcdata(dev)%>"/>
         <input class="cbi-button cbi-input-find" type="submit" value="<%:Repeat scan%>"/>
     </form>
-    <form class="inline" action="<%=url('admin/services/travelmate/stations')%>" method="post">
+    <form class="inline" action="<%=luci.dispatcher.build_url('admin/services/travelmate/stations')%>" method="post">
         <input class="cbi-button cbi-button-reset" type="submit" value="<%:Back to overview%>"/>
     </form>
 </div>
index febdbd5..1158966 100644 (file)
@@ -7,7 +7,7 @@ msgstr ""
 "Language-Team: \n"
 "MIME-Version: 1.0\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Generator: Poedit 2.0.3\n"
+"X-Generator: Poedit 2.0.5\n"
 "Last-Translator: INAGAKI Hiroshi <musashino.open@gmail.com>\n"
 "Plural-Forms: nplurals=1; plural=0;\n"
 "Language: ja\n"
@@ -31,9 +31,21 @@ msgstr "Travelmate の処理が開始されるまでの、追加の遅延時間
 msgid "Advanced"
 msgstr "詳細設定"
 
+msgid "Authentication"
+msgstr "認証"
+
+msgid "Automatic"
+msgstr "自動"
+
+msgid "BSSID"
+msgstr "BSSID"
+
 msgid "Back to overview"
 msgstr "概要へ戻る"
 
+msgid "Cipher"
+msgstr "暗号化方式"
+
 msgid ""
 "Configuration of the travelmate package to to enable travel router "
 "functionality."
@@ -61,6 +73,9 @@ msgstr "このアップリンクを削除"
 msgid "Device"
 msgstr "デバイス"
 
+msgid "EAP-Method"
+msgstr "EAP メソッド"
+
 msgid "Edit"
 msgstr "編集"
 
@@ -107,6 +122,19 @@ msgstr ""
 "詳細な情報は <a href=\"%s\" target=\"_blank\">オンライン ドキュメント</a> を"
 "確認してください。"
 
+msgid "Force CCMP (AES)"
+msgstr "CCMP (AES)"
+
+msgid "Force TKIP"
+msgstr "TKIP"
+
+msgid "Force TKIP and CCMP (AES)"
+msgstr "TKIP と CCMP (AES)"
+
+msgid "Force a manual uplink rescan / reconnect in 'trigger' mode."
+msgstr ""
+"'trigger' モード時に、手動でアップリンクの再スキャンと再接続を行います。"
+
 msgid "How long should travelmate wait for a successful wlan interface reload."
 msgstr ""
 "無線LAN インターフェースのリロードが成功するまでの、Travelmate の待機時間で"
@@ -115,6 +143,9 @@ msgstr ""
 msgid "How many times should travelmate try to connect to an Uplink."
 msgstr "Travelmate がアップリンクへの接続を試行する回数です。"
 
+msgid "Identity"
+msgstr "ID"
+
 msgid "Input file not found, please check your configuration."
 msgstr "入力ファイルが見つかりません。設定を確認してください。"
 
@@ -143,12 +174,8 @@ msgstr "下へ"
 msgid "Move up"
 msgstr "上へ"
 
-msgid ""
-"Name of the uplink interface that triggers travelmate processing in 'manual' "
-"mode."
-msgstr ""
-"'manual' モード時に Travelmate の処理のトリガーとなる、アップリンク インター"
-"フェースの名前です。"
+msgid "Name of the used uplink interface."
+msgstr "使用されるアップリンク インターフェースの名前です。"
 
 msgid "Online Status"
 msgstr "オンライン ステータス"
@@ -166,8 +193,23 @@ msgstr "実行間隔"
 msgid "Overview"
 msgstr "概要"
 
-msgid "Passphrase (%s)"
-msgstr "暗号フレーズ (%s)"
+msgid "Passphrase"
+msgstr "パスフレーズ"
+
+msgid "Password"
+msgstr "パスワード"
+
+msgid "Password of Private Key"
+msgstr "秘密鍵のパスワード"
+
+msgid "Path to CA-Certificate"
+msgstr "CA 証明書へのパス"
+
+msgid "Path to Client-Certificate"
+msgstr "クライアント証明書へのパス"
+
+msgid "Path to Private Key"
+msgstr "秘密鍵へのパス"
 
 msgid ""
 "Provides an overview of all configured uplinks for the travelmate interface "
@@ -191,7 +233,7 @@ msgstr "再スキャン"
 msgid "Restrict travelmate to a dedicated radio, e.g. 'radio0'."
 msgstr "Travelmate が指定された無線に接続するよう制御します。(例: 'radio0')"
 
-msgid "Runtime information"
+msgid "Runtime Information"
 msgstr "実行情報"
 
 msgid "SSID"
@@ -209,8 +251,8 @@ msgstr "スキャン:"
 msgid "Signal strength"
 msgstr "信号強度"
 
-msgid "Specify the secret encryption key here."
-msgstr "暗号キーを設定します。"
+msgid "Station ID (SSID/BSSID)"
+msgstr "ステーション ID (SSID / BSSID)"
 
 msgid "Station Interface"
 msgstr "ステーション インターフェース"
@@ -218,9 +260,6 @@ msgstr "ステーション インターフェース"
 msgid "Station Radio"
 msgstr "ステーション電波"
 
-msgid "Station SSID"
-msgstr "ステーション SSID"
-
 msgid ""
 "This form allows you to modify the content of the main firewall "
 "configuration file (/etc/config/firewall)."
@@ -281,6 +320,9 @@ msgstr "不明"
 msgid "Uplink / Trigger interface"
 msgstr "アップリンク / トリガー インターフェース"
 
+msgid "Uplink BSSID"
+msgstr "アップリンク BSSID"
+
 msgid "Uplink SSID"
 msgstr "アップリンク SSID"
 
@@ -293,14 +335,20 @@ msgstr "ログファイルの確認"
 msgid "WEP"
 msgstr "WEP"
 
-msgid "WEP passphrase"
-msgstr "WEP 暗号キー"
+msgid "WEP-Passphrase"
+msgstr "WEP パスフレーズ"
+
+msgid "WPA"
+msgstr "WPA"
+
+msgid "WPA-Passphrase"
+msgstr "WPA パスフレーズ"
 
-msgid "WPA / WPA2"
-msgstr "WPA / WPA2"
+msgid "WPA/WPA2"
+msgstr "WPA/WPA2"
 
-msgid "WPA passphrase"
-msgstr "WPA 暗号キー"
+msgid "WPA2"
+msgstr "WPA2"
 
 msgid "Wireless Scan"
 msgstr "無線スキャン"
index 41fab70..e36860e 100644 (file)
@@ -31,9 +31,21 @@ msgstr ""
 msgid "Advanced"
 msgstr ""
 
+msgid "Authentication"
+msgstr ""
+
+msgid "Automatic"
+msgstr ""
+
+msgid "BSSID"
+msgstr ""
+
 msgid "Back to overview"
 msgstr ""
 
+msgid "Cipher"
+msgstr ""
+
 msgid ""
 "Configuration of the travelmate package to to enable travel router "
 "functionality."
@@ -58,6 +70,9 @@ msgstr ""
 msgid "Device"
 msgstr ""
 
+msgid "EAP-Method"
+msgstr ""
+
 msgid "Edit"
 msgstr ""
 
@@ -102,12 +117,27 @@ msgid ""
 "documentation</a>"
 msgstr ""
 
+msgid "Force CCMP (AES)"
+msgstr ""
+
+msgid "Force TKIP"
+msgstr ""
+
+msgid "Force TKIP and CCMP (AES)"
+msgstr ""
+
+msgid "Force a manual uplink rescan / reconnect in 'trigger' mode."
+msgstr ""
+
 msgid "How long should travelmate wait for a successful wlan interface reload."
 msgstr ""
 
 msgid "How many times should travelmate try to connect to an Uplink."
 msgstr ""
 
+msgid "Identity"
+msgstr ""
+
 msgid "Input file not found, please check your configuration."
 msgstr ""
 
@@ -134,9 +164,7 @@ msgstr ""
 msgid "Move up"
 msgstr ""
 
-msgid ""
-"Name of the uplink interface that triggers travelmate processing in 'manual' "
-"mode."
+msgid "Name of the used uplink interface."
 msgstr ""
 
 msgid "Online Status"
@@ -155,7 +183,22 @@ msgstr ""
 msgid "Overview"
 msgstr ""
 
-msgid "Passphrase (%s)"
+msgid "Passphrase"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Password of Private Key"
+msgstr ""
+
+msgid "Path to CA-Certificate"
+msgstr ""
+
+msgid "Path to Client-Certificate"
+msgstr ""
+
+msgid "Path to Private Key"
 msgstr ""
 
 msgid ""
@@ -176,7 +219,7 @@ msgstr ""
 msgid "Restrict travelmate to a dedicated radio, e.g. 'radio0'."
 msgstr ""
 
-msgid "Runtime information"
+msgid "Runtime Information"
 msgstr ""
 
 msgid "SSID"
@@ -194,7 +237,7 @@ msgstr ""
 msgid "Signal strength"
 msgstr ""
 
-msgid "Specify the secret encryption key here."
+msgid "Station ID (SSID/BSSID)"
 msgstr ""
 
 msgid "Station Interface"
@@ -203,9 +246,6 @@ msgstr ""
 msgid "Station Radio"
 msgstr ""
 
-msgid "Station SSID"
-msgstr ""
-
 msgid ""
 "This form allows you to modify the content of the main firewall "
 "configuration file (/etc/config/firewall)."
@@ -255,6 +295,9 @@ msgstr ""
 msgid "Uplink / Trigger interface"
 msgstr ""
 
+msgid "Uplink BSSID"
+msgstr ""
+
 msgid "Uplink SSID"
 msgstr ""
 
@@ -267,13 +310,19 @@ msgstr ""
 msgid "WEP"
 msgstr ""
 
-msgid "WEP passphrase"
+msgid "WEP-Passphrase"
+msgstr ""
+
+msgid "WPA"
+msgstr ""
+
+msgid "WPA-Passphrase"
 msgstr ""
 
-msgid "WPA / WPA2"
+msgid "WPA/WPA2"
 msgstr ""
 
-msgid "WPA passphrase"
+msgid "WPA2"
 msgstr ""
 
 msgid "Wireless Scan"
index a9ceafe..d104724 100644 (file)
@@ -20,9 +20,21 @@ msgstr ""
 msgid "Advanced"
 msgstr ""
 
+msgid "Authentication"
+msgstr ""
+
+msgid "Automatic"
+msgstr ""
+
+msgid "BSSID"
+msgstr ""
+
 msgid "Back to overview"
 msgstr ""
 
+msgid "Cipher"
+msgstr ""
+
 msgid ""
 "Configuration of the travelmate package to to enable travel router "
 "functionality."
@@ -47,6 +59,9 @@ msgstr ""
 msgid "Device"
 msgstr ""
 
+msgid "EAP-Method"
+msgstr ""
+
 msgid "Edit"
 msgstr ""
 
@@ -91,12 +106,27 @@ msgid ""
 "documentation</a>"
 msgstr ""
 
+msgid "Force CCMP (AES)"
+msgstr ""
+
+msgid "Force TKIP"
+msgstr ""
+
+msgid "Force TKIP and CCMP (AES)"
+msgstr ""
+
+msgid "Force a manual uplink rescan / reconnect in 'trigger' mode."
+msgstr ""
+
 msgid "How long should travelmate wait for a successful wlan interface reload."
 msgstr ""
 
 msgid "How many times should travelmate try to connect to an Uplink."
 msgstr ""
 
+msgid "Identity"
+msgstr ""
+
 msgid "Input file not found, please check your configuration."
 msgstr ""
 
@@ -123,9 +153,7 @@ msgstr ""
 msgid "Move up"
 msgstr ""
 
-msgid ""
-"Name of the uplink interface that triggers travelmate processing in 'manual' "
-"mode."
+msgid "Name of the used uplink interface."
 msgstr ""
 
 msgid "Online Status"
@@ -144,7 +172,22 @@ msgstr ""
 msgid "Overview"
 msgstr ""
 
-msgid "Passphrase (%s)"
+msgid "Passphrase"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Password of Private Key"
+msgstr ""
+
+msgid "Path to CA-Certificate"
+msgstr ""
+
+msgid "Path to Client-Certificate"
+msgstr ""
+
+msgid "Path to Private Key"
 msgstr ""
 
 msgid ""
@@ -165,7 +208,7 @@ msgstr ""
 msgid "Restrict travelmate to a dedicated radio, e.g. 'radio0'."
 msgstr ""
 
-msgid "Runtime information"
+msgid "Runtime Information"
 msgstr ""
 
 msgid "SSID"
@@ -183,7 +226,7 @@ msgstr ""
 msgid "Signal strength"
 msgstr ""
 
-msgid "Specify the secret encryption key here."
+msgid "Station ID (SSID/BSSID)"
 msgstr ""
 
 msgid "Station Interface"
@@ -192,9 +235,6 @@ msgstr ""
 msgid "Station Radio"
 msgstr ""
 
-msgid "Station SSID"
-msgstr ""
-
 msgid ""
 "This form allows you to modify the content of the main firewall "
 "configuration file (/etc/config/firewall)."
@@ -244,6 +284,9 @@ msgstr ""
 msgid "Uplink / Trigger interface"
 msgstr ""
 
+msgid "Uplink BSSID"
+msgstr ""
+
 msgid "Uplink SSID"
 msgstr ""
 
@@ -256,13 +299,19 @@ msgstr ""
 msgid "WEP"
 msgstr ""
 
-msgid "WEP passphrase"
+msgid "WEP-Passphrase"
+msgstr ""
+
+msgid "WPA"
+msgstr ""
+
+msgid "WPA-Passphrase"
 msgstr ""
 
-msgid "WPA / WPA2"
+msgid "WPA/WPA2"
 msgstr ""
 
-msgid "WPA passphrase"
+msgid "WPA2"
 msgstr ""
 
 msgid "Wireless Scan"
index b9dae4f..fe2dd64 100644 (file)
@@ -17,8 +17,8 @@ msgid ""
 "ACLs specify which external ports may be redirected to which internal "
 "addresses and ports"
 msgstr ""
-"アクセス制御リスト(ACL) は、どの外部ポートからどの内部アドレス及びポートへ"
-"ã\83ªã\83\80ã\82¤ã\83¬ã\82¯ã\83\88ã\81\99ã\82\8bã\81\8bã\82\92設å®\9aã\81\97ã\81¾ã\81\99ã\80\82"
+"アクセス制御リスト(ACL) は、どの外部ポートからどの内部アドレス及びポートへ"
+"ダイレクトするかを設定します。"
 
 msgid "Action"
 msgstr "動作"
@@ -132,8 +132,8 @@ msgid ""
 "UPnP allows clients in the local network to automatically configure the "
 "router."
 msgstr ""
-"UPnPを使用することで、ローカルネットワーク内のクライアントが自動的にルータ"
-"構成することができます。"
+"UPnPを使用することで、ローカルネットワーク内のクライアントが自動的にルータ"
+"構成することができます。"
 
 msgid "UPnP lease file"
 msgstr "UPnP リースファイル"
index 40d0a06..476e7fd 100644 (file)
@@ -1274,7 +1274,7 @@ true
 
 
 <h3>Usage:</h3>
-It is normally not possible to rename files across fileystems.
+It is normally not possible to rename files across filesystems.
 
 
 
index 5d08719..5bfd7a6 100644 (file)
@@ -47,7 +47,7 @@ module "nixio.fs"
 -- @name nixio.fs.rename
 -- @param      src     Source path
 -- @param      dest Destination path
--- @usage      It is normally not possible to rename files accross fileystems.
+-- @usage      It is normally not possible to rename files accross filesystems.
 -- @return     true
 
 --- Remove an empty directory.
index e69534b..ec3d1b0 100644 (file)
@@ -605,7 +605,7 @@ msgstr "Canal"
 msgid "Check"
 msgstr "Comprovació"
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr ""
 
 msgid "Check this option to delete the existing networks from this radio."
index bff89c8..2b93b35 100644 (file)
@@ -598,7 +598,7 @@ msgstr "Kanál"
 msgid "Check"
 msgstr "Kontrola"
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr ""
 
 msgid "Check this option to delete the existing networks from this radio."
index eb9221f..9e19bd1 100644 (file)
@@ -612,7 +612,7 @@ msgstr "Kanal"
 msgid "Check"
 msgstr "Prüfen"
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr "Dateisysteme prüfen"
 
 msgid "Check this option to delete the existing networks from this radio."
index ca8240f..b742380 100644 (file)
@@ -607,7 +607,7 @@ msgstr "Κανάλι"
 msgid "Check"
 msgstr "Έλεγχος"
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr ""
 
 msgid "Check this option to delete the existing networks from this radio."
index 6db22b6..2e70796 100644 (file)
@@ -596,7 +596,7 @@ msgstr "Channel"
 msgid "Check"
 msgstr "Check"
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr ""
 
 msgid "Check this option to delete the existing networks from this radio."
index 088bdbd..6aae853 100644 (file)
@@ -603,7 +603,7 @@ msgstr "Canal"
 msgid "Check"
 msgstr "Comprobar"
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr ""
 
 msgid "Check this option to delete the existing networks from this radio."
index a94ffb3..4f2cc96 100644 (file)
@@ -608,7 +608,7 @@ msgstr "Canal"
 msgid "Check"
 msgstr "Vérification"
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr ""
 
 msgid "Check this option to delete the existing networks from this radio."
index 2997941..aca6537 100644 (file)
@@ -598,7 +598,7 @@ msgstr "ערוץ"
 msgid "Check"
 msgstr "לבדוק"
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr ""
 
 msgid "Check this option to delete the existing networks from this radio."
index 00b4d77..96ac3f2 100644 (file)
@@ -603,7 +603,7 @@ msgstr "Csatorna"
 msgid "Check"
 msgstr "Ellenőrzés"
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr ""
 
 msgid "Check this option to delete the existing networks from this radio."
index b90ca79..bc1e255 100644 (file)
@@ -610,7 +610,7 @@ msgstr "Canale"
 msgid "Check"
 msgstr "Verifica"
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr "Controlla i filesystem prima di montare"
 
 msgid "Check this option to delete the existing networks from this radio."
index 1d321f9..9254b1d 100644 (file)
@@ -603,7 +603,7 @@ msgstr "チャネル"
 msgid "Check"
 msgstr "チェック"
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr "マウント前にファイルシステムをチェックする"
 
 msgid "Check this option to delete the existing networks from this radio."
index cde3c04..2e3ac4e 100644 (file)
@@ -592,7 +592,7 @@ msgstr ""
 msgid "Check"
 msgstr ""
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr ""
 
 msgid "Check this option to delete the existing networks from this radio."
index 74d3e19..bb2331b 100644 (file)
@@ -582,7 +582,7 @@ msgstr "Saluran"
 msgid "Check"
 msgstr ""
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr ""
 
 msgid "Check this option to delete the existing networks from this radio."
index f1bfec4..1517463 100644 (file)
@@ -594,7 +594,7 @@ msgstr "Kanal"
 msgid "Check"
 msgstr "Kontroller"
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr ""
 
 msgid "Check this option to delete the existing networks from this radio."
index 22902c4..1a6538f 100644 (file)
@@ -611,7 +611,7 @@ msgstr "Kanał"
 msgid "Check"
 msgstr "Sprawdź"
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr ""
 
 msgid "Check this option to delete the existing networks from this radio."
index eef8eba..4d9a753 100644 (file)
@@ -643,7 +643,7 @@ msgstr "Canal"
 msgid "Check"
 msgstr "Verificar"
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr ""
 "Execute a verificação do sistema de arquivos antes da montagem do dispositivo"
 
index aadcccc..18c7079 100644 (file)
@@ -607,7 +607,7 @@ msgstr "Canal"
 msgid "Check"
 msgstr "Verificar"
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr ""
 
 msgid "Check this option to delete the existing networks from this radio."
index 029b395..25ada00 100644 (file)
@@ -590,7 +590,7 @@ msgstr "Canal"
 msgid "Check"
 msgstr "Verificare"
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr ""
 
 msgid "Check this option to delete the existing networks from this radio."
index 9a3cf43..54925e6 100644 (file)
@@ -607,7 +607,7 @@ msgstr "Канал"
 msgid "Check"
 msgstr "Проверить"
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr ""
 
 msgid "Check this option to delete the existing networks from this radio."
index 82fd389..4ce56eb 100644 (file)
@@ -576,7 +576,7 @@ msgstr ""
 msgid "Check"
 msgstr ""
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr ""
 
 msgid "Check this option to delete the existing networks from this radio."
index 3360ccb..fb3eb7b 100644 (file)
@@ -588,7 +588,7 @@ msgstr "Kanal"
 msgid "Check"
 msgstr "Kontrollera"
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr "Kontrollera filsystemen innan de monteras"
 
 msgid "Check this option to delete the existing networks from this radio."
index 1c21925..4737604 100644 (file)
@@ -569,7 +569,7 @@ msgstr ""
 msgid "Check"
 msgstr ""
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr ""
 
 msgid "Check this option to delete the existing networks from this radio."
index 334ef00..d0c18f2 100644 (file)
@@ -589,7 +589,7 @@ msgstr ""
 msgid "Check"
 msgstr ""
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr ""
 
 msgid "Check this option to delete the existing networks from this radio."
index de7259b..d0157e1 100644 (file)
@@ -616,7 +616,7 @@ msgstr "Канал"
 msgid "Check"
 msgstr "Перевірити"
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr ""
 
 msgid "Check this option to delete the existing networks from this radio."
index 48f6b73..988938f 100644 (file)
@@ -583,7 +583,7 @@ msgstr "Kênh"
 msgid "Check"
 msgstr ""
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr ""
 
 msgid "Check this option to delete the existing networks from this radio."
index f516d42..42d1dd7 100644 (file)
@@ -585,7 +585,7 @@ msgstr "信道"
 msgid "Check"
 msgstr "检查"
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr "在挂载前检查文件系统"
 
 msgid "Check this option to delete the existing networks from this radio."
index c0abad2..924d8b4 100644 (file)
@@ -588,7 +588,7 @@ msgstr "頻道"
 msgid "Check"
 msgstr "檢查"
 
-msgid "Check fileystems before mount"
+msgid "Check filesystems before mount"
 msgstr ""
 
 msgid "Check this option to delete the existing networks from this radio."
index fd466d5..3ce5351 100644 (file)
@@ -62,7 +62,7 @@ o = s:option(Flag, "auto_mount", translate("Automount Filesystem"), translate("A
 o.default = o.enabled
 o.rmempty = false
 
-o = s:option(Flag, "check_fs", translate("Check fileystems before mount"), translate("Automatically check filesystem for errors before mounting"))
+o = s:option(Flag, "check_fs", translate("Check filesystems before mount"), translate("Automatically check filesystem for errors before mounting"))
 o.default = o.disabled
 o.rmempty = false
 
index b4baedf..ea6ee91 100644 (file)
                                                tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
 
                                        var host = hosts[duid2mac(st[1][i].duid)];
-                                       if (host)
-                                               tr.insertCell(-1).innerHTML = String.format(
-                                                       '<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis">%s</div>',
-                                                       ((host.name && (host.ipv4 || host.ipv6))
-                                                               ? '%h (%s)'.format(host.name, host.ipv4 || host.ipv6)
-                                                               : '%h'.format(host.name || host.ipv4 || host.ipv6)).nobr()
-                                               );
+                                       if (!st[1][i].hostname)
+                                               tr.insertCell(-1).innerHTML =
+                                                       (host && (host.name || host.ipv4 || host.ipv6))
+                                                               ? '<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space: nowrap">? (%h)</div>'.format(host.name || host.ipv4 || host.ipv6)
+                                                               : '?';
                                        else
-                                               tr.insertCell(-1).innerHTML = st[1][i].hostname ? st[1][i].hostname : '?';
+                                               tr.insertCell(-1).innerHTML =
+                                                       (host && host.name && st[1][i].hostname != host.name)
+                                                               ? '<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space: nowrap">%h (%h)</div>'.format(st[1][i].hostname, host.name)
+                                                               : st[1][i].hostname;
 
                                        tr.insertCell(-1).innerHTML = st[1][i].ip6addr;
                                        tr.insertCell(-1).innerHTML = st[1][i].duid;
index d29a894..18f66c2 100644 (file)
@@ -38,7 +38,7 @@
                local wan6 = ntm:get_wan6net()
 
                local conn_count = tonumber(
-                       fs.readfile("/proc/sys/net/netfilter/nf_conntrack_count")) or 0
+                       fs.readfile("/proc/sys/net/netfilter/nf_conntrack_count") or "") or 0
 
                local conn_max = tonumber((
                        luci.sys.exec("sysctl net.nf_conntrack_max") or
                                                tr.className = 'cbi-section-table-row cbi-rowstyle-' + ((i % 2) + 1);
 
                                        var host = hosts[duid2mac(info.leases6[i].duid)];
-                                       if (host)
-                                               tr.insertCell(-1).innerHTML = String.format(
-                                                       '<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis">%s</div>',
-                                                       ((host.name && (host.ipv4 || host.ipv6))
-                                                               ? '%h (%s)'.format(host.name, host.ipv4 || host.ipv6)
-                                                               : '%h'.format(host.name || host.ipv4 || host.ipv6)).nobr()
-                                               );
+                                       if (!info.leases6[i].hostname)
+                                               tr.insertCell(-1).innerHTML =
+                                                       (host && (host.name || host.ipv4 || host.ipv6))
+                                                               ? '<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space: nowrap">? (%h)</div>'.format(host.name || host.ipv4 || host.ipv6)
+                                                               : '?';
                                        else
-                                               tr.insertCell(-1).innerHTML = info.leases6[i].hostname ? info.leases6[i].hostname : '?';
+                                               tr.insertCell(-1).innerHTML =
+                                                       (host && host.name && info.leases6[i].hostname != host.name)
+                                                               ? '<div style="max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space: nowrap">%h (%h)</div>'.format(info.leases6[i].hostname, host.name)
+                                                               : info.leases6[i].hostname;
 
                                        tr.insertCell(-1).innerHTML = info.leases6[i].ip6addr;
                                        tr.insertCell(-1).innerHTML = info.leases6[i].duid;